From dfee0058ef308fc46fda9d4c68d7d70fe6086329 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 5 Mar 2014 15:49:37 -0600 Subject: [PATCH] Bug 939276 - Use a single GLContext for all SkiaGL canvases r=jgilbert,vlad,gwright,bjacob --HG-- rename : gfx/gl/GLContextSkia.cpp => gfx/gl/SkiaGLGlue.cpp --- .../canvas/src/CanvasRenderingContext2D.cpp | 134 +++++++----------- content/canvas/src/CanvasRenderingContext2D.h | 5 +- gfx/2d/2D.h | 21 +-- gfx/2d/DrawTargetSkia.cpp | 126 ++++------------ gfx/2d/DrawTargetSkia.h | 28 +--- gfx/2d/Factory.cpp | 17 +-- gfx/2d/Types.h | 3 +- gfx/gl/GLContextSkia.h | 8 -- gfx/gl/GLScreenBuffer.cpp | 3 +- gfx/gl/GLScreenBuffer.h | 3 +- gfx/gl/SharedSurfaceGL.cpp | 46 ++++-- gfx/gl/SharedSurfaceGL.h | 11 +- gfx/gl/{GLContextSkia.cpp => SkiaGLGlue.cpp} | 20 ++- gfx/gl/SkiaGLGlue.h | 64 +++++++++ gfx/gl/SurfaceStream.cpp | 17 +++ gfx/gl/SurfaceStream.h | 8 +- gfx/gl/moz.build | 4 +- gfx/layers/CopyableCanvasLayer.cpp | 4 +- gfx/layers/CopyableCanvasLayer.h | 9 ++ gfx/layers/Layers.h | 9 ++ gfx/layers/client/CanvasClient.cpp | 23 ++- gfx/layers/client/ClientCanvasLayer.cpp | 51 ++++++- gfx/layers/client/ClientCanvasLayer.h | 14 +- gfx/layers/opengl/TextureClientOGL.cpp | 2 +- gfx/layers/opengl/TextureClientOGL.h | 3 +- gfx/thebes/gfxPlatform.cpp | 55 +++++-- gfx/thebes/gfxPlatform.h | 8 +- 27 files changed, 400 insertions(+), 296 deletions(-) delete mode 100644 gfx/gl/GLContextSkia.h rename gfx/gl/{GLContextSkia.cpp => SkiaGLGlue.cpp} (97%) create mode 100755 gfx/gl/SkiaGLGlue.h diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index ff799d38f534..4beba864fa99 100755 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -94,14 +94,14 @@ #include "GLContext.h" #include "GLContextProvider.h" -#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 +430,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 +532,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 +555,7 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() NS_IF_RELEASE(sErrorTarget); } -#ifdef USE_SKIA_GPU RemoveDemotableContext(this); -#endif } JSObject* @@ -638,6 +623,7 @@ CanvasRenderingContext2D::Reset() } mTarget = nullptr; + mStream = nullptr; // reset hit regions #ifdef ACCESSIBILITY @@ -765,8 +751,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); @@ -774,6 +759,7 @@ void CanvasRenderingContext2D::Demote() RefPtr snapshot = mTarget->Snapshot(); RefPtr oldTarget = mTarget; mTarget = nullptr; + mStream = nullptr; mResetLayer = true; mForceSoftware = true; @@ -792,11 +778,8 @@ void CanvasRenderingContext2D::Demote() } mTarget->SetTransform(oldTarget->GetTransform()); -#endif } -#ifdef USE_SKIA_GPU - std::vector& CanvasRenderingContext2D::DemotableContexts() { @@ -807,11 +790,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) @@ -845,8 +824,6 @@ CheckSizeForSkiaGL(IntSize size) { return size.width >= minsize && size.height >= minsize; } -#endif - void CanvasRenderingContext2D::EnsureTarget() { @@ -872,42 +849,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; + 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); + if (mTarget) { + mStream = gfx::SurfaceStream::CreateForType(SurfaceStreamType::TripleBuffer, glue->GetGLContext()); + AddDemotableContext(this); + } else { + printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n"); + } } - - if (glContext) { - SkAutoTUnref i(CreateGrGLInterfaceFromGLContext(glContext)); - mTarget = Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(glContext, i, size, format); - AddDemotableContext(this); - } else { + if (!mTarget) { 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); } } @@ -1092,12 +1056,10 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx, JS::HandleGetUserData(&g2DContextLayerUserData)); CanvasLayer::Data data; - data.mGLContext = static_cast(mTarget->GetGLContext()); + if (mStream) { + SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); + + if (glue) { + data.mGLContext = glue->GetGLContext(); + data.mStream = mStream.get(); + } + } else { + data.mDrawTarget = mTarget; + } + if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) { nsRefPtr ret = aOldLayer; return ret.forget(); @@ -4184,15 +4150,17 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder, canvasLayer->SetUserData(&g2DContextLayerUserData, userData); CanvasLayer::Data data; -#ifdef USE_SKIA_GPU - GLContext* glContext = static_cast(mTarget->GetGLContext()); - if (glContext) { - canvasLayer->SetPreTransactionCallback( - CanvasRenderingContext2DUserData::PreTransactionCallback, userData); - data.mGLContext = glContext; - } else -#endif - { + if (mStream) { + SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); + + if (glue) { + canvasLayer->SetPreTransactionCallback( + CanvasRenderingContext2DUserData::PreTransactionCallback, userData); + data.mGLContext = glue->GetGLContext(); + data.mStream = mStream.get(); + data.mTexID = (uint32_t)((uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE)); + } + } else { data.mDrawTarget = mTarget; } diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index 73edb6ed0f69..c3fb0aa16f9a 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 { @@ -596,7 +597,6 @@ protected: return CurrentState().font; } -#if USE_SKIA_GPU static std::vector& DemotableContexts(); static void DemoteOldestContextIfNecessary(); @@ -605,7 +605,6 @@ protected: // Do not use GL bool mForceSoftware; -#endif // Member vars int32_t mWidth, mHeight; @@ -632,6 +631,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 5a161f223aad..0db291fac88c 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -971,15 +971,10 @@ 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(); } @@ -1085,13 +1080,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 2edec2f6ad99..09637fedf181 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -79,80 +79,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 @@ -189,15 +115,12 @@ GetBitmapForSurface(SourceSurface* aSurface) } DrawTargetSkia::DrawTargetSkia() - : mSnapshot(nullptr) + : mTexture(0), mSnapshot(nullptr) { } DrawTargetSkia::~DrawTargetSkia() { -#ifdef USE_SKIA_GPU - RemoveGLDrawTarget(this); -#endif } TemporaryRef @@ -770,45 +693,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 @@ -840,6 +751,17 @@ DrawTargetSkia::SetTransform(const Matrix& aTransform) mTransform = aTransform; } +void* +DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType) +{ + if (aType == NativeSurfaceType::OPENGL_TEXTURE) { + return (void*)((uintptr_t)mTexture); + } + + return nullptr; +} + + TemporaryRef DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const { diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index 4970048d5134..c8efe7fef529 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -100,23 +100,15 @@ public: virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const; virtual TemporaryRef CreateFilter(FilterType aType); virtual void SetTransform(const Matrix &aTransform); + virtual void *GetNativeSurface(NativeSurfaceType aType); bool Init(const IntSize &aSize, SurfaceFormat aFormat); 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; #endif operator std::string() const { @@ -134,18 +126,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 2e3d3b14bce6..ce491502c888 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -586,30 +586,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/2d/Types.h b/gfx/2d/Types.h index ec0943334470..8f51a91553f8 100644 --- a/gfx/2d/Types.h +++ b/gfx/2d/Types.h @@ -96,7 +96,8 @@ MOZ_BEGIN_ENUM_CLASS(NativeSurfaceType, int8_t) CAIRO_SURFACE, CAIRO_CONTEXT, CGCONTEXT, - CGCONTEXT_ACCELERATED + CGCONTEXT_ACCELERATED, + OPENGL_TEXTURE MOZ_END_ENUM_CLASS(NativeSurfaceType) MOZ_BEGIN_ENUM_CLASS(NativeFontType, int8_t) 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 index 120ac72a601f..ed554da77a22 100755 --- 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..4e96b0647f2d 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -283,8 +283,24 @@ SharedSurface_Basic::SharedSurface_Basic(GLContext* gl, gl, size, hasAlpha) - , mTex(tex) + , mTex(tex), mFB(0) { + mGL->MakeCurrent(); + mGL->fGenFramebuffers(1, &mFB); + + ScopedBindFramebuffer autoFB(mGL, mFB); + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_TEXTURE_2D, + mTex, + 0); + + GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); + if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) { + mGL->fDeleteFramebuffers(1, &mFB); + mFB = 0; + } + mData = Factory::CreateDataSourceSurfaceWithStride(size, format, GetAlignedStride<4>(size.width * BytesPerPixel(format))); } @@ -294,16 +310,19 @@ SharedSurface_Basic::~SharedSurface_Basic() if (!mGL->MakeCurrent()) return; + if (mFB) + mGL->fDeleteFramebuffers(1, &mFB); + mGL->fDeleteTextures(1, &mTex); } void SharedSurface_Basic::Fence() { - MOZ_ASSERT(mData->GetSize() == mGL->OffscreenSize()); - mGL->MakeCurrent(); + ScopedBindFramebuffer autoFB(mGL, mFB); + DataSourceSurface::MappedSurface map; mData->Map(DataSourceSurface::MapType::WRITE, &map); nsRefPtr wrappedData = @@ -311,7 +330,7 @@ SharedSurface_Basic::Fence() ThebesIntSize(mData->GetSize()), map.mStride, SurfaceFormatToImageFormat(mData->GetFormat())); - ReadScreenIntoImageSurface(mGL, wrappedData); + ReadPixelsIntoImageSurface(mGL, wrappedData); mData->Unmap(); } @@ -322,15 +341,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 +366,9 @@ SharedSurface_GLTexture::~SharedSurface_GLTexture() if (!mGL->MakeCurrent()) return; - mGL->fDeleteTextures(1, &mTex); + if (mOwnsTex) { + mGL->fDeleteTextures(1, &mTex); + } if (mSync) { mGL->fDeleteSync(mSync); diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h index 70221aa2e7df..5abf56abe582 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" @@ -135,6 +136,8 @@ public: protected: const GLuint mTex; + GLuint mFB; + RefPtr mData; SharedSurface_Basic(GLContext* gl, @@ -192,7 +195,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 +207,7 @@ public: protected: GLContext* mConsGL; const GLuint mTex; + const bool mOwnsTex; GLsync mSync; mutable Mutex mMutex; @@ -210,7 +215,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 +224,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 similarity index 97% rename from gfx/gl/GLContextSkia.cpp rename to gfx/gl/SkiaGLGlue.cpp index 9c46f86e6541..25467d50ec95 100755 --- a/gfx/gl/GLContextSkia.cpp +++ b/gfx/gl/SkiaGLGlue.cpp @@ -3,6 +3,7 @@ * 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/GrContext.h" #include "skia/GrGLInterface.h" #include "mozilla/gfx/2D.h" #include "mozilla/ThreadLocal.h" @@ -16,9 +17,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 +30,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()) { @@ -775,7 +778,7 @@ GrGLvoid glVertexPointer_mozilla(GrGLint size, GrGLenum type, GrGLsizei stride, } // extern "C" -GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) +static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) { GrGLInterface* i = new GrGLInterface(); i->fCallback = EnsureGLContext; @@ -934,3 +937,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..1d80021566fb --- /dev/null +++ b/gfx/gl/SkiaGLGlue.h @@ -0,0 +1,64 @@ +/* -*- 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" + +#ifdef USE_SKIA_GPU + +#include "GLContext.h" +#include "skia/GrGLInterface.h" +#include "skia/GrContext.h" + +namespace mozilla { +namespace gl { + +class SkiaGLGlue : public GenericAtomicRefCounted +{ +public: + SkiaGLGlue(GLContext* context); + GLContext* GetGLContext() const { return mGLContext.get(); } + GrContext* GetGrContext() const { return mGrContext.get(); } + +protected: + virtual ~SkiaGLGlue() { + /* + * 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 + */ + mGrContext = nullptr; + mGrGLInterface = nullptr; + mGLContext = nullptr; + } + +private: + RefPtr mGLContext; + SkRefPtr mGrGLInterface; + SkRefPtr mGrContext; +}; + +} +} + +#else + +class GrContext; + +namespace mozilla { +namespace gl { + +class GLContext; + +class SkiaGLGlue : public GenericAtomicRefCounted +{ +public: + SkiaGLGlue(GLContext* context); + GLContext* GetGLContext() const { return nullptr; } + GrContext* GetGrContext() const { return nullptr; } +}; +} +} + +#endif \ No newline at end of file diff --git a/gfx/gl/SurfaceStream.cpp b/gfx/gl/SurfaceStream.cpp index b28cfff6af4b..bf105160e4a8 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" @@ -53,6 +54,22 @@ SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glC return result; } +bool +SurfaceStream_TripleBuffer::CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) +{ + if (!mProducer) { + New(factory, src->Size(), mProducer); + if (!mProducer) { + return false; + } + } + + MOZ_ASSERT(src->Size() == mProducer->Size(), "Size mismatch"); + + SharedSurface::Copy(src, mProducer, factory); + return true; +} + void SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size, SharedSurface*& surf) diff --git a/gfx/gl/SurfaceStream.h b/gfx/gl/SurfaceStream.h index d7c7a1994760..a7b4f5961ee6 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 bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) { MOZ_ASSERT(0); return false; } + protected: // SwapCons will return the same surface more than once, // if nothing new has been published. @@ -189,6 +194,7 @@ protected: public: SurfaceStream_TripleBuffer(SurfaceStream* prevStream); virtual ~SurfaceStream_TripleBuffer(); + virtual bool 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 a5bec15a7e7d..37ba82a5d1ec 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); } @@ -48,6 +49,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"); @@ -70,7 +72,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 ca92c8a11c49..22448118c326 100644 --- a/gfx/layers/CopyableCanvasLayer.h +++ b/gfx/layers/CopyableCanvasLayer.h @@ -22,6 +22,13 @@ #include "nsISupportsImpl.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; + RefPtr mStream; + uint32_t mCanvasFramebuffer; bool mIsGLAlphaPremult; diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 56f04b6d648a..ef38bb9af4b9 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 { @@ -1796,6 +1797,8 @@ public: Data() : mDrawTarget(nullptr) , mGLContext(nullptr) + , mStream(nullptr) + , mTexID(0) , mSize(0,0) , mIsGLAlphaPremult(false) { } @@ -1804,6 +1807,12 @@ public: mozilla::gfx::DrawTarget *mDrawTarget; // a DrawTarget for the canvas contents mozilla::gl::GLContext* mGLContext; // or this, for GL. + // Canvas/SkiaGL uses this + mozilla::gfx::SurfaceStream* mStream; + + // ID of the texture backing the canvas layer (defaults to 0) + uint32_t mTexID; + // The size of the canvas content nsIntSize mSize; diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index 24a4d34b9e5d..b2ec194f4e46 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -116,7 +116,18 @@ 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; + + // Copy our current surface to the current producer surface in our stream, then + // call SwapProducer to make a new buffer ready. + 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; @@ -255,7 +266,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 855aa7ef8dbf..cc30cf3814a5 100644 --- a/gfx/layers/client/ClientCanvasLayer.cpp +++ b/gfx/layers/client/ClientCanvasLayer.cpp @@ -33,15 +33,34 @@ using namespace mozilla::gl; namespace mozilla { namespace layers { +ClientCanvasLayer::~ClientCanvasLayer() +{ + MOZ_COUNT_DTOR(ClientCanvasLayer); + if (mCanvasClient) { + mCanvasClient->OnDetach(); + mCanvasClient = nullptr; + } + if (mTextureSurface) { + delete mTextureSurface; + } +} + 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()); @@ -53,11 +72,11 @@ ClientCanvasLayer::Initialize(const Data& aData) 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!"); @@ -67,15 +86,35 @@ 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) { + if (mStream) { + // We're using a stream other than the one in the default screen + mFactory = factory; + if (!mFactory) { + // Absolutely must have a factory here, so create a basic one + mFactory = new SurfaceFactory_Basic(mGLContext, caps); + } + + 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 if (factory) { screen->Morph(factory, streamType); } } diff --git a/gfx/layers/client/ClientCanvasLayer.h b/gfx/layers/client/ClientCanvasLayer.h index 6338e0348430..37e5a1e6a539 100644 --- a/gfx/layers/client/ClientCanvasLayer.h +++ b/gfx/layers/client/ClientCanvasLayer.h @@ -33,17 +33,12 @@ public: ClientCanvasLayer(ClientLayerManager* aLayerManager) : CopyableCanvasLayer(aLayerManager, static_cast(MOZ_THIS_IN_INITIALIZER_LIST())) + , mTextureSurface(nullptr) + , mFactory(nullptr) { MOZ_COUNT_CTOR(ClientCanvasLayer); } - virtual ~ClientCanvasLayer() - { - MOZ_COUNT_DTOR(ClientCanvasLayer); - if (mCanvasClient) { - mCanvasClient->OnDetach(); - mCanvasClient = nullptr; - } - } + virtual ~ClientCanvasLayer(); virtual void SetVisibleRegion(const nsIntRegion& aRegion) { @@ -97,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 776d2619cdd5..c522e585a367 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -76,6 +76,9 @@ #ifdef USE_SKIA #include "mozilla/Hal.h" #include "skia/SkGraphics.h" + +#include "SkiaGLGlue.h" + #endif #include "mozilla/Preferences.h" @@ -202,6 +205,8 @@ MemoryPressureObserver::Observe(nsISupports *aSubject, { NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic"); Factory::PurgeAllCaches(); + + gfxPlatform::GetPlatform()->PurgeSkiaCache(); return NS_OK; } @@ -266,6 +271,8 @@ gfxPlatform::gfxPlatform() mLayersUseDeprecated = false; #endif + mSkiaGlue = nullptr; + uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA); uint32_t contentMask = BackendTypeBit(BackendType::CAIRO); InitBackendPrefs(canvasMask, BackendType::CAIRO, @@ -422,10 +429,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) { @@ -825,9 +828,8 @@ gfxPlatform::UseAcceleratedSkiaCanvas() } void -gfxPlatform::InitializeSkiaCaches() +gfxPlatform::InitializeSkiaCacheLimits() { -#ifdef USE_SKIA_GPU if (UseAcceleratedSkiaCanvas()) { bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache(); int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems(); @@ -847,12 +849,47 @@ gfxPlatform::InitializeSkiaCaches() } } -#ifdef DEBUG + #ifdef DEBUG printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit); + #endif + + mSkiaGlue->GetGrContext()->setTextureCacheLimits(cacheItemLimit, cacheSizeLimit); + } +} + +mozilla::gl::SkiaGLGlue* +gfxPlatform::GetSkiaGLGlue() +{ +#ifdef USE_SKIA_GPU + 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); + MOZ_ASSERT(mSkiaGlue->GetGrContext(), "No GrContext"); + InitializeSkiaCacheLimits(); + } #endif - Factory::SetGlobalSkiaCacheLimits(cacheItemLimit, cacheSizeLimit); - } + return mSkiaGlue; +} + +void +gfxPlatform::PurgeSkiaCache() +{ +#ifdef USE_SKIA_GPU + if (!mSkiaGlue) + return; + + mSkiaGlue->GetGrContext()->freeGpuResources(); #endif } diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index e1de1b29b9a4..a127c77d151b 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -40,6 +40,7 @@ struct gfxRGBA; namespace mozilla { namespace gl { class GLContext; +class SkiaGLGlue; } namespace gfx { class DrawTarget; @@ -283,8 +284,7 @@ public: } virtual bool UseAcceleratedSkiaCanvas(); - - virtual void InitializeSkiaCaches(); + virtual void InitializeSkiaCacheLimits(); void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend)); @@ -598,6 +598,9 @@ public: bool PreferMemoryOverShmem() const; bool UseDeprecatedTextures() const { return mLayersUseDeprecated; } + mozilla::gl::SkiaGLGlue* GetSkiaGLGlue(); + void PurgeSkiaCache(); + protected: gfxPlatform(); virtual ~gfxPlatform(); @@ -711,6 +714,7 @@ private: mozilla::RefPtr mRecorder; bool mLayersPreferMemoryOverShmem; bool mLayersUseDeprecated; + mozilla::RefPtr mSkiaGlue; }; #endif /* GFX_PLATFORM_H */