Bug 1760684 [wpt PR 33213] - Update wpt metadata, a=testonly
[gecko.git] / gfx / webrender_bindings / RenderD3D11TextureHost.cpp
blobfedd0156ad29725d31330b531f74d03be587c5b5
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 uint32_t aArrayIndex,
22 gfx::SurfaceFormat aFormat,
23 gfx::YUVColorSpace aYUVColorSpace,
24 gfx::ColorRange aColorRange,
25 gfx::IntSize aSize)
26 : mHandle(aHandle),
27 mArrayIndex(aArrayIndex),
28 mSurface(0),
29 mStream(0),
30 mTextureHandle{0},
31 mFormat(aFormat),
32 mYUVColorSpace(aYUVColorSpace),
33 mColorRange(aColorRange),
34 mSize(aSize),
35 mLocked(false) {
36 MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHost, RenderTextureHost);
37 MOZ_ASSERT((mFormat != gfx::SurfaceFormat::NV12 &&
38 mFormat != gfx::SurfaceFormat::P010 &&
39 mFormat != gfx::SurfaceFormat::P016) ||
40 (mSize.width % 2 == 0 && mSize.height % 2 == 0));
41 MOZ_ASSERT(aHandle);
44 RenderDXGITextureHost::~RenderDXGITextureHost() {
45 MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHost, RenderTextureHost);
46 DeleteTextureHandle();
49 ID3D11Texture2D* RenderDXGITextureHost::GetD3D11Texture2DWithGL() {
50 if (mTexture) {
51 return mTexture;
54 if (!mGL) {
55 // SingletonGL is always used on Windows with ANGLE.
56 mGL = RenderThread::Get()->SingletonGL();
59 if (!EnsureD3D11Texture2DWithGL()) {
60 return nullptr;
63 return mTexture;
66 size_t RenderDXGITextureHost::GetPlaneCount() const {
67 if (mFormat == gfx::SurfaceFormat::NV12 ||
68 mFormat == gfx::SurfaceFormat::P010 ||
69 mFormat == gfx::SurfaceFormat::P016) {
70 return 2;
72 return 1;
75 template <typename T>
76 static bool MapTexture(T* aHost, RenderCompositor* aCompositor,
77 RefPtr<ID3D11Texture2D>& aTexture,
78 RefPtr<ID3D11DeviceContext>& aDeviceContext,
79 RefPtr<ID3D11Texture2D>& aCpuTexture,
80 D3D11_MAPPED_SUBRESOURCE& aMappedSubresource) {
81 if (!aCompositor) {
82 return false;
85 RenderCompositorD3D11SWGL* compositor =
86 aCompositor->AsRenderCompositorD3D11SWGL();
87 if (!compositor) {
88 return false;
91 if (!aHost->EnsureD3D11Texture2D(compositor->GetDevice())) {
92 return false;
95 if (!aHost->LockInternal()) {
96 return false;
99 D3D11_TEXTURE2D_DESC textureDesc = {0};
100 aTexture->GetDesc(&textureDesc);
102 compositor->GetDevice()->GetImmediateContext(getter_AddRefs(aDeviceContext));
104 textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
105 textureDesc.Usage = D3D11_USAGE_STAGING;
106 textureDesc.BindFlags = 0;
107 textureDesc.MiscFlags = 0;
108 textureDesc.MipLevels = 1;
109 HRESULT hr = compositor->GetDevice()->CreateTexture2D(
110 &textureDesc, nullptr, getter_AddRefs(aCpuTexture));
111 if (FAILED(hr)) {
112 return false;
115 aDeviceContext->CopyResource(aCpuTexture, aTexture);
116 aHost->Unlock();
118 hr = aDeviceContext->Map(aCpuTexture, 0, D3D11_MAP_READ, 0,
119 &aMappedSubresource);
120 return SUCCEEDED(hr);
123 bool RenderDXGITextureHost::MapPlane(RenderCompositor* aCompositor,
124 uint8_t aChannelIndex,
125 PlaneInfo& aPlaneInfo) {
126 // TODO: We currently readback from the GPU texture into a new
127 // staging texture every time this is mapped. We might be better
128 // off retaining the mapped memory to trade performance for memory
129 // usage.
130 if (!mCpuTexture && !MapTexture(this, aCompositor, mTexture, mDeviceContext,
131 mCpuTexture, mMappedSubresource)) {
132 return false;
135 aPlaneInfo.mSize = GetSize(aChannelIndex);
136 aPlaneInfo.mStride = mMappedSubresource.RowPitch;
137 aPlaneInfo.mData = mMappedSubresource.pData;
139 // If this is the second plane, then offset the data pointer by the
140 // size of the first plane.
141 if (aChannelIndex == 1) {
142 aPlaneInfo.mData =
143 (uint8_t*)aPlaneInfo.mData + aPlaneInfo.mStride * GetSize(0).height;
145 return true;
148 void RenderDXGITextureHost::UnmapPlanes() {
149 mMappedSubresource.pData = nullptr;
150 if (mCpuTexture) {
151 mDeviceContext->Unmap(mCpuTexture, 0);
152 mCpuTexture = nullptr;
154 mDeviceContext = nullptr;
157 bool RenderDXGITextureHost::EnsureD3D11Texture2DWithGL() {
158 if (mTexture) {
159 return true;
162 const auto& gle = gl::GLContextEGL::Cast(mGL);
163 const auto& egl = gle->mEgl;
165 // Fetch the D3D11 device.
166 EGLDeviceEXT eglDevice = nullptr;
167 egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
168 MOZ_ASSERT(eglDevice);
169 ID3D11Device* device = nullptr;
170 egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
171 (EGLAttrib*)&device);
172 // There's a chance this might fail if we end up on d3d9 angle for some
173 // reason.
174 if (!device) {
175 gfxCriticalNote << "RenderDXGITextureHost device is not available";
176 return false;
179 return EnsureD3D11Texture2D(device);
182 bool RenderDXGITextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
183 if (mTexture) {
184 RefPtr<ID3D11Device> device;
185 mTexture->GetDevice(getter_AddRefs(device));
186 if (aDevice != device) {
187 gfxCriticalNote << "RenderDXGITextureHost uses obsoleted device";
188 return false;
190 return true;
193 // Get the D3D11 texture from shared handle.
194 HRESULT hr = aDevice->OpenSharedResource(
195 (HANDLE)mHandle, __uuidof(ID3D11Texture2D),
196 (void**)(ID3D11Texture2D**)getter_AddRefs(mTexture));
197 if (FAILED(hr)) {
198 MOZ_ASSERT(false,
199 "RenderDXGITextureHost::EnsureLockable(): Failed to open shared "
200 "texture");
201 gfxCriticalNote
202 << "RenderDXGITextureHost Failed to open shared texture, hr="
203 << gfx::hexa(hr);
204 return false;
206 MOZ_ASSERT(mTexture.get());
207 mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
208 return true;
211 bool RenderDXGITextureHost::EnsureLockable(wr::ImageRendering aRendering) {
212 if (mTextureHandle[0]) {
213 // Update filter if filter was changed.
214 if (IsFilterUpdateNecessary(aRendering)) {
215 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
216 LOCAL_GL_TEXTURE_EXTERNAL_OES,
217 mTextureHandle[0], aRendering);
218 // Cache new rendering filter.
219 mCachedRendering = aRendering;
220 // NV12 and P016 uses two handles.
221 if (mFormat == gfx::SurfaceFormat::NV12 ||
222 mFormat == gfx::SurfaceFormat::P010 ||
223 mFormat == gfx::SurfaceFormat::P016) {
224 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE1,
225 LOCAL_GL_TEXTURE_EXTERNAL_OES,
226 mTextureHandle[1], aRendering);
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], aRendering);
265 // Cache new rendering filter.
266 mCachedRendering = aRendering;
267 ok &=
268 bool(egl->fStreamConsumerGLTextureExternalAttribsNV(mStream, nullptr));
269 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
270 } else {
271 // The nv12/p016 format.
273 // Setup the NV12 stream consumer/producer.
274 EGLAttrib consumerAttributes[] = {
275 LOCAL_EGL_COLOR_BUFFER_TYPE,
276 LOCAL_EGL_YUV_BUFFER_EXT,
277 LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT,
279 LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
281 LOCAL_EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
283 LOCAL_EGL_NONE,
285 mGL->fGenTextures(2, mTextureHandle);
286 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
287 LOCAL_GL_TEXTURE_EXTERNAL_OES,
288 mTextureHandle[0], aRendering);
289 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE1,
290 LOCAL_GL_TEXTURE_EXTERNAL_OES,
291 mTextureHandle[1], aRendering);
292 // Cache new rendering filter.
293 mCachedRendering = aRendering;
294 ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
295 mStream, consumerAttributes));
296 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
299 const EGLAttrib frameAttributes[] = {
300 LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
301 static_cast<EGLAttrib>(mArrayIndex),
302 LOCAL_EGL_NONE,
305 // Insert the d3d texture.
306 ok &= bool(egl->fStreamPostD3DTextureANGLE(mStream, (void*)mTexture.get(),
307 frameAttributes));
309 if (!ok) {
310 gfxCriticalNote << "RenderDXGITextureHost init stream failed";
311 DeleteTextureHandle();
312 return false;
315 // Now, we could get the gl handle from the stream.
316 MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStream));
318 return true;
321 wr::WrExternalImage RenderDXGITextureHost::Lock(uint8_t aChannelIndex,
322 gl::GLContext* aGL,
323 wr::ImageRendering aRendering) {
324 if (mGL.get() != aGL) {
325 // Release the texture handle in the previous gl context.
326 DeleteTextureHandle();
327 mGL = aGL;
330 if (!mGL) {
331 // XXX Software WebRender is not handled yet.
332 // Software WebRender does not provide GLContext
333 gfxCriticalNoteOnce
334 << "Software WebRender is not suppored by RenderDXGITextureHost.";
335 return InvalidToWrExternalImage();
338 if (!EnsureLockable(aRendering)) {
339 return InvalidToWrExternalImage();
342 if (!LockInternal()) {
343 return InvalidToWrExternalImage();
346 gfx::IntSize size = GetSize(aChannelIndex);
347 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), 0, 0,
348 size.width, size.height);
351 bool RenderDXGITextureHost::LockInternal() {
352 if (!mLocked) {
353 if (mKeyedMutex) {
354 HRESULT hr = mKeyedMutex->AcquireSync(0, 10000);
355 if (hr != S_OK) {
356 gfxCriticalError() << "RenderDXGITextureHost AcquireSync timeout, hr="
357 << gfx::hexa(hr);
358 return false;
361 mLocked = true;
363 return true;
366 void RenderDXGITextureHost::Unlock() {
367 if (mLocked) {
368 if (mKeyedMutex) {
369 mKeyedMutex->ReleaseSync(0);
371 mLocked = false;
375 void RenderDXGITextureHost::ClearCachedResources() {
376 DeleteTextureHandle();
377 mGL = nullptr;
380 void RenderDXGITextureHost::DeleteTextureHandle() {
381 if (mTextureHandle[0] == 0) {
382 return;
385 MOZ_ASSERT(mGL.get());
386 if (!mGL) {
387 return;
390 if (mGL->MakeCurrent()) {
391 mGL->fDeleteTextures(2, mTextureHandle);
393 const auto& gle = gl::GLContextEGL::Cast(mGL);
394 const auto& egl = gle->mEgl;
395 if (mSurface) {
396 egl->fDestroySurface(mSurface);
398 if (mStream) {
399 egl->fDestroyStreamKHR(mStream);
403 for (int i = 0; i < 2; ++i) {
404 mTextureHandle[i] = 0;
407 mTexture = nullptr;
408 mKeyedMutex = nullptr;
409 mSurface = 0;
410 mStream = 0;
413 GLuint RenderDXGITextureHost::GetGLHandle(uint8_t aChannelIndex) const {
414 MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
415 mFormat == gfx::SurfaceFormat::P010 ||
416 mFormat == gfx::SurfaceFormat::P016) &&
417 aChannelIndex < 2) ||
418 aChannelIndex < 1);
419 return mTextureHandle[aChannelIndex];
422 gfx::IntSize RenderDXGITextureHost::GetSize(uint8_t aChannelIndex) const {
423 MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
424 mFormat == gfx::SurfaceFormat::P010 ||
425 mFormat == gfx::SurfaceFormat::P016) &&
426 aChannelIndex < 2) ||
427 aChannelIndex < 1);
429 if (aChannelIndex == 0) {
430 return mSize;
431 } else {
432 // The CbCr channel size is a half of Y channel size in NV12 format.
433 return mSize / 2;
437 RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
438 WindowsHandle (&aHandles)[3], gfx::YUVColorSpace aYUVColorSpace,
439 gfx::ColorDepth aColorDepth, gfx::ColorRange aColorRange,
440 gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr)
441 : mHandles{aHandles[0], aHandles[1], aHandles[2]},
442 mSurfaces{0},
443 mStreams{0},
444 mTextureHandles{0},
445 mYUVColorSpace(aYUVColorSpace),
446 mColorDepth(aColorDepth),
447 mColorRange(aColorRange),
448 mSizeY(aSizeY),
449 mSizeCbCr(aSizeCbCr),
450 mLocked(false) {
451 MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
452 // Assume the chroma planes are rounded up if the luma plane is odd sized.
453 MOZ_ASSERT((mSizeCbCr.width == mSizeY.width ||
454 mSizeCbCr.width == (mSizeY.width + 1) >> 1) &&
455 (mSizeCbCr.height == mSizeY.height ||
456 mSizeCbCr.height == (mSizeY.height + 1) >> 1));
457 MOZ_ASSERT(aHandles[0] && aHandles[1] && aHandles[2]);
460 bool RenderDXGIYCbCrTextureHost::MapPlane(RenderCompositor* aCompositor,
461 uint8_t aChannelIndex,
462 PlaneInfo& aPlaneInfo) {
463 D3D11_MAPPED_SUBRESOURCE mappedSubresource;
464 if (!MapTexture(this, aCompositor, mTextures[aChannelIndex], mDeviceContext,
465 mCpuTexture[aChannelIndex], mappedSubresource)) {
466 return false;
469 aPlaneInfo.mSize = GetSize(aChannelIndex);
470 aPlaneInfo.mStride = mappedSubresource.RowPitch;
471 aPlaneInfo.mData = mappedSubresource.pData;
472 return true;
475 void RenderDXGIYCbCrTextureHost::UnmapPlanes() {
476 for (uint32_t i = 0; i < 3; i++) {
477 if (mCpuTexture[i]) {
478 mDeviceContext->Unmap(mCpuTexture[i], 0);
479 mCpuTexture[i] = nullptr;
482 mDeviceContext = nullptr;
485 RenderDXGIYCbCrTextureHost::~RenderDXGIYCbCrTextureHost() {
486 MOZ_COUNT_DTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
487 DeleteTextureHandle();
490 bool RenderDXGIYCbCrTextureHost::EnsureLockable(wr::ImageRendering aRendering) {
491 if (mTextureHandles[0]) {
492 // Update filter if filter was changed.
493 if (IsFilterUpdateNecessary(aRendering)) {
494 for (int i = 0; i < 3; ++i) {
495 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0 + i,
496 LOCAL_GL_TEXTURE_EXTERNAL_OES,
497 mTextureHandles[i], aRendering);
498 // Cache new rendering filter.
499 mCachedRendering = aRendering;
502 return true;
505 const auto& gle = gl::GLContextEGL::Cast(mGL);
506 const auto& egl = gle->mEgl;
508 // The eglCreatePbufferFromClientBuffer doesn't support R8 format, so we
509 // use EGLStream to get the converted gl handle from d3d R8 texture.
511 if (!egl->IsExtensionSupported(
512 gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
513 !egl->IsExtensionSupported(
514 gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
515 gfxCriticalNote
516 << "RenderDXGIYCbCrTextureHost egl extensions are not suppored";
517 return false;
520 // Fetch the D3D11 device.
521 EGLDeviceEXT eglDevice = nullptr;
522 egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
523 MOZ_ASSERT(eglDevice);
524 ID3D11Device* device = nullptr;
525 egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
526 (EGLAttrib*)&device);
527 // There's a chance this might fail if we end up on d3d9 angle for some
528 // reason.
529 if (!device) {
530 gfxCriticalNote << "RenderDXGIYCbCrTextureHost device is not available";
531 return false;
534 EnsureD3D11Texture2D(device);
536 mGL->fGenTextures(3, mTextureHandles);
537 bool ok = true;
538 for (int i = 0; i < 3; ++i) {
539 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0 + i,
540 LOCAL_GL_TEXTURE_EXTERNAL_OES,
541 mTextureHandles[i], aRendering);
542 // Cache new rendering filter.
543 mCachedRendering = aRendering;
545 // Create the EGLStream.
546 mStreams[i] = egl->fCreateStreamKHR(nullptr);
547 MOZ_ASSERT(mStreams[i]);
549 ok &= bool(
550 egl->fStreamConsumerGLTextureExternalAttribsNV(mStreams[i], nullptr));
551 ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStreams[i], nullptr));
553 // Insert the R8 texture.
554 ok &= bool(egl->fStreamPostD3DTextureANGLE(
555 mStreams[i], (void*)mTextures[i].get(), nullptr));
557 // Now, we could get the R8 gl handle from the stream.
558 MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStreams[i]));
561 if (!ok) {
562 gfxCriticalNote << "RenderDXGIYCbCrTextureHost init stream failed";
563 DeleteTextureHandle();
564 return false;
567 return true;
570 bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
571 if (mTextures[0]) {
572 RefPtr<ID3D11Device> device;
573 mTextures[0]->GetDevice(getter_AddRefs(device));
574 if (aDevice != device) {
575 gfxCriticalNote << "RenderDXGIYCbCrTextureHost uses obsoleted device";
576 return false;
580 if (mTextureHandles[0]) {
581 return true;
584 for (int i = 0; i < 3; ++i) {
585 // Get the R8 D3D11 texture from shared handle.
586 HRESULT hr = aDevice->OpenSharedResource(
587 (HANDLE)mHandles[i], __uuidof(ID3D11Texture2D),
588 (void**)(ID3D11Texture2D**)getter_AddRefs(mTextures[i]));
589 if (FAILED(hr)) {
590 NS_WARNING(
591 "RenderDXGIYCbCrTextureHost::EnsureLockable(): Failed to open "
592 "shared "
593 "texture");
594 gfxCriticalNote
595 << "RenderDXGIYCbCrTextureHost Failed to open shared texture, hr="
596 << gfx::hexa(hr);
597 return false;
601 for (int i = 0; i < 3; ++i) {
602 mTextures[i]->QueryInterface(
603 (IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutexs[i]));
605 return true;
608 bool RenderDXGIYCbCrTextureHost::LockInternal() {
609 if (!mLocked) {
610 if (mKeyedMutexs[0]) {
611 for (const auto& mutex : mKeyedMutexs) {
612 HRESULT hr = mutex->AcquireSync(0, 10000);
613 if (hr != S_OK) {
614 gfxCriticalError()
615 << "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr="
616 << gfx::hexa(hr);
617 return false;
621 mLocked = true;
623 return true;
626 wr::WrExternalImage RenderDXGIYCbCrTextureHost::Lock(
627 uint8_t aChannelIndex, gl::GLContext* aGL, wr::ImageRendering aRendering) {
628 if (mGL.get() != aGL) {
629 // Release the texture handle in the previous gl context.
630 DeleteTextureHandle();
631 mGL = aGL;
634 if (!mGL) {
635 // XXX Software WebRender is not handled yet.
636 // Software WebRender does not provide GLContext
637 gfxCriticalNoteOnce << "Software WebRender is not suppored by "
638 "RenderDXGIYCbCrTextureHost.";
639 return InvalidToWrExternalImage();
642 if (!EnsureLockable(aRendering)) {
643 return InvalidToWrExternalImage();
646 if (!LockInternal()) {
647 return InvalidToWrExternalImage();
650 gfx::IntSize size = GetSize(aChannelIndex);
651 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), 0, 0,
652 size.width, size.height);
655 void RenderDXGIYCbCrTextureHost::Unlock() {
656 if (mLocked) {
657 if (mKeyedMutexs[0]) {
658 for (const auto& mutex : mKeyedMutexs) {
659 mutex->ReleaseSync(0);
662 mLocked = false;
666 void RenderDXGIYCbCrTextureHost::ClearCachedResources() {
667 DeleteTextureHandle();
668 mGL = nullptr;
671 GLuint RenderDXGIYCbCrTextureHost::GetGLHandle(uint8_t aChannelIndex) const {
672 MOZ_ASSERT(aChannelIndex < 3);
674 return mTextureHandles[aChannelIndex];
677 gfx::IntSize RenderDXGIYCbCrTextureHost::GetSize(uint8_t aChannelIndex) const {
678 MOZ_ASSERT(aChannelIndex < 3);
680 if (aChannelIndex == 0) {
681 return mSizeY;
682 } else {
683 return mSizeCbCr;
687 void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
688 if (mTextureHandles[0] == 0) {
689 return;
692 MOZ_ASSERT(mGL.get());
693 if (!mGL) {
694 return;
697 if (mGL->MakeCurrent()) {
698 mGL->fDeleteTextures(3, mTextureHandles);
700 const auto& gle = gl::GLContextEGL::Cast(mGL);
701 const auto& egl = gle->mEgl;
702 for (int i = 0; i < 3; ++i) {
703 mTextureHandles[i] = 0;
704 mTextures[i] = nullptr;
705 mKeyedMutexs[i] = nullptr;
707 if (mSurfaces[i]) {
708 egl->fDestroySurface(mSurfaces[i]);
709 mSurfaces[i] = 0;
711 if (mStreams[i]) {
712 egl->fDestroyStreamKHR(mStreams[i]);
713 mStreams[i] = 0;
719 } // namespace wr
720 } // namespace mozilla