gfx/gl/SharedSurfaceANGLE.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial