Bug 1833753 [wpt PR 40065] - Allow newly-added test to also pass when mutation events...
[gecko.git] / gfx / webrender_bindings / RenderD3D11TextureHost.cpp
blob232f8572cb12341b620f10e6359379c2800fa319
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/Logging.h"
17 #include "mozilla/layers/TextureD3D11.h"
19 namespace mozilla {
20 namespace wr {
22 RenderDXGITextureHost::RenderDXGITextureHost(
23 WindowsHandle aHandle,
24 Maybe<layers::GpuProcessTextureId>& aGpuProcessTextureId,
25 uint32_t aArrayIndex, gfx::SurfaceFormat aFormat,
26 gfx::ColorSpace2 aColorSpace, gfx::ColorRange aColorRange,
27 gfx::IntSize aSize)
28 : mHandle(aHandle),
29 mGpuProcessTextureId(aGpuProcessTextureId),
30 mArrayIndex(aArrayIndex),
31 mSurface(0),
32 mStream(0),
33 mTextureHandle{0},
34 mFormat(aFormat),
35 mColorSpace(aColorSpace),
36 mColorRange(aColorRange),
37 mSize(aSize),
38 mLocked(false) {
39 MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHost, RenderTextureHost);
40 MOZ_ASSERT((mFormat != gfx::SurfaceFormat::NV12 &&
41 mFormat != gfx::SurfaceFormat::P010 &&
42 mFormat != gfx::SurfaceFormat::P016) ||
43 (mSize.width % 2 == 0 && mSize.height % 2 == 0));
44 MOZ_ASSERT((aHandle && aGpuProcessTextureId.isNothing()) ||
45 (!aHandle && aGpuProcessTextureId.isSome()));
48 RenderDXGITextureHost::~RenderDXGITextureHost() {
49 MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHost, RenderTextureHost);
50 DeleteTextureHandle();
53 ID3D11Texture2D* RenderDXGITextureHost::GetD3D11Texture2DWithGL() {
54 if (mTexture) {
55 return mTexture;
58 if (!mGL) {
59 // SingletonGL is always used on Windows with ANGLE.
60 mGL = RenderThread::Get()->SingletonGL();
63 if (!EnsureD3D11Texture2DWithGL()) {
64 return nullptr;
67 return mTexture;
70 size_t RenderDXGITextureHost::GetPlaneCount() const {
71 if (mFormat == gfx::SurfaceFormat::NV12 ||
72 mFormat == gfx::SurfaceFormat::P010 ||
73 mFormat == gfx::SurfaceFormat::P016) {
74 return 2;
76 return 1;
79 template <typename T>
80 static bool MapTexture(T* aHost, RenderCompositor* aCompositor,
81 RefPtr<ID3D11Texture2D>& aTexture,
82 RefPtr<ID3D11DeviceContext>& aDeviceContext,
83 RefPtr<ID3D11Texture2D>& aCpuTexture,
84 D3D11_MAPPED_SUBRESOURCE& aMappedSubresource) {
85 if (!aCompositor) {
86 return false;
89 RenderCompositorD3D11SWGL* compositor =
90 aCompositor->AsRenderCompositorD3D11SWGL();
91 if (!compositor) {
92 return false;
95 if (!aHost->EnsureD3D11Texture2D(compositor->GetDevice())) {
96 return false;
99 if (!aHost->LockInternal()) {
100 return false;
103 D3D11_TEXTURE2D_DESC textureDesc = {0};
104 aTexture->GetDesc(&textureDesc);
106 compositor->GetDevice()->GetImmediateContext(getter_AddRefs(aDeviceContext));
108 textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
109 textureDesc.Usage = D3D11_USAGE_STAGING;
110 textureDesc.BindFlags = 0;
111 textureDesc.MiscFlags = 0;
112 textureDesc.MipLevels = 1;
113 HRESULT hr = compositor->GetDevice()->CreateTexture2D(
114 &textureDesc, nullptr, getter_AddRefs(aCpuTexture));
115 if (FAILED(hr)) {
116 return false;
119 aDeviceContext->CopyResource(aCpuTexture, aTexture);
120 aHost->Unlock();
122 hr = aDeviceContext->Map(aCpuTexture, 0, D3D11_MAP_READ, 0,
123 &aMappedSubresource);
124 return SUCCEEDED(hr);
127 bool RenderDXGITextureHost::MapPlane(RenderCompositor* aCompositor,
128 uint8_t aChannelIndex,
129 PlaneInfo& aPlaneInfo) {
130 // TODO: We currently readback from the GPU texture into a new
131 // staging texture every time this is mapped. We might be better
132 // off retaining the mapped memory to trade performance for memory
133 // usage.
134 if (!mCpuTexture && !MapTexture(this, aCompositor, mTexture, mDeviceContext,
135 mCpuTexture, mMappedSubresource)) {
136 return false;
139 aPlaneInfo.mSize = GetSize(aChannelIndex);
140 aPlaneInfo.mStride = mMappedSubresource.RowPitch;
141 aPlaneInfo.mData = mMappedSubresource.pData;
143 // If this is the second plane, then offset the data pointer by the
144 // size of the first plane.
145 if (aChannelIndex == 1) {
146 aPlaneInfo.mData =
147 (uint8_t*)aPlaneInfo.mData + aPlaneInfo.mStride * GetSize(0).height;
149 return true;
152 void RenderDXGITextureHost::UnmapPlanes() {
153 mMappedSubresource.pData = nullptr;
154 if (mCpuTexture) {
155 mDeviceContext->Unmap(mCpuTexture, 0);
156 mCpuTexture = nullptr;
158 mDeviceContext = nullptr;
161 bool RenderDXGITextureHost::EnsureD3D11Texture2DWithGL() {
162 if (mTexture) {
163 return true;
166 if (mGpuProcessTextureId.isSome()) {
167 auto* textureMap = layers::GpuProcessD3D11TextureMap::Get();
168 if (textureMap) {
169 RefPtr<ID3D11Texture2D> texture;
170 mTexture = textureMap->GetTexture(mGpuProcessTextureId.ref());
171 if (mTexture) {
172 return true;
175 return false;
178 const auto& gle = gl::GLContextEGL::Cast(mGL);
179 const auto& egl = gle->mEgl;
181 // Fetch the D3D11 device.
182 EGLDeviceEXT eglDevice = nullptr;
183 egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
184 MOZ_ASSERT(eglDevice);
185 ID3D11Device* device = nullptr;
186 egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
187 (EGLAttrib*)&device);
188 // There's a chance this might fail if we end up on d3d9 angle for some
189 // reason.
190 if (!device) {
191 gfxCriticalNote << "RenderDXGITextureHost device is not available";
192 return false;
195 return EnsureD3D11Texture2D(device);
198 bool RenderDXGITextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
199 if (mTexture) {
200 RefPtr<ID3D11Device> device;
201 mTexture->GetDevice(getter_AddRefs(device));
202 if (aDevice != device) {
203 gfxCriticalNote << "RenderDXGITextureHost uses obsoleted device";
204 return false;
206 return true;
209 // Get the D3D11 texture from shared handle.
210 HRESULT hr = aDevice->OpenSharedResource(
211 (HANDLE)mHandle, __uuidof(ID3D11Texture2D),
212 (void**)(ID3D11Texture2D**)getter_AddRefs(mTexture));
213 if (FAILED(hr)) {
214 MOZ_ASSERT(false,
215 "RenderDXGITextureHost::EnsureLockable(): Failed to open shared "
216 "texture");
217 gfxCriticalNote
218 << "RenderDXGITextureHost Failed to open shared texture, hr="
219 << gfx::hexa(hr);
220 return false;
222 MOZ_ASSERT(mTexture.get());
223 mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
224 return true;
227 bool RenderDXGITextureHost::EnsureLockable() {
228 if (mTextureHandle[0]) {
229 return true;
232 const auto& gle = gl::GLContextEGL::Cast(mGL);
233 const auto& egl = gle->mEgl;
235 // We use EGLStream to get the converted gl handle from d3d texture. The
236 // NV_stream_consumer_gltexture_yuv and ANGLE_stream_producer_d3d_texture
237 // could support nv12 and rgb d3d texture format.
238 if (!egl->IsExtensionSupported(
239 gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
240 !egl->IsExtensionSupported(
241 gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
242 gfxCriticalNote << "RenderDXGITextureHost egl extensions are not suppored";
243 return false;
246 // Get the D3D11 texture from shared handle.
247 if (!EnsureD3D11Texture2DWithGL()) {
248 return false;
251 // Create the EGLStream.
252 mStream = egl->fCreateStreamKHR(nullptr);
253 MOZ_ASSERT(mStream);
255 bool ok = true;
256 if (mFormat != gfx::SurfaceFormat::NV12 &&
257 mFormat != gfx::SurfaceFormat::P010 &&
258 mFormat != gfx::SurfaceFormat::P016) {
259 // The non-nv12 format.
261 mGL->fGenTextures(1, mTextureHandle);
262 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
263 LOCAL_GL_TEXTURE_EXTERNAL_OES,
264 mTextureHandle[0]);
265 ok &=
266 bool(egl->fStreamConsumerGLTextureExternalAttribsNV(mStream, nullptr));
267 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
268 } else {
269 // The nv12/p016 format.
271 // Setup the NV12 stream consumer/producer.
272 EGLAttrib consumerAttributes[] = {
273 LOCAL_EGL_COLOR_BUFFER_TYPE,
274 LOCAL_EGL_YUV_BUFFER_EXT,
275 LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT,
277 LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
279 LOCAL_EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
281 LOCAL_EGL_NONE,
283 mGL->fGenTextures(2, mTextureHandle);
284 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
285 LOCAL_GL_TEXTURE_EXTERNAL_OES,
286 mTextureHandle[0]);
287 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE1,
288 LOCAL_GL_TEXTURE_EXTERNAL_OES,
289 mTextureHandle[1]);
290 ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
291 mStream, consumerAttributes));
292 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
295 const EGLAttrib frameAttributes[] = {
296 LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
297 static_cast<EGLAttrib>(mArrayIndex),
298 LOCAL_EGL_NONE,
301 // Insert the d3d texture.
302 ok &= bool(egl->fStreamPostD3DTextureANGLE(mStream, (void*)mTexture.get(),
303 frameAttributes));
305 if (!ok) {
306 gfxCriticalNote << "RenderDXGITextureHost init stream failed";
307 DeleteTextureHandle();
308 return false;
311 // Now, we could get the gl handle from the stream.
312 MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStream));
314 return true;
317 wr::WrExternalImage RenderDXGITextureHost::Lock(uint8_t aChannelIndex,
318 gl::GLContext* aGL) {
319 if (mGL.get() != aGL) {
320 // Release the texture handle in the previous gl context.
321 DeleteTextureHandle();
322 mGL = aGL;
325 if (!mGL) {
326 // XXX Software WebRender is not handled yet.
327 // Software WebRender does not provide GLContext
328 gfxCriticalNoteOnce
329 << "Software WebRender is not suppored by RenderDXGITextureHost.";
330 return InvalidToWrExternalImage();
333 if (!EnsureLockable()) {
334 return InvalidToWrExternalImage();
337 if (!LockInternal()) {
338 return InvalidToWrExternalImage();
341 const auto uvs = GetUvCoords(GetSize(aChannelIndex));
342 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), uvs.first.x,
343 uvs.first.y, uvs.second.x,
344 uvs.second.y);
347 bool RenderDXGITextureHost::LockInternal() {
348 if (!mLocked) {
349 if (mKeyedMutex) {
350 HRESULT hr = mKeyedMutex->AcquireSync(0, 10000);
351 if (hr != S_OK) {
352 gfxCriticalError() << "RenderDXGITextureHost AcquireSync timeout, hr="
353 << gfx::hexa(hr);
354 return false;
357 mLocked = true;
359 return true;
362 void RenderDXGITextureHost::Unlock() {
363 if (mLocked) {
364 if (mKeyedMutex) {
365 mKeyedMutex->ReleaseSync(0);
367 mLocked = false;
371 void RenderDXGITextureHost::ClearCachedResources() {
372 DeleteTextureHandle();
373 mGL = nullptr;
376 void RenderDXGITextureHost::DeleteTextureHandle() {
377 if (mTextureHandle[0] == 0) {
378 return;
381 MOZ_ASSERT(mGL.get());
382 if (!mGL) {
383 return;
386 if (mGL->MakeCurrent()) {
387 mGL->fDeleteTextures(2, mTextureHandle);
389 const auto& gle = gl::GLContextEGL::Cast(mGL);
390 const auto& egl = gle->mEgl;
391 if (mSurface) {
392 egl->fDestroySurface(mSurface);
394 if (mStream) {
395 egl->fDestroyStreamKHR(mStream);
399 for (int i = 0; i < 2; ++i) {
400 mTextureHandle[i] = 0;
403 mTexture = nullptr;
404 mKeyedMutex = nullptr;
405 mSurface = 0;
406 mStream = 0;
409 GLuint RenderDXGITextureHost::GetGLHandle(uint8_t aChannelIndex) const {
410 MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
411 mFormat == gfx::SurfaceFormat::P010 ||
412 mFormat == gfx::SurfaceFormat::P016) &&
413 aChannelIndex < 2) ||
414 aChannelIndex < 1);
415 return mTextureHandle[aChannelIndex];
418 gfx::IntSize RenderDXGITextureHost::GetSize(uint8_t aChannelIndex) const {
419 MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
420 mFormat == gfx::SurfaceFormat::P010 ||
421 mFormat == gfx::SurfaceFormat::P016) &&
422 aChannelIndex < 2) ||
423 aChannelIndex < 1);
425 if (aChannelIndex == 0) {
426 return mSize;
427 } else {
428 // The CbCr channel size is a half of Y channel size in NV12 format.
429 return mSize / 2;
433 RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
434 WindowsHandle (&aHandles)[3], gfx::YUVColorSpace aYUVColorSpace,
435 gfx::ColorDepth aColorDepth, gfx::ColorRange aColorRange,
436 gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr)
437 : mHandles{aHandles[0], aHandles[1], aHandles[2]},
438 mSurfaces{0},
439 mStreams{0},
440 mTextureHandles{0},
441 mYUVColorSpace(aYUVColorSpace),
442 mColorDepth(aColorDepth),
443 mColorRange(aColorRange),
444 mSizeY(aSizeY),
445 mSizeCbCr(aSizeCbCr),
446 mLocked(false) {
447 MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
448 // Assume the chroma planes are rounded up if the luma plane is odd sized.
449 MOZ_ASSERT((mSizeCbCr.width == mSizeY.width ||
450 mSizeCbCr.width == (mSizeY.width + 1) >> 1) &&
451 (mSizeCbCr.height == mSizeY.height ||
452 mSizeCbCr.height == (mSizeY.height + 1) >> 1));
453 MOZ_ASSERT(aHandles[0] && aHandles[1] && aHandles[2]);
456 bool RenderDXGIYCbCrTextureHost::MapPlane(RenderCompositor* aCompositor,
457 uint8_t aChannelIndex,
458 PlaneInfo& aPlaneInfo) {
459 D3D11_MAPPED_SUBRESOURCE mappedSubresource;
460 if (!MapTexture(this, aCompositor, mTextures[aChannelIndex], mDeviceContext,
461 mCpuTexture[aChannelIndex], mappedSubresource)) {
462 return false;
465 aPlaneInfo.mSize = GetSize(aChannelIndex);
466 aPlaneInfo.mStride = mappedSubresource.RowPitch;
467 aPlaneInfo.mData = mappedSubresource.pData;
468 return true;
471 void RenderDXGIYCbCrTextureHost::UnmapPlanes() {
472 for (uint32_t i = 0; i < 3; i++) {
473 if (mCpuTexture[i]) {
474 mDeviceContext->Unmap(mCpuTexture[i], 0);
475 mCpuTexture[i] = nullptr;
478 mDeviceContext = nullptr;
481 RenderDXGIYCbCrTextureHost::~RenderDXGIYCbCrTextureHost() {
482 MOZ_COUNT_DTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
483 DeleteTextureHandle();
486 bool RenderDXGIYCbCrTextureHost::EnsureLockable() {
487 if (mTextureHandles[0]) {
488 return true;
491 const auto& gle = gl::GLContextEGL::Cast(mGL);
492 const auto& egl = gle->mEgl;
494 // The eglCreatePbufferFromClientBuffer doesn't support R8 format, so we
495 // use EGLStream to get the converted gl handle from d3d R8 texture.
497 if (!egl->IsExtensionSupported(
498 gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
499 !egl->IsExtensionSupported(
500 gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
501 gfxCriticalNote
502 << "RenderDXGIYCbCrTextureHost egl extensions are not suppored";
503 return false;
506 // Fetch the D3D11 device.
507 EGLDeviceEXT eglDevice = nullptr;
508 egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
509 MOZ_ASSERT(eglDevice);
510 ID3D11Device* device = nullptr;
511 egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
512 (EGLAttrib*)&device);
513 // There's a chance this might fail if we end up on d3d9 angle for some
514 // reason.
515 if (!device) {
516 gfxCriticalNote << "RenderDXGIYCbCrTextureHost device is not available";
517 return false;
520 EnsureD3D11Texture2D(device);
522 mGL->fGenTextures(3, mTextureHandles);
523 bool ok = true;
524 for (int i = 0; i < 3; ++i) {
525 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0 + i,
526 LOCAL_GL_TEXTURE_EXTERNAL_OES,
527 mTextureHandles[i]);
529 // Create the EGLStream.
530 mStreams[i] = egl->fCreateStreamKHR(nullptr);
531 MOZ_ASSERT(mStreams[i]);
533 ok &= bool(
534 egl->fStreamConsumerGLTextureExternalAttribsNV(mStreams[i], nullptr));
535 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStreams[i], nullptr));
537 // Insert the R8 texture.
538 ok &= bool(egl->fStreamPostD3DTextureANGLE(
539 mStreams[i], (void*)mTextures[i].get(), nullptr));
541 // Now, we could get the R8 gl handle from the stream.
542 MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStreams[i]));
545 if (!ok) {
546 gfxCriticalNote << "RenderDXGIYCbCrTextureHost init stream failed";
547 DeleteTextureHandle();
548 return false;
551 return true;
554 bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
555 if (mTextures[0]) {
556 RefPtr<ID3D11Device> device;
557 mTextures[0]->GetDevice(getter_AddRefs(device));
558 if (aDevice != device) {
559 gfxCriticalNote << "RenderDXGIYCbCrTextureHost uses obsoleted device";
560 return false;
564 if (mTextureHandles[0]) {
565 return true;
568 for (int i = 0; i < 3; ++i) {
569 // Get the R8 D3D11 texture from shared handle.
570 HRESULT hr = aDevice->OpenSharedResource(
571 (HANDLE)mHandles[i], __uuidof(ID3D11Texture2D),
572 (void**)(ID3D11Texture2D**)getter_AddRefs(mTextures[i]));
573 if (FAILED(hr)) {
574 NS_WARNING(
575 "RenderDXGIYCbCrTextureHost::EnsureLockable(): Failed to open "
576 "shared "
577 "texture");
578 gfxCriticalNote
579 << "RenderDXGIYCbCrTextureHost Failed to open shared texture, hr="
580 << gfx::hexa(hr);
581 return false;
585 for (int i = 0; i < 3; ++i) {
586 mTextures[i]->QueryInterface(
587 (IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutexs[i]));
589 return true;
592 bool RenderDXGIYCbCrTextureHost::LockInternal() {
593 if (!mLocked) {
594 if (mKeyedMutexs[0]) {
595 for (const auto& mutex : mKeyedMutexs) {
596 HRESULT hr = mutex->AcquireSync(0, 10000);
597 if (hr != S_OK) {
598 gfxCriticalError()
599 << "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr="
600 << gfx::hexa(hr);
601 return false;
605 mLocked = true;
607 return true;
610 wr::WrExternalImage RenderDXGIYCbCrTextureHost::Lock(uint8_t aChannelIndex,
611 gl::GLContext* aGL) {
612 if (mGL.get() != aGL) {
613 // Release the texture handle in the previous gl context.
614 DeleteTextureHandle();
615 mGL = aGL;
618 if (!mGL) {
619 // XXX Software WebRender is not handled yet.
620 // Software WebRender does not provide GLContext
621 gfxCriticalNoteOnce << "Software WebRender is not suppored by "
622 "RenderDXGIYCbCrTextureHost.";
623 return InvalidToWrExternalImage();
626 if (!EnsureLockable()) {
627 return InvalidToWrExternalImage();
630 if (!LockInternal()) {
631 return InvalidToWrExternalImage();
634 const auto uvs = GetUvCoords(GetSize(aChannelIndex));
635 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), uvs.first.x,
636 uvs.first.y, uvs.second.x,
637 uvs.second.y);
640 void RenderDXGIYCbCrTextureHost::Unlock() {
641 if (mLocked) {
642 if (mKeyedMutexs[0]) {
643 for (const auto& mutex : mKeyedMutexs) {
644 mutex->ReleaseSync(0);
647 mLocked = false;
651 void RenderDXGIYCbCrTextureHost::ClearCachedResources() {
652 DeleteTextureHandle();
653 mGL = nullptr;
656 GLuint RenderDXGIYCbCrTextureHost::GetGLHandle(uint8_t aChannelIndex) const {
657 MOZ_ASSERT(aChannelIndex < 3);
659 return mTextureHandles[aChannelIndex];
662 gfx::IntSize RenderDXGIYCbCrTextureHost::GetSize(uint8_t aChannelIndex) const {
663 MOZ_ASSERT(aChannelIndex < 3);
665 if (aChannelIndex == 0) {
666 return mSizeY;
667 } else {
668 return mSizeCbCr;
672 void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
673 if (mTextureHandles[0] == 0) {
674 return;
677 MOZ_ASSERT(mGL.get());
678 if (!mGL) {
679 return;
682 if (mGL->MakeCurrent()) {
683 mGL->fDeleteTextures(3, mTextureHandles);
685 const auto& gle = gl::GLContextEGL::Cast(mGL);
686 const auto& egl = gle->mEgl;
687 for (int i = 0; i < 3; ++i) {
688 mTextureHandles[i] = 0;
689 mTextures[i] = nullptr;
690 mKeyedMutexs[i] = nullptr;
692 if (mSurfaces[i]) {
693 egl->fDestroySurface(mSurfaces[i]);
694 mSurfaces[i] = 0;
696 if (mStreams[i]) {
697 egl->fDestroyStreamKHR(mStreams[i]);
698 mStreams[i] = 0;
704 } // namespace wr
705 } // namespace mozilla