1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "RenderD3D11TextureHost.h"
9 #include "GLContextEGL.h"
10 #include "GLLibraryEGL.h"
11 #include "RenderThread.h"
12 #include "RenderCompositor.h"
13 #include "RenderCompositorD3D11SWGL.h"
14 #include "ScopedGLHelpers.h"
15 #include "mozilla/DebugOnly.h"
16 #include "mozilla/gfx/CanvasManagerParent.h"
17 #include "mozilla/gfx/DeviceManagerDx.h"
18 #include "mozilla/gfx/Logging.h"
19 #include "mozilla/layers/FenceD3D11.h"
20 #include "mozilla/layers/GpuProcessD3D11QueryMap.h"
21 #include "mozilla/layers/GpuProcessD3D11TextureMap.h"
22 #include "mozilla/layers/TextureD3D11.h"
27 RenderDXGITextureHost::RenderDXGITextureHost(
28 RefPtr
<gfx::FileHandleWrapper
> aHandle
,
29 Maybe
<layers::GpuProcessTextureId
>& aGpuProcessTextureId
,
30 uint32_t aArrayIndex
, gfx::SurfaceFormat aFormat
,
31 gfx::ColorSpace2 aColorSpace
, gfx::ColorRange aColorRange
,
32 gfx::IntSize aSize
, bool aHasKeyedMutex
, gfx::FenceInfo
& aAcquireFenceInfo
,
33 Maybe
<layers::GpuProcessQueryId
>& aGpuProcessQueryId
)
35 mGpuProcessTextureId(aGpuProcessTextureId
),
36 mGpuProcessQueryId(aGpuProcessQueryId
),
37 mArrayIndex(aArrayIndex
),
42 mColorSpace(aColorSpace
),
43 mColorRange(aColorRange
),
45 mHasKeyedMutex(aHasKeyedMutex
),
46 mAcquireFenceInfo(aAcquireFenceInfo
),
48 MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHost
, RenderTextureHost
);
49 MOZ_ASSERT((mFormat
!= gfx::SurfaceFormat::NV12
&&
50 mFormat
!= gfx::SurfaceFormat::P010
&&
51 mFormat
!= gfx::SurfaceFormat::P016
) ||
52 (mSize
.width
% 2 == 0 && mSize
.height
% 2 == 0));
53 MOZ_ASSERT((aHandle
&& aGpuProcessTextureId
.isNothing()) ||
54 (!aHandle
&& aGpuProcessTextureId
.isSome()));
57 RenderDXGITextureHost::~RenderDXGITextureHost() {
58 MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHost
, RenderTextureHost
);
59 DeleteTextureHandle();
62 RefPtr
<ID3D11Query
> RenderDXGITextureHost::GetQuery() {
63 if (mGpuProcessQueryId
.isNothing()) {
67 auto* queryMap
= layers::GpuProcessD3D11QueryMap::Get();
72 auto query
= queryMap
->GetQuery(mGpuProcessQueryId
.ref());
74 gfxCriticalNoteOnce
<< "Failed to get ID3D11Query";
80 ID3D11Texture2D
* RenderDXGITextureHost::GetD3D11Texture2DWithGL() {
86 // SingletonGL is always used on Windows with ANGLE.
87 mGL
= RenderThread::Get()->SingletonGL();
90 if (!EnsureD3D11Texture2DWithGL()) {
97 size_t RenderDXGITextureHost::GetPlaneCount() const {
98 if (mFormat
== gfx::SurfaceFormat::NV12
||
99 mFormat
== gfx::SurfaceFormat::P010
||
100 mFormat
== gfx::SurfaceFormat::P016
) {
106 template <typename T
>
107 static bool MapTexture(T
* aHost
, RenderCompositor
* aCompositor
,
108 RefPtr
<ID3D11Texture2D
>& aTexture
,
109 RefPtr
<ID3D11DeviceContext
>& aDeviceContext
,
110 RefPtr
<ID3D11Texture2D
>& aCpuTexture
,
111 D3D11_MAPPED_SUBRESOURCE
& aMappedSubresource
) {
116 RenderCompositorD3D11SWGL
* compositor
=
117 aCompositor
->AsRenderCompositorD3D11SWGL();
122 if (!aHost
->EnsureD3D11Texture2D(compositor
->GetDevice())) {
126 if (!aHost
->LockInternal()) {
130 D3D11_TEXTURE2D_DESC textureDesc
= {0};
131 aTexture
->GetDesc(&textureDesc
);
133 compositor
->GetDevice()->GetImmediateContext(getter_AddRefs(aDeviceContext
));
135 textureDesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
;
136 textureDesc
.Usage
= D3D11_USAGE_STAGING
;
137 textureDesc
.BindFlags
= 0;
138 textureDesc
.MiscFlags
= 0;
139 textureDesc
.MipLevels
= 1;
140 HRESULT hr
= compositor
->GetDevice()->CreateTexture2D(
141 &textureDesc
, nullptr, getter_AddRefs(aCpuTexture
));
146 aDeviceContext
->CopyResource(aCpuTexture
, aTexture
);
149 hr
= aDeviceContext
->Map(aCpuTexture
, 0, D3D11_MAP_READ
, 0,
150 &aMappedSubresource
);
151 return SUCCEEDED(hr
);
154 bool RenderDXGITextureHost::MapPlane(RenderCompositor
* aCompositor
,
155 uint8_t aChannelIndex
,
156 PlaneInfo
& aPlaneInfo
) {
157 // TODO: We currently readback from the GPU texture into a new
158 // staging texture every time this is mapped. We might be better
159 // off retaining the mapped memory to trade performance for memory
161 if (!mCpuTexture
&& !MapTexture(this, aCompositor
, mTexture
, mDeviceContext
,
162 mCpuTexture
, mMappedSubresource
)) {
166 aPlaneInfo
.mSize
= GetSize(aChannelIndex
);
167 aPlaneInfo
.mStride
= mMappedSubresource
.RowPitch
;
168 aPlaneInfo
.mData
= mMappedSubresource
.pData
;
170 // If this is the second plane, then offset the data pointer by the
171 // size of the first plane.
172 if (aChannelIndex
== 1) {
174 (uint8_t*)aPlaneInfo
.mData
+ aPlaneInfo
.mStride
* GetSize(0).height
;
179 void RenderDXGITextureHost::UnmapPlanes() {
180 mMappedSubresource
.pData
= nullptr;
182 mDeviceContext
->Unmap(mCpuTexture
, 0);
183 mCpuTexture
= nullptr;
185 mDeviceContext
= nullptr;
188 bool RenderDXGITextureHost::EnsureD3D11Texture2DWithGL() {
193 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
194 const auto& egl
= gle
->mEgl
;
196 // Fetch the D3D11 device.
197 EGLDeviceEXT eglDevice
= nullptr;
198 egl
->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT
, (EGLAttrib
*)&eglDevice
);
199 MOZ_ASSERT(eglDevice
);
200 ID3D11Device
* device
= nullptr;
201 egl
->mLib
->fQueryDeviceAttribEXT(eglDevice
, LOCAL_EGL_D3D11_DEVICE_ANGLE
,
202 (EGLAttrib
*)&device
);
203 // There's a chance this might fail if we end up on d3d9 angle for some
206 gfxCriticalNote
<< "RenderDXGITextureHost device is not available";
210 return EnsureD3D11Texture2D(device
);
213 bool RenderDXGITextureHost::EnsureD3D11Texture2D(ID3D11Device
* aDevice
) {
215 RefPtr
<ID3D11Device
> device
;
216 mTexture
->GetDevice(getter_AddRefs(device
));
217 if (aDevice
!= device
) {
218 gfxCriticalNote
<< "RenderDXGITextureHost uses obsoleted device";
224 if (mGpuProcessTextureId
.isSome()) {
225 auto* textureMap
= layers::GpuProcessD3D11TextureMap::Get();
227 RefPtr
<ID3D11Texture2D
> texture
;
228 textureMap
->WaitTextureReady(mGpuProcessTextureId
.ref());
229 mTexture
= textureMap
->GetTexture(mGpuProcessTextureId
.ref());
233 gfxCriticalNote
<< "GpuProcessTextureId is not valid";
239 RefPtr
<ID3D11Device1
> device1
;
240 aDevice
->QueryInterface((ID3D11Device1
**)getter_AddRefs(device1
));
242 gfxCriticalNoteOnce
<< "Failed to get ID3D11Device1";
246 // Get the D3D11 texture from shared handle.
247 HRESULT hr
= device1
->OpenSharedResource1(
248 (HANDLE
)mHandle
->GetHandle(), __uuidof(ID3D11Texture2D
),
249 (void**)(ID3D11Texture2D
**)getter_AddRefs(mTexture
));
252 "RenderDXGITextureHost::EnsureLockable(): Failed to open shared "
255 << "RenderDXGITextureHost Failed to open shared texture, hr="
259 MOZ_ASSERT(mTexture
.get());
260 mTexture
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(mKeyedMutex
));
262 MOZ_ASSERT(mHasKeyedMutex
== !!mKeyedMutex
);
263 if (mHasKeyedMutex
!= !!mKeyedMutex
) {
264 gfxCriticalNoteOnce
<< "KeyedMutex mismatch";
269 bool RenderDXGITextureHost::EnsureLockable() {
270 if (mTextureHandle
[0]) {
274 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
275 const auto& egl
= gle
->mEgl
;
277 // We use EGLStream to get the converted gl handle from d3d texture. The
278 // NV_stream_consumer_gltexture_yuv and ANGLE_stream_producer_d3d_texture
279 // could support nv12 and rgb d3d texture format.
280 if (!egl
->IsExtensionSupported(
281 gl::EGLExtension::NV_stream_consumer_gltexture_yuv
) ||
282 !egl
->IsExtensionSupported(
283 gl::EGLExtension::ANGLE_stream_producer_d3d_texture
)) {
284 gfxCriticalNote
<< "RenderDXGITextureHost egl extensions are not suppored";
288 // Get the D3D11 texture from shared handle.
289 if (!EnsureD3D11Texture2DWithGL()) {
293 // Create the EGLStream.
294 mStream
= egl
->fCreateStreamKHR(nullptr);
298 if (mFormat
!= gfx::SurfaceFormat::NV12
&&
299 mFormat
!= gfx::SurfaceFormat::P010
&&
300 mFormat
!= gfx::SurfaceFormat::P016
) {
301 // The non-nv12 format.
303 mGL
->fGenTextures(1, mTextureHandle
);
304 ActivateBindAndTexParameteri(mGL
, LOCAL_GL_TEXTURE0
,
305 LOCAL_GL_TEXTURE_EXTERNAL_OES
,
308 bool(egl
->fStreamConsumerGLTextureExternalAttribsNV(mStream
, nullptr));
309 ok
&= bool(egl
->fCreateStreamProducerD3DTextureANGLE(mStream
, nullptr));
311 // The nv12/p016 format.
313 // Setup the NV12 stream consumer/producer.
314 EGLAttrib consumerAttributes
[] = {
315 LOCAL_EGL_COLOR_BUFFER_TYPE
,
316 LOCAL_EGL_YUV_BUFFER_EXT
,
317 LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT
,
319 LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV
,
321 LOCAL_EGL_YUV_PLANE1_TEXTURE_UNIT_NV
,
325 mGL
->fGenTextures(2, mTextureHandle
);
326 ActivateBindAndTexParameteri(mGL
, LOCAL_GL_TEXTURE0
,
327 LOCAL_GL_TEXTURE_EXTERNAL_OES
,
329 ActivateBindAndTexParameteri(mGL
, LOCAL_GL_TEXTURE1
,
330 LOCAL_GL_TEXTURE_EXTERNAL_OES
,
332 ok
&= bool(egl
->fStreamConsumerGLTextureExternalAttribsNV(
333 mStream
, consumerAttributes
));
334 ok
&= bool(egl
->fCreateStreamProducerD3DTextureANGLE(mStream
, nullptr));
337 const EGLAttrib frameAttributes
[] = {
338 LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE
,
339 static_cast<EGLAttrib
>(mArrayIndex
),
343 // Insert the d3d texture.
344 ok
&= bool(egl
->fStreamPostD3DTextureANGLE(mStream
, (void*)mTexture
.get(),
348 gfxCriticalNote
<< "RenderDXGITextureHost init stream failed";
349 DeleteTextureHandle();
353 // Now, we could get the gl handle from the stream.
354 MOZ_ALWAYS_TRUE(egl
->fStreamConsumerAcquireKHR(mStream
));
359 wr::WrExternalImage
RenderDXGITextureHost::Lock(uint8_t aChannelIndex
,
360 gl::GLContext
* aGL
) {
361 if (mGL
.get() != aGL
) {
362 // Release the texture handle in the previous gl context.
363 DeleteTextureHandle();
368 // XXX Software WebRender is not handled yet.
369 // Software WebRender does not provide GLContext
371 << "Software WebRender is not suppored by RenderDXGITextureHost.";
372 return InvalidToWrExternalImage();
375 if (!EnsureLockable()) {
376 return InvalidToWrExternalImage();
379 if (!LockInternal()) {
380 return InvalidToWrExternalImage();
383 const auto uvs
= GetUvCoords(GetSize(aChannelIndex
));
384 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex
), uvs
.first
.x
,
385 uvs
.first
.y
, uvs
.second
.x
,
389 bool RenderDXGITextureHost::LockInternal() {
391 if (mAcquireFenceInfo
.mFenceHandle
) {
392 if (!mAcquireFence
) {
393 mAcquireFence
= layers::FenceD3D11::CreateFromHandle(
394 mAcquireFenceInfo
.mFenceHandle
);
397 MOZ_ASSERT(mAcquireFenceInfo
.mFenceHandle
== mAcquireFence
->mHandle
);
399 mAcquireFence
->Update(mAcquireFenceInfo
.mFenceValue
);
400 RefPtr
<ID3D11Device
> d3d11Device
=
401 gfx::DeviceManagerDx::Get()->GetCompositorDevice();
402 mAcquireFence
->Wait(d3d11Device
);
406 HRESULT hr
= mKeyedMutex
->AcquireSync(0, 10000);
408 gfxCriticalError() << "RenderDXGITextureHost AcquireSync timeout, hr="
418 void RenderDXGITextureHost::Unlock() {
421 mKeyedMutex
->ReleaseSync(0);
427 void RenderDXGITextureHost::ClearCachedResources() {
428 DeleteTextureHandle();
432 void RenderDXGITextureHost::DeleteTextureHandle() {
433 if (mTextureHandle
[0] == 0) {
437 MOZ_ASSERT(mGL
.get());
442 if (mGL
->MakeCurrent()) {
443 mGL
->fDeleteTextures(2, mTextureHandle
);
445 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
446 const auto& egl
= gle
->mEgl
;
448 egl
->fDestroySurface(mSurface
);
451 egl
->fDestroyStreamKHR(mStream
);
455 for (int i
= 0; i
< 2; ++i
) {
456 mTextureHandle
[i
] = 0;
460 mKeyedMutex
= nullptr;
465 GLuint
RenderDXGITextureHost::GetGLHandle(uint8_t aChannelIndex
) const {
466 MOZ_ASSERT(((mFormat
== gfx::SurfaceFormat::NV12
||
467 mFormat
== gfx::SurfaceFormat::P010
||
468 mFormat
== gfx::SurfaceFormat::P016
) &&
469 aChannelIndex
< 2) ||
471 return mTextureHandle
[aChannelIndex
];
474 gfx::IntSize
RenderDXGITextureHost::GetSize(uint8_t aChannelIndex
) const {
475 MOZ_ASSERT(((mFormat
== gfx::SurfaceFormat::NV12
||
476 mFormat
== gfx::SurfaceFormat::P010
||
477 mFormat
== gfx::SurfaceFormat::P016
) &&
478 aChannelIndex
< 2) ||
481 if (aChannelIndex
== 0) {
484 // The CbCr channel size is a half of Y channel size in NV12 format.
489 bool RenderDXGITextureHost::SyncObjectNeeded() {
490 return mGpuProcessTextureId
.isNothing() && !mHasKeyedMutex
&&
491 !mAcquireFenceInfo
.mFenceHandle
;
494 RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
495 RefPtr
<gfx::FileHandleWrapper
> (&aHandles
)[3],
496 gfx::YUVColorSpace aYUVColorSpace
, gfx::ColorDepth aColorDepth
,
497 gfx::ColorRange aColorRange
, gfx::IntSize aSizeY
, gfx::IntSize aSizeCbCr
)
498 : mHandles
{aHandles
[0], aHandles
[1], aHandles
[2]},
502 mYUVColorSpace(aYUVColorSpace
),
503 mColorDepth(aColorDepth
),
504 mColorRange(aColorRange
),
506 mSizeCbCr(aSizeCbCr
),
508 MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost
, RenderTextureHost
);
509 // Assume the chroma planes are rounded up if the luma plane is odd sized.
510 MOZ_ASSERT((mSizeCbCr
.width
== mSizeY
.width
||
511 mSizeCbCr
.width
== (mSizeY
.width
+ 1) >> 1) &&
512 (mSizeCbCr
.height
== mSizeY
.height
||
513 mSizeCbCr
.height
== (mSizeY
.height
+ 1) >> 1));
514 MOZ_ASSERT(aHandles
[0] && aHandles
[1] && aHandles
[2]);
517 bool RenderDXGIYCbCrTextureHost::MapPlane(RenderCompositor
* aCompositor
,
518 uint8_t aChannelIndex
,
519 PlaneInfo
& aPlaneInfo
) {
520 D3D11_MAPPED_SUBRESOURCE mappedSubresource
;
521 if (!MapTexture(this, aCompositor
, mTextures
[aChannelIndex
], mDeviceContext
,
522 mCpuTexture
[aChannelIndex
], mappedSubresource
)) {
526 aPlaneInfo
.mSize
= GetSize(aChannelIndex
);
527 aPlaneInfo
.mStride
= mappedSubresource
.RowPitch
;
528 aPlaneInfo
.mData
= mappedSubresource
.pData
;
532 void RenderDXGIYCbCrTextureHost::UnmapPlanes() {
533 for (uint32_t i
= 0; i
< 3; i
++) {
534 if (mCpuTexture
[i
]) {
535 mDeviceContext
->Unmap(mCpuTexture
[i
], 0);
536 mCpuTexture
[i
] = nullptr;
539 mDeviceContext
= nullptr;
542 RenderDXGIYCbCrTextureHost::~RenderDXGIYCbCrTextureHost() {
543 MOZ_COUNT_DTOR_INHERITED(RenderDXGIYCbCrTextureHost
, RenderTextureHost
);
544 DeleteTextureHandle();
547 bool RenderDXGIYCbCrTextureHost::EnsureLockable() {
548 if (mTextureHandles
[0]) {
552 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
553 const auto& egl
= gle
->mEgl
;
555 // The eglCreatePbufferFromClientBuffer doesn't support R8 format, so we
556 // use EGLStream to get the converted gl handle from d3d R8 texture.
558 if (!egl
->IsExtensionSupported(
559 gl::EGLExtension::NV_stream_consumer_gltexture_yuv
) ||
560 !egl
->IsExtensionSupported(
561 gl::EGLExtension::ANGLE_stream_producer_d3d_texture
)) {
563 << "RenderDXGIYCbCrTextureHost egl extensions are not suppored";
567 // Fetch the D3D11 device.
568 EGLDeviceEXT eglDevice
= nullptr;
569 egl
->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT
, (EGLAttrib
*)&eglDevice
);
570 MOZ_ASSERT(eglDevice
);
571 ID3D11Device
* device
= nullptr;
572 egl
->mLib
->fQueryDeviceAttribEXT(eglDevice
, LOCAL_EGL_D3D11_DEVICE_ANGLE
,
573 (EGLAttrib
*)&device
);
574 // There's a chance this might fail if we end up on d3d9 angle for some
577 gfxCriticalNote
<< "RenderDXGIYCbCrTextureHost device is not available";
581 if (!EnsureD3D11Texture2D(device
)) {
585 mGL
->fGenTextures(3, mTextureHandles
);
587 for (int i
= 0; i
< 3; ++i
) {
588 ActivateBindAndTexParameteri(mGL
, LOCAL_GL_TEXTURE0
+ i
,
589 LOCAL_GL_TEXTURE_EXTERNAL_OES
,
592 // Create the EGLStream.
593 mStreams
[i
] = egl
->fCreateStreamKHR(nullptr);
594 MOZ_ASSERT(mStreams
[i
]);
597 egl
->fStreamConsumerGLTextureExternalAttribsNV(mStreams
[i
], nullptr));
598 ok
&= bool(egl
->fCreateStreamProducerD3DTextureANGLE(mStreams
[i
], nullptr));
600 // Insert the R8 texture.
601 ok
&= bool(egl
->fStreamPostD3DTextureANGLE(
602 mStreams
[i
], (void*)mTextures
[i
].get(), nullptr));
604 // Now, we could get the R8 gl handle from the stream.
605 MOZ_ALWAYS_TRUE(egl
->fStreamConsumerAcquireKHR(mStreams
[i
]));
609 gfxCriticalNote
<< "RenderDXGIYCbCrTextureHost init stream failed";
610 DeleteTextureHandle();
617 bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device
* aDevice
) {
618 RefPtr
<ID3D11Device1
> device1
;
619 aDevice
->QueryInterface((ID3D11Device1
**)getter_AddRefs(device1
));
621 gfxCriticalNoteOnce
<< "Failed to get ID3D11Device1";
626 RefPtr
<ID3D11Device
> device
;
627 mTextures
[0]->GetDevice(getter_AddRefs(device
));
628 if (aDevice
!= device
) {
629 gfxCriticalNote
<< "RenderDXGIYCbCrTextureHost uses obsoleted device";
634 if (mTextureHandles
[0]) {
638 for (int i
= 0; i
< 3; ++i
) {
639 // Get the R8 D3D11 texture from shared handle.
640 HRESULT hr
= device1
->OpenSharedResource1(
641 (HANDLE
)mHandles
[i
]->GetHandle(), __uuidof(ID3D11Texture2D
),
642 (void**)(ID3D11Texture2D
**)getter_AddRefs(mTextures
[i
]));
645 "RenderDXGIYCbCrTextureHost::EnsureLockable(): Failed to open "
649 << "RenderDXGIYCbCrTextureHost Failed to open shared texture, hr="
655 for (int i
= 0; i
< 3; ++i
) {
656 mTextures
[i
]->QueryInterface(
657 (IDXGIKeyedMutex
**)getter_AddRefs(mKeyedMutexs
[i
]));
662 bool RenderDXGIYCbCrTextureHost::LockInternal() {
664 if (mKeyedMutexs
[0]) {
665 for (const auto& mutex
: mKeyedMutexs
) {
666 HRESULT hr
= mutex
->AcquireSync(0, 10000);
669 << "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr="
680 wr::WrExternalImage
RenderDXGIYCbCrTextureHost::Lock(uint8_t aChannelIndex
,
681 gl::GLContext
* aGL
) {
682 if (mGL
.get() != aGL
) {
683 // Release the texture handle in the previous gl context.
684 DeleteTextureHandle();
689 // XXX Software WebRender is not handled yet.
690 // Software WebRender does not provide GLContext
691 gfxCriticalNoteOnce
<< "Software WebRender is not suppored by "
692 "RenderDXGIYCbCrTextureHost.";
693 return InvalidToWrExternalImage();
696 if (!EnsureLockable()) {
697 return InvalidToWrExternalImage();
700 if (!LockInternal()) {
701 return InvalidToWrExternalImage();
704 const auto uvs
= GetUvCoords(GetSize(aChannelIndex
));
705 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex
), uvs
.first
.x
,
706 uvs
.first
.y
, uvs
.second
.x
,
710 void RenderDXGIYCbCrTextureHost::Unlock() {
712 if (mKeyedMutexs
[0]) {
713 for (const auto& mutex
: mKeyedMutexs
) {
714 mutex
->ReleaseSync(0);
721 void RenderDXGIYCbCrTextureHost::ClearCachedResources() {
722 DeleteTextureHandle();
726 GLuint
RenderDXGIYCbCrTextureHost::GetGLHandle(uint8_t aChannelIndex
) const {
727 MOZ_ASSERT(aChannelIndex
< 3);
729 return mTextureHandles
[aChannelIndex
];
732 gfx::IntSize
RenderDXGIYCbCrTextureHost::GetSize(uint8_t aChannelIndex
) const {
733 MOZ_ASSERT(aChannelIndex
< 3);
735 if (aChannelIndex
== 0) {
742 void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
743 if (mTextureHandles
[0] == 0) {
747 MOZ_ASSERT(mGL
.get());
752 if (mGL
->MakeCurrent()) {
753 mGL
->fDeleteTextures(3, mTextureHandles
);
755 const auto& gle
= gl::GLContextEGL::Cast(mGL
);
756 const auto& egl
= gle
->mEgl
;
757 for (int i
= 0; i
< 3; ++i
) {
758 mTextureHandles
[i
] = 0;
759 mTextures
[i
] = nullptr;
760 mKeyedMutexs
[i
] = nullptr;
763 egl
->fDestroySurface(mSurfaces
[i
]);
767 egl
->fDestroyStreamKHR(mStreams
[i
]);
775 } // namespace mozilla