1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SharedSurfaceANGLE.h"
9 #include "GLContextEGL.h"
10 #include "GLLibraryEGL.h"
11 #include "mozilla/gfx/DeviceManagerDx.h"
12 #include "mozilla/gfx/FileHandleWrapper.h"
13 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
18 static ID3D11Device
* GetD3D11DeviceOfEGLDisplay(GLContextEGL
* gle
) {
19 const auto& egl
= gle
->mEgl
;
22 !egl
->mLib
->IsExtensionSupported(gl::EGLLibExtension::EXT_device_query
)) {
26 // Fetch the D3D11 device.
27 EGLDeviceEXT eglDevice
= nullptr;
28 egl
->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT
, (EGLAttrib
*)&eglDevice
);
29 MOZ_ASSERT(eglDevice
);
30 ID3D11Device
* device
= nullptr;
31 egl
->mLib
->fQueryDeviceAttribEXT(eglDevice
, LOCAL_EGL_D3D11_DEVICE_ANGLE
,
39 // Returns `EGL_NO_SURFACE` (`0`) on error.
40 static EGLSurface
CreatePBufferSurface(EglDisplay
* egl
, EGLConfig config
,
41 const gfx::IntSize
& size
,
42 RefPtr
<ID3D11Texture2D
> texture2D
) {
43 const EGLint attribs
[] = {LOCAL_EGL_WIDTH
, size
.width
, LOCAL_EGL_HEIGHT
,
44 size
.height
, LOCAL_EGL_NONE
};
45 const auto buffer
= reinterpret_cast<EGLClientBuffer
>(texture2D
.get());
47 EGLSurface surface
= egl
->fCreatePbufferFromClientBuffer(
48 LOCAL_EGL_D3D_TEXTURE_ANGLE
, buffer
, config
, attribs
);
50 EGLint err
= egl
->mLib
->fGetError();
51 gfxCriticalError() << "Failed to create Pbuffer surface error: "
52 << gfx::hexa(err
) << " Size : " << size
;
60 UniquePtr
<SharedSurface_ANGLEShareHandle
>
61 SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc
& desc
) {
62 const auto& gle
= GLContextEGL::Cast(desc
.gl
);
63 const auto& egl
= gle
->mEgl
;
65 MOZ_ASSERT(egl
->IsExtensionSupported(
66 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle
));
68 auto* device
= GetD3D11DeviceOfEGLDisplay(gle
);
73 // Create a texture in case we need to readback.
74 const DXGI_FORMAT format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
75 CD3D11_TEXTURE2D_DESC
texDesc(
76 format
, desc
.size
.width
, desc
.size
.height
, 1, 1,
77 D3D11_BIND_SHADER_RESOURCE
| D3D11_BIND_RENDER_TARGET
);
78 texDesc
.MiscFlags
= D3D11_RESOURCE_MISC_SHARED_NTHANDLE
|
79 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
;
81 RefPtr
<ID3D11Texture2D
> texture2D
;
83 device
->CreateTexture2D(&texDesc
, nullptr, getter_AddRefs(texture2D
));
88 RefPtr
<IDXGIResource1
> texDXGI
;
89 hr
= texture2D
->QueryInterface(__uuidof(IDXGIResource1
),
90 getter_AddRefs(texDXGI
));
95 HANDLE sharedHandle
= nullptr;
96 texDXGI
->CreateSharedHandle(
97 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
100 RefPtr
<gfx::FileHandleWrapper
> handle
=
101 new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle
));
103 RefPtr
<IDXGIKeyedMutex
> keyedMutex
;
104 texture2D
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(keyedMutex
));
109 const auto& config
= gle
->mSurfaceConfig
;
113 CreatePBufferSurface(egl
.get(), config
, desc
.size
, texture2D
);
114 if (!pbuffer
) return nullptr;
116 return AsUnique(new SharedSurface_ANGLEShareHandle(
117 desc
, egl
, pbuffer
, std::move(handle
), keyedMutex
));
120 SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(
121 const SharedSurfaceDesc
& desc
, const std::weak_ptr
<EglDisplay
>& egl
,
122 EGLSurface pbuffer
, RefPtr
<gfx::FileHandleWrapper
>&& aSharedHandle
,
123 const RefPtr
<IDXGIKeyedMutex
>& keyedMutex
)
124 : SharedSurface(desc
, nullptr),
127 mSharedHandle(std::move(aSharedHandle
)),
128 mKeyedMutex(keyedMutex
) {}
130 SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() {
131 const auto& gl
= mDesc
.gl
;
133 if (gl
&& GLContextEGL::Cast(gl
)->GetEGLSurfaceOverride() == mPBuffer
) {
134 GLContextEGL::Cast(gl
)->SetEGLSurfaceOverride(EGL_NO_SURFACE
);
136 const auto egl
= mEGL
.lock();
138 egl
->fDestroySurface(mPBuffer
);
142 void SharedSurface_ANGLEShareHandle::LockProdImpl() {
143 const auto& gl
= mDesc
.gl
;
144 GLContextEGL::Cast(gl
)->SetEGLSurfaceOverride(mPBuffer
);
147 void SharedSurface_ANGLEShareHandle::UnlockProdImpl() {}
149 void SharedSurface_ANGLEShareHandle::ProducerAcquireImpl() {
150 HRESULT hr
= mKeyedMutex
->AcquireSync(0, 10000);
151 if (hr
== WAIT_TIMEOUT
) {
152 MOZ_CRASH("GFX: ANGLE share handle timeout");
156 void SharedSurface_ANGLEShareHandle::ProducerReleaseImpl() {
157 const auto& gl
= mDesc
.gl
;
158 // XXX: ReleaseSync() has an implicit flush of the D3D commands
159 // whether we need Flush() or not depends on the ANGLE semantics.
160 // For now, we'll just do it
162 mKeyedMutex
->ReleaseSync(0);
165 void SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl() {
166 ProducerAcquireImpl();
169 void SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl() {
170 mKeyedMutex
->ReleaseSync(0);
173 Maybe
<layers::SurfaceDescriptor
>
174 SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor() {
175 const auto format
= gfx::SurfaceFormat::B8G8R8A8
;
176 return Some(layers::SurfaceDescriptorD3D10(
177 mSharedHandle
, /* gpuProcessTextureId */ Nothing(),
178 /* arrayIndex */ 0, format
, mDesc
.size
, mDesc
.colorSpace
,
179 gfx::ColorRange::FULL
, /* hasKeyedMutex */ true,
180 /* fenceInfo */ Nothing(), /* gpuProcessQueryId */ Nothing()));
183 ////////////////////////////////////////////////////////////////////////////////
187 UniquePtr
<SurfaceFactory_ANGLEShareHandle
>
188 SurfaceFactory_ANGLEShareHandle::Create(GLContext
& gl
) {
189 if (!gl
.IsANGLE()) return nullptr;
191 const auto& gle
= *GLContextEGL::Cast(&gl
);
192 const auto& egl
= gle
.mEgl
;
194 if (!egl
->IsExtensionSupported(
195 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle
)) {
199 if (XRE_IsContentProcess()) {
200 gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
203 gfx::DeviceManagerDx
* dm
= gfx::DeviceManagerDx::Get();
205 if (gl
.IsWARP() != dm
->IsWARP() || !dm
->TextureSharingWorks()) {
209 return AsUnique(new SurfaceFactory_ANGLEShareHandle(
210 {&gl
, SharedSurfaceType::EGLSurfaceANGLE
, layers::TextureType::D3D11
,
215 } /* namespace mozilla */