gfx/gl/SharedSurfaceANGLE.cpp

changeset 0
6474c204b198
     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 */

mercurial