1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/SharedSurfaceANGLE.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,279 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "SharedSurfaceANGLE.h" 1.10 + 1.11 +#include "GLContextEGL.h" 1.12 + 1.13 +using namespace mozilla::gfx; 1.14 + 1.15 +namespace mozilla { 1.16 +namespace gl { 1.17 + 1.18 +SurfaceFactory_ANGLEShareHandle* 1.19 +SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, 1.20 + ID3D10Device1* d3d, 1.21 + const SurfaceCaps& caps) 1.22 +{ 1.23 + GLLibraryEGL* egl = &sEGLLibrary; 1.24 + if (!egl) 1.25 + return nullptr; 1.26 + 1.27 + if (!egl->IsExtensionSupported( 1.28 + GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle)) 1.29 + { 1.30 + return nullptr; 1.31 + } 1.32 + 1.33 + return new SurfaceFactory_ANGLEShareHandle(gl, egl, d3d, caps); 1.34 +} 1.35 + 1.36 +EGLDisplay 1.37 +SharedSurface_ANGLEShareHandle::Display() 1.38 +{ 1.39 + return mEGL->Display(); 1.40 +} 1.41 + 1.42 + 1.43 +SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() 1.44 +{ 1.45 + mEGL->fDestroySurface(Display(), mPBuffer); 1.46 +} 1.47 + 1.48 +void 1.49 +SharedSurface_ANGLEShareHandle::LockProdImpl() 1.50 +{ 1.51 + GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(mPBuffer); 1.52 +} 1.53 + 1.54 +void 1.55 +SharedSurface_ANGLEShareHandle::UnlockProdImpl() 1.56 +{ 1.57 +} 1.58 + 1.59 + 1.60 +void 1.61 +SharedSurface_ANGLEShareHandle::Fence() 1.62 +{ 1.63 + mGL->fFinish(); 1.64 +} 1.65 + 1.66 +bool 1.67 +SharedSurface_ANGLEShareHandle::WaitSync() 1.68 +{ 1.69 + // Since we glFinish in Fence(), we're always going to be resolved here. 1.70 + return true; 1.71 +} 1.72 + 1.73 +static void 1.74 +FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs, 1.75 + int redBits, int greenBits, 1.76 + int blueBits, int alphaBits, 1.77 + int depthBits, int stencilBits) 1.78 +{ 1.79 + aAttrs.Clear(); 1.80 + 1.81 +#if defined(A1) || defined(A2) 1.82 +#error The temp-macro names we want are already defined. 1.83 +#endif 1.84 + 1.85 +#define A1(_x) do { aAttrs.AppendElement(_x); } while (0) 1.86 +#define A2(_x,_y) do { A1(_x); A1(_y); } while (0) 1.87 + 1.88 + A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT); 1.89 + A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT); 1.90 + 1.91 + A2(LOCAL_EGL_RED_SIZE, redBits); 1.92 + A2(LOCAL_EGL_GREEN_SIZE, greenBits); 1.93 + A2(LOCAL_EGL_BLUE_SIZE, blueBits); 1.94 + A2(LOCAL_EGL_ALPHA_SIZE, alphaBits); 1.95 + 1.96 + A2(LOCAL_EGL_DEPTH_SIZE, depthBits); 1.97 + A2(LOCAL_EGL_STENCIL_SIZE, stencilBits); 1.98 + 1.99 + A1(LOCAL_EGL_NONE); 1.100 +#undef A1 1.101 +#undef A2 1.102 +} 1.103 + 1.104 +static void 1.105 +FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs, 1.106 + bool bpp16, bool hasAlpha, 1.107 + int depthBits, int stencilBits) 1.108 +{ 1.109 + int red = 0; 1.110 + int green = 0; 1.111 + int blue = 0; 1.112 + int alpha = 0; 1.113 + 1.114 + if (bpp16) { 1.115 + if (hasAlpha) { 1.116 + red = green = blue = alpha = 4; 1.117 + } else { 1.118 + red = 5; 1.119 + green = 6; 1.120 + blue = 5; 1.121 + } 1.122 + } else { 1.123 + red = green = blue = 8; 1.124 + if (hasAlpha) 1.125 + alpha = 8; 1.126 + } 1.127 + 1.128 + FillPBufferAttribs_ByBits(attribs, 1.129 + red, green, blue, alpha, 1.130 + depthBits, stencilBits); 1.131 +} 1.132 + 1.133 +static EGLConfig 1.134 +ChooseConfig(GLContext* gl, 1.135 + GLLibraryEGL* egl, 1.136 + const SurfaceCaps& caps) 1.137 +{ 1.138 + MOZ_ASSERT(egl); 1.139 + MOZ_ASSERT(caps.color); 1.140 + 1.141 + // We might want 24-bit depth, but we're only (fairly) sure to get 16-bit. 1.142 + int depthBits = caps.depth ? 16 : 0; 1.143 + int stencilBits = caps.stencil ? 8 : 0; 1.144 + 1.145 + // Ok, now we have everything. 1.146 + nsTArray<EGLint> attribs(32); 1.147 + FillPBufferAttribs_BySizes(attribs, 1.148 + caps.bpp16, caps.alpha, 1.149 + depthBits, stencilBits); 1.150 + 1.151 + // Time to try to get this config: 1.152 + EGLConfig configs[64]; 1.153 + int numConfigs = sizeof(configs)/sizeof(EGLConfig); 1.154 + int foundConfigs = 0; 1.155 + 1.156 + if (!egl->fChooseConfig(egl->Display(), 1.157 + attribs.Elements(), 1.158 + configs, numConfigs, 1.159 + &foundConfigs) || 1.160 + !foundConfigs) 1.161 + { 1.162 + NS_WARNING("No configs found for the requested formats."); 1.163 + return EGL_NO_CONFIG; 1.164 + } 1.165 + 1.166 + // TODO: Pick a config progamatically instead of hoping that 1.167 + // the first config will be minimally matching our request. 1.168 + EGLConfig config = configs[0]; 1.169 + 1.170 + if (gl->DebugMode()) { 1.171 + egl->DumpEGLConfig(config); 1.172 + } 1.173 + 1.174 + return config; 1.175 +} 1.176 + 1.177 + 1.178 +// Returns EGL_NO_SURFACE on error. 1.179 +static EGLSurface CreatePBufferSurface(GLLibraryEGL* egl, 1.180 + EGLDisplay display, 1.181 + EGLConfig config, 1.182 + const gfx::IntSize& size) 1.183 +{ 1.184 + EGLint attribs[] = { 1.185 + LOCAL_EGL_WIDTH, size.width, 1.186 + LOCAL_EGL_HEIGHT, size.height, 1.187 + LOCAL_EGL_NONE 1.188 + }; 1.189 + 1.190 + EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs); 1.191 + 1.192 + return surface; 1.193 +} 1.194 + 1.195 +SharedSurface_ANGLEShareHandle* 1.196 +SharedSurface_ANGLEShareHandle::Create(GLContext* gl, ID3D10Device1* d3d, 1.197 + EGLContext context, EGLConfig config, 1.198 + const gfx::IntSize& size, bool hasAlpha) 1.199 +{ 1.200 + GLLibraryEGL* egl = &sEGLLibrary; 1.201 + MOZ_ASSERT(egl); 1.202 + MOZ_ASSERT(egl->IsExtensionSupported( 1.203 + GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle)); 1.204 + 1.205 + if (!context || !config) 1.206 + return nullptr; 1.207 + 1.208 + EGLDisplay display = egl->Display(); 1.209 + EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size); 1.210 + if (!pbuffer) 1.211 + return nullptr; 1.212 + 1.213 + 1.214 + // Declare everything before 'goto's. 1.215 + HANDLE shareHandle = nullptr; 1.216 + nsRefPtr<ID3D10Texture2D> texture; 1.217 + nsRefPtr<ID3D10ShaderResourceView> srv; 1.218 + 1.219 + // On failure, goto CleanUpIfFailed. 1.220 + // If |failed|, CleanUpIfFailed will clean up and return null. 1.221 + bool failed = true; 1.222 + HRESULT hr; 1.223 + 1.224 + // Off to the races! 1.225 + if (!egl->fQuerySurfacePointerANGLE( 1.226 + display, 1.227 + pbuffer, 1.228 + LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, 1.229 + &shareHandle)) 1.230 + { 1.231 + NS_ERROR("Failed to grab ShareHandle for PBuffer!"); 1.232 + goto CleanUpIfFailed; 1.233 + } 1.234 + 1.235 + // Ok, we have a valid PBuffer with ShareHandle. 1.236 + // Let's attach it to D3D. 1.237 + hr = d3d->OpenSharedResource(shareHandle, 1.238 + __uuidof(ID3D10Texture2D), 1.239 + getter_AddRefs(texture)); 1.240 + if (FAILED(hr)) { 1.241 + NS_ERROR("Failed to open shared resource!"); 1.242 + goto CleanUpIfFailed; 1.243 + } 1.244 + 1.245 + hr = d3d->CreateShaderResourceView(texture, nullptr, getter_AddRefs(srv)); 1.246 + if (FAILED(hr)) { 1.247 + NS_ERROR("Failed to create SRV!"); 1.248 + goto CleanUpIfFailed; 1.249 + } 1.250 + 1.251 + failed = false; 1.252 + 1.253 +CleanUpIfFailed: 1.254 + if (failed) { 1.255 + NS_WARNING("CleanUpIfFailed"); 1.256 + egl->fDestroySurface(egl->Display(), pbuffer); 1.257 + return nullptr; 1.258 + } 1.259 + 1.260 + return new SharedSurface_ANGLEShareHandle(gl, egl, 1.261 + size, hasAlpha, 1.262 + context, pbuffer, 1.263 + texture, srv); 1.264 +} 1.265 + 1.266 + 1.267 +SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl, 1.268 + GLLibraryEGL* egl, 1.269 + ID3D10Device1* d3d, 1.270 + const SurfaceCaps& caps) 1.271 + : SurfaceFactory_GL(gl, SharedSurfaceType::EGLSurfaceANGLE, caps) 1.272 + , mProdGL(gl) 1.273 + , mEGL(egl) 1.274 + , mConsD3D(d3d) 1.275 +{ 1.276 + mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps); 1.277 + mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext(); 1.278 + MOZ_ASSERT(mConfig && mContext); 1.279 +} 1.280 + 1.281 +} /* namespace gl */ 1.282 +} /* namespace mozilla */