gfx/gl/SharedSurfaceANGLE.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "SharedSurfaceANGLE.h"
michael@0 7
michael@0 8 #include "GLContextEGL.h"
michael@0 9
michael@0 10 using namespace mozilla::gfx;
michael@0 11
michael@0 12 namespace mozilla {
michael@0 13 namespace gl {
michael@0 14
michael@0 15 SurfaceFactory_ANGLEShareHandle*
michael@0 16 SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
michael@0 17 ID3D10Device1* d3d,
michael@0 18 const SurfaceCaps& caps)
michael@0 19 {
michael@0 20 GLLibraryEGL* egl = &sEGLLibrary;
michael@0 21 if (!egl)
michael@0 22 return nullptr;
michael@0 23
michael@0 24 if (!egl->IsExtensionSupported(
michael@0 25 GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle))
michael@0 26 {
michael@0 27 return nullptr;
michael@0 28 }
michael@0 29
michael@0 30 return new SurfaceFactory_ANGLEShareHandle(gl, egl, d3d, caps);
michael@0 31 }
michael@0 32
michael@0 33 EGLDisplay
michael@0 34 SharedSurface_ANGLEShareHandle::Display()
michael@0 35 {
michael@0 36 return mEGL->Display();
michael@0 37 }
michael@0 38
michael@0 39
michael@0 40 SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle()
michael@0 41 {
michael@0 42 mEGL->fDestroySurface(Display(), mPBuffer);
michael@0 43 }
michael@0 44
michael@0 45 void
michael@0 46 SharedSurface_ANGLEShareHandle::LockProdImpl()
michael@0 47 {
michael@0 48 GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(mPBuffer);
michael@0 49 }
michael@0 50
michael@0 51 void
michael@0 52 SharedSurface_ANGLEShareHandle::UnlockProdImpl()
michael@0 53 {
michael@0 54 }
michael@0 55
michael@0 56
michael@0 57 void
michael@0 58 SharedSurface_ANGLEShareHandle::Fence()
michael@0 59 {
michael@0 60 mGL->fFinish();
michael@0 61 }
michael@0 62
michael@0 63 bool
michael@0 64 SharedSurface_ANGLEShareHandle::WaitSync()
michael@0 65 {
michael@0 66 // Since we glFinish in Fence(), we're always going to be resolved here.
michael@0 67 return true;
michael@0 68 }
michael@0 69
michael@0 70 static void
michael@0 71 FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs,
michael@0 72 int redBits, int greenBits,
michael@0 73 int blueBits, int alphaBits,
michael@0 74 int depthBits, int stencilBits)
michael@0 75 {
michael@0 76 aAttrs.Clear();
michael@0 77
michael@0 78 #if defined(A1) || defined(A2)
michael@0 79 #error The temp-macro names we want are already defined.
michael@0 80 #endif
michael@0 81
michael@0 82 #define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
michael@0 83 #define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
michael@0 84
michael@0 85 A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT);
michael@0 86 A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT);
michael@0 87
michael@0 88 A2(LOCAL_EGL_RED_SIZE, redBits);
michael@0 89 A2(LOCAL_EGL_GREEN_SIZE, greenBits);
michael@0 90 A2(LOCAL_EGL_BLUE_SIZE, blueBits);
michael@0 91 A2(LOCAL_EGL_ALPHA_SIZE, alphaBits);
michael@0 92
michael@0 93 A2(LOCAL_EGL_DEPTH_SIZE, depthBits);
michael@0 94 A2(LOCAL_EGL_STENCIL_SIZE, stencilBits);
michael@0 95
michael@0 96 A1(LOCAL_EGL_NONE);
michael@0 97 #undef A1
michael@0 98 #undef A2
michael@0 99 }
michael@0 100
michael@0 101 static void
michael@0 102 FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs,
michael@0 103 bool bpp16, bool hasAlpha,
michael@0 104 int depthBits, int stencilBits)
michael@0 105 {
michael@0 106 int red = 0;
michael@0 107 int green = 0;
michael@0 108 int blue = 0;
michael@0 109 int alpha = 0;
michael@0 110
michael@0 111 if (bpp16) {
michael@0 112 if (hasAlpha) {
michael@0 113 red = green = blue = alpha = 4;
michael@0 114 } else {
michael@0 115 red = 5;
michael@0 116 green = 6;
michael@0 117 blue = 5;
michael@0 118 }
michael@0 119 } else {
michael@0 120 red = green = blue = 8;
michael@0 121 if (hasAlpha)
michael@0 122 alpha = 8;
michael@0 123 }
michael@0 124
michael@0 125 FillPBufferAttribs_ByBits(attribs,
michael@0 126 red, green, blue, alpha,
michael@0 127 depthBits, stencilBits);
michael@0 128 }
michael@0 129
michael@0 130 static EGLConfig
michael@0 131 ChooseConfig(GLContext* gl,
michael@0 132 GLLibraryEGL* egl,
michael@0 133 const SurfaceCaps& caps)
michael@0 134 {
michael@0 135 MOZ_ASSERT(egl);
michael@0 136 MOZ_ASSERT(caps.color);
michael@0 137
michael@0 138 // We might want 24-bit depth, but we're only (fairly) sure to get 16-bit.
michael@0 139 int depthBits = caps.depth ? 16 : 0;
michael@0 140 int stencilBits = caps.stencil ? 8 : 0;
michael@0 141
michael@0 142 // Ok, now we have everything.
michael@0 143 nsTArray<EGLint> attribs(32);
michael@0 144 FillPBufferAttribs_BySizes(attribs,
michael@0 145 caps.bpp16, caps.alpha,
michael@0 146 depthBits, stencilBits);
michael@0 147
michael@0 148 // Time to try to get this config:
michael@0 149 EGLConfig configs[64];
michael@0 150 int numConfigs = sizeof(configs)/sizeof(EGLConfig);
michael@0 151 int foundConfigs = 0;
michael@0 152
michael@0 153 if (!egl->fChooseConfig(egl->Display(),
michael@0 154 attribs.Elements(),
michael@0 155 configs, numConfigs,
michael@0 156 &foundConfigs) ||
michael@0 157 !foundConfigs)
michael@0 158 {
michael@0 159 NS_WARNING("No configs found for the requested formats.");
michael@0 160 return EGL_NO_CONFIG;
michael@0 161 }
michael@0 162
michael@0 163 // TODO: Pick a config progamatically instead of hoping that
michael@0 164 // the first config will be minimally matching our request.
michael@0 165 EGLConfig config = configs[0];
michael@0 166
michael@0 167 if (gl->DebugMode()) {
michael@0 168 egl->DumpEGLConfig(config);
michael@0 169 }
michael@0 170
michael@0 171 return config;
michael@0 172 }
michael@0 173
michael@0 174
michael@0 175 // Returns EGL_NO_SURFACE on error.
michael@0 176 static EGLSurface CreatePBufferSurface(GLLibraryEGL* egl,
michael@0 177 EGLDisplay display,
michael@0 178 EGLConfig config,
michael@0 179 const gfx::IntSize& size)
michael@0 180 {
michael@0 181 EGLint attribs[] = {
michael@0 182 LOCAL_EGL_WIDTH, size.width,
michael@0 183 LOCAL_EGL_HEIGHT, size.height,
michael@0 184 LOCAL_EGL_NONE
michael@0 185 };
michael@0 186
michael@0 187 EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs);
michael@0 188
michael@0 189 return surface;
michael@0 190 }
michael@0 191
michael@0 192 SharedSurface_ANGLEShareHandle*
michael@0 193 SharedSurface_ANGLEShareHandle::Create(GLContext* gl, ID3D10Device1* d3d,
michael@0 194 EGLContext context, EGLConfig config,
michael@0 195 const gfx::IntSize& size, bool hasAlpha)
michael@0 196 {
michael@0 197 GLLibraryEGL* egl = &sEGLLibrary;
michael@0 198 MOZ_ASSERT(egl);
michael@0 199 MOZ_ASSERT(egl->IsExtensionSupported(
michael@0 200 GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
michael@0 201
michael@0 202 if (!context || !config)
michael@0 203 return nullptr;
michael@0 204
michael@0 205 EGLDisplay display = egl->Display();
michael@0 206 EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size);
michael@0 207 if (!pbuffer)
michael@0 208 return nullptr;
michael@0 209
michael@0 210
michael@0 211 // Declare everything before 'goto's.
michael@0 212 HANDLE shareHandle = nullptr;
michael@0 213 nsRefPtr<ID3D10Texture2D> texture;
michael@0 214 nsRefPtr<ID3D10ShaderResourceView> srv;
michael@0 215
michael@0 216 // On failure, goto CleanUpIfFailed.
michael@0 217 // If |failed|, CleanUpIfFailed will clean up and return null.
michael@0 218 bool failed = true;
michael@0 219 HRESULT hr;
michael@0 220
michael@0 221 // Off to the races!
michael@0 222 if (!egl->fQuerySurfacePointerANGLE(
michael@0 223 display,
michael@0 224 pbuffer,
michael@0 225 LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
michael@0 226 &shareHandle))
michael@0 227 {
michael@0 228 NS_ERROR("Failed to grab ShareHandle for PBuffer!");
michael@0 229 goto CleanUpIfFailed;
michael@0 230 }
michael@0 231
michael@0 232 // Ok, we have a valid PBuffer with ShareHandle.
michael@0 233 // Let's attach it to D3D.
michael@0 234 hr = d3d->OpenSharedResource(shareHandle,
michael@0 235 __uuidof(ID3D10Texture2D),
michael@0 236 getter_AddRefs(texture));
michael@0 237 if (FAILED(hr)) {
michael@0 238 NS_ERROR("Failed to open shared resource!");
michael@0 239 goto CleanUpIfFailed;
michael@0 240 }
michael@0 241
michael@0 242 hr = d3d->CreateShaderResourceView(texture, nullptr, getter_AddRefs(srv));
michael@0 243 if (FAILED(hr)) {
michael@0 244 NS_ERROR("Failed to create SRV!");
michael@0 245 goto CleanUpIfFailed;
michael@0 246 }
michael@0 247
michael@0 248 failed = false;
michael@0 249
michael@0 250 CleanUpIfFailed:
michael@0 251 if (failed) {
michael@0 252 NS_WARNING("CleanUpIfFailed");
michael@0 253 egl->fDestroySurface(egl->Display(), pbuffer);
michael@0 254 return nullptr;
michael@0 255 }
michael@0 256
michael@0 257 return new SharedSurface_ANGLEShareHandle(gl, egl,
michael@0 258 size, hasAlpha,
michael@0 259 context, pbuffer,
michael@0 260 texture, srv);
michael@0 261 }
michael@0 262
michael@0 263
michael@0 264 SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
michael@0 265 GLLibraryEGL* egl,
michael@0 266 ID3D10Device1* d3d,
michael@0 267 const SurfaceCaps& caps)
michael@0 268 : SurfaceFactory_GL(gl, SharedSurfaceType::EGLSurfaceANGLE, caps)
michael@0 269 , mProdGL(gl)
michael@0 270 , mEGL(egl)
michael@0 271 , mConsD3D(d3d)
michael@0 272 {
michael@0 273 mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
michael@0 274 mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext();
michael@0 275 MOZ_ASSERT(mConfig && mContext);
michael@0 276 }
michael@0 277
michael@0 278 } /* namespace gl */
michael@0 279 } /* namespace mozilla */

mercurial