Bug 1699062 - Flatten toolkit/themes/*/global/alerts/. r=desktop-theme-reviewers,dao
[gecko.git] / gfx / webrender_bindings / RenderD3D11TextureHost.cpp
blob0f307727cff21c71365493f2f00acfd6b7cc76f0
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 <d3d11.h>
11 #include "GLContextEGL.h"
12 #include "GLLibraryEGL.h"
13 #include "ScopedGLHelpers.h"
14 #include "mozilla/DebugOnly.h"
15 #include "mozilla/gfx/Logging.h"
17 namespace mozilla {
18 namespace wr {
20 RenderDXGITextureHost::RenderDXGITextureHost(WindowsHandle aHandle,
21 gfx::SurfaceFormat aFormat,
22 gfx::YUVColorSpace aYUVColorSpace,
23 gfx::ColorRange aColorRange,
24 gfx::IntSize aSize)
25 : mHandle(aHandle),
26 mSurface(0),
27 mStream(0),
28 mTextureHandle{0},
29 mFormat(aFormat),
30 mYUVColorSpace(aYUVColorSpace),
31 mColorRange(aColorRange),
32 mSize(aSize),
33 mLocked(false) {
34 MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHost, RenderTextureHost);
35 MOZ_ASSERT((mFormat != gfx::SurfaceFormat::NV12 &&
36 mFormat != gfx::SurfaceFormat::P010 &&
37 mFormat != gfx::SurfaceFormat::P016) ||
38 (mSize.width % 2 == 0 && mSize.height % 2 == 0));
39 MOZ_ASSERT(aHandle);
42 RenderDXGITextureHost::~RenderDXGITextureHost() {
43 MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHost, RenderTextureHost);
44 DeleteTextureHandle();
47 ID3D11Texture2D* RenderDXGITextureHost::GetD3D11Texture2DWithGL() {
48 if (mTexture) {
49 return mTexture;
52 if (!mGL) {
53 // SingletonGL is always used on Windows with ANGLE.
54 mGL = RenderThread::Get()->SingletonGL();
57 if (!EnsureD3D11Texture2DWithGL()) {
58 return nullptr;
61 return mTexture;
64 size_t RenderDXGITextureHost::GetPlaneCount() const {
65 if (mFormat == gfx::SurfaceFormat::NV12 ||
66 mFormat == gfx::SurfaceFormat::P010 ||
67 mFormat == gfx::SurfaceFormat::P016) {
68 return 2;
70 return 1;
73 template <typename T>
74 static bool MapTexture(T* aHost, RenderCompositor* aCompositor,
75 RefPtr<ID3D11Texture2D>& aTexture,
76 RefPtr<ID3D11DeviceContext>& aDeviceContext,
77 RefPtr<ID3D11Texture2D>& aCpuTexture,
78 D3D11_MAPPED_SUBRESOURCE& aMappedSubresource) {
79 if (!aCompositor) {
80 return false;
83 RenderCompositorD3D11SWGL* compositor =
84 aCompositor->AsRenderCompositorD3D11SWGL();
85 if (!compositor) {
86 return false;
89 if (!aHost->EnsureD3D11Texture2D(compositor->GetDevice())) {
90 return false;
93 if (!aHost->LockInternal()) {
94 return false;
97 D3D11_TEXTURE2D_DESC textureDesc = {0};
98 aTexture->GetDesc(&textureDesc);
100 compositor->GetDevice()->GetImmediateContext(getter_AddRefs(aDeviceContext));
102 textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
103 textureDesc.Usage = D3D11_USAGE_STAGING;
104 textureDesc.BindFlags = 0;
105 textureDesc.MiscFlags = 0;
106 textureDesc.MipLevels = 1;
107 HRESULT hr = compositor->GetDevice()->CreateTexture2D(
108 &textureDesc, nullptr, getter_AddRefs(aCpuTexture));
109 if (FAILED(hr)) {
110 return false;
113 aDeviceContext->CopyResource(aCpuTexture, aTexture);
114 aHost->Unlock();
116 hr = aDeviceContext->Map(aCpuTexture, 0, D3D11_MAP_READ, 0,
117 &aMappedSubresource);
118 return SUCCEEDED(hr);
121 bool RenderDXGITextureHost::MapPlane(RenderCompositor* aCompositor,
122 uint8_t aChannelIndex,
123 PlaneInfo& aPlaneInfo) {
124 // TODO: We currently readback from the GPU texture into a new
125 // staging texture every time this is mapped. We might be better
126 // off retaining the mapped memory to trade performance for memory
127 // usage.
128 if (!mCpuTexture && !MapTexture(this, aCompositor, mTexture, mDeviceContext,
129 mCpuTexture, mMappedSubresource)) {
130 return false;
133 aPlaneInfo.mSize = GetSize(aChannelIndex);
134 aPlaneInfo.mStride = mMappedSubresource.RowPitch;
135 aPlaneInfo.mData = mMappedSubresource.pData;
137 // If this is the second plane, then offset the data pointer by the
138 // size of the first plane.
139 if (aChannelIndex == 1) {
140 aPlaneInfo.mData =
141 (uint8_t*)aPlaneInfo.mData + aPlaneInfo.mStride * GetSize(0).height;
143 return true;
146 void RenderDXGITextureHost::UnmapPlanes() {
147 mMappedSubresource.pData = nullptr;
148 if (mCpuTexture) {
149 mDeviceContext->Unmap(mCpuTexture, 0);
150 mCpuTexture = nullptr;
152 mDeviceContext = nullptr;
155 bool RenderDXGITextureHost::EnsureD3D11Texture2DWithGL() {
156 if (mTexture) {
157 return true;
160 const auto& gle = gl::GLContextEGL::Cast(mGL);
161 const auto& egl = gle->mEgl;
163 // Fetch the D3D11 device.
164 EGLDeviceEXT eglDevice = nullptr;
165 egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
166 MOZ_ASSERT(eglDevice);
167 ID3D11Device* device = nullptr;
168 egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
169 (EGLAttrib*)&device);
170 // There's a chance this might fail if we end up on d3d9 angle for some
171 // reason.
172 if (!device) {
173 gfxCriticalNote << "RenderDXGITextureHost device is not available";
174 return false;
177 return EnsureD3D11Texture2D(device);
180 bool RenderDXGITextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
181 if (mTexture) {
182 RefPtr<ID3D11Device> device;
183 mTexture->GetDevice(getter_AddRefs(device));
184 if (aDevice != device) {
185 gfxCriticalNote << "RenderDXGITextureHost uses obsoleted device";
186 return false;
188 return true;
191 // Get the D3D11 texture from shared handle.
192 HRESULT hr = aDevice->OpenSharedResource(
193 (HANDLE)mHandle, __uuidof(ID3D11Texture2D),
194 (void**)(ID3D11Texture2D**)getter_AddRefs(mTexture));
195 if (FAILED(hr)) {
196 MOZ_ASSERT(false,
197 "RenderDXGITextureHost::EnsureLockable(): Failed to open shared "
198 "texture");
199 gfxCriticalNote
200 << "RenderDXGITextureHost Failed to open shared texture, hr="
201 << gfx::hexa(hr);
202 return false;
204 MOZ_ASSERT(mTexture.get());
205 mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
206 return true;
209 bool RenderDXGITextureHost::EnsureLockable(wr::ImageRendering aRendering) {
210 if (mTextureHandle[0]) {
211 // Update filter if filter was changed.
212 if (IsFilterUpdateNecessary(aRendering)) {
213 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
214 LOCAL_GL_TEXTURE_EXTERNAL_OES,
215 mTextureHandle[0], aRendering);
216 // Cache new rendering filter.
217 mCachedRendering = aRendering;
218 // NV12 and P016 uses two handles.
219 if (mFormat == gfx::SurfaceFormat::NV12 ||
220 mFormat == gfx::SurfaceFormat::P010 ||
221 mFormat == gfx::SurfaceFormat::P016) {
222 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE1,
223 LOCAL_GL_TEXTURE_EXTERNAL_OES,
224 mTextureHandle[1], aRendering);
227 return true;
230 const auto& gle = gl::GLContextEGL::Cast(mGL);
231 const auto& egl = gle->mEgl;
233 // We use EGLStream to get the converted gl handle from d3d texture. The
234 // NV_stream_consumer_gltexture_yuv and ANGLE_stream_producer_d3d_texture
235 // could support nv12 and rgb d3d texture format.
236 if (!egl->IsExtensionSupported(
237 gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
238 !egl->IsExtensionSupported(
239 gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
240 gfxCriticalNote << "RenderDXGITextureHost egl extensions are not suppored";
241 return false;
244 // Get the D3D11 texture from shared handle.
245 if (!EnsureD3D11Texture2DWithGL()) {
246 return false;
249 // Create the EGLStream.
250 mStream = egl->fCreateStreamKHR(nullptr);
251 MOZ_ASSERT(mStream);
253 bool ok = true;
254 if (mFormat != gfx::SurfaceFormat::NV12 &&
255 mFormat != gfx::SurfaceFormat::P010 &&
256 mFormat != gfx::SurfaceFormat::P016) {
257 // The non-nv12 format.
259 mGL->fGenTextures(1, mTextureHandle);
260 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
261 LOCAL_GL_TEXTURE_EXTERNAL_OES,
262 mTextureHandle[0], aRendering);
263 // Cache new rendering filter.
264 mCachedRendering = aRendering;
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], aRendering);
287 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE1,
288 LOCAL_GL_TEXTURE_EXTERNAL_OES,
289 mTextureHandle[1], aRendering);
290 // Cache new rendering filter.
291 mCachedRendering = aRendering;
292 ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
293 mStream, consumerAttributes));
294 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
297 // Insert the d3d texture.
298 ok &= bool(
299 egl->fStreamPostD3DTextureANGLE(mStream, (void*)mTexture.get(), nullptr));
301 if (!ok) {
302 gfxCriticalNote << "RenderDXGITextureHost init stream failed";
303 DeleteTextureHandle();
304 return false;
307 // Now, we could get the gl handle from the stream.
308 MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStream));
310 return true;
313 wr::WrExternalImage RenderDXGITextureHost::Lock(uint8_t aChannelIndex,
314 gl::GLContext* aGL,
315 wr::ImageRendering aRendering) {
316 if (mGL.get() != aGL) {
317 // Release the texture handle in the previous gl context.
318 DeleteTextureHandle();
319 mGL = aGL;
322 if (!mGL) {
323 // XXX Software WebRender is not handled yet.
324 // Software WebRender does not provide GLContext
325 gfxCriticalNoteOnce
326 << "Software WebRender is not suppored by RenderDXGITextureHost.";
327 return InvalidToWrExternalImage();
330 if (!EnsureLockable(aRendering)) {
331 return InvalidToWrExternalImage();
334 if (!LockInternal()) {
335 return InvalidToWrExternalImage();
338 gfx::IntSize size = GetSize(aChannelIndex);
339 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), 0, 0,
340 size.width, size.height);
343 bool RenderDXGITextureHost::LockInternal() {
344 if (!mLocked) {
345 if (mKeyedMutex) {
346 HRESULT hr = mKeyedMutex->AcquireSync(0, 10000);
347 if (hr != S_OK) {
348 gfxCriticalError() << "RenderDXGITextureHost AcquireSync timeout, hr="
349 << gfx::hexa(hr);
350 return false;
353 mLocked = true;
355 return true;
358 void RenderDXGITextureHost::Unlock() {
359 if (mLocked) {
360 if (mKeyedMutex) {
361 mKeyedMutex->ReleaseSync(0);
363 mLocked = false;
367 void RenderDXGITextureHost::ClearCachedResources() {
368 DeleteTextureHandle();
369 mGL = nullptr;
372 void RenderDXGITextureHost::DeleteTextureHandle() {
373 if (mTextureHandle[0] == 0) {
374 return;
377 MOZ_ASSERT(mGL.get());
378 if (!mGL) {
379 return;
382 if (mGL->MakeCurrent()) {
383 mGL->fDeleteTextures(2, mTextureHandle);
385 const auto& gle = gl::GLContextEGL::Cast(mGL);
386 const auto& egl = gle->mEgl;
387 if (mSurface) {
388 egl->fDestroySurface(mSurface);
390 if (mStream) {
391 egl->fDestroyStreamKHR(mStream);
395 for (int i = 0; i < 2; ++i) {
396 mTextureHandle[i] = 0;
399 mTexture = nullptr;
400 mKeyedMutex = nullptr;
401 mSurface = 0;
402 mStream = 0;
405 GLuint RenderDXGITextureHost::GetGLHandle(uint8_t aChannelIndex) const {
406 MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
407 mFormat == gfx::SurfaceFormat::P010 ||
408 mFormat == gfx::SurfaceFormat::P016) &&
409 aChannelIndex < 2) ||
410 aChannelIndex < 1);
411 return mTextureHandle[aChannelIndex];
414 gfx::IntSize RenderDXGITextureHost::GetSize(uint8_t aChannelIndex) const {
415 MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
416 mFormat == gfx::SurfaceFormat::P010 ||
417 mFormat == gfx::SurfaceFormat::P016) &&
418 aChannelIndex < 2) ||
419 aChannelIndex < 1);
421 if (aChannelIndex == 0) {
422 return mSize;
423 } else {
424 // The CbCr channel size is a half of Y channel size in NV12 format.
425 return mSize / 2;
429 RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
430 WindowsHandle (&aHandles)[3], gfx::YUVColorSpace aYUVColorSpace,
431 gfx::ColorDepth aColorDepth, gfx::ColorRange aColorRange,
432 gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr)
433 : mHandles{aHandles[0], aHandles[1], aHandles[2]},
434 mSurfaces{0},
435 mStreams{0},
436 mTextureHandles{0},
437 mYUVColorSpace(aYUVColorSpace),
438 mColorDepth(aColorDepth),
439 mColorRange(aColorRange),
440 mSizeY(aSizeY),
441 mSizeCbCr(aSizeCbCr),
442 mLocked(false) {
443 MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
444 // Assume the chroma planes are rounded up if the luma plane is odd sized.
445 MOZ_ASSERT((mSizeCbCr.width == mSizeY.width ||
446 mSizeCbCr.width == (mSizeY.width + 1) >> 1) &&
447 (mSizeCbCr.height == mSizeY.height ||
448 mSizeCbCr.height == (mSizeY.height + 1) >> 1));
449 MOZ_ASSERT(aHandles[0] && aHandles[1] && aHandles[2]);
452 bool RenderDXGIYCbCrTextureHost::MapPlane(RenderCompositor* aCompositor,
453 uint8_t aChannelIndex,
454 PlaneInfo& aPlaneInfo) {
455 D3D11_MAPPED_SUBRESOURCE mappedSubresource;
456 if (!MapTexture(this, aCompositor, mTextures[aChannelIndex], mDeviceContext,
457 mCpuTexture[aChannelIndex], mappedSubresource)) {
458 return false;
461 aPlaneInfo.mSize = GetSize(aChannelIndex);
462 aPlaneInfo.mStride = mappedSubresource.RowPitch;
463 aPlaneInfo.mData = mappedSubresource.pData;
464 return true;
467 void RenderDXGIYCbCrTextureHost::UnmapPlanes() {
468 for (uint32_t i = 0; i < 3; i++) {
469 if (mCpuTexture[i]) {
470 mDeviceContext->Unmap(mCpuTexture[i], 0);
471 mCpuTexture[i] = nullptr;
474 mDeviceContext = nullptr;
477 RenderDXGIYCbCrTextureHost::~RenderDXGIYCbCrTextureHost() {
478 MOZ_COUNT_DTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
479 DeleteTextureHandle();
482 bool RenderDXGIYCbCrTextureHost::EnsureLockable(wr::ImageRendering aRendering) {
483 if (mTextureHandles[0]) {
484 // Update filter if filter was changed.
485 if (IsFilterUpdateNecessary(aRendering)) {
486 for (int i = 0; i < 3; ++i) {
487 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0 + i,
488 LOCAL_GL_TEXTURE_EXTERNAL_OES,
489 mTextureHandles[i], aRendering);
490 // Cache new rendering filter.
491 mCachedRendering = aRendering;
494 return true;
497 const auto& gle = gl::GLContextEGL::Cast(mGL);
498 const auto& egl = gle->mEgl;
500 // The eglCreatePbufferFromClientBuffer doesn't support R8 format, so we
501 // use EGLStream to get the converted gl handle from d3d R8 texture.
503 if (!egl->IsExtensionSupported(
504 gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
505 !egl->IsExtensionSupported(
506 gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
507 gfxCriticalNote
508 << "RenderDXGIYCbCrTextureHost egl extensions are not suppored";
509 return false;
512 // Fetch the D3D11 device.
513 EGLDeviceEXT eglDevice = nullptr;
514 egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
515 MOZ_ASSERT(eglDevice);
516 ID3D11Device* device = nullptr;
517 egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
518 (EGLAttrib*)&device);
519 // There's a chance this might fail if we end up on d3d9 angle for some
520 // reason.
521 if (!device) {
522 gfxCriticalNote << "RenderDXGIYCbCrTextureHost device is not available";
523 return false;
526 EnsureD3D11Texture2D(device);
528 mGL->fGenTextures(3, mTextureHandles);
529 bool ok = true;
530 for (int i = 0; i < 3; ++i) {
531 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0 + i,
532 LOCAL_GL_TEXTURE_EXTERNAL_OES,
533 mTextureHandles[i], aRendering);
534 // Cache new rendering filter.
535 mCachedRendering = aRendering;
537 // Create the EGLStream.
538 mStreams[i] = egl->fCreateStreamKHR(nullptr);
539 MOZ_ASSERT(mStreams[i]);
541 ok &= bool(
542 egl->fStreamConsumerGLTextureExternalAttribsNV(mStreams[i], nullptr));
543 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStreams[i], nullptr));
545 // Insert the R8 texture.
546 ok &= bool(egl->fStreamPostD3DTextureANGLE(
547 mStreams[i], (void*)mTextures[i].get(), nullptr));
549 // Now, we could get the R8 gl handle from the stream.
550 MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStreams[i]));
553 if (!ok) {
554 gfxCriticalNote << "RenderDXGIYCbCrTextureHost init stream failed";
555 DeleteTextureHandle();
556 return false;
559 return true;
562 bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
563 if (mTextures[0]) {
564 RefPtr<ID3D11Device> device;
565 mTextures[0]->GetDevice(getter_AddRefs(device));
566 if (aDevice != device) {
567 gfxCriticalNote << "RenderDXGIYCbCrTextureHost uses obsoleted device";
568 return false;
572 if (mTextureHandles[0]) {
573 return true;
576 for (int i = 0; i < 3; ++i) {
577 // Get the R8 D3D11 texture from shared handle.
578 HRESULT hr = aDevice->OpenSharedResource(
579 (HANDLE)mHandles[i], __uuidof(ID3D11Texture2D),
580 (void**)(ID3D11Texture2D**)getter_AddRefs(mTextures[i]));
581 if (FAILED(hr)) {
582 NS_WARNING(
583 "RenderDXGIYCbCrTextureHost::EnsureLockable(): Failed to open "
584 "shared "
585 "texture");
586 gfxCriticalNote
587 << "RenderDXGIYCbCrTextureHost Failed to open shared texture, hr="
588 << gfx::hexa(hr);
589 return false;
593 for (int i = 0; i < 3; ++i) {
594 mTextures[i]->QueryInterface(
595 (IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutexs[i]));
597 return true;
600 bool RenderDXGIYCbCrTextureHost::LockInternal() {
601 if (!mLocked) {
602 if (mKeyedMutexs[0]) {
603 for (const auto& mutex : mKeyedMutexs) {
604 HRESULT hr = mutex->AcquireSync(0, 10000);
605 if (hr != S_OK) {
606 gfxCriticalError()
607 << "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr="
608 << gfx::hexa(hr);
609 return false;
613 mLocked = true;
615 return true;
618 wr::WrExternalImage RenderDXGIYCbCrTextureHost::Lock(
619 uint8_t aChannelIndex, gl::GLContext* aGL, wr::ImageRendering aRendering) {
620 if (mGL.get() != aGL) {
621 // Release the texture handle in the previous gl context.
622 DeleteTextureHandle();
623 mGL = aGL;
626 if (!mGL) {
627 // XXX Software WebRender is not handled yet.
628 // Software WebRender does not provide GLContext
629 gfxCriticalNoteOnce << "Software WebRender is not suppored by "
630 "RenderDXGIYCbCrTextureHost.";
631 return InvalidToWrExternalImage();
634 if (!EnsureLockable(aRendering)) {
635 return InvalidToWrExternalImage();
638 if (!LockInternal()) {
639 return InvalidToWrExternalImage();
642 gfx::IntSize size = GetSize(aChannelIndex);
643 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), 0, 0,
644 size.width, size.height);
647 void RenderDXGIYCbCrTextureHost::Unlock() {
648 if (mLocked) {
649 if (mKeyedMutexs[0]) {
650 for (const auto& mutex : mKeyedMutexs) {
651 mutex->ReleaseSync(0);
654 mLocked = false;
658 void RenderDXGIYCbCrTextureHost::ClearCachedResources() {
659 DeleteTextureHandle();
660 mGL = nullptr;
663 GLuint RenderDXGIYCbCrTextureHost::GetGLHandle(uint8_t aChannelIndex) const {
664 MOZ_ASSERT(aChannelIndex < 3);
666 return mTextureHandles[aChannelIndex];
669 gfx::IntSize RenderDXGIYCbCrTextureHost::GetSize(uint8_t aChannelIndex) const {
670 MOZ_ASSERT(aChannelIndex < 3);
672 if (aChannelIndex == 0) {
673 return mSizeY;
674 } else {
675 return mSizeCbCr;
679 void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
680 if (mTextureHandles[0] == 0) {
681 return;
684 MOZ_ASSERT(mGL.get());
685 if (!mGL) {
686 return;
689 if (mGL->MakeCurrent()) {
690 mGL->fDeleteTextures(3, mTextureHandles);
692 const auto& gle = gl::GLContextEGL::Cast(mGL);
693 const auto& egl = gle->mEgl;
694 for (int i = 0; i < 3; ++i) {
695 mTextureHandles[i] = 0;
696 mTextures[i] = nullptr;
697 mKeyedMutexs[i] = nullptr;
699 if (mSurfaces[i]) {
700 egl->fDestroySurface(mSurfaces[i]);
701 mSurfaces[i] = 0;
703 if (mStreams[i]) {
704 egl->fDestroyStreamKHR(mStreams[i]);
705 mStreams[i] = 0;
711 } // namespace wr
712 } // namespace mozilla