From ee9a1556e58a34801c0f4fde979ea01adc5aa2bf Mon Sep 17 00:00:00 2001 From: James Willcox Date: Fri, 14 Feb 2014 15:55:58 -0600 Subject: [PATCH] Bug 939276 - Use a single GLContext for all SkiaGL canvases r=bjacob,gwright,dglastonbury --HG-- rename : gfx/gl/GLContextSkia.cpp => gfx/gl/SkiaGLGlue.cpp --- .../canvas/src/CanvasRenderingContext2D.cpp | 128 +++++++----------- content/canvas/src/CanvasRenderingContext2D.h | 5 +- gfx/2d/2D.h | 25 ++-- gfx/2d/DrawTargetSkia.cpp | 115 ++-------------- gfx/2d/DrawTargetSkia.h | 28 +--- gfx/2d/Factory.cpp | 17 +-- gfx/gl/GLContextSkia.h | 8 -- gfx/gl/GLScreenBuffer.cpp | 3 +- gfx/gl/GLScreenBuffer.h | 3 +- gfx/gl/SharedSurfaceGL.cpp | 27 +++- gfx/gl/SharedSurfaceGL.h | 10 +- gfx/gl/{GLContextSkia.cpp => SkiaGLGlue.cpp} | 19 ++- gfx/gl/SkiaGLGlue.h | 34 +++++ gfx/gl/SurfaceStream.cpp | 15 ++ gfx/gl/SurfaceStream.h | 8 +- gfx/gl/moz.build | 4 +- gfx/layers/CopyableCanvasLayer.cpp | 4 +- gfx/layers/CopyableCanvasLayer.h | 9 ++ gfx/layers/Layers.h | 11 ++ gfx/layers/client/CanvasClient.cpp | 20 ++- gfx/layers/client/ClientCanvasLayer.cpp | 39 +++++- gfx/layers/client/ClientCanvasLayer.h | 5 + gfx/layers/opengl/TextureClientOGL.cpp | 2 +- gfx/layers/opengl/TextureClientOGL.h | 3 +- gfx/thebes/gfxPlatform.cpp | 85 ++++++++---- gfx/thebes/gfxPlatform.h | 15 +- 26 files changed, 348 insertions(+), 294 deletions(-) mode change 100644 => 100755 content/canvas/src/CanvasRenderingContext2D.cpp delete mode 100644 gfx/gl/GLContextSkia.h mode change 100644 => 100755 gfx/gl/GLScreenBuffer.cpp rename gfx/gl/{GLContextSkia.cpp => SkiaGLGlue.cpp} (97%) mode change 100644 => 100755 create mode 100755 gfx/gl/SkiaGLGlue.h diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp old mode 100644 new mode 100755 index 82c8dc52c56f..eea47172856b --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -97,11 +97,13 @@ #ifdef USE_SKIA_GPU #undef free // apparently defined by some windows header, clashing with a free() // method in SkTypes.h -#include "GLContextSkia.h" +#include "SkiaGLGlue.h" +#include "SurfaceStream.h" #include "SurfaceTypes.h" -#include "nsIGfxInfo.h" #endif + using mozilla::gl::GLContext; +using mozilla::gl::SkiaGLGlue; using mozilla::gl::GLContextProvider; #ifdef XP_WIN @@ -430,28 +432,18 @@ public: } } -#ifdef USE_SKIA_GPU static void PreTransactionCallback(void* aData) { CanvasRenderingContext2DUserData* self = static_cast(aData); CanvasRenderingContext2D* context = self->mContext; - if (!context) + if (!context || !context->mStream || !context->mTarget) return; - GLContext* glContext = static_cast(context->mTarget->GetGLContext()); - if (!glContext) - return; - - if (context->mTarget) { - // Since SkiaGL default to store drawing command until flush - // We will have to flush it before present. - context->mTarget->Flush(); - } - glContext->MakeCurrent(); - glContext->PublishFrame(); + // Since SkiaGL default to store drawing command until flush + // We will have to flush it before present. + context->mTarget->Flush(); } -#endif static void DidTransactionCallback(void* aData) { @@ -542,18 +534,15 @@ DrawTarget* CanvasRenderingContext2D::sErrorTarget = nullptr; CanvasRenderingContext2D::CanvasRenderingContext2D() - : mZero(false), mOpaque(false), mResetLayer(true) + : mForceSoftware(false), mZero(false), mOpaque(false), mResetLayer(true) , mIPC(false) + , mStream(nullptr) , mIsEntireFrameInvalid(false) , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false) , mInvalidateCount(0) { sNumLivingContexts++; SetIsDOMBinding(); - -#ifdef USE_SKIA_GPU - mForceSoftware = false; -#endif } CanvasRenderingContext2D::~CanvasRenderingContext2D() @@ -568,9 +557,7 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() NS_IF_RELEASE(sErrorTarget); } -#ifdef USE_SKIA_GPU RemoveDemotableContext(this); -#endif } JSObject* @@ -629,6 +616,7 @@ CanvasRenderingContext2D::Reset() } mTarget = nullptr; + mStream = nullptr; // Since the target changes the backing texture will change, and this will // no longer be valid. @@ -750,8 +738,7 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r) void CanvasRenderingContext2D::Demote() { -#ifdef USE_SKIA_GPU - if (!IsTargetValid() || mForceSoftware || !mTarget->GetGLContext()) + if (!IsTargetValid() || mForceSoftware || !mStream) return; RemoveDemotableContext(this); @@ -759,6 +746,7 @@ void CanvasRenderingContext2D::Demote() RefPtr snapshot = mTarget->Snapshot(); RefPtr oldTarget = mTarget; mTarget = nullptr; + mStream = nullptr; mResetLayer = true; mForceSoftware = true; @@ -777,11 +765,8 @@ void CanvasRenderingContext2D::Demote() } mTarget->SetTransform(oldTarget->GetTransform()); -#endif } -#ifdef USE_SKIA_GPU - std::vector& CanvasRenderingContext2D::DemotableContexts() { @@ -792,11 +777,7 @@ CanvasRenderingContext2D::DemotableContexts() void CanvasRenderingContext2D::DemoteOldestContextIfNecessary() { -#ifdef MOZ_GFX_OPTIMIZE_MOBILE - const size_t kMaxContexts = 2; -#else - const size_t kMaxContexts = 16; -#endif + const size_t kMaxContexts = 64; std::vector& contexts = DemotableContexts(); if (contexts.size() < kMaxContexts) @@ -830,8 +811,6 @@ CheckSizeForSkiaGL(IntSize size) { return size.width >= minsize && size.height >= minsize; } -#endif - void CanvasRenderingContext2D::EnsureTarget() { @@ -857,42 +836,29 @@ CanvasRenderingContext2D::EnsureTarget() } if (layerManager) { -#ifdef USE_SKIA_GPU - if (gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas()) { - SurfaceCaps caps = SurfaceCaps::ForRGBA(); - caps.preserve = true; - -#ifdef MOZ_WIDGET_GONK - layers::ShadowLayerForwarder *forwarder = layerManager->AsShadowForwarder(); - if (forwarder) { - caps.surfaceAllocator = static_cast(forwarder); - } -#endif - + if (gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() && + !mForceSoftware && + CheckSizeForSkiaGL(size)) { DemoteOldestContextIfNecessary(); - nsRefPtr glContext; - nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); - nsString vendor; +#ifdef USE_SKIA_GPU + SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); - if (!mForceSoftware && CheckSizeForSkiaGL(size)) - { - glContext = GLContextProvider::CreateOffscreen(gfxIntSize(size.width, size.height), - caps); - } + if (glue) { + mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format); + MOZ_ASSERT(mTarget, "Failed to create SkiaGL DrawTarget"); - if (glContext) { - SkAutoTUnref i(CreateGrGLInterfaceFromGLContext(glContext)); - mTarget = Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(glContext, i, size, format); + mStream = gfx::SurfaceStream::CreateForType(SurfaceStreamType::TripleBuffer, glue->GetGLContext()); AddDemotableContext(this); - } else { + } else +#endif + { mTarget = layerManager->CreateDrawTarget(size, format); } } else -#endif - mTarget = layerManager->CreateDrawTarget(size, format); + mTarget = layerManager->CreateDrawTarget(size, format); } else { - mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format); + mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format); } } @@ -1077,12 +1043,10 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx, JS::HandleGetUserData(&g2DContextLayerUserData)); CanvasLayer::Data data; - data.mGLContext = static_cast(mTarget->GetGLContext()); +#ifdef USE_SKIA_GPU + if (mStream) { + SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); + + if (glue) { + data.mGLContext = glue->GetGLContext(); + data.mStream = mStream.get(); + } + } else +#endif + { + data.mDrawTarget = mTarget; + } + if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) { nsRefPtr ret = aOldLayer; return ret.forget(); @@ -4091,11 +4062,16 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder, CanvasLayer::Data data; #ifdef USE_SKIA_GPU - GLContext* glContext = static_cast(mTarget->GetGLContext()); - if (glContext) { - canvasLayer->SetPreTransactionCallback( - CanvasRenderingContext2DUserData::PreTransactionCallback, userData); - data.mGLContext = glContext; + if (mStream) { + SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); + + if (glue) { + canvasLayer->SetPreTransactionCallback( + CanvasRenderingContext2DUserData::PreTransactionCallback, userData); + data.mGLContext = glue->GetGLContext(); + data.mStream = mStream.get(); + data.mTexID = mTarget->GetTextureID(); + } } else #endif { diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index f39b1658acbf..31a39a47360a 100644 --- a/content/canvas/src/CanvasRenderingContext2D.h +++ b/content/canvas/src/CanvasRenderingContext2D.h @@ -31,6 +31,7 @@ class nsXULElement; namespace mozilla { namespace gfx { class SourceSurface; +class SurfaceStream; } namespace dom { @@ -593,7 +594,6 @@ protected: return CurrentState().font; } -#if USE_SKIA_GPU static std::vector& DemotableContexts(); static void DemoteOldestContextIfNecessary(); @@ -602,7 +602,6 @@ protected: // Do not use GL bool mForceSoftware; -#endif // Member vars int32_t mWidth, mHeight; @@ -629,6 +628,8 @@ protected: // sErrorTarget. mozilla::RefPtr mTarget; + RefPtr mStream; + /** * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever * Redraw is called, reset to false when Render is called. diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 501a99d7da69..10cb70e4f87c 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -962,18 +962,17 @@ public: return mPermitSubpixelAA; } - virtual GenericRefCountedBase* GetGLContext() const { - return nullptr; - } - #ifdef USE_SKIA_GPU - virtual void InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, - GrGLInterface* aGrGLInterface, - const IntSize &aSize, - SurfaceFormat aFormat) + virtual void InitWithGrContext(GrContext* aGrContext, + const IntSize &aSize, + SurfaceFormat aFormat) { MOZ_CRASH(); } + + virtual uint32_t GetTextureID() const { + return 0; + } #endif protected: @@ -1075,13 +1074,9 @@ public: #ifdef USE_SKIA_GPU static TemporaryRef - CreateDrawTargetSkiaWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, - GrGLInterface* aGrGLInterface, - const IntSize &aSize, - SurfaceFormat aFormat); - - static void - SetGlobalSkiaCacheLimits(int aCount, int aSizeInBytes); + CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, + const IntSize &aSize, + SurfaceFormat aFormat); #endif static void PurgeAllCaches(); diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 433c2f205050..bda90d7ab06f 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -77,80 +77,6 @@ public: ExtendMode mExtendMode; }; -#ifdef USE_SKIA_GPU -int DrawTargetSkia::sTextureCacheCount = 256; -int DrawTargetSkia::sTextureCacheSizeInBytes = 96*1024*1024; - -static std::vector& -GLDrawTargets() -{ - static std::vector targets; - return targets; -} - -void -DrawTargetSkia::RebalanceCacheLimits() -{ - // Divide the global cache limits equally between all currently active GL-backed - // Skia DrawTargets. - std::vector& targets = GLDrawTargets(); - uint32_t targetCount = targets.size(); - if (targetCount == 0) - return; - - int individualCacheSize = sTextureCacheSizeInBytes / targetCount; - for (uint32_t i = 0; i < targetCount; i++) { - targets[i]->SetCacheLimits(sTextureCacheCount, individualCacheSize); - } -} - -static void -AddGLDrawTarget(DrawTargetSkia* target) -{ - GLDrawTargets().push_back(target); - DrawTargetSkia::RebalanceCacheLimits(); -} - -static void -RemoveGLDrawTarget(DrawTargetSkia* target) -{ - std::vector& targets = GLDrawTargets(); - std::vector::iterator it = std::find(targets.begin(), targets.end(), target); - if (it != targets.end()) { - targets.erase(it); - DrawTargetSkia::RebalanceCacheLimits(); - } -} - -void -DrawTargetSkia::SetGlobalCacheLimits(int aCount, int aSizeInBytes) -{ - sTextureCacheCount = aCount; - sTextureCacheSizeInBytes = aSizeInBytes; - - DrawTargetSkia::RebalanceCacheLimits(); -} - -void -DrawTargetSkia::PurgeCaches() -{ - if (mGrContext) { - mGrContext->freeGpuResources(); - } -} - -/* static */ void -DrawTargetSkia::PurgeAllCaches() -{ - std::vector& targets = GLDrawTargets(); - uint32_t targetCount = targets.size(); - for (uint32_t i = 0; i < targetCount; i++) { - targets[i]->PurgeCaches(); - } -} - -#endif - /** * When constructing a temporary SkBitmap via GetBitmapForSurface, we may also * have to construct a temporary DataSourceSurface, which must live as long as @@ -187,15 +113,12 @@ GetBitmapForSurface(SourceSurface* aSurface) } DrawTargetSkia::DrawTargetSkia() - : mSnapshot(nullptr) + : mTexture(0), mSnapshot(nullptr) { } DrawTargetSkia::~DrawTargetSkia() { -#ifdef USE_SKIA_GPU - RemoveGLDrawTarget(this); -#endif } TemporaryRef @@ -768,45 +691,33 @@ DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat) #ifdef USE_SKIA_GPU void -DrawTargetSkia::InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, - GrGLInterface* aGrGLInterface, - const IntSize &aSize, - SurfaceFormat aFormat) +DrawTargetSkia::InitWithGrContext(GrContext* aGrContext, + const IntSize &aSize, + SurfaceFormat aFormat) { - mGLContext = aGLContext; + mGrContext = aGrContext; + mSize = aSize; mFormat = aFormat; - mGrGLInterface = aGrGLInterface; - mGrGLInterface->fCallbackData = reinterpret_cast(this); - - GrBackendContext backendContext = reinterpret_cast(aGrGLInterface); - SkAutoTUnref gr(GrContext::Create(kOpenGL_GrBackend, backendContext)); - mGrContext = gr.get(); - - GrBackendRenderTargetDesc targetDescriptor; + GrTextureDesc targetDescriptor; + targetDescriptor.fFlags = kRenderTarget_GrTextureFlagBit; targetDescriptor.fWidth = mSize.width; targetDescriptor.fHeight = mSize.height; targetDescriptor.fConfig = GfxFormatToGrConfig(mFormat); targetDescriptor.fOrigin = kBottomLeft_GrSurfaceOrigin; targetDescriptor.fSampleCnt = 0; - targetDescriptor.fRenderTargetHandle = 0; // GLContext always exposes the right framebuffer as id 0 - SkAutoTUnref target(mGrContext->wrapBackendRenderTarget(targetDescriptor)); - SkAutoTUnref device(new SkGpuDevice(mGrContext.get(), target.get())); + SkAutoTUnref skiaTexture(mGrContext->createUncachedTexture(targetDescriptor, NULL, 0)); + + mTexture = (uint32_t)skiaTexture->getTextureHandle(); + + SkAutoTUnref device(new SkGpuDevice(mGrContext.get(), skiaTexture->asRenderTarget())); SkAutoTUnref canvas(new SkCanvas(device.get())); mCanvas = canvas.get(); - - AddGLDrawTarget(this); } -void -DrawTargetSkia::SetCacheLimits(int aCount, int aSizeInBytes) -{ - MOZ_ASSERT(mGrContext, "No GrContext!"); - mGrContext->setTextureCacheLimits(aCount, aSizeInBytes); -} #endif void diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index 0b9548f04df1..9a39e64c0c0a 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -104,18 +104,10 @@ public: void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); #ifdef USE_SKIA_GPU - virtual GenericRefCountedBase* GetGLContext() const MOZ_OVERRIDE { return mGLContext; } - void InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, - GrGLInterface* aGrGLInterface, - const IntSize &aSize, - SurfaceFormat aFormat) MOZ_OVERRIDE; - - void SetCacheLimits(int aCount, int aSizeInBytes); - void PurgeCaches(); - - static void SetGlobalCacheLimits(int aCount, int aSizeInBytes); - static void RebalanceCacheLimits(); - static void PurgeAllCaches(); + void InitWithGrContext(GrContext* aGrContext, + const IntSize &aSize, + SurfaceFormat aFormat) MOZ_OVERRIDE; + uint32_t GetTextureID() const { return mTexture; } #endif operator std::string() const { @@ -133,18 +125,8 @@ private: SkRect SkRectCoveringWholeSurface() const; #ifdef USE_SKIA_GPU - /* - * These members have inter-dependencies, but do not keep each other alive, so - * destruction order is very important here: mGrContext uses mGrGLInterface, and - * through it, uses mGLContext, so it is important that they be declared in the - * present order. - */ - RefPtr mGLContext; - SkRefPtr mGrGLInterface; SkRefPtr mGrContext; - - static int sTextureCacheCount; - static int sTextureCacheSizeInBytes; + uint32_t mTexture; #endif IntSize mSize; diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 5787d69d2069..a9e3dcd9336b 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -585,30 +585,21 @@ Factory::D2DCleanup() #ifdef USE_SKIA_GPU TemporaryRef -Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, - GrGLInterface* aGrGLInterface, - const IntSize &aSize, - SurfaceFormat aFormat) +Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, + const IntSize &aSize, + SurfaceFormat aFormat) { DrawTargetSkia* newDrawTargetSkia = new DrawTargetSkia(); - newDrawTargetSkia->InitWithGLContextAndGrGLInterface(aGLContext, aGrGLInterface, aSize, aFormat); + newDrawTargetSkia->InitWithGrContext(aGrContext, aSize, aFormat); RefPtr newTarget = newDrawTargetSkia; return newTarget; } -void -Factory::SetGlobalSkiaCacheLimits(int aCount, int aSizeInBytes) -{ - DrawTargetSkia::SetGlobalCacheLimits(aCount, aSizeInBytes); -} #endif // USE_SKIA_GPU void Factory::PurgeAllCaches() { -#ifdef USE_SKIA_GPU - DrawTargetSkia::PurgeAllCaches(); -#endif } #ifdef USE_SKIA_FREETYPE diff --git a/gfx/gl/GLContextSkia.h b/gfx/gl/GLContextSkia.h deleted file mode 100644 index 2f9994ef56d2..000000000000 --- a/gfx/gl/GLContextSkia.h +++ /dev/null @@ -1,8 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "skia/GrGLInterface.h" - -GrGLInterface* CreateGrGLInterfaceFromGLContext(mozilla::gl::GLContext* context); diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp old mode 100644 new mode 100755 index 120ac72a601f..ed554da77a22 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -43,6 +43,7 @@ GLScreenBuffer::Create(GLContext* gl, #ifdef MOZ_WIDGET_GONK /* On B2G, we want a Gralloc factory, and we want one right at the start */ if (!factory && + caps.surfaceAllocator && XRE_GetProcessType() != GeckoProcessType_Default) { factory = new SurfaceFactory_Gralloc(gl, caps); @@ -70,7 +71,6 @@ GLScreenBuffer::Create(GLContext* gl, GLScreenBuffer::~GLScreenBuffer() { - delete mStream; delete mDraw; delete mRead; @@ -378,7 +378,6 @@ GLScreenBuffer::Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamTyp SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream); MOZ_ASSERT(newStream); - delete mStream; mStream = newStream; } diff --git a/gfx/gl/GLScreenBuffer.h b/gfx/gl/GLScreenBuffer.h index 4ba86ba74ff8..d899eba5f18d 100644 --- a/gfx/gl/GLScreenBuffer.h +++ b/gfx/gl/GLScreenBuffer.h @@ -16,6 +16,7 @@ #define SCREEN_BUFFER_H_ #include "SurfaceTypes.h" +#include "SurfaceStream.h" #include "GLContextTypes.h" #include "GLDefs.h" #include "mozilla/gfx/2D.h" @@ -156,7 +157,7 @@ protected: GLContext* const mGL; // Owns us. SurfaceCaps mCaps; SurfaceFactory_GL* mFactory; // Owned by us. - SurfaceStream* mStream; // Owned by us. + RefPtr mStream; DrawBuffer* mDraw; // Owned by us. ReadBuffer* mRead; // Owned by us. diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp index 28b49eb3e712..4b9991c0f029 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -284,6 +284,7 @@ SharedSurface_Basic::SharedSurface_Basic(GLContext* gl, size, hasAlpha) , mTex(tex) + , mFB(gl, tex) { mData = Factory::CreateDataSourceSurfaceWithStride(size, format, GetAlignedStride<4>(size.width * BytesPerPixel(format))); @@ -300,10 +301,10 @@ SharedSurface_Basic::~SharedSurface_Basic() void SharedSurface_Basic::Fence() { - MOZ_ASSERT(mData->GetSize() == mGL->OffscreenSize()); - mGL->MakeCurrent(); + ScopedBindFramebuffer autoFB(mGL, mFB.FB()); + DataSourceSurface::MappedSurface map; mData->Map(DataSourceSurface::MapType::WRITE, &map); nsRefPtr wrappedData = @@ -311,7 +312,7 @@ SharedSurface_Basic::Fence() ThebesIntSize(mData->GetSize()), map.mStride, SurfaceFormatToImageFormat(mData->GetFormat())); - ReadScreenIntoImageSurface(mGL, wrappedData); + ReadPixelsIntoImageSurface(mGL, wrappedData); mData->Unmap(); } @@ -322,15 +323,24 @@ SharedSurface_GLTexture::Create(GLContext* prodGL, GLContext* consGL, const GLFormats& formats, const gfx::IntSize& size, - bool hasAlpha) + bool hasAlpha, + GLuint texture) { MOZ_ASSERT(prodGL); MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL)); prodGL->MakeCurrent(); - GLuint tex = CreateTextureForOffscreen(prodGL, formats, size); - return new SharedSurface_GLTexture(prodGL, consGL, size, hasAlpha, tex); + GLuint tex = texture; + + bool ownsTex = false; + + if (!tex) { + tex = CreateTextureForOffscreen(prodGL, formats, size); + ownsTex = true; + } + + return new SharedSurface_GLTexture(prodGL, consGL, size, hasAlpha, tex, ownsTex); } SharedSurface_GLTexture::~SharedSurface_GLTexture() @@ -338,7 +348,10 @@ SharedSurface_GLTexture::~SharedSurface_GLTexture() if (!mGL->MakeCurrent()) return; - mGL->fDeleteTextures(1, &mTex); + if (mOwnsTex) { + GLuint tex = mTex; + mGL->fDeleteTextures(1, &mTex); + } if (mSync) { mGL->fDeleteSync(mSync); diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h index 70221aa2e7df..9ddb2215724c 100644 --- a/gfx/gl/SharedSurfaceGL.h +++ b/gfx/gl/SharedSurfaceGL.h @@ -6,6 +6,7 @@ #ifndef SHARED_SURFACE_GL_H_ #define SHARED_SURFACE_GL_H_ +#include "ScopedGLHelpers.h" #include "SharedSurface.h" #include "SurfaceFactory.h" #include "SurfaceTypes.h" @@ -136,6 +137,7 @@ public: protected: const GLuint mTex; RefPtr mData; + ScopedFramebufferForTexture mFB; SharedSurface_Basic(GLContext* gl, const gfx::IntSize& size, @@ -192,7 +194,8 @@ public: GLContext* consGL, const GLFormats& formats, const gfx::IntSize& size, - bool hasAlpha); + bool hasAlpha, + GLuint texture = 0); static SharedSurface_GLTexture* Cast(SharedSurface* surf) { MOZ_ASSERT(surf->Type() == SharedSurfaceType::GLTextureShare); @@ -203,6 +206,7 @@ public: protected: GLContext* mConsGL; const GLuint mTex; + const bool mOwnsTex; GLsync mSync; mutable Mutex mMutex; @@ -210,7 +214,8 @@ protected: GLContext* consGL, const gfx::IntSize& size, bool hasAlpha, - GLuint tex) + GLuint tex, + bool ownsTex) : SharedSurface_GL(SharedSurfaceType::GLTextureShare, AttachmentType::GLTexture, prodGL, @@ -218,6 +223,7 @@ protected: hasAlpha) , mConsGL(consGL) , mTex(tex) + , mOwnsTex(ownsTex) , mSync(0) , mMutex("SharedSurface_GLTexture mutex") { diff --git a/gfx/gl/GLContextSkia.cpp b/gfx/gl/SkiaGLGlue.cpp old mode 100644 new mode 100755 similarity index 97% rename from gfx/gl/GLContextSkia.cpp rename to gfx/gl/SkiaGLGlue.cpp index 54c4d9f0cd93..0fdf82d1f109 --- a/gfx/gl/GLContextSkia.cpp +++ b/gfx/gl/SkiaGLGlue.cpp @@ -16,9 +16,11 @@ #endif #include "GLContext.h" +#include "SkiaGLGlue.h" using mozilla::gl::GLContext; using mozilla::gl::GLFeature; +using mozilla::gl::SkiaGLGlue; using mozilla::gfx::DrawTarget; static mozilla::ThreadLocal sGLContext; @@ -27,8 +29,8 @@ extern "C" { void EnsureGLContext(const GrGLInterface* i) { - const DrawTarget* drawTarget = reinterpret_cast(i->fCallbackData); - GLContext* gl = static_cast(drawTarget->GetGLContext()); + const SkiaGLGlue* contextSkia = reinterpret_cast(i->fCallbackData); + GLContext* gl = contextSkia->GetGLContext(); gl->MakeCurrent(); if (!sGLContext.initialized()) { @@ -713,7 +715,7 @@ GrGLvoid glGenVertexArrays_mozilla(GrGLsizei n, GrGLuint *arrays) { } // extern "C" -GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) +static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) { GrGLInterface* i = new GrGLInterface(); i->fCallback = EnsureGLContext; @@ -858,3 +860,14 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) return i; } + +SkiaGLGlue::SkiaGLGlue(GLContext* context) + : mGLContext(context) +{ + SkAutoTUnref i(CreateGrGLInterfaceFromGLContext(mGLContext)); + i->fCallbackData = reinterpret_cast(this); + mGrGLInterface = i; + SkAutoTUnref gr(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get())); + + mGrContext = gr; +} diff --git a/gfx/gl/SkiaGLGlue.h b/gfx/gl/SkiaGLGlue.h new file mode 100755 index 000000000000..918cd76f1b6d --- /dev/null +++ b/gfx/gl/SkiaGLGlue.h @@ -0,0 +1,34 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/RefPtr.h" +#include "skia/GrGLInterface.h" +#include "skia/GrContext.h" + +namespace mozilla { +namespace gl { + +class GLContext; + +class SkiaGLGlue : public GenericAtomicRefCounted +{ +public: + SkiaGLGlue(GLContext* context); + GLContext* GetGLContext() const { return mGLContext.get(); } + GrContext* GetGrContext() const { return mGrContext.get(); } +private: + /* + * These members have inter-dependencies, but do not keep each other alive, so + * destruction order is very important here: mGrContext uses mGrGLInterface, and + * through it, uses mGLContext, so it is important that they be declared in the + * present order. + */ + RefPtr mGLContext; + SkRefPtr mGrGLInterface; + SkRefPtr mGrContext; +}; + +} +} diff --git a/gfx/gl/SurfaceStream.cpp b/gfx/gl/SurfaceStream.cpp index 1b55ded14d0e..b4776b616132 100644 --- a/gfx/gl/SurfaceStream.cpp +++ b/gfx/gl/SurfaceStream.cpp @@ -7,6 +7,7 @@ #include "gfxPoint.h" #include "SharedSurface.h" +#include "SharedSurfaceGL.h" #include "SurfaceFactory.h" #include "GeckoProfiler.h" @@ -56,6 +57,20 @@ SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glC return result; } +void +SurfaceStream_TripleBuffer::CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) +{ + if (!mProducer) { + New(factory, src->Size(), mProducer); + } + + MOZ_ASSERT(mProducer); + + mProducer->LockProd(); + SharedSurface::Copy(src, mProducer, factory); + mProducer->UnlockProd(); +} + void SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size, SharedSurface*& surf) diff --git a/gfx/gl/SurfaceStream.h b/gfx/gl/SurfaceStream.h index a597f614b650..cc616254476f 100644 --- a/gfx/gl/SurfaceStream.h +++ b/gfx/gl/SurfaceStream.h @@ -11,6 +11,7 @@ #include "mozilla/Monitor.h" #include "mozilla/Attributes.h" #include "mozilla/gfx/Point.h" +#include "mozilla/GenericRefCounted.h" #include "SurfaceTypes.h" namespace mozilla { @@ -24,7 +25,7 @@ class SharedSurface; class SurfaceFactory; // Owned by: ScreenBuffer -class SurfaceStream +class SurfaceStream : public GenericAtomicRefCounted { public: typedef enum { @@ -50,6 +51,8 @@ public: const SurfaceStreamType mType; mozilla::gl::GLContext* GLContext() const { return mGLContext; } + + protected: // |mProd| is owned by us, but can be ripped away when // creating a new GLStream from this one. @@ -121,6 +124,8 @@ public: virtual SharedSurface* Resize(SurfaceFactory* factory, const gfx::IntSize& size); + virtual void CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) { MOZ_ASSERT(0); } + protected: // SwapCons will return the same surface more than once, // if nothing new has been published. @@ -192,6 +197,7 @@ protected: public: SurfaceStream_TripleBuffer(SurfaceStream* prevStream); virtual ~SurfaceStream_TripleBuffer(); + virtual void CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory); private: // Common constructor code. diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build index 64e90c38332d..533b71f1715c 100644 --- a/gfx/gl/moz.build +++ b/gfx/gl/moz.build @@ -75,9 +75,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 'SharedSurfaceANGLE.cpp', ] if CONFIG['MOZ_ENABLE_SKIA_GPU']: - EXPORTS += ['GLContextSkia.h'] + EXPORTS += ['SkiaGLGlue.h'] UNIFIED_SOURCES += [ - 'GLContextSkia.cpp', + 'SkiaGLGlue.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': diff --git a/gfx/layers/CopyableCanvasLayer.cpp b/gfx/layers/CopyableCanvasLayer.cpp index 747708617f23..bc564b423de0 100644 --- a/gfx/layers/CopyableCanvasLayer.cpp +++ b/gfx/layers/CopyableCanvasLayer.cpp @@ -32,6 +32,7 @@ namespace layers { CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) : CanvasLayer(aLayerManager, aImplData) + , mStream(nullptr) { MOZ_COUNT_CTOR(CopyableCanvasLayer); mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false); @@ -49,6 +50,7 @@ CopyableCanvasLayer::Initialize(const Data& aData) if (aData.mGLContext) { mGLContext = aData.mGLContext; + mStream = aData.mStream; mIsGLAlphaPremult = aData.mIsGLAlphaPremult; mNeedsYFlip = true; MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen"); @@ -71,7 +73,7 @@ CopyableCanvasLayer::Initialize(const Data& aData) bool CopyableCanvasLayer::IsDataValid(const Data& aData) { - return mGLContext == aData.mGLContext; + return mGLContext == aData.mGLContext && mStream == aData.mStream; } void diff --git a/gfx/layers/CopyableCanvasLayer.h b/gfx/layers/CopyableCanvasLayer.h index 7a6bbc398897..520fefc270e9 100644 --- a/gfx/layers/CopyableCanvasLayer.h +++ b/gfx/layers/CopyableCanvasLayer.h @@ -22,6 +22,13 @@ #include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc namespace mozilla { + +namespace gfx { +class SurfaceStream; +class SharedSurface; +class SurfaceFactory; +} + namespace layers { class CanvasClientWebGL; @@ -54,6 +61,8 @@ protected: nsRefPtr mGLContext; mozilla::RefPtr mDrawTarget; + gfx::SurfaceStream* mStream; + uint32_t mCanvasFramebuffer; bool mIsGLAlphaPremult; diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index b28b03362759..d5666d65f66b 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -63,6 +63,7 @@ class GLContext; namespace gfx { class DrawTarget; +class SurfaceStream; } namespace css { @@ -1790,6 +1791,8 @@ public: Data() : mDrawTarget(nullptr) , mGLContext(nullptr) + , mStream(nullptr) + , mTexID(0) , mSize(0,0) , mIsGLAlphaPremult(false) { } @@ -1798,6 +1801,14 @@ public: mozilla::gfx::DrawTarget *mDrawTarget; // a DrawTarget for the canvas contents mozilla::gl::GLContext* mGLContext; // or this, for GL. +#ifdef USE_SKIA_GPU + // Canvas/SkiaGL uses this + mozilla::gfx::SurfaceStream* mStream; + + // ID of the texture backing the canvas layer (defaults to 0) + uint32_t mTexID; +#endif + // The size of the canvas content nsIntSize mSize; diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index b84d9654fbff..5dadfb0a6646 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -112,7 +112,15 @@ void CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { GLScreenBuffer* screen = aLayer->mGLContext->Screen(); - SurfaceStream* stream = screen->Stream(); + SurfaceStream* stream = nullptr; + + if (aLayer->mStream) { + stream = aLayer->mStream; + stream->CopySurfaceToProducer(aLayer->mTextureSurface, aLayer->mFactory); + stream->SwapProducer(aLayer->mFactory, gfx::IntSize(aSize.width, aSize.height)); + } else { + stream = screen->Stream(); + } bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); bool bufferCreated = false; @@ -251,7 +259,15 @@ DeprecatedCanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLaye mDeprecatedTextureClient->EnsureAllocated(aSize, gfxContentType::COLOR); GLScreenBuffer* screen = aLayer->mGLContext->Screen(); - SurfaceStream* stream = screen->Stream(); + SurfaceStream* stream = nullptr; + + if (aLayer->mStream) { + stream = aLayer->mStream; + stream->CopySurfaceToProducer(aLayer->mTextureSurface, aLayer->mFactory); + stream->SwapProducer(aLayer->mFactory, gfx::IntSize(aSize.width, aSize.height)); + } else { + stream = screen->Stream(); + } bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); if (isCrossProcess) { diff --git a/gfx/layers/client/ClientCanvasLayer.cpp b/gfx/layers/client/ClientCanvasLayer.cpp index 1955030b362c..39417a036a60 100644 --- a/gfx/layers/client/ClientCanvasLayer.cpp +++ b/gfx/layers/client/ClientCanvasLayer.cpp @@ -36,27 +36,34 @@ void ClientCanvasLayer::Initialize(const Data& aData) { CopyableCanvasLayer::Initialize(aData); - + mCanvasClient = nullptr; if (mGLContext) { GLScreenBuffer* screen = mGLContext->Screen(); + + SurfaceCaps caps = screen->Caps(); + if (mStream) { + // The screen caps are irrelevant if we're using a separate stream + caps = GetContentFlags() & CONTENT_OPAQUE ? SurfaceCaps::ForRGB() : SurfaceCaps::ForRGBA(); + } + SurfaceStreamType streamType = SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread, screen->PreserveBuffer()); SurfaceFactory_GL* factory = nullptr; if (!mForceReadback) { - if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) { + if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LAYERS_OPENGL) { if (mGLContext->GetContextType() == GLContextType::EGL) { bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); if (!isCrossProcess) { // [Basic/OGL Layers, OMTC] WebGL layer init. - factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps()); + factory = SurfaceFactory_EGLImage::Create(mGLContext, caps); } else { // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing) #ifdef MOZ_WIDGET_GONK - factory = new SurfaceFactory_Gralloc(mGLContext, screen->Caps(), ClientManager()->AsShadowForwarder()); + factory = new SurfaceFactory_Gralloc(mGLContext, caps, ClientManager()->AsShadowForwarder()); #else // we could do readback here maybe NS_NOTREACHED("isCrossProcess but not on native B2G!"); @@ -66,16 +73,34 @@ ClientCanvasLayer::Initialize(const Data& aData) // [Basic Layers, OMTC] WebGL layer init. // Well, this *should* work... #ifdef XP_MACOSX - factory = new SurfaceFactory_IOSurface(mGLContext, screen->Caps()); + factory = new SurfaceFactory_IOSurface(mGLContext, caps); #else - factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, screen->Caps()); + factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, caps); #endif } } } if (factory) { - screen->Morph(factory, streamType); + if (mStream) { + // We're using a stream other than the one in the default screen + mFactory = factory; + + gfx::IntSize size = gfx::IntSize(aData.mSize.width, aData.mSize.height); + mTextureSurface = SharedSurface_GLTexture::Create(mGLContext, mGLContext, + mGLContext->GetGLFormats(), + size, caps.alpha, aData.mTexID); + SharedSurface* producer = mStream->SwapProducer(mFactory, size); + if (!producer) { + // Fallback to basic factory + delete mFactory; + mFactory = new SurfaceFactory_Basic(mGLContext, caps); + producer = mStream->SwapProducer(mFactory, size); + MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory"); + } + } else { + screen->Morph(factory, streamType); + } } } } diff --git a/gfx/layers/client/ClientCanvasLayer.h b/gfx/layers/client/ClientCanvasLayer.h index c46ac332f558..bb7ba5170b17 100644 --- a/gfx/layers/client/ClientCanvasLayer.h +++ b/gfx/layers/client/ClientCanvasLayer.h @@ -33,6 +33,8 @@ public: ClientCanvasLayer(ClientLayerManager* aLayerManager) : CopyableCanvasLayer(aLayerManager, static_cast(MOZ_THIS_IN_INITIALIZER_LIST())) + , mTextureSurface(nullptr) + , mFactory(nullptr) { MOZ_COUNT_CTOR(ClientCanvasLayer); } @@ -90,6 +92,9 @@ protected: RefPtr mCanvasClient; + gfx::SharedSurface* mTextureSurface; + gfx::SurfaceFactory* mFactory; + friend class DeprecatedCanvasClient2D; friend class CanvasClient2D; friend class DeprecatedCanvasClientSurfaceStream; diff --git a/gfx/layers/opengl/TextureClientOGL.cpp b/gfx/layers/opengl/TextureClientOGL.cpp index f3f25c5a4b24..c80737afed41 100644 --- a/gfx/layers/opengl/TextureClientOGL.cpp +++ b/gfx/layers/opengl/TextureClientOGL.cpp @@ -86,7 +86,6 @@ SharedTextureClientOGL::IsAllocated() const StreamTextureClientOGL::StreamTextureClientOGL(TextureFlags aFlags) : TextureClient(aFlags) - , mStream(0) , mIsLocked(false) { } @@ -131,6 +130,7 @@ StreamTextureClientOGL::InitWith(gfx::SurfaceStream* aStream) { MOZ_ASSERT(!IsAllocated()); mStream = aStream; + mGL = mStream->GLContext(); } bool diff --git a/gfx/layers/opengl/TextureClientOGL.h b/gfx/layers/opengl/TextureClientOGL.h index 9b0d661000c1..333cc2ac705e 100644 --- a/gfx/layers/opengl/TextureClientOGL.h +++ b/gfx/layers/opengl/TextureClientOGL.h @@ -97,8 +97,9 @@ public: virtual gfx::IntSize GetSize() const { return gfx::IntSize(); } protected: - gfx::SurfaceStream* mStream; bool mIsLocked; + RefPtr mStream; + RefPtr mGL; }; } // namespace diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 83b9a19537a6..a79465ffc202 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -76,6 +76,11 @@ #ifdef USE_SKIA #include "mozilla/Hal.h" #include "skia/SkGraphics.h" + +#ifdef USE_SKIA_GPU +#include "SkiaGLGlue.h" +#endif + #endif #include "mozilla/Preferences.h" @@ -231,6 +236,11 @@ MemoryPressureObserver::Observe(nsISupports *aSubject, { NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic"); Factory::PurgeAllCaches(); + +#if USE_SKIA_GPU + gfxPlatform::GetPlatform()->PurgeSkiaCache(); +#endif + return NS_OK; } @@ -298,6 +308,10 @@ gfxPlatform::gfxPlatform() mLayersUseDeprecated = false; #endif +#ifdef USE_SKIA_GPU + mSkiaGlue = nullptr; +#endif + Preferences::AddBoolVarCache(&mDrawLayerBorders, "layers.draw-borders", false); @@ -482,10 +496,6 @@ gfxPlatform::Init() CreateCMSOutputProfile(); -#ifdef USE_SKIA - gPlatform->InitializeSkiaCaches(); -#endif - // Listen to memory pressure event so we can purge DrawTarget caches nsCOMPtr obs = mozilla::services::GetObserverService(); if (obs) { @@ -892,39 +902,68 @@ gfxPlatform::UseAcceleratedSkiaCanvas() mPreferredCanvasBackend == BackendType::SKIA; } -void -gfxPlatform::InitializeSkiaCaches() +static void +InitializeSkiaCacheLimits(GrContext* context) { #ifdef USE_SKIA_GPU - if (UseAcceleratedSkiaCanvas()) { - bool usingDynamicCache = Preferences::GetBool("gfx.canvas.skiagl.dynamic-cache", false); + bool usingDynamicCache = Preferences::GetBool("gfx.canvas.skiagl.dynamic-cache", false); - int cacheItemLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-items", 256); - int cacheSizeLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-size", 96); + int cacheItemLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-items", 256); + int cacheSizeLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-size", 96); - // Prefs are in megabytes, but we want the sizes in bytes - cacheSizeLimit *= 1024*1024; + // Prefs are in megabytes, but we want the sizes in bytes + cacheSizeLimit *= 1024*1024; - if (usingDynamicCache) { - uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory(); + if (usingDynamicCache) { + uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory(); - if (totalMemory <= 256*1024*1024) { - // We need a very minimal cache on 256 meg devices - cacheSizeLimit = 2*1024*1024; - } else if (totalMemory > 0) { - cacheSizeLimit = totalMemory / 16; - } + if (totalMemory <= 256*1024*1024) { + // We need a very minimal cache on 256 meg devices + cacheSizeLimit = 2*1024*1024; + } else if (totalMemory > 0) { + cacheSizeLimit = totalMemory / 16; } + } #ifdef DEBUG - printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit); + printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit); #endif - Factory::SetGlobalSkiaCacheLimits(cacheItemLimit, cacheSizeLimit); - } + context->setTextureCacheLimits(cacheItemLimit, cacheSizeLimit); #endif } +#ifdef USE_SKIA_GPU +mozilla::gl::SkiaGLGlue* +gfxPlatform::GetSkiaGLGlue() +{ + if (!mSkiaGlue) { + // Dummy context. We always draw into a FBO. + // FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it + // stands, this only works on the main thread. + mozilla::gfx::SurfaceCaps caps = mozilla::gfx::SurfaceCaps::ForRGBA(); + nsRefPtr glContext = mozilla::gl::GLContextProvider::CreateOffscreen(gfxIntSize(16, 16), caps); + if (!glContext) { + printf_stderr("Failed to create GLContext for SkiaGL!\n"); + return nullptr; + } + mSkiaGlue = new mozilla::gl::SkiaGLGlue(glContext); + InitializeSkiaCacheLimits(mSkiaGlue->GetGrContext()); + } + + return mSkiaGlue; +} + +void +gfxPlatform::PurgeSkiaCache() +{ + if (!mSkiaGlue) + return; + + mSkiaGlue->GetGrContext()->freeGpuResources(); +} +#endif + already_AddRefed gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget) { diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 699a40c45eaf..e6c1a0817d81 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -40,6 +40,10 @@ struct gfxRGBA; namespace mozilla { namespace gl { class GLContext; + +#if USE_SKIA_GPU +class SkiaGLGlue; +#endif } namespace gfx { class DrawTarget; @@ -284,8 +288,6 @@ public: virtual bool UseAcceleratedSkiaCanvas(); - virtual void InitializeSkiaCaches(); - void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend)); aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas()); @@ -632,6 +634,11 @@ public: bool PreferMemoryOverShmem() const; bool UseDeprecatedTextures() const { return mLayersUseDeprecated; } +#ifdef USE_SKIA_GPU + mozilla::gl::SkiaGLGlue* GetSkiaGLGlue(); + void PurgeSkiaCache(); +#endif + protected: gfxPlatform(); virtual ~gfxPlatform(); @@ -752,6 +759,10 @@ private: bool mDrawLayerBorders; bool mDrawTileBorders; bool mDrawBigImageBorders; + +#ifdef USE_SKIA_GPU + mozilla::RefPtr mSkiaGlue; +#endif }; #endif /* GFX_PLATFORM_H */