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/D3D11Checks.h"
12 #include "mozilla/gfx/DeviceManagerDx.h"
13 #include "mozilla/gfx/FileHandleWrapper.h"
14 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
19 static ID3D11Device
* GetD3D11DeviceOfEGLDisplay(GLContextEGL
* gle
) {
20 const auto& egl
= gle
->mEgl
;
23 !egl
->mLib
->IsExtensionSupported(gl::EGLLibExtension::EXT_device_query
)) {
27 // Fetch the D3D11 device.
28 EGLDeviceEXT eglDevice
= nullptr;
29 egl
->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT
, (EGLAttrib
*)&eglDevice
);
30 MOZ_ASSERT(eglDevice
);
31 ID3D11Device
* device
= nullptr;
32 egl
->mLib
->fQueryDeviceAttribEXT(eglDevice
, LOCAL_EGL_D3D11_DEVICE_ANGLE
,
40 // Returns `EGL_NO_SURFACE` (`0`) on error.
41 static EGLSurface
CreatePBufferSurface(EglDisplay
* egl
, EGLConfig config
,
42 const gfx::IntSize
& size
,
43 RefPtr
<ID3D11Texture2D
> texture2D
) {
44 const EGLint attribs
[] = {LOCAL_EGL_WIDTH
, size
.width
, LOCAL_EGL_HEIGHT
,
45 size
.height
, LOCAL_EGL_NONE
};
46 const auto buffer
= reinterpret_cast<EGLClientBuffer
>(texture2D
.get());
48 EGLSurface surface
= egl
->fCreatePbufferFromClientBuffer(
49 LOCAL_EGL_D3D_TEXTURE_ANGLE
, buffer
, config
, attribs
);
51 EGLint err
= egl
->mLib
->fGetError();
52 gfxCriticalError() << "Failed to create Pbuffer surface error: "
53 << gfx::hexa(err
) << " Size : " << size
;
61 UniquePtr
<SharedSurface_ANGLEShareHandle
>
62 SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc
& desc
) {
63 const auto& gle
= GLContextEGL::Cast(desc
.gl
);
64 const auto& egl
= gle
->mEgl
;
66 MOZ_ASSERT(egl
->IsExtensionSupported(
67 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle
));
69 auto* device
= GetD3D11DeviceOfEGLDisplay(gle
);
74 // Create a texture in case we need to readback.
75 const DXGI_FORMAT format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
76 CD3D11_TEXTURE2D_DESC
texDesc(
77 format
, desc
.size
.width
, desc
.size
.height
, 1, 1,
78 D3D11_BIND_SHADER_RESOURCE
| D3D11_BIND_RENDER_TARGET
);
79 texDesc
.MiscFlags
= D3D11_RESOURCE_MISC_SHARED_NTHANDLE
|
80 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
;
82 RefPtr
<ID3D11Texture2D
> texture2D
;
84 device
->CreateTexture2D(&texDesc
, nullptr, getter_AddRefs(texture2D
));
89 RefPtr
<IDXGIResource1
> texDXGI
;
90 hr
= texture2D
->QueryInterface(__uuidof(IDXGIResource1
),
91 getter_AddRefs(texDXGI
));
96 HANDLE sharedHandle
= nullptr;
97 texDXGI
->CreateSharedHandle(
98 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
101 RefPtr
<gfx::FileHandleWrapper
> handle
=
102 new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle
));
104 RefPtr
<IDXGIKeyedMutex
> keyedMutex
;
105 texture2D
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(keyedMutex
));
110 const auto& config
= gle
->mSurfaceConfig
;
114 CreatePBufferSurface(egl
.get(), config
, desc
.size
, texture2D
);
115 if (!pbuffer
) return nullptr;
117 return AsUnique(new SharedSurface_ANGLEShareHandle(
118 desc
, egl
, pbuffer
, std::move(handle
), keyedMutex
));
121 SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(
122 const SharedSurfaceDesc
& desc
, const std::weak_ptr
<EglDisplay
>& egl
,
123 EGLSurface pbuffer
, RefPtr
<gfx::FileHandleWrapper
>&& aSharedHandle
,
124 const RefPtr
<IDXGIKeyedMutex
>& keyedMutex
)
125 : SharedSurface(desc
, nullptr),
128 mSharedHandle(std::move(aSharedHandle
)),
129 mKeyedMutex(keyedMutex
) {}
131 SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() {
132 const auto& gl
= mDesc
.gl
;
134 if (gl
&& GLContextEGL::Cast(gl
)->GetEGLSurfaceOverride() == mPBuffer
) {
135 GLContextEGL::Cast(gl
)->SetEGLSurfaceOverride(EGL_NO_SURFACE
);
137 const auto egl
= mEGL
.lock();
139 egl
->fDestroySurface(mPBuffer
);
143 void SharedSurface_ANGLEShareHandle::LockProdImpl() {
144 const auto& gl
= mDesc
.gl
;
145 GLContextEGL::Cast(gl
)->SetEGLSurfaceOverride(mPBuffer
);
148 void SharedSurface_ANGLEShareHandle::UnlockProdImpl() {}
150 bool SharedSurface_ANGLEShareHandle::ProducerAcquireImpl() {
151 HRESULT hr
= mKeyedMutex
->AcquireSync(0, 10000);
152 return gfx::D3D11Checks::DidAcquireSyncSucceed(__func__
, hr
);
155 void SharedSurface_ANGLEShareHandle::ProducerReleaseImpl() {
156 const auto& gl
= mDesc
.gl
;
157 // XXX: ReleaseSync() has an implicit flush of the D3D commands
158 // whether we need Flush() or not depends on the ANGLE semantics.
159 // For now, we'll just do it
161 mKeyedMutex
->ReleaseSync(0);
164 bool SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl() {
165 return ProducerAcquireImpl();
168 void SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl() {
169 mKeyedMutex
->ReleaseSync(0);
172 Maybe
<layers::SurfaceDescriptor
>
173 SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor() {
174 const auto format
= gfx::SurfaceFormat::B8G8R8A8
;
175 return Some(layers::SurfaceDescriptorD3D10(
176 mSharedHandle
, /* gpuProcessTextureId */ Nothing(),
177 /* arrayIndex */ 0, format
, mDesc
.size
, mDesc
.colorSpace
,
178 gfx::ColorRange::FULL
, /* hasKeyedMutex */ true,
179 /* fenceInfo */ Nothing()));
182 ////////////////////////////////////////////////////////////////////////////////
186 UniquePtr
<SurfaceFactory_ANGLEShareHandle
>
187 SurfaceFactory_ANGLEShareHandle::Create(GLContext
& gl
) {
188 if (!gl
.IsANGLE()) return nullptr;
190 const auto& gle
= *GLContextEGL::Cast(&gl
);
191 const auto& egl
= gle
.mEgl
;
193 if (!egl
->IsExtensionSupported(
194 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle
)) {
198 if (XRE_IsContentProcess()) {
199 gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
202 gfx::DeviceManagerDx
* dm
= gfx::DeviceManagerDx::Get();
204 if (gl
.IsWARP() != dm
->IsWARP() || !dm
->TextureSharingWorks()) {
208 return AsUnique(new SurfaceFactory_ANGLEShareHandle(
209 {&gl
, SharedSurfaceType::EGLSurfaceANGLE
, layers::TextureType::D3D11
,
214 } /* namespace mozilla */