gfx/gl/SharedSurfaceGL.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

     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 "SharedSurfaceGL.h"
     7 #include "GLContext.h"
     8 #include "GLBlitHelper.h"
     9 #include "ScopedGLHelpers.h"
    10 #include "gfxImageSurface.h"
    11 #include "mozilla/gfx/2D.h"
    12 #include "GLReadTexImageHelper.h"
    14 using namespace mozilla::gfx;
    16 namespace mozilla {
    17 namespace gl {
    19 // |src| must begin and end locked, though we may
    20 // temporarily unlock it if we need to.
    21 void
    22 SharedSurface_GL::ProdCopy(SharedSurface_GL* src, SharedSurface_GL* dest,
    23                            SurfaceFactory_GL* factory)
    24 {
    25     GLContext* gl = src->GL();
    27     gl->MakeCurrent();
    29     if (src->AttachType() == AttachmentType::Screen &&
    30         dest->AttachType() == AttachmentType::Screen)
    31     {
    32         // Here, we actually need to blit through a temp surface, so let's make one.
    33         nsAutoPtr<SharedSurface_GLTexture> tempSurf(
    34             SharedSurface_GLTexture::Create(gl, gl,
    35                                             factory->Formats(),
    36                                             src->Size(),
    37                                             factory->Caps().alpha));
    39         ProdCopy(src, tempSurf, factory);
    40         ProdCopy(tempSurf, dest, factory);
    41         return;
    42     }
    44     if (src->AttachType() == AttachmentType::Screen) {
    45         SharedSurface_GL* origLocked = gl->GetLockedSurface();
    46         bool srcNeedsUnlock = false;
    47         bool origNeedsRelock = false;
    48         if (origLocked != src) {
    49             if (origLocked) {
    50                 origLocked->UnlockProd();
    51                 origNeedsRelock = true;
    52             }
    54             src->LockProd();
    55             srcNeedsUnlock = true;
    56         }
    58         if (dest->AttachType() == AttachmentType::GLTexture) {
    59             GLuint destTex = dest->ProdTexture();
    60             GLenum destTarget = dest->ProdTextureTarget();
    62             gl->BlitHelper()->BlitFramebufferToTexture(0, destTex, src->Size(), dest->Size(), destTarget);
    63         } else if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
    64             GLuint destRB = dest->ProdRenderbuffer();
    65             ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
    67             gl->BlitHelper()->BlitFramebufferToFramebuffer(0, destWrapper.FB(),
    68                                                            src->Size(), dest->Size());
    69         } else {
    70             MOZ_CRASH("Unhandled dest->AttachType().");
    71         }
    73         if (srcNeedsUnlock)
    74             src->UnlockProd();
    76         if (origNeedsRelock)
    77             origLocked->LockProd();
    79         return;
    80     }
    82     if (dest->AttachType() == AttachmentType::Screen) {
    83         SharedSurface_GL* origLocked = gl->GetLockedSurface();
    84         bool destNeedsUnlock = false;
    85         bool origNeedsRelock = false;
    86         if (origLocked != dest) {
    87             if (origLocked) {
    88                 origLocked->UnlockProd();
    89                 origNeedsRelock = true;
    90             }
    92             dest->LockProd();
    93             destNeedsUnlock = true;
    94         }
    96         if (src->AttachType() == AttachmentType::GLTexture) {
    97             GLuint srcTex = src->ProdTexture();
    98             GLenum srcTarget = src->ProdTextureTarget();
   100             gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0, src->Size(), dest->Size(), srcTarget);
   101         } else if (src->AttachType() == AttachmentType::GLRenderbuffer) {
   102             GLuint srcRB = src->ProdRenderbuffer();
   103             ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
   105             gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), 0,
   106                                                            src->Size(), dest->Size());
   107         } else {
   108             MOZ_CRASH("Unhandled src->AttachType().");
   109         }
   111         if (destNeedsUnlock)
   112             dest->UnlockProd();
   114         if (origNeedsRelock)
   115             origLocked->LockProd();
   117         return;
   118     }
   120     // Alright, done with cases involving Screen types.
   121     // Only {src,dest}x{texture,renderbuffer} left.
   123     if (src->AttachType() == AttachmentType::GLTexture) {
   124         GLuint srcTex = src->ProdTexture();
   125         GLenum srcTarget = src->ProdTextureTarget();
   127         if (dest->AttachType() == AttachmentType::GLTexture) {
   128             GLuint destTex = dest->ProdTexture();
   129             GLenum destTarget = dest->ProdTextureTarget();
   131             gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex,
   132                                                    src->Size(), dest->Size(),
   133                                                    srcTarget, destTarget);
   135             return;
   136         }
   138         if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
   139             GLuint destRB = dest->ProdRenderbuffer();
   140             ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
   142             gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(),
   143                                                        src->Size(), dest->Size(), srcTarget);
   145             return;
   146         }
   148         MOZ_CRASH("Unhandled dest->AttachType().");
   149     }
   151     if (src->AttachType() == AttachmentType::GLRenderbuffer) {
   152         GLuint srcRB = src->ProdRenderbuffer();
   153         ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
   155         if (dest->AttachType() == AttachmentType::GLTexture) {
   156             GLuint destTex = dest->ProdTexture();
   157             GLenum destTarget = dest->ProdTextureTarget();
   159             gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex,
   160                                                        src->Size(), dest->Size(), destTarget);
   162             return;
   163         }
   165         if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
   166             GLuint destRB = dest->ProdRenderbuffer();
   167             ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
   169             gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(),
   170                                                            src->Size(), dest->Size());
   172             return;
   173         }
   175         MOZ_CRASH("Unhandled dest->AttachType().");
   176     }
   178     MOZ_CRASH("Unhandled src->AttachType().");
   179 }
   181 void
   182 SharedSurface_GL::LockProd()
   183 {
   184     MOZ_ASSERT(!mIsLocked);
   186     LockProdImpl();
   188     mGL->LockSurface(this);
   189     mIsLocked = true;
   190 }
   192 void
   193 SharedSurface_GL::UnlockProd()
   194 {
   195     if (!mIsLocked)
   196         return;
   198     UnlockProdImpl();
   200     mGL->UnlockSurface(this);
   201     mIsLocked = false;
   202 }
   205 SurfaceFactory_GL::SurfaceFactory_GL(GLContext* gl,
   206                                      SharedSurfaceType type,
   207                                      const SurfaceCaps& caps)
   208     : SurfaceFactory(type, caps)
   209     , mGL(gl)
   210     , mFormats(gl->ChooseGLFormats(caps))
   211 {
   212     ChooseBufferBits(caps, mDrawCaps, mReadCaps);
   213 }
   215 void
   216 SurfaceFactory_GL::ChooseBufferBits(const SurfaceCaps& caps,
   217                                     SurfaceCaps& drawCaps,
   218                                     SurfaceCaps& readCaps) const
   219 {
   220     SurfaceCaps screenCaps;
   222     screenCaps.color = caps.color;
   223     screenCaps.alpha = caps.alpha;
   224     screenCaps.bpp16 = caps.bpp16;
   226     screenCaps.depth = caps.depth;
   227     screenCaps.stencil = caps.stencil;
   229     screenCaps.antialias = caps.antialias;
   230     screenCaps.preserve = caps.preserve;
   232     if (caps.antialias) {
   233         drawCaps = screenCaps;
   234         readCaps.Clear();
   236         // Color caps need to be duplicated in readCaps.
   237         readCaps.color = caps.color;
   238         readCaps.alpha = caps.alpha;
   239         readCaps.bpp16 = caps.bpp16;
   240     } else {
   241         drawCaps.Clear();
   242         readCaps = screenCaps;
   243     }
   244 }
   247 SharedSurface_Basic*
   248 SharedSurface_Basic::Create(GLContext* gl,
   249                             const GLFormats& formats,
   250                             const IntSize& size,
   251                             bool hasAlpha)
   252 {
   253     gl->MakeCurrent();
   254     GLuint tex = CreateTexture(gl, formats.color_texInternalFormat,
   255                                formats.color_texFormat,
   256                                formats.color_texType,
   257                                size);
   259     SurfaceFormat format = SurfaceFormat::B8G8R8X8;
   260     switch (formats.color_texInternalFormat) {
   261     case LOCAL_GL_RGB:
   262     case LOCAL_GL_RGB8:
   263         if (formats.color_texType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
   264             format = SurfaceFormat::R5G6B5;
   265         else
   266             format = SurfaceFormat::B8G8R8X8;
   267         break;
   268     case LOCAL_GL_RGBA:
   269     case LOCAL_GL_RGBA8:
   270         format = SurfaceFormat::B8G8R8A8;
   271         break;
   272     default:
   273         MOZ_CRASH("Unhandled Tex format.");
   274     }
   275     return new SharedSurface_Basic(gl, size, hasAlpha, format, tex);
   276 }
   278 SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
   279                                          const IntSize& size,
   280                                          bool hasAlpha,
   281                                          SurfaceFormat format,
   282                                          GLuint tex)
   283     : SharedSurface_GL(SharedSurfaceType::Basic,
   284                        AttachmentType::GLTexture,
   285                        gl,
   286                        size,
   287                        hasAlpha)
   288     , mTex(tex), mFB(0)
   289 {
   290     mGL->MakeCurrent();
   291     mGL->fGenFramebuffers(1, &mFB);
   293     ScopedBindFramebuffer autoFB(mGL, mFB);
   294     mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
   295                               LOCAL_GL_COLOR_ATTACHMENT0,
   296                               LOCAL_GL_TEXTURE_2D,
   297                               mTex,
   298                               0);
   300     GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
   301     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
   302         mGL->fDeleteFramebuffers(1, &mFB);
   303         mFB = 0;
   304     }
   306     mData = Factory::CreateDataSourceSurfaceWithStride(size, format,
   307               GetAlignedStride<4>(size.width * BytesPerPixel(format)));
   308 }
   310 SharedSurface_Basic::~SharedSurface_Basic()
   311 {
   312     if (!mGL->MakeCurrent())
   313         return;
   315     if (mFB)
   316         mGL->fDeleteFramebuffers(1, &mFB);
   318     mGL->fDeleteTextures(1, &mTex);
   319 }
   321 void
   322 SharedSurface_Basic::Fence()
   323 {
   324     mGL->MakeCurrent();
   326     ScopedBindFramebuffer autoFB(mGL, mFB);
   328     DataSourceSurface::MappedSurface map;
   329     mData->Map(DataSourceSurface::MapType::WRITE, &map);
   330     nsRefPtr<gfxImageSurface> wrappedData =
   331       new gfxImageSurface(map.mData,
   332                           ThebesIntSize(mData->GetSize()),
   333                           map.mStride,
   334                           SurfaceFormatToImageFormat(mData->GetFormat()));
   335     ReadPixelsIntoImageSurface(mGL, wrappedData);
   336     mData->Unmap();
   337 }
   341 SharedSurface_GLTexture*
   342 SharedSurface_GLTexture::Create(GLContext* prodGL,
   343                                 GLContext* consGL,
   344                                 const GLFormats& formats,
   345                                 const gfx::IntSize& size,
   346                                 bool hasAlpha,
   347                                 GLuint texture)
   348 {
   349     MOZ_ASSERT(prodGL);
   350     MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL));
   352     prodGL->MakeCurrent();
   354     GLuint tex = texture;
   356     bool ownsTex = false;
   358     if (!tex) {
   359       tex = CreateTextureForOffscreen(prodGL, formats, size);
   360       ownsTex = true;
   361     }
   363     return new SharedSurface_GLTexture(prodGL, consGL, size, hasAlpha, tex, ownsTex);
   364 }
   366 SharedSurface_GLTexture::~SharedSurface_GLTexture()
   367 {
   368     if (!mGL->MakeCurrent())
   369         return;
   371     if (mOwnsTex) {
   372         mGL->fDeleteTextures(1, &mTex);
   373     }
   375     if (mSync) {
   376         mGL->fDeleteSync(mSync);
   377     }
   378 }
   380 void
   381 SharedSurface_GLTexture::Fence()
   382 {
   383     MutexAutoLock lock(mMutex);
   384     mGL->MakeCurrent();
   386     if (mConsGL && mGL->IsExtensionSupported(GLContext::ARB_sync)) {
   387         if (mSync) {
   388             mGL->fDeleteSync(mSync);
   389             mSync = 0;
   390         }
   392         mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
   393         if (mSync) {
   394             mGL->fFlush();
   395             return;
   396         }
   397     }
   398     MOZ_ASSERT(!mSync);
   400     mGL->fFinish();
   401 }
   403 bool
   404 SharedSurface_GLTexture::WaitSync()
   405 {
   406     MutexAutoLock lock(mMutex);
   407     if (!mSync) {
   408         // We must have used glFinish instead of glFenceSync.
   409         return true;
   410     }
   412     mConsGL->MakeCurrent();
   413     MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
   415     mConsGL->fWaitSync(mSync,
   416                        0,
   417                        LOCAL_GL_TIMEOUT_IGNORED);
   418     mConsGL->fDeleteSync(mSync);
   419     mSync = 0;
   421     return true;
   422 }
   424 GLuint
   425 SharedSurface_GLTexture::ConsTexture(GLContext* consGL)
   426 {
   427     MutexAutoLock lock(mMutex);
   428     MOZ_ASSERT(consGL);
   429     MOZ_ASSERT(mGL->SharesWith(consGL));
   430     MOZ_ASSERT_IF(mConsGL, consGL == mConsGL);
   432     mConsGL = consGL;
   434     return mTex;
   435 }
   437 } /* namespace gfx */
   438 } /* namespace mozilla */

mercurial