LCOV - code coverage report
Current view: top level - gfx/gl - GLScreenBuffer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 472 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 47 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "GLScreenBuffer.h"
       7             : 
       8             : #include <cstring>
       9             : #include "CompositorTypes.h"
      10             : #include "gfxPrefs.h"
      11             : #include "GLContext.h"
      12             : #include "GLBlitHelper.h"
      13             : #include "GLReadTexImageHelper.h"
      14             : #include "SharedSurfaceEGL.h"
      15             : #include "SharedSurfaceGL.h"
      16             : #include "ScopedGLHelpers.h"
      17             : #include "gfx2DGlue.h"
      18             : #include "../layers/ipc/ShadowLayers.h"
      19             : #include "mozilla/layers/TextureForwarder.h"
      20             : #include "mozilla/layers/TextureClientSharedSurface.h"
      21             : 
      22             : #ifdef XP_WIN
      23             : #include "SharedSurfaceANGLE.h"         // for SurfaceFactory_ANGLEShareHandle
      24             : #include "SharedSurfaceD3D11Interop.h"  // for SurfaceFactory_D3D11Interop
      25             : #include "mozilla/gfx/DeviceManagerDx.h"
      26             : #endif
      27             : 
      28             : #ifdef XP_MACOSX
      29             : #include "SharedSurfaceIO.h"
      30             : #endif
      31             : 
      32             : #ifdef GL_PROVIDER_GLX
      33             : #include "GLXLibrary.h"
      34             : #include "SharedSurfaceGLX.h"
      35             : #endif
      36             : 
      37             : namespace mozilla {
      38             : namespace gl {
      39             : 
      40             : using gfx::SurfaceFormat;
      41             : 
      42             : UniquePtr<GLScreenBuffer>
      43           0 : GLScreenBuffer::Create(GLContext* gl,
      44             :                        const gfx::IntSize& size,
      45             :                        const SurfaceCaps& caps)
      46             : {
      47           0 :     UniquePtr<GLScreenBuffer> ret;
      48           0 :     if (caps.antialias &&
      49           0 :         !gl->IsSupported(GLFeature::framebuffer_multisample))
      50             :     {
      51           0 :         return Move(ret);
      52             :     }
      53             : 
      54           0 :     layers::TextureFlags flags = layers::TextureFlags::ORIGIN_BOTTOM_LEFT;
      55           0 :     if (!caps.premultAlpha) {
      56           0 :         flags |= layers::TextureFlags::NON_PREMULTIPLIED;
      57             :     }
      58             : 
      59           0 :     UniquePtr<SurfaceFactory> factory = MakeUnique<SurfaceFactory_Basic>(gl, caps, flags);
      60             : 
      61           0 :     ret.reset( new GLScreenBuffer(gl, caps, Move(factory)) );
      62           0 :     return Move(ret);
      63             : }
      64             : 
      65             : /* static */ UniquePtr<SurfaceFactory>
      66           0 : GLScreenBuffer::CreateFactory(GLContext* gl,
      67             :                               const SurfaceCaps& caps,
      68             :                               KnowsCompositor* compositorConnection,
      69             :                               const layers::TextureFlags& flags)
      70             : {
      71           0 :   return CreateFactory(gl, caps, compositorConnection->GetTextureForwarder(),
      72           0 :                        compositorConnection->GetCompositorBackendType(), flags);
      73             : }
      74             : 
      75             : /* static */ UniquePtr<SurfaceFactory>
      76           0 : GLScreenBuffer::CreateFactory(GLContext* gl,
      77             :                               const SurfaceCaps& caps,
      78             :                               LayersIPCChannel* ipcChannel,
      79             :                               const mozilla::layers::LayersBackend backend,
      80             :                               const layers::TextureFlags& flags)
      81             : {
      82           0 :     UniquePtr<SurfaceFactory> factory = nullptr;
      83           0 :     if (!gfxPrefs::WebGLForceLayersReadback()) {
      84           0 :         switch (backend) {
      85             :             case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
      86             : #if defined(XP_MACOSX)
      87             :                 factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
      88             : #elif defined(GL_PROVIDER_GLX)
      89           0 :                 if (sGLXLibrary.UseTextureFromPixmap())
      90           0 :                   factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
      91             : #elif defined(MOZ_WIDGET_UIKIT)
      92             :                 factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags);
      93             : #elif defined(MOZ_WIDGET_ANDROID)
      94             :                 if (XRE_IsParentProcess()) {
      95             :                     factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
      96             :                 } else {
      97             :                     factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
      98             :                 }
      99             : #else
     100             :                 if (gl->GetContextType() == GLContextType::EGL) {
     101             :                     if (XRE_IsParentProcess()) {
     102             :                         factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
     103             :                     }
     104             :                 }
     105             : #endif
     106           0 :                 break;
     107             :             }
     108             :             case mozilla::layers::LayersBackend::LAYERS_D3D11: {
     109             : #ifdef XP_WIN
     110             :                 // Enable surface sharing only if ANGLE and compositing devices
     111             :                 // are both WARP or both not WARP
     112             :                 gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get();
     113             :                 if (gl->IsANGLE() &&
     114             :                     (gl->IsWARP() == dm->IsWARP()) &&
     115             :                     dm->TextureSharingWorks())
     116             :                 {
     117             :                     factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, ipcChannel, flags);
     118             :                 }
     119             : 
     120             :                 if (!factory && gfxPrefs::WebGLDXGLEnabled()) {
     121             :                   factory = SurfaceFactory_D3D11Interop::Create(gl, caps, ipcChannel, flags);
     122             :                 }
     123             : #endif
     124           0 :               break;
     125             :             }
     126             :             default:
     127           0 :               break;
     128             :         }
     129             : 
     130             : #ifdef GL_PROVIDER_GLX
     131           0 :         if (!factory && sGLXLibrary.UseTextureFromPixmap()) {
     132           0 :             factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
     133             :         }
     134             : #endif
     135             :     }
     136             : 
     137           0 :     return factory;
     138             : }
     139             : 
     140           0 : GLScreenBuffer::GLScreenBuffer(GLContext* gl,
     141             :                                const SurfaceCaps& caps,
     142           0 :                                UniquePtr<SurfaceFactory> factory)
     143             :     : mGL(gl)
     144             :     , mCaps(caps)
     145           0 :     , mFactory(Move(factory))
     146             :     , mNeedsBlit(true)
     147             :     , mUserReadBufferMode(LOCAL_GL_BACK)
     148             :     , mUserDrawBufferMode(LOCAL_GL_BACK)
     149             :     , mUserDrawFB(0)
     150             :     , mUserReadFB(0)
     151             :     , mInternalDrawFB(0)
     152             :     , mInternalReadFB(0)
     153             : #ifdef DEBUG
     154             :     , mInInternalMode_DrawFB(true)
     155           0 :     , mInInternalMode_ReadFB(true)
     156             : #endif
     157           0 : { }
     158             : 
     159           0 : GLScreenBuffer::~GLScreenBuffer()
     160             : {
     161           0 :     mFactory = nullptr;
     162           0 :     mDraw = nullptr;
     163           0 :     mRead = nullptr;
     164             : 
     165           0 :     if (!mBack)
     166           0 :         return;
     167             : 
     168             :     // Detach mBack cleanly.
     169           0 :     mBack->Surf()->ProducerRelease();
     170           0 : }
     171             : 
     172             : void
     173           0 : GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const
     174             : {
     175           0 :     GLuint drawFB = DrawFB();
     176           0 :     GLuint readFB = ReadFB();
     177             : 
     178           0 :     if (!gl->IsSupported(GLFeature::split_framebuffer)) {
     179           0 :         MOZ_ASSERT(drawFB == readFB);
     180           0 :         gl->raw_fBindFramebuffer(target, readFB);
     181           0 :         return;
     182             :     }
     183             : 
     184           0 :     switch (target) {
     185             :     case LOCAL_GL_FRAMEBUFFER:
     186           0 :         gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB);
     187           0 :         gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB);
     188           0 :         break;
     189             : 
     190             :     case LOCAL_GL_DRAW_FRAMEBUFFER_EXT:
     191           0 :         gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB);
     192           0 :         break;
     193             : 
     194             :     case LOCAL_GL_READ_FRAMEBUFFER_EXT:
     195           0 :         gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB);
     196           0 :         break;
     197             : 
     198             :     default:
     199           0 :         MOZ_CRASH("GFX: Bad `target` for BindFramebuffer.");
     200             :     }
     201             : }
     202             : 
     203             : void
     204           0 : GLScreenBuffer::BindFB(GLuint fb)
     205             : {
     206           0 :     GLuint drawFB = DrawFB();
     207           0 :     GLuint readFB = ReadFB();
     208             : 
     209           0 :     mUserDrawFB = fb;
     210           0 :     mUserReadFB = fb;
     211           0 :     mInternalDrawFB = (fb == 0) ? drawFB : fb;
     212           0 :     mInternalReadFB = (fb == 0) ? readFB : fb;
     213             : 
     214           0 :     if (mInternalDrawFB == mInternalReadFB) {
     215           0 :         mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB);
     216             :     } else {
     217           0 :         MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer));
     218           0 :         mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB);
     219           0 :         mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB);
     220             :     }
     221             : 
     222             : #ifdef DEBUG
     223           0 :     mInInternalMode_DrawFB = false;
     224           0 :     mInInternalMode_ReadFB = false;
     225             : #endif
     226           0 : }
     227             : 
     228             : void
     229           0 : GLScreenBuffer::BindDrawFB(GLuint fb)
     230             : {
     231           0 :     MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer));
     232             : 
     233           0 :     GLuint drawFB = DrawFB();
     234           0 :     mUserDrawFB = fb;
     235           0 :     mInternalDrawFB = (fb == 0) ? drawFB : fb;
     236             : 
     237           0 :     mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB);
     238             : 
     239             : #ifdef DEBUG
     240           0 :     mInInternalMode_DrawFB = false;
     241             : #endif
     242           0 : }
     243             : 
     244             : void
     245           0 : GLScreenBuffer::BindReadFB(GLuint fb)
     246             : {
     247           0 :     MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer));
     248             : 
     249           0 :     GLuint readFB = ReadFB();
     250           0 :     mUserReadFB = fb;
     251           0 :     mInternalReadFB = (fb == 0) ? readFB : fb;
     252             : 
     253           0 :     mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB);
     254             : 
     255             : #ifdef DEBUG
     256           0 :     mInInternalMode_ReadFB = false;
     257             : #endif
     258           0 : }
     259             : 
     260             : void
     261           0 : GLScreenBuffer::BindFB_Internal(GLuint fb)
     262             : {
     263           0 :     mInternalDrawFB = mUserDrawFB = fb;
     264           0 :     mInternalReadFB = mUserReadFB = fb;
     265           0 :     mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB);
     266             : 
     267             : #ifdef DEBUG
     268           0 :     mInInternalMode_DrawFB = true;
     269           0 :     mInInternalMode_ReadFB = true;
     270             : #endif
     271           0 : }
     272             : 
     273             : void
     274           0 : GLScreenBuffer::BindDrawFB_Internal(GLuint fb)
     275             : {
     276           0 :     MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer));
     277             : 
     278           0 :     mInternalDrawFB = mUserDrawFB = fb;
     279           0 :     mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB);
     280             : 
     281             : #ifdef DEBUG
     282           0 :     mInInternalMode_DrawFB = true;
     283             : #endif
     284           0 : }
     285             : 
     286             : void
     287           0 : GLScreenBuffer::BindReadFB_Internal(GLuint fb)
     288             : {
     289           0 :     MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer));
     290             : 
     291           0 :     mInternalReadFB = mUserReadFB = fb;
     292           0 :     mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB);
     293             : 
     294             : #ifdef DEBUG
     295           0 :     mInInternalMode_ReadFB = true;
     296             : #endif
     297           0 : }
     298             : 
     299             : 
     300             : GLuint
     301           0 : GLScreenBuffer::GetDrawFB() const
     302             : {
     303             : #ifdef DEBUG
     304           0 :     MOZ_ASSERT(mGL->IsCurrent());
     305           0 :     MOZ_ASSERT(!mInInternalMode_DrawFB);
     306             : 
     307             :     // Don't need a branch here, because:
     308             :     // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6
     309             :     // We use raw_ here because this is debug code and we need to see what
     310             :     // the driver thinks.
     311           0 :     GLuint actual = 0;
     312           0 :     mGL->raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual);
     313             : 
     314           0 :     GLuint predicted = mInternalDrawFB;
     315           0 :     if (predicted != actual) {
     316             :         printf_stderr("Misprediction: Bound draw FB predicted: %d. Was: %d.\n",
     317           0 :                       predicted, actual);
     318           0 :         MOZ_ASSERT(false, "Draw FB binding misprediction!");
     319             :     }
     320             : #endif
     321             : 
     322           0 :     return mUserDrawFB;
     323             : }
     324             : 
     325             : GLuint
     326           0 : GLScreenBuffer::GetReadFB() const
     327             : {
     328             : #ifdef DEBUG
     329           0 :     MOZ_ASSERT(mGL->IsCurrent());
     330           0 :     MOZ_ASSERT(!mInInternalMode_ReadFB);
     331             : 
     332             :     // We use raw_ here because this is debug code and we need to see what
     333             :     // the driver thinks.
     334           0 :     GLuint actual = 0;
     335           0 :     if (mGL->IsSupported(GLFeature::split_framebuffer))
     336           0 :         mGL->raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual);
     337             :     else
     338           0 :         mGL->raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)&actual);
     339             : 
     340           0 :     GLuint predicted = mInternalReadFB;
     341           0 :     if (predicted != actual) {
     342             :         printf_stderr("Misprediction: Bound read FB predicted: %d. Was: %d.\n",
     343           0 :                       predicted, actual);
     344           0 :         MOZ_ASSERT(false, "Read FB binding misprediction!");
     345             :     }
     346             : #endif
     347             : 
     348           0 :     return mUserReadFB;
     349             : }
     350             : 
     351             : GLuint
     352           0 : GLScreenBuffer::GetFB() const
     353             : {
     354           0 :     MOZ_ASSERT(GetDrawFB() == GetReadFB());
     355           0 :     return GetDrawFB();
     356             : }
     357             : 
     358             : 
     359             : void
     360           0 : GLScreenBuffer::DeletingFB(GLuint fb)
     361             : {
     362           0 :     if (fb == mInternalDrawFB) {
     363           0 :         mInternalDrawFB = 0;
     364           0 :         mUserDrawFB = 0;
     365             :     }
     366           0 :     if (fb == mInternalReadFB) {
     367           0 :         mInternalReadFB = 0;
     368           0 :         mUserReadFB = 0;
     369             :     }
     370           0 : }
     371             : 
     372             : 
     373             : void
     374           0 : GLScreenBuffer::AfterDrawCall()
     375             : {
     376           0 :     if (mUserDrawFB != 0)
     377           0 :         return;
     378             : 
     379           0 :     RequireBlit();
     380             : }
     381             : 
     382             : void
     383           0 : GLScreenBuffer::BeforeReadCall()
     384             : {
     385           0 :     if (mUserReadFB != 0)
     386           0 :         return;
     387             : 
     388           0 :     AssureBlitted();
     389             : }
     390             : 
     391             : bool
     392           0 : GLScreenBuffer::CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x,
     393             :                                GLint y, GLsizei width, GLsizei height, GLint border)
     394             : {
     395             :     SharedSurface* surf;
     396           0 :     if (GetReadFB() == 0) {
     397           0 :         surf = SharedSurf();
     398             :     } else {
     399           0 :         surf = mGL->mFBOMapping[GetReadFB()];
     400             :     }
     401           0 :     if (surf) {
     402           0 :         return surf->CopyTexImage2D(target, level, internalformat,  x, y, width, height, border);
     403             :     }
     404             : 
     405           0 :     return false;
     406             : }
     407             : 
     408             : bool
     409           0 : GLScreenBuffer::ReadPixels(GLint x, GLint y,
     410             :                            GLsizei width, GLsizei height,
     411             :                            GLenum format, GLenum type,
     412             :                            GLvoid* pixels)
     413             : {
     414             :     // If the currently bound framebuffer is backed by a SharedSurface
     415             :     // then it might want to override how we read pixel data from it.
     416             :     // This is normally only the default framebuffer, but we can also
     417             :     // have SharedSurfaces bound to other framebuffers when doing
     418             :     // readback for BasicLayers.
     419             :     SharedSurface* surf;
     420           0 :     if (GetReadFB() == 0) {
     421           0 :         surf = SharedSurf();
     422             :     } else {
     423           0 :         surf = mGL->mFBOMapping[GetReadFB()];
     424             :     }
     425           0 :     if (surf) {
     426           0 :         return surf->ReadPixels(x, y, width, height, format, type, pixels);
     427             :     }
     428             : 
     429           0 :     return false;
     430             : }
     431             : 
     432             : void
     433           0 : GLScreenBuffer::RequireBlit()
     434             : {
     435           0 :     mNeedsBlit = true;
     436           0 : }
     437             : 
     438             : void
     439           0 : GLScreenBuffer::AssureBlitted()
     440             : {
     441           0 :     if (!mNeedsBlit)
     442           0 :         return;
     443             : 
     444           0 :     if (mDraw) {
     445           0 :         GLuint drawFB = DrawFB();
     446           0 :         GLuint readFB = ReadFB();
     447             : 
     448           0 :         MOZ_ASSERT(drawFB != 0);
     449           0 :         MOZ_ASSERT(drawFB != readFB);
     450           0 :         MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer));
     451           0 :         MOZ_ASSERT(mDraw->mSize == mRead->Size());
     452             : 
     453           0 :         ScopedBindFramebuffer boundFB(mGL);
     454           0 :         ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false);
     455             : 
     456           0 :         BindReadFB_Internal(drawFB);
     457           0 :         BindDrawFB_Internal(readFB);
     458             : 
     459           0 :         if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
     460           0 :             const gfx::IntSize&  srcSize = mDraw->mSize;
     461           0 :             const gfx::IntSize& destSize = mRead->Size();
     462             : 
     463           0 :             mGL->raw_fBlitFramebuffer(0, 0,  srcSize.width,  srcSize.height,
     464           0 :                                       0, 0, destSize.width, destSize.height,
     465             :                                       LOCAL_GL_COLOR_BUFFER_BIT,
     466           0 :                                       LOCAL_GL_NEAREST);
     467           0 :         } else if (mGL->IsExtensionSupported(GLContext::APPLE_framebuffer_multisample)) {
     468           0 :             mGL->fResolveMultisampleFramebufferAPPLE();
     469             :         } else {
     470           0 :             MOZ_CRASH("GFX: No available blit methods.");
     471             :         }
     472             :         // Done!
     473             :     }
     474             : 
     475           0 :     mNeedsBlit = false;
     476             : }
     477             : 
     478             : void
     479           0 : GLScreenBuffer::Morph(UniquePtr<SurfaceFactory> newFactory)
     480             : {
     481           0 :     MOZ_RELEASE_ASSERT(newFactory, "newFactory must not be null");
     482           0 :     mFactory = Move(newFactory);
     483           0 : }
     484             : 
     485             : bool
     486           0 : GLScreenBuffer::Attach(SharedSurface* surf, const gfx::IntSize& size)
     487             : {
     488           0 :     ScopedBindFramebuffer autoFB(mGL);
     489             : 
     490           0 :     const bool readNeedsUnlock = (mRead && SharedSurf());
     491           0 :     if (readNeedsUnlock) {
     492           0 :         SharedSurf()->UnlockProd();
     493             :     }
     494             : 
     495           0 :     surf->LockProd();
     496             : 
     497           0 :     if (mRead &&
     498           0 :         surf->mAttachType == SharedSurf()->mAttachType &&
     499           0 :         size == Size())
     500             :     {
     501             :         // Same size, same type, ready for reuse!
     502           0 :         mRead->Attach(surf);
     503             :     } else {
     504             :         // Else something changed, so resize:
     505           0 :         UniquePtr<DrawBuffer> draw;
     506           0 :         bool drawOk = true;
     507             : 
     508             :         /* Don't change out the draw buffer unless we resize. In the
     509             :          * preserveDrawingBuffer:true case, prior contents of the buffer must
     510             :          * be retained. If we're using a draw buffer, it's an MSAA buffer, so
     511             :          * even if we copy the previous frame into the (single-sampled) read
     512             :          * buffer, if we need to re-resolve from draw to read (as triggered by
     513             :          * drawing), we'll need the old MSAA content to still be in the draw
     514             :          * buffer.
     515             :          */
     516           0 :         if (!mDraw || size != Size())
     517           0 :             drawOk = CreateDraw(size, &draw);  // Can be null.
     518             : 
     519           0 :         UniquePtr<ReadBuffer> read = CreateRead(surf);
     520           0 :         bool readOk = !!read;
     521             : 
     522           0 :         if (!drawOk || !readOk) {
     523           0 :             surf->UnlockProd();
     524           0 :             if (readNeedsUnlock) {
     525           0 :                 SharedSurf()->LockProd();
     526             :             }
     527           0 :             return false;
     528             :         }
     529             : 
     530           0 :         if (draw)
     531           0 :             mDraw = Move(draw);
     532             : 
     533           0 :         mRead = Move(read);
     534             :     }
     535             : 
     536             :     // Check that we're all set up.
     537           0 :     MOZ_ASSERT(SharedSurf() == surf);
     538             : 
     539             :     // Update the ReadBuffer mode.
     540           0 :     if (mGL->IsSupported(gl::GLFeature::read_buffer)) {
     541           0 :         BindFB(0);
     542           0 :         mRead->SetReadBuffer(mUserReadBufferMode);
     543             :     }
     544             : 
     545             :     // Update the DrawBuffer mode.
     546           0 :     if (mGL->IsSupported(gl::GLFeature::draw_buffers)) {
     547           0 :         BindFB(0);
     548           0 :         SetDrawBuffer(mUserDrawBufferMode);
     549             :     }
     550             : 
     551           0 :     RequireBlit();
     552             : 
     553           0 :     return true;
     554             : }
     555             : 
     556             : bool
     557           0 : GLScreenBuffer::Swap(const gfx::IntSize& size)
     558             : {
     559           0 :     RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size);
     560           0 :     if (!newBack)
     561           0 :         return false;
     562             : 
     563             :     // In the case of DXGL interop, the new surface needs to be acquired before
     564             :     // it is attached so that the interop surface is locked, which populates
     565             :     // the GL renderbuffer. This results in the renderbuffer being ready and
     566             :     // attachment to framebuffer succeeds in Attach() call.
     567           0 :     newBack->Surf()->ProducerAcquire();
     568             : 
     569           0 :     if (!Attach(newBack->Surf(), size)) {
     570           0 :         newBack->Surf()->ProducerRelease();
     571           0 :         return false;
     572             :     }
     573             :     // Attach was successful.
     574             : 
     575           0 :     mFront = mBack;
     576           0 :     mBack = newBack;
     577             : 
     578           0 :     if (ShouldPreserveBuffer() &&
     579           0 :         mFront &&
     580           0 :         mBack &&
     581           0 :         !mDraw)
     582             :     {
     583           0 :         auto src  = mFront->Surf();
     584           0 :         auto dest = mBack->Surf();
     585             : 
     586             :         //uint32_t srcPixel = ReadPixel(src);
     587             :         //uint32_t destPixel = ReadPixel(dest);
     588             :         //printf_stderr("Before: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
     589             : #ifdef DEBUG
     590           0 :         GLContext::LocalErrorScope errorScope(*mGL);
     591             : #endif
     592             : 
     593           0 :         SharedSurface::ProdCopy(src, dest, mFactory.get());
     594             : 
     595             : #ifdef DEBUG
     596           0 :         MOZ_ASSERT(!errorScope.GetError());
     597             : #endif
     598             : 
     599             :         //srcPixel = ReadPixel(src);
     600             :         //destPixel = ReadPixel(dest);
     601             :         //printf_stderr("After: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel);
     602             :     }
     603             : 
     604             :     // XXX: We would prefer to fence earlier on platforms that don't need
     605             :     // the full ProducerAcquire/ProducerRelease semantics, so that the fence
     606             :     // doesn't include the copy operation. Unfortunately, the current API
     607             :     // doesn't expose a good way to do that.
     608           0 :     if (mFront) {
     609           0 :         mFront->Surf()->ProducerRelease();
     610             :     }
     611             : 
     612           0 :     return true;
     613             : }
     614             : 
     615             : bool
     616           0 : GLScreenBuffer::PublishFrame(const gfx::IntSize& size)
     617             : {
     618           0 :     AssureBlitted();
     619             : 
     620           0 :     bool good = Swap(size);
     621           0 :     return good;
     622             : }
     623             : 
     624             : bool
     625           0 : GLScreenBuffer::Resize(const gfx::IntSize& size)
     626             : {
     627           0 :     RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size);
     628           0 :     if (!newBack)
     629           0 :         return false;
     630             : 
     631           0 :     if (!Attach(newBack->Surf(), size))
     632           0 :         return false;
     633             : 
     634           0 :     if (mBack)
     635           0 :         mBack->Surf()->ProducerRelease();
     636             : 
     637           0 :     mBack = newBack;
     638             : 
     639           0 :     mBack->Surf()->ProducerAcquire();
     640             : 
     641           0 :     return true;
     642             : }
     643             : 
     644             : bool
     645           0 : GLScreenBuffer::CreateDraw(const gfx::IntSize& size,
     646             :                            UniquePtr<DrawBuffer>* out_buffer)
     647             : {
     648           0 :     GLContext* gl = mFactory->mGL;
     649           0 :     const GLFormats& formats = mFactory->mFormats;
     650           0 :     const SurfaceCaps& caps = mFactory->DrawCaps();
     651             : 
     652           0 :     return DrawBuffer::Create(gl, caps, formats, size, out_buffer);
     653             : }
     654             : 
     655             : UniquePtr<ReadBuffer>
     656           0 : GLScreenBuffer::CreateRead(SharedSurface* surf)
     657             : {
     658           0 :     GLContext* gl = mFactory->mGL;
     659           0 :     const GLFormats& formats = mFactory->mFormats;
     660           0 :     const SurfaceCaps& caps = mFactory->ReadCaps();
     661             : 
     662           0 :     return ReadBuffer::Create(gl, caps, formats, surf);
     663             : }
     664             : 
     665             : void
     666           0 : GLScreenBuffer::SetDrawBuffer(GLenum mode)
     667             : {
     668           0 :     MOZ_ASSERT(mGL->IsSupported(gl::GLFeature::draw_buffers));
     669           0 :     MOZ_ASSERT(GetDrawFB() == 0);
     670             : 
     671           0 :     if (!mGL->IsSupported(GLFeature::draw_buffers))
     672           0 :         return;
     673             : 
     674           0 :     mUserDrawBufferMode = mode;
     675             : 
     676           0 :     GLuint fb = mDraw ? mDraw->mFB : mRead->mFB;
     677             :     GLenum internalMode;
     678             : 
     679           0 :     switch (mode) {
     680             :     case LOCAL_GL_BACK:
     681           0 :         internalMode = (fb == 0) ? LOCAL_GL_BACK
     682             :                                  : LOCAL_GL_COLOR_ATTACHMENT0;
     683           0 :         break;
     684             : 
     685             :     case LOCAL_GL_NONE:
     686           0 :         internalMode = LOCAL_GL_NONE;
     687           0 :         break;
     688             : 
     689             :     default:
     690           0 :         MOZ_CRASH("GFX: Bad value.");
     691             :     }
     692             : 
     693           0 :     mGL->MakeCurrent();
     694           0 :     mGL->fDrawBuffers(1, &internalMode);
     695             : }
     696             : 
     697             : void
     698           0 : GLScreenBuffer::SetReadBuffer(GLenum mode)
     699             : {
     700           0 :     MOZ_ASSERT(mGL->IsSupported(gl::GLFeature::read_buffer));
     701           0 :     MOZ_ASSERT(GetReadFB() == 0);
     702             : 
     703           0 :     mUserReadBufferMode = mode;
     704           0 :     mRead->SetReadBuffer(mUserReadBufferMode);
     705           0 : }
     706             : 
     707             : bool
     708           0 : GLScreenBuffer::IsDrawFramebufferDefault() const
     709             : {
     710           0 :     if (!mDraw)
     711           0 :         return IsReadFramebufferDefault();
     712           0 :     return mDraw->mFB == 0;
     713             : }
     714             : 
     715             : bool
     716           0 : GLScreenBuffer::IsReadFramebufferDefault() const
     717             : {
     718           0 :     return SharedSurf()->mAttachType == AttachmentType::Screen;
     719             : }
     720             : 
     721             : uint32_t
     722           0 : GLScreenBuffer::DepthBits() const
     723             : {
     724           0 :     const GLFormats& formats = mFactory->mFormats;
     725             : 
     726           0 :     if (formats.depth == LOCAL_GL_DEPTH_COMPONENT16)
     727           0 :         return 16;
     728             : 
     729           0 :     return 24;
     730             : }
     731             : 
     732             : ////////////////////////////////////////////////////////////////////////
     733             : // Utils
     734             : 
     735             : static void
     736           0 : RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples,
     737             :                              GLenum aInternalFormat, const gfx::IntSize& aSize)
     738             : {
     739           0 :     if (aSamples) {
     740             :         aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER,
     741             :                                              aSamples,
     742             :                                              aInternalFormat,
     743           0 :                                              aSize.width, aSize.height);
     744             :     } else {
     745             :         aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
     746             :                                   aInternalFormat,
     747           0 :                                   aSize.width, aSize.height);
     748             :     }
     749           0 : }
     750             : 
     751             : static GLuint
     752           0 : CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples,
     753             :                    const gfx::IntSize& aSize)
     754             : {
     755           0 :     GLuint rb = 0;
     756           0 :     aGL->fGenRenderbuffers(1, &rb);
     757           0 :     ScopedBindRenderbuffer autoRB(aGL, rb);
     758             : 
     759           0 :     RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize);
     760             : 
     761           0 :     return rb;
     762             : }
     763             : 
     764             : static void
     765           0 : CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats,
     766             :                                 const gfx::IntSize& aSize, bool aMultisample,
     767             :                                 GLuint* aColorMSRB, GLuint* aDepthRB,
     768             :                                 GLuint* aStencilRB)
     769             : {
     770           0 :     GLsizei samples = aMultisample ? aFormats.samples : 0;
     771           0 :     if (aColorMSRB) {
     772           0 :         MOZ_ASSERT(aFormats.samples > 0);
     773           0 :         MOZ_ASSERT(aFormats.color_rbFormat);
     774             : 
     775           0 :         GLenum colorFormat = aFormats.color_rbFormat;
     776           0 :         if (aGL->IsANGLE()) {
     777           0 :             MOZ_ASSERT(colorFormat == LOCAL_GL_RGBA8);
     778           0 :             colorFormat = LOCAL_GL_BGRA8_EXT;
     779             :         }
     780             : 
     781           0 :         *aColorMSRB = CreateRenderbuffer(aGL, colorFormat, samples, aSize);
     782             :     }
     783             : 
     784           0 :     if (aDepthRB &&
     785           0 :         aStencilRB &&
     786           0 :         aFormats.depthStencil)
     787             :     {
     788           0 :         *aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize);
     789           0 :         *aStencilRB = *aDepthRB;
     790             :     } else {
     791           0 :         if (aDepthRB) {
     792           0 :             MOZ_ASSERT(aFormats.depth);
     793             : 
     794           0 :             *aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize);
     795             :         }
     796             : 
     797           0 :         if (aStencilRB) {
     798           0 :             MOZ_ASSERT(aFormats.stencil);
     799             : 
     800           0 :             *aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize);
     801             :         }
     802             :     }
     803           0 : }
     804             : 
     805             : ////////////////////////////////////////////////////////////////////////
     806             : // DrawBuffer
     807             : 
     808             : bool
     809           0 : DrawBuffer::Create(GLContext* const gl,
     810             :                    const SurfaceCaps& caps,
     811             :                    const GLFormats& formats,
     812             :                    const gfx::IntSize& size,
     813             :                    UniquePtr<DrawBuffer>* out_buffer)
     814             : {
     815           0 :     MOZ_ASSERT(out_buffer);
     816           0 :     *out_buffer = nullptr;
     817             : 
     818           0 :     if (!caps.color) {
     819           0 :         MOZ_ASSERT(!caps.alpha && !caps.depth && !caps.stencil);
     820             : 
     821             :         // Nothing is needed.
     822           0 :         return true;
     823             :     }
     824             : 
     825           0 :     if (caps.antialias) {
     826           0 :         if (formats.samples == 0)
     827           0 :             return false; // Can't create it.
     828             : 
     829           0 :         MOZ_ASSERT(formats.samples <= gl->MaxSamples());
     830             :     }
     831             : 
     832           0 :     GLuint colorMSRB = 0;
     833           0 :     GLuint depthRB   = 0;
     834           0 :     GLuint stencilRB = 0;
     835             : 
     836           0 :     GLuint* pColorMSRB = caps.antialias ? &colorMSRB : nullptr;
     837           0 :     GLuint* pDepthRB   = caps.depth     ? &depthRB   : nullptr;
     838           0 :     GLuint* pStencilRB = caps.stencil   ? &stencilRB : nullptr;
     839             : 
     840           0 :     if (!formats.color_rbFormat)
     841           0 :         pColorMSRB = nullptr;
     842             : 
     843           0 :     if (pDepthRB && pStencilRB) {
     844           0 :         if (!formats.depth && !formats.depthStencil)
     845           0 :             pDepthRB = nullptr;
     846             : 
     847           0 :         if (!formats.stencil && !formats.depthStencil)
     848           0 :             pStencilRB = nullptr;
     849             :     } else {
     850           0 :         if (!formats.depth)
     851           0 :             pDepthRB = nullptr;
     852             : 
     853           0 :         if (!formats.stencil)
     854           0 :             pStencilRB = nullptr;
     855             :     }
     856             : 
     857           0 :     GLContext::LocalErrorScope localError(*gl);
     858             : 
     859           0 :     CreateRenderbuffersForOffscreen(gl, formats, size, caps.antialias,
     860           0 :                                     pColorMSRB, pDepthRB, pStencilRB);
     861             : 
     862           0 :     GLuint fb = 0;
     863           0 :     gl->fGenFramebuffers(1, &fb);
     864           0 :     gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb);
     865             : 
     866           0 :     const GLsizei samples = formats.samples;
     867             :     UniquePtr<DrawBuffer> ret( new DrawBuffer(gl, size, samples, fb, colorMSRB,
     868           0 :                                               depthRB, stencilRB) );
     869             : 
     870           0 :     GLenum err = localError.GetError();
     871           0 :     MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
     872           0 :     if (err || !gl->IsFramebufferComplete(fb))
     873           0 :         return false;
     874             : 
     875           0 :     *out_buffer = Move(ret);
     876           0 :     return true;
     877             : }
     878             : 
     879           0 : DrawBuffer::~DrawBuffer()
     880             : {
     881           0 :     if (!mGL->MakeCurrent())
     882           0 :         return;
     883             : 
     884           0 :     GLuint fb = mFB;
     885             :     GLuint rbs[] = {
     886           0 :         mColorMSRB,
     887           0 :         mDepthRB,
     888           0 :         (mStencilRB != mDepthRB) ? mStencilRB : 0, // Don't double-delete DEPTH_STENCIL RBs.
     889           0 :     };
     890             : 
     891           0 :     mGL->fDeleteFramebuffers(1, &fb);
     892           0 :     mGL->fDeleteRenderbuffers(3, rbs);
     893           0 : }
     894             : 
     895             : ////////////////////////////////////////////////////////////////////////
     896             : // ReadBuffer
     897             : 
     898             : UniquePtr<ReadBuffer>
     899           0 : ReadBuffer::Create(GLContext* gl,
     900             :                    const SurfaceCaps& caps,
     901             :                    const GLFormats& formats,
     902             :                    SharedSurface* surf)
     903             : {
     904           0 :     MOZ_ASSERT(surf);
     905             : 
     906           0 :     if (surf->mAttachType == AttachmentType::Screen) {
     907             :         // Don't need anything. Our read buffer will be the 'screen'.
     908             :         return UniquePtr<ReadBuffer>( new ReadBuffer(gl, 0, 0, 0,
     909           0 :                                                      surf) );
     910             :     }
     911             : 
     912           0 :     GLuint depthRB = 0;
     913           0 :     GLuint stencilRB = 0;
     914             : 
     915           0 :     GLuint* pDepthRB   = caps.depth   ? &depthRB   : nullptr;
     916           0 :     GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr;
     917             : 
     918           0 :     GLContext::LocalErrorScope localError(*gl);
     919             : 
     920           0 :     CreateRenderbuffersForOffscreen(gl, formats, surf->mSize, caps.antialias,
     921           0 :                                     nullptr, pDepthRB, pStencilRB);
     922             : 
     923           0 :     GLuint colorTex = 0;
     924           0 :     GLuint colorRB = 0;
     925           0 :     GLenum target = 0;
     926             : 
     927           0 :     switch (surf->mAttachType) {
     928             :     case AttachmentType::GLTexture:
     929           0 :         colorTex = surf->ProdTexture();
     930           0 :         target = surf->ProdTextureTarget();
     931           0 :         break;
     932             :     case AttachmentType::GLRenderbuffer:
     933           0 :         colorRB = surf->ProdRenderbuffer();
     934           0 :         break;
     935             :     default:
     936           0 :         MOZ_CRASH("GFX: Unknown attachment type, create?");
     937             :     }
     938           0 :     MOZ_ASSERT(colorTex || colorRB);
     939             : 
     940           0 :     GLuint fb = 0;
     941           0 :     gl->fGenFramebuffers(1, &fb);
     942           0 :     gl->AttachBuffersToFB(colorTex, colorRB, depthRB, stencilRB, fb, target);
     943           0 :     gl->mFBOMapping[fb] = surf;
     944             : 
     945             :     UniquePtr<ReadBuffer> ret( new ReadBuffer(gl, fb, depthRB,
     946           0 :                                               stencilRB, surf) );
     947             : 
     948           0 :     GLenum err = localError.GetError();
     949           0 :     MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
     950           0 :     if (err)
     951           0 :         return nullptr;
     952             : 
     953           0 :     const bool needsAcquire = !surf->IsProducerAcquired();
     954           0 :     if (needsAcquire) {
     955           0 :         surf->ProducerReadAcquire();
     956             :     }
     957           0 :     const bool isComplete = gl->IsFramebufferComplete(fb);
     958           0 :     if (needsAcquire) {
     959           0 :         surf->ProducerReadRelease();
     960             :     }
     961             : 
     962           0 :     if (!isComplete)
     963           0 :         return nullptr;
     964             : 
     965           0 :     return Move(ret);
     966             : }
     967             : 
     968           0 : ReadBuffer::~ReadBuffer()
     969             : {
     970           0 :     if (!mGL->MakeCurrent())
     971           0 :         return;
     972             : 
     973           0 :     GLuint fb = mFB;
     974             :     GLuint rbs[] = {
     975           0 :         mDepthRB,
     976           0 :         (mStencilRB != mDepthRB) ? mStencilRB : 0, // Don't double-delete DEPTH_STENCIL RBs.
     977           0 :     };
     978             : 
     979           0 :     mGL->fDeleteFramebuffers(1, &fb);
     980           0 :     mGL->fDeleteRenderbuffers(2, rbs);
     981             : 
     982           0 :     mGL->mFBOMapping.erase(mFB);
     983           0 : }
     984             : 
     985             : void
     986           0 : ReadBuffer::Attach(SharedSurface* surf)
     987             : {
     988           0 :     MOZ_ASSERT(surf && mSurf);
     989           0 :     MOZ_ASSERT(surf->mAttachType == mSurf->mAttachType);
     990           0 :     MOZ_ASSERT(surf->mSize == mSurf->mSize);
     991             : 
     992             :     // Nothing else is needed for AttachType Screen.
     993           0 :     if (surf->mAttachType != AttachmentType::Screen) {
     994           0 :         GLuint colorTex = 0;
     995           0 :         GLuint colorRB = 0;
     996           0 :         GLenum target = 0;
     997             : 
     998           0 :         switch (surf->mAttachType) {
     999             :         case AttachmentType::GLTexture:
    1000           0 :             colorTex = surf->ProdTexture();
    1001           0 :             target = surf->ProdTextureTarget();
    1002           0 :             break;
    1003             :         case AttachmentType::GLRenderbuffer:
    1004           0 :             colorRB = surf->ProdRenderbuffer();
    1005           0 :             break;
    1006             :         default:
    1007           0 :             MOZ_CRASH("GFX: Unknown attachment type, attach?");
    1008             :         }
    1009             : 
    1010           0 :         mGL->AttachBuffersToFB(colorTex, colorRB, 0, 0, mFB, target);
    1011           0 :         mGL->mFBOMapping[mFB] = surf;
    1012           0 :         MOZ_ASSERT(mGL->IsFramebufferComplete(mFB));
    1013             :     }
    1014             : 
    1015           0 :     mSurf = surf;
    1016           0 : }
    1017             : 
    1018             : const gfx::IntSize&
    1019           0 : ReadBuffer::Size() const
    1020             : {
    1021           0 :     return mSurf->mSize;
    1022             : }
    1023             : 
    1024             : void
    1025           0 : ReadBuffer::SetReadBuffer(GLenum userMode) const
    1026             : {
    1027           0 :     if (!mGL->IsSupported(GLFeature::read_buffer))
    1028           0 :         return;
    1029             : 
    1030             :     GLenum internalMode;
    1031             : 
    1032           0 :     switch (userMode) {
    1033             :     case LOCAL_GL_BACK:
    1034             :     case LOCAL_GL_FRONT:
    1035           0 :         internalMode = (mFB == 0) ? userMode
    1036             :                                   : LOCAL_GL_COLOR_ATTACHMENT0;
    1037           0 :         break;
    1038             : 
    1039             :     case LOCAL_GL_NONE:
    1040           0 :         internalMode = LOCAL_GL_NONE;
    1041           0 :         break;
    1042             : 
    1043             :     default:
    1044           0 :         MOZ_CRASH("GFX: Bad value.");
    1045             :     }
    1046             : 
    1047           0 :     mGL->MakeCurrent();
    1048           0 :     mGL->fReadBuffer(internalMode);
    1049             : }
    1050             : 
    1051             : } /* namespace gl */
    1052             : } /* namespace mozilla */

Generated by: LCOV version 1.13