LCOV - code coverage report
Current view: top level - gfx/gl - SharedSurface.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 301 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 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 "SharedSurface.h"
       7             : 
       8             : #include "../2d/2D.h"
       9             : #include "GLBlitHelper.h"
      10             : #include "GLContext.h"
      11             : #include "GLReadTexImageHelper.h"
      12             : #include "GLScreenBuffer.h"
      13             : #include "nsThreadUtils.h"
      14             : #include "ScopedGLHelpers.h"
      15             : #include "SharedSurfaceGL.h"
      16             : #include "mozilla/layers/CompositorTypes.h"
      17             : #include "mozilla/layers/TextureClientSharedSurface.h"
      18             : #include "mozilla/layers/TextureForwarder.h"
      19             : #include "mozilla/Unused.h"
      20             : #include "VRManagerChild.h"
      21             : 
      22             : namespace mozilla {
      23             : namespace gl {
      24             : 
      25             : /*static*/ void
      26           0 : SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest,
      27             :                         SurfaceFactory* factory)
      28             : {
      29           0 :     GLContext* gl = src->mGL;
      30             : 
      31             :     // If `src` begins locked, it must end locked, though we may
      32             :     // temporarily unlock it if we need to.
      33           0 :     MOZ_ASSERT((src == gl->GetLockedSurface()) == src->IsLocked());
      34             : 
      35           0 :     gl->MakeCurrent();
      36             : 
      37           0 :     if (src->mAttachType  == AttachmentType::Screen &&
      38           0 :         dest->mAttachType == AttachmentType::Screen)
      39             :     {
      40             :         // Here, we actually need to blit through a temp surface, so let's make one.
      41           0 :         UniquePtr<SharedSurface_Basic> tempSurf;
      42           0 :         tempSurf = SharedSurface_Basic::Create(gl, factory->mFormats, src->mSize,
      43           0 :                                                factory->mCaps.alpha);
      44             : 
      45           0 :         ProdCopy(src, tempSurf.get(), factory);
      46           0 :         ProdCopy(tempSurf.get(), dest, factory);
      47           0 :         return;
      48             :     }
      49             : 
      50           0 :     if (src->mAttachType == AttachmentType::Screen) {
      51           0 :         SharedSurface* origLocked = gl->GetLockedSurface();
      52           0 :         bool srcNeedsUnlock = false;
      53           0 :         bool origNeedsRelock = false;
      54           0 :         if (origLocked != src) {
      55           0 :             if (origLocked) {
      56           0 :                 origLocked->UnlockProd();
      57           0 :                 origNeedsRelock = true;
      58             :             }
      59             : 
      60           0 :             src->LockProd();
      61           0 :             srcNeedsUnlock = true;
      62             :         }
      63             : 
      64           0 :         if (dest->mAttachType == AttachmentType::GLTexture) {
      65           0 :             GLuint destTex = dest->ProdTexture();
      66           0 :             GLenum destTarget = dest->ProdTextureTarget();
      67             : 
      68           0 :             gl->BlitHelper()->BlitFramebufferToTexture(0, destTex,
      69             :                                                        src->mSize,
      70             :                                                        dest->mSize,
      71             :                                                        destTarget,
      72           0 :                                                        true);
      73           0 :         } else if (dest->mAttachType == AttachmentType::GLRenderbuffer) {
      74           0 :             GLuint destRB = dest->ProdRenderbuffer();
      75           0 :             ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
      76             : 
      77           0 :             gl->BlitHelper()->BlitFramebufferToFramebuffer(0,
      78             :                                                            destWrapper.FB(),
      79             :                                                            src->mSize,
      80             :                                                            dest->mSize,
      81           0 :                                                            true);
      82             :         } else {
      83           0 :             MOZ_CRASH("GFX: Unhandled dest->mAttachType 1.");
      84             :         }
      85             : 
      86           0 :         if (srcNeedsUnlock)
      87           0 :             src->UnlockProd();
      88             : 
      89           0 :         if (origNeedsRelock)
      90           0 :             origLocked->LockProd();
      91             : 
      92           0 :         return;
      93             :     }
      94             : 
      95           0 :     if (dest->mAttachType == AttachmentType::Screen) {
      96           0 :         SharedSurface* origLocked = gl->GetLockedSurface();
      97           0 :         bool destNeedsUnlock = false;
      98           0 :         bool origNeedsRelock = false;
      99           0 :         if (origLocked != dest) {
     100           0 :             if (origLocked) {
     101           0 :                 origLocked->UnlockProd();
     102           0 :                 origNeedsRelock = true;
     103             :             }
     104             : 
     105           0 :             dest->LockProd();
     106           0 :             destNeedsUnlock = true;
     107             :         }
     108             : 
     109           0 :         if (src->mAttachType == AttachmentType::GLTexture) {
     110           0 :             GLuint srcTex = src->ProdTexture();
     111           0 :             GLenum srcTarget = src->ProdTextureTarget();
     112             : 
     113           0 :             gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0,
     114             :                                                        src->mSize,
     115             :                                                        dest->mSize,
     116             :                                                        srcTarget,
     117           0 :                                                        !!gl->Screen());
     118           0 :         } else if (src->mAttachType == AttachmentType::GLRenderbuffer) {
     119           0 :             GLuint srcRB = src->ProdRenderbuffer();
     120           0 :             ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
     121             : 
     122           0 :             gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(),
     123             :                                                            0,
     124             :                                                            src->mSize,
     125             :                                                            dest->mSize,
     126           0 :                                                            true);
     127             :         } else {
     128           0 :             MOZ_CRASH("GFX: Unhandled src->mAttachType 2.");
     129             :         }
     130             : 
     131           0 :         if (destNeedsUnlock)
     132           0 :             dest->UnlockProd();
     133             : 
     134           0 :         if (origNeedsRelock)
     135           0 :             origLocked->LockProd();
     136             : 
     137           0 :         return;
     138             :     }
     139             : 
     140             :     // Alright, done with cases involving Screen types.
     141             :     // Only {src,dest}x{texture,renderbuffer} left.
     142             : 
     143           0 :     if (src->mAttachType == AttachmentType::GLTexture) {
     144           0 :         GLuint srcTex = src->ProdTexture();
     145           0 :         GLenum srcTarget = src->ProdTextureTarget();
     146             : 
     147           0 :         if (dest->mAttachType == AttachmentType::GLTexture) {
     148           0 :             GLuint destTex = dest->ProdTexture();
     149           0 :             GLenum destTarget = dest->ProdTextureTarget();
     150             : 
     151           0 :             gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex,
     152             :                                                    src->mSize, dest->mSize,
     153           0 :                                                    srcTarget, destTarget);
     154             : 
     155           0 :             return;
     156             :         }
     157             : 
     158           0 :         if (dest->mAttachType == AttachmentType::GLRenderbuffer) {
     159           0 :             GLuint destRB = dest->ProdRenderbuffer();
     160           0 :             ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
     161             : 
     162           0 :             gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(),
     163           0 :                                                        src->mSize, dest->mSize, srcTarget);
     164             : 
     165           0 :             return;
     166             :         }
     167             : 
     168           0 :         MOZ_CRASH("GFX: Unhandled dest->mAttachType 3.");
     169             :     }
     170             : 
     171           0 :     if (src->mAttachType == AttachmentType::GLRenderbuffer) {
     172           0 :         GLuint srcRB = src->ProdRenderbuffer();
     173           0 :         ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
     174             : 
     175           0 :         if (dest->mAttachType == AttachmentType::GLTexture) {
     176           0 :             GLuint destTex = dest->ProdTexture();
     177           0 :             GLenum destTarget = dest->ProdTextureTarget();
     178             : 
     179           0 :             gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex,
     180           0 :                                                        src->mSize, dest->mSize, destTarget);
     181             : 
     182           0 :             return;
     183             :         }
     184             : 
     185           0 :         if (dest->mAttachType == AttachmentType::GLRenderbuffer) {
     186           0 :             GLuint destRB = dest->ProdRenderbuffer();
     187           0 :             ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
     188             : 
     189           0 :             gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(),
     190           0 :                                                            src->mSize, dest->mSize);
     191             : 
     192           0 :             return;
     193             :         }
     194             : 
     195           0 :         MOZ_CRASH("GFX: Unhandled dest->mAttachType 4.");
     196             :     }
     197             : 
     198           0 :     MOZ_CRASH("GFX: Unhandled src->mAttachType 5.");
     199             : }
     200             : 
     201             : ////////////////////////////////////////////////////////////////////////
     202             : // SharedSurface
     203             : 
     204             : 
     205           0 : SharedSurface::SharedSurface(SharedSurfaceType type,
     206             :                              AttachmentType attachType,
     207             :                              GLContext* gl,
     208             :                              const gfx::IntSize& size,
     209             :                              bool hasAlpha,
     210           0 :                              bool canRecycle)
     211             :     : mType(type)
     212             :     , mAttachType(attachType)
     213             :     , mGL(gl)
     214             :     , mSize(size)
     215             :     , mHasAlpha(hasAlpha)
     216             :     , mCanRecycle(canRecycle)
     217             :     , mIsLocked(false)
     218           0 :     , mIsProducerAcquired(false)
     219           0 : { }
     220             : 
     221             : layers::TextureFlags
     222           0 : SharedSurface::GetTextureFlags() const
     223             : {
     224           0 :     return layers::TextureFlags::NO_FLAGS;
     225             : }
     226             : 
     227             : void
     228           0 : SharedSurface::LockProd()
     229             : {
     230           0 :     MOZ_ASSERT(!mIsLocked);
     231             : 
     232           0 :     LockProdImpl();
     233             : 
     234           0 :     mGL->LockSurface(this);
     235           0 :     mIsLocked = true;
     236           0 : }
     237             : 
     238             : void
     239           0 : SharedSurface::UnlockProd()
     240             : {
     241           0 :     if (!mIsLocked)
     242           0 :         return;
     243             : 
     244           0 :     UnlockProdImpl();
     245             : 
     246           0 :     mGL->UnlockSurface(this);
     247           0 :     mIsLocked = false;
     248             : }
     249             : 
     250             : ////////////////////////////////////////////////////////////////////////
     251             : // SurfaceFactory
     252             : 
     253             : static void
     254           0 : ChooseBufferBits(const SurfaceCaps& caps,
     255             :                  SurfaceCaps* const out_drawCaps,
     256             :                  SurfaceCaps* const out_readCaps)
     257             : {
     258           0 :     MOZ_ASSERT(out_drawCaps);
     259           0 :     MOZ_ASSERT(out_readCaps);
     260             : 
     261           0 :     SurfaceCaps screenCaps;
     262             : 
     263           0 :     screenCaps.color = caps.color;
     264           0 :     screenCaps.alpha = caps.alpha;
     265           0 :     screenCaps.bpp16 = caps.bpp16;
     266             : 
     267           0 :     screenCaps.depth = caps.depth;
     268           0 :     screenCaps.stencil = caps.stencil;
     269             : 
     270           0 :     screenCaps.antialias = caps.antialias;
     271           0 :     screenCaps.preserve = caps.preserve;
     272             : 
     273           0 :     if (caps.antialias) {
     274           0 :         *out_drawCaps = screenCaps;
     275           0 :         out_readCaps->Clear();
     276             : 
     277             :         // Color caps need to be duplicated in readCaps.
     278           0 :         out_readCaps->color = caps.color;
     279           0 :         out_readCaps->alpha = caps.alpha;
     280           0 :         out_readCaps->bpp16 = caps.bpp16;
     281             :     } else {
     282           0 :         out_drawCaps->Clear();
     283           0 :         *out_readCaps = screenCaps;
     284             :     }
     285           0 : }
     286             : 
     287           0 : SurfaceFactory::SurfaceFactory(SharedSurfaceType type, GLContext* gl,
     288             :                                const SurfaceCaps& caps,
     289             :                                const RefPtr<layers::LayersIPCChannel>& allocator,
     290           0 :                                const layers::TextureFlags& flags)
     291             :     : mType(type)
     292             :     , mGL(gl)
     293             :     , mCaps(caps)
     294             :     , mAllocator(allocator)
     295           0 :     , mFlags(flags)
     296             :     , mFormats(gl->ChooseGLFormats(caps))
     297           0 :     , mMutex("SurfaceFactor::mMutex")
     298             : {
     299           0 :     ChooseBufferBits(mCaps, &mDrawCaps, &mReadCaps);
     300           0 : }
     301             : 
     302           0 : SurfaceFactory::~SurfaceFactory()
     303             : {
     304           0 :     while (!mRecycleTotalPool.empty()) {
     305           0 :         RefPtr<layers::SharedSurfaceTextureClient> tex = *mRecycleTotalPool.begin();
     306           0 :         StopRecycling(tex);
     307           0 :         tex->CancelWaitForRecycle();
     308             :     }
     309             : 
     310           0 :     MOZ_RELEASE_ASSERT(mRecycleTotalPool.empty(),"GFX: Surface recycle pool not empty.");
     311             : 
     312             :     // If we mRecycleFreePool.clear() before StopRecycling(), we may try to recycle it,
     313             :     // fail, call StopRecycling(), then return here and call it again.
     314           0 :     mRecycleFreePool.clear();
     315           0 : }
     316             : 
     317             : already_AddRefed<layers::SharedSurfaceTextureClient>
     318           0 : SurfaceFactory::NewTexClient(const gfx::IntSize& size, const layers::LayersIPCChannel* aLayersChannel)
     319             : {
     320           0 :     while (!mRecycleFreePool.empty()) {
     321           0 :         RefPtr<layers::SharedSurfaceTextureClient> cur = mRecycleFreePool.front();
     322           0 :         mRecycleFreePool.pop();
     323             : 
     324           0 :         if (cur->Surf()->mSize == size){
     325             :             // In the general case, textureClients transit textures through
     326             :             // CompositorForwarder. But, the textureClient created by VRManagerChild
     327             :             // has a different LayerIPCChannel, PVRManager. Therefore, textureClients
     328             :             // need to be separated into different cases.
     329           0 :             if ((aLayersChannel && aLayersChannel == cur->GetAllocator()) ||
     330           0 :                 (cur->GetAllocator() != gfx::VRManagerChild::Get())) {
     331           0 :                 cur->Surf()->WaitForBufferOwnership();
     332           0 :                 return cur.forget();
     333             :             }
     334             :         }
     335             : 
     336           0 :         StopRecycling(cur);
     337             :     }
     338             : 
     339           0 :     UniquePtr<SharedSurface> surf = Move(CreateShared(size));
     340           0 :     if (!surf)
     341           0 :         return nullptr;
     342             : 
     343           0 :     RefPtr<layers::SharedSurfaceTextureClient> ret;
     344           0 :     ret = layers::SharedSurfaceTextureClient::Create(Move(surf), this, mAllocator, mFlags);
     345             : 
     346           0 :     StartRecycling(ret);
     347             : 
     348           0 :     return ret.forget();
     349             : }
     350             : 
     351             : void
     352           0 : SurfaceFactory::StartRecycling(layers::SharedSurfaceTextureClient* tc)
     353             : {
     354           0 :     tc->SetRecycleCallback(&SurfaceFactory::RecycleCallback, static_cast<void*>(this));
     355             : 
     356           0 :     bool didInsert = mRecycleTotalPool.insert(tc);
     357           0 :     MOZ_RELEASE_ASSERT(didInsert, "GFX: Shared surface texture client was not inserted to recycle.");
     358             :     mozilla::Unused << didInsert;
     359           0 : }
     360             : 
     361             : void
     362           0 : SurfaceFactory::StopRecycling(layers::SharedSurfaceTextureClient* tc)
     363             : {
     364           0 :     MutexAutoLock autoLock(mMutex);
     365             :     // Must clear before releasing ref.
     366           0 :     tc->ClearRecycleCallback();
     367             : 
     368           0 :     bool didErase = mRecycleTotalPool.erase(tc);
     369           0 :     MOZ_RELEASE_ASSERT(didErase, "GFX: Shared texture surface client was not erased.");
     370             :     mozilla::Unused << didErase;
     371           0 : }
     372             : 
     373             : /*static*/ void
     374           0 : SurfaceFactory::RecycleCallback(layers::TextureClient* rawTC, void* rawFactory)
     375             : {
     376           0 :     RefPtr<layers::SharedSurfaceTextureClient> tc;
     377           0 :     tc = static_cast<layers::SharedSurfaceTextureClient*>(rawTC);
     378           0 :     SurfaceFactory* factory = static_cast<SurfaceFactory*>(rawFactory);
     379             : 
     380           0 :     if (tc->Surf()->mCanRecycle) {
     381           0 :         if (factory->Recycle(tc))
     382           0 :             return;
     383             :     }
     384             : 
     385             :     // Did not recover the tex client. End the (re)cycle!
     386           0 :     factory->StopRecycling(tc);
     387             : }
     388             : 
     389             : bool
     390           0 : SurfaceFactory::Recycle(layers::SharedSurfaceTextureClient* texClient)
     391             : {
     392           0 :     MOZ_ASSERT(texClient);
     393           0 :     MutexAutoLock autoLock(mMutex);
     394             : 
     395           0 :     if (mRecycleFreePool.size() >= 2) {
     396           0 :         return false;
     397             :     }
     398             : 
     399           0 :     RefPtr<layers::SharedSurfaceTextureClient> texClientRef = texClient;
     400           0 :     mRecycleFreePool.push(texClientRef);
     401           0 :     return true;
     402             : }
     403             : 
     404             : ////////////////////////////////////////////////////////////////////////////////
     405             : // ScopedReadbackFB
     406             : 
     407           0 : ScopedReadbackFB::ScopedReadbackFB(SharedSurface* src)
     408             :     : mGL(src->mGL)
     409           0 :     , mAutoFB(mGL)
     410             :     , mTempFB(0)
     411             :     , mTempTex(0)
     412             :     , mSurfToUnlock(nullptr)
     413           0 :     , mSurfToLock(nullptr)
     414             : {
     415           0 :     switch (src->mAttachType) {
     416             :     case AttachmentType::GLRenderbuffer:
     417             :         {
     418           0 :             mGL->fGenFramebuffers(1, &mTempFB);
     419           0 :             mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB);
     420             : 
     421           0 :             GLuint rb = src->ProdRenderbuffer();
     422           0 :             mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
     423             :                                           LOCAL_GL_COLOR_ATTACHMENT0,
     424           0 :                                           LOCAL_GL_RENDERBUFFER, rb);
     425           0 :             break;
     426             :         }
     427             :     case AttachmentType::GLTexture:
     428             :         {
     429           0 :             mGL->fGenFramebuffers(1, &mTempFB);
     430           0 :             mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB);
     431             : 
     432           0 :             GLuint tex = src->ProdTexture();
     433           0 :             GLenum texImageTarget = src->ProdTextureTarget();
     434           0 :             mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
     435             :                                        LOCAL_GL_COLOR_ATTACHMENT0,
     436           0 :                                        texImageTarget, tex, 0);
     437           0 :             break;
     438             :         }
     439             :     case AttachmentType::Screen:
     440             :         {
     441           0 :             SharedSurface* origLocked = mGL->GetLockedSurface();
     442           0 :             if (origLocked != src) {
     443           0 :                 if (origLocked) {
     444           0 :                     mSurfToLock = origLocked;
     445           0 :                     mSurfToLock->UnlockProd();
     446             :                 }
     447             : 
     448           0 :                 mSurfToUnlock = src;
     449           0 :                 mSurfToUnlock->LockProd();
     450             :             }
     451             : 
     452             :             // TODO: This should just be BindFB, but we don't have
     453             :             // the patch for this yet. (bug 1045955)
     454           0 :             MOZ_ASSERT(mGL->Screen());
     455           0 :             mGL->Screen()->BindReadFB_Internal(0);
     456           0 :             break;
     457             :         }
     458             :     default:
     459           0 :         MOZ_CRASH("GFX: Unhandled `mAttachType`.");
     460             :     }
     461             : 
     462           0 :     if (src->NeedsIndirectReads()) {
     463           0 :         mGL->fGenTextures(1, &mTempTex);
     464             : 
     465             :         {
     466           0 :             ScopedBindTexture autoTex(mGL, mTempTex);
     467             : 
     468           0 :             GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA
     469           0 :                                            : LOCAL_GL_RGB;
     470           0 :             auto width = src->mSize.width;
     471           0 :             auto height = src->mSize.height;
     472           0 :             mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width,
     473           0 :                                  height, 0);
     474             :         }
     475             : 
     476           0 :         mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
     477             :                                    LOCAL_GL_COLOR_ATTACHMENT0,
     478           0 :                                    LOCAL_GL_TEXTURE_2D, mTempTex, 0);
     479             :     }
     480           0 : }
     481             : 
     482           0 : ScopedReadbackFB::~ScopedReadbackFB()
     483             : {
     484           0 :     if (mTempFB) {
     485           0 :         mGL->fDeleteFramebuffers(1, &mTempFB);
     486             :     }
     487           0 :     if (mTempTex) {
     488           0 :         mGL->fDeleteTextures(1, &mTempTex);
     489             :     }
     490           0 :     if (mSurfToUnlock) {
     491           0 :         mSurfToUnlock->UnlockProd();
     492             :     }
     493           0 :     if (mSurfToLock) {
     494           0 :         mSurfToLock->LockProd();
     495             :     }
     496           0 : }
     497             : 
     498             : ////////////////////////////////////////////////////////////////////////////////
     499             : 
     500             : class AutoLockBits
     501             : {
     502             :     gfx::DrawTarget* mDT;
     503             :     uint8_t* mLockedBits;
     504             : 
     505             : public:
     506           0 :     explicit AutoLockBits(gfx::DrawTarget* dt)
     507           0 :         : mDT(dt)
     508           0 :         , mLockedBits(nullptr)
     509             :     {
     510           0 :         MOZ_ASSERT(mDT);
     511           0 :     }
     512             : 
     513           0 :     bool Lock(uint8_t** data, gfx::IntSize* size, int32_t* stride,
     514             :               gfx::SurfaceFormat* format)
     515             :     {
     516           0 :         if (!mDT->LockBits(data, size, stride, format))
     517           0 :             return false;
     518             : 
     519           0 :         mLockedBits = *data;
     520           0 :         return true;
     521             :     }
     522             : 
     523           0 :     ~AutoLockBits() {
     524           0 :         if (mLockedBits)
     525           0 :             mDT->ReleaseBits(mLockedBits);
     526           0 :     }
     527             : };
     528             : 
     529             : bool
     530           0 : ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst)
     531             : {
     532           0 :     AutoLockBits lock(dst);
     533             : 
     534             :     uint8_t* dstBytes;
     535           0 :     gfx::IntSize dstSize;
     536             :     int32_t dstStride;
     537             :     gfx::SurfaceFormat dstFormat;
     538           0 :     if (!lock.Lock(&dstBytes, &dstSize, &dstStride, &dstFormat))
     539           0 :         return false;
     540             : 
     541           0 :     const bool isDstRGBA = (dstFormat == gfx::SurfaceFormat::R8G8B8A8 ||
     542           0 :                             dstFormat == gfx::SurfaceFormat::R8G8B8X8);
     543           0 :     MOZ_ASSERT_IF(!isDstRGBA, dstFormat == gfx::SurfaceFormat::B8G8R8A8 ||
     544             :                               dstFormat == gfx::SurfaceFormat::B8G8R8X8);
     545             : 
     546           0 :     size_t width = src->mSize.width;
     547           0 :     size_t height = src->mSize.height;
     548           0 :     MOZ_ASSERT(width == (size_t)dstSize.width);
     549           0 :     MOZ_ASSERT(height == (size_t)dstSize.height);
     550             : 
     551             :     GLenum readGLFormat;
     552             :     GLenum readType;
     553             : 
     554             :     {
     555           0 :         ScopedReadbackFB autoReadback(src);
     556             : 
     557             : 
     558             :         // We have a source FB, now we need a format.
     559           0 :         GLenum dstGLFormat = isDstRGBA ? LOCAL_GL_BGRA : LOCAL_GL_RGBA;
     560           0 :         GLenum dstType = LOCAL_GL_UNSIGNED_BYTE;
     561             : 
     562             :         // We actually don't care if they match, since we can handle
     563             :         // any read{Format,Type} we get.
     564           0 :         GLContext* gl = src->mGL;
     565             :         GetActualReadFormats(gl, dstGLFormat, dstType, &readGLFormat,
     566           0 :                              &readType);
     567             : 
     568           0 :         MOZ_ASSERT(readGLFormat == LOCAL_GL_RGBA ||
     569             :                    readGLFormat == LOCAL_GL_BGRA);
     570           0 :         MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
     571             : 
     572             :         // ReadPixels from the current FB into lockedBits.
     573             :         {
     574           0 :             size_t alignment = 8;
     575           0 :             if (dstStride % 4 == 0)
     576           0 :                 alignment = 4;
     577             : 
     578           0 :             ScopedPackState scopedPackState(gl);
     579           0 :             if (alignment != 4) {
     580           0 :                 gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, alignment);
     581             :             }
     582             : 
     583           0 :             gl->raw_fReadPixels(0, 0, width, height, readGLFormat, readType,
     584           0 :                                 dstBytes);
     585             :         }
     586             :     }
     587             : 
     588           0 :     const bool isReadRGBA = readGLFormat == LOCAL_GL_RGBA;
     589             : 
     590           0 :     if (isReadRGBA != isDstRGBA) {
     591           0 :         for (size_t j = 0; j < height; ++j) {
     592           0 :             uint8_t* rowItr = dstBytes + j*dstStride;
     593           0 :             uint8_t* rowEnd = rowItr + 4*width;
     594           0 :             while (rowItr != rowEnd) {
     595           0 :                 Swap(rowItr[0], rowItr[2]);
     596           0 :                 rowItr += 4;
     597             :             }
     598             :         }
     599             :     }
     600             : 
     601           0 :     return true;
     602             : }
     603             : 
     604             : uint32_t
     605           0 : ReadPixel(SharedSurface* src)
     606             : {
     607           0 :     GLContext* gl = src->mGL;
     608             : 
     609             :     uint32_t pixel;
     610             : 
     611           0 :     ScopedReadbackFB a(src);
     612             :     {
     613           0 :         ScopedPackState scopedPackState(gl);
     614             : 
     615           0 :         UniquePtr<uint8_t[]> bytes(new uint8_t[4]);
     616             :         gl->raw_fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
     617           0 :                             bytes.get());
     618           0 :         memcpy(&pixel, bytes.get(), 4);
     619             :     }
     620             : 
     621           0 :     return pixel;
     622             : }
     623             : 
     624             : } // namespace gl
     625             : 
     626             : } /* namespace mozilla */

Generated by: LCOV version 1.13