Bug 939276 - Use a single GLContext for all SkiaGL canvases r=vlad,gwright,bjacob

This commit is contained in:
James Willcox
2014-02-20 16:20:28 -06:00
parent 7c213dada5
commit 51a7c02955
27 changed files with 409 additions and 306 deletions

118
content/canvas/src/CanvasRenderingContext2D.cpp Normal file → Executable file
View File

@@ -94,14 +94,14 @@
#include "GLContext.h" #include "GLContext.h"
#include "GLContextProvider.h" #include "GLContextProvider.h"
#ifdef USE_SKIA_GPU
#undef free // apparently defined by some windows header, clashing with a free() #undef free // apparently defined by some windows header, clashing with a free()
// method in SkTypes.h // method in SkTypes.h
#include "GLContextSkia.h" #include "SkiaGLGlue.h"
#include "SurfaceStream.h"
#include "SurfaceTypes.h" #include "SurfaceTypes.h"
#include "nsIGfxInfo.h"
#endif
using mozilla::gl::GLContext; using mozilla::gl::GLContext;
using mozilla::gl::SkiaGLGlue;
using mozilla::gl::GLContextProvider; using mozilla::gl::GLContextProvider;
#ifdef XP_WIN #ifdef XP_WIN
@@ -430,28 +430,18 @@ public:
} }
} }
#ifdef USE_SKIA_GPU
static void PreTransactionCallback(void* aData) static void PreTransactionCallback(void* aData)
{ {
CanvasRenderingContext2DUserData* self = CanvasRenderingContext2DUserData* self =
static_cast<CanvasRenderingContext2DUserData*>(aData); static_cast<CanvasRenderingContext2DUserData*>(aData);
CanvasRenderingContext2D* context = self->mContext; CanvasRenderingContext2D* context = self->mContext;
if (!context) if (!context || !context->mStream || !context->mTarget)
return; return;
GLContext* glContext = static_cast<GLContext*>(context->mTarget->GetGLContext());
if (!glContext)
return;
if (context->mTarget) {
// Since SkiaGL default to store drawing command until flush // Since SkiaGL default to store drawing command until flush
// We will have to flush it before present. // We will have to flush it before present.
context->mTarget->Flush(); context->mTarget->Flush();
} }
glContext->MakeCurrent();
glContext->PublishFrame();
}
#endif
static void DidTransactionCallback(void* aData) static void DidTransactionCallback(void* aData)
{ {
@@ -542,18 +532,15 @@ DrawTarget* CanvasRenderingContext2D::sErrorTarget = nullptr;
CanvasRenderingContext2D::CanvasRenderingContext2D() CanvasRenderingContext2D::CanvasRenderingContext2D()
: mZero(false), mOpaque(false), mResetLayer(true) : mForceSoftware(false), mZero(false), mOpaque(false), mResetLayer(true)
, mIPC(false) , mIPC(false)
, mStream(nullptr)
, mIsEntireFrameInvalid(false) , mIsEntireFrameInvalid(false)
, mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false) , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
, mInvalidateCount(0) , mInvalidateCount(0)
{ {
sNumLivingContexts++; sNumLivingContexts++;
SetIsDOMBinding(); SetIsDOMBinding();
#ifdef USE_SKIA_GPU
mForceSoftware = false;
#endif
} }
CanvasRenderingContext2D::~CanvasRenderingContext2D() CanvasRenderingContext2D::~CanvasRenderingContext2D()
@@ -568,9 +555,7 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D()
NS_IF_RELEASE(sErrorTarget); NS_IF_RELEASE(sErrorTarget);
} }
#ifdef USE_SKIA_GPU
RemoveDemotableContext(this); RemoveDemotableContext(this);
#endif
} }
JSObject* JSObject*
@@ -629,6 +614,7 @@ CanvasRenderingContext2D::Reset()
} }
mTarget = nullptr; mTarget = nullptr;
mStream = nullptr;
// Since the target changes the backing texture will change, and this will // Since the target changes the backing texture will change, and this will
// no longer be valid. // no longer be valid.
@@ -750,8 +736,7 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
void CanvasRenderingContext2D::Demote() void CanvasRenderingContext2D::Demote()
{ {
#ifdef USE_SKIA_GPU if (!IsTargetValid() || mForceSoftware || !mStream)
if (!IsTargetValid() || mForceSoftware || !mTarget->GetGLContext())
return; return;
RemoveDemotableContext(this); RemoveDemotableContext(this);
@@ -759,6 +744,7 @@ void CanvasRenderingContext2D::Demote()
RefPtr<SourceSurface> snapshot = mTarget->Snapshot(); RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
RefPtr<DrawTarget> oldTarget = mTarget; RefPtr<DrawTarget> oldTarget = mTarget;
mTarget = nullptr; mTarget = nullptr;
mStream = nullptr;
mResetLayer = true; mResetLayer = true;
mForceSoftware = true; mForceSoftware = true;
@@ -777,11 +763,8 @@ void CanvasRenderingContext2D::Demote()
} }
mTarget->SetTransform(oldTarget->GetTransform()); mTarget->SetTransform(oldTarget->GetTransform());
#endif
} }
#ifdef USE_SKIA_GPU
std::vector<CanvasRenderingContext2D*>& std::vector<CanvasRenderingContext2D*>&
CanvasRenderingContext2D::DemotableContexts() CanvasRenderingContext2D::DemotableContexts()
{ {
@@ -792,11 +775,7 @@ CanvasRenderingContext2D::DemotableContexts()
void void
CanvasRenderingContext2D::DemoteOldestContextIfNecessary() CanvasRenderingContext2D::DemoteOldestContextIfNecessary()
{ {
#ifdef MOZ_GFX_OPTIMIZE_MOBILE const size_t kMaxContexts = 64;
const size_t kMaxContexts = 2;
#else
const size_t kMaxContexts = 16;
#endif
std::vector<CanvasRenderingContext2D*>& contexts = DemotableContexts(); std::vector<CanvasRenderingContext2D*>& contexts = DemotableContexts();
if (contexts.size() < kMaxContexts) if (contexts.size() < kMaxContexts)
@@ -830,8 +809,6 @@ CheckSizeForSkiaGL(IntSize size) {
return size.width >= minsize && size.height >= minsize; return size.width >= minsize && size.height >= minsize;
} }
#endif
void void
CanvasRenderingContext2D::EnsureTarget() CanvasRenderingContext2D::EnsureTarget()
{ {
@@ -857,39 +834,26 @@ CanvasRenderingContext2D::EnsureTarget()
} }
if (layerManager) { if (layerManager) {
#ifdef USE_SKIA_GPU if (gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() &&
if (gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas()) { !mForceSoftware &&
SurfaceCaps caps = SurfaceCaps::ForRGBA(); CheckSizeForSkiaGL(size)) {
caps.preserve = true;
#ifdef MOZ_WIDGET_GONK
layers::ShadowLayerForwarder *forwarder = layerManager->AsShadowForwarder();
if (forwarder) {
caps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
}
#endif
DemoteOldestContextIfNecessary(); DemoteOldestContextIfNecessary();
nsRefPtr<GLContext> glContext; SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
nsString vendor;
if (!mForceSoftware && CheckSizeForSkiaGL(size)) if (glue) {
{ mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
glContext = GLContextProvider::CreateOffscreen(gfxIntSize(size.width, size.height), if (mTarget) {
caps); mStream = gfx::SurfaceStream::CreateForType(SurfaceStreamType::TripleBuffer, glue->GetGLContext());
}
if (glContext) {
SkAutoTUnref<GrGLInterface> i(CreateGrGLInterfaceFromGLContext(glContext));
mTarget = Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(glContext, i, size, format);
AddDemotableContext(this); AddDemotableContext(this);
} else { } else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
}
}
if (!mTarget) {
mTarget = layerManager->CreateDrawTarget(size, format); mTarget = layerManager->CreateDrawTarget(size, format);
} }
} else } else
#endif
mTarget = layerManager->CreateDrawTarget(size, format); mTarget = layerManager->CreateDrawTarget(size, format);
} else { } else {
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format); mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
@@ -1077,12 +1041,10 @@ CanvasRenderingContext2D::SetContextOptions(JSContext* aCx, JS::Handle<JS::Value
ContextAttributes2D attributes; ContextAttributes2D attributes;
NS_ENSURE_TRUE(attributes.Init(aCx, aOptions), NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(attributes.Init(aCx, aOptions), NS_ERROR_UNEXPECTED);
#ifdef USE_SKIA_GPU
if (Preferences::GetBool("gfx.canvas.willReadFrequently.enable", false)) { if (Preferences::GetBool("gfx.canvas.willReadFrequently.enable", false)) {
// Use software when there is going to be a lot of readback // Use software when there is going to be a lot of readback
mForceSoftware = attributes.mWillReadFrequently; mForceSoftware = attributes.mWillReadFrequently;
} }
#endif
return NS_OK; return NS_OK;
} }
@@ -3246,7 +3208,6 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
NS_ENSURE_SUCCESS_VOID(rv); NS_ENSURE_SUCCESS_VOID(rv);
} }
#ifdef USE_SKIA_GPU
static bool static bool
IsStandardCompositeOp(CompositionOp op) IsStandardCompositeOp(CompositionOp op)
{ {
@@ -3262,7 +3223,6 @@ IsStandardCompositeOp(CompositionOp op)
op == CompositionOp::OP_ADD || op == CompositionOp::OP_ADD ||
op == CompositionOp::OP_XOR); op == CompositionOp::OP_XOR);
} }
#endif
void void
CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op, CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op,
@@ -3303,11 +3263,9 @@ CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op,
// XXX ERRMSG we need to report an error to developers here! (bug 329026) // XXX ERRMSG we need to report an error to developers here! (bug 329026)
else return; else return;
#ifdef USE_SKIA_GPU
if (!IsStandardCompositeOp(comp_op)) { if (!IsStandardCompositeOp(comp_op)) {
Demote(); Demote();
} }
#endif
#undef CANVAS_OP_TO_GFX_OP #undef CANVAS_OP_TO_GFX_OP
CurrentState().op = comp_op; CurrentState().op = comp_op;
@@ -3353,11 +3311,9 @@ CanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op,
error.Throw(NS_ERROR_FAILURE); error.Throw(NS_ERROR_FAILURE);
} }
#ifdef USE_SKIA_GPU
if (!IsStandardCompositeOp(comp_op)) { if (!IsStandardCompositeOp(comp_op)) {
Demote(); Demote();
} }
#endif
#undef CANVAS_OP_TO_GFX_OP #undef CANVAS_OP_TO_GFX_OP
} }
@@ -4057,7 +4013,17 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
aOldLayer->GetUserData(&g2DContextLayerUserData)); aOldLayer->GetUserData(&g2DContextLayerUserData));
CanvasLayer::Data data; CanvasLayer::Data data;
data.mGLContext = static_cast<GLContext*>(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)) { if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) {
nsRefPtr<CanvasLayer> ret = aOldLayer; nsRefPtr<CanvasLayer> ret = aOldLayer;
return ret.forget(); return ret.forget();
@@ -4090,15 +4056,17 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
canvasLayer->SetUserData(&g2DContextLayerUserData, userData); canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
CanvasLayer::Data data; CanvasLayer::Data data;
#ifdef USE_SKIA_GPU if (mStream) {
GLContext* glContext = static_cast<GLContext*>(mTarget->GetGLContext()); SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
if (glContext) {
if (glue) {
canvasLayer->SetPreTransactionCallback( canvasLayer->SetPreTransactionCallback(
CanvasRenderingContext2DUserData::PreTransactionCallback, userData); CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
data.mGLContext = glContext; data.mGLContext = glue->GetGLContext();
} else data.mStream = mStream.get();
#endif data.mTexID = (uint32_t)((uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE));
{ }
} else {
data.mDrawTarget = mTarget; data.mDrawTarget = mTarget;
} }

View File

@@ -31,6 +31,7 @@ class nsXULElement;
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class SourceSurface; class SourceSurface;
class SurfaceStream;
} }
namespace dom { namespace dom {
@@ -593,7 +594,6 @@ protected:
return CurrentState().font; return CurrentState().font;
} }
#if USE_SKIA_GPU
static std::vector<CanvasRenderingContext2D*>& DemotableContexts(); static std::vector<CanvasRenderingContext2D*>& DemotableContexts();
static void DemoteOldestContextIfNecessary(); static void DemoteOldestContextIfNecessary();
@@ -602,7 +602,6 @@ protected:
// Do not use GL // Do not use GL
bool mForceSoftware; bool mForceSoftware;
#endif
// Member vars // Member vars
int32_t mWidth, mHeight; int32_t mWidth, mHeight;
@@ -629,6 +628,8 @@ protected:
// sErrorTarget. // sErrorTarget.
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget; mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
RefPtr<gfx::SurfaceStream> mStream;
/** /**
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
* Redraw is called, reset to false when Render is called. * Redraw is called, reset to false when Render is called.

View File

@@ -962,13 +962,8 @@ public:
return mPermitSubpixelAA; return mPermitSubpixelAA;
} }
virtual GenericRefCountedBase* GetGLContext() const {
return nullptr;
}
#ifdef USE_SKIA_GPU #ifdef USE_SKIA_GPU
virtual void InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, virtual void InitWithGrContext(GrContext* aGrContext,
GrGLInterface* aGrGLInterface,
const IntSize &aSize, const IntSize &aSize,
SurfaceFormat aFormat) SurfaceFormat aFormat)
{ {
@@ -1075,13 +1070,9 @@ public:
#ifdef USE_SKIA_GPU #ifdef USE_SKIA_GPU
static TemporaryRef<DrawTarget> static TemporaryRef<DrawTarget>
CreateDrawTargetSkiaWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
GrGLInterface* aGrGLInterface,
const IntSize &aSize, const IntSize &aSize,
SurfaceFormat aFormat); SurfaceFormat aFormat);
static void
SetGlobalSkiaCacheLimits(int aCount, int aSizeInBytes);
#endif #endif
static void PurgeAllCaches(); static void PurgeAllCaches();

View File

@@ -78,80 +78,6 @@ public:
ExtendMode mExtendMode; ExtendMode mExtendMode;
}; };
#ifdef USE_SKIA_GPU
int DrawTargetSkia::sTextureCacheCount = 256;
int DrawTargetSkia::sTextureCacheSizeInBytes = 96*1024*1024;
static std::vector<DrawTargetSkia*>&
GLDrawTargets()
{
static std::vector<DrawTargetSkia*> targets;
return targets;
}
void
DrawTargetSkia::RebalanceCacheLimits()
{
// Divide the global cache limits equally between all currently active GL-backed
// Skia DrawTargets.
std::vector<DrawTargetSkia*>& 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<DrawTargetSkia*>& targets = GLDrawTargets();
std::vector<DrawTargetSkia*>::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<DrawTargetSkia*>& 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 * When constructing a temporary SkBitmap via GetBitmapForSurface, we may also
* have to construct a temporary DataSourceSurface, which must live as long as * have to construct a temporary DataSourceSurface, which must live as long as
@@ -188,15 +114,12 @@ GetBitmapForSurface(SourceSurface* aSurface)
} }
DrawTargetSkia::DrawTargetSkia() DrawTargetSkia::DrawTargetSkia()
: mSnapshot(nullptr) : mTexture(0), mSnapshot(nullptr)
{ {
} }
DrawTargetSkia::~DrawTargetSkia() DrawTargetSkia::~DrawTargetSkia()
{ {
#ifdef USE_SKIA_GPU
RemoveGLDrawTarget(this);
#endif
} }
TemporaryRef<SourceSurface> TemporaryRef<SourceSurface>
@@ -769,45 +692,33 @@ DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
#ifdef USE_SKIA_GPU #ifdef USE_SKIA_GPU
void void
DrawTargetSkia::InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, DrawTargetSkia::InitWithGrContext(GrContext* aGrContext,
GrGLInterface* aGrGLInterface,
const IntSize &aSize, const IntSize &aSize,
SurfaceFormat aFormat) SurfaceFormat aFormat)
{ {
mGLContext = aGLContext; mGrContext = aGrContext;
mSize = aSize; mSize = aSize;
mFormat = aFormat; mFormat = aFormat;
mGrGLInterface = aGrGLInterface; GrTextureDesc targetDescriptor;
mGrGLInterface->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(this);
GrBackendContext backendContext = reinterpret_cast<GrBackendContext>(aGrGLInterface);
SkAutoTUnref<GrContext> gr(GrContext::Create(kOpenGL_GrBackend, backendContext));
mGrContext = gr.get();
GrBackendRenderTargetDesc targetDescriptor;
targetDescriptor.fFlags = kRenderTarget_GrTextureFlagBit;
targetDescriptor.fWidth = mSize.width; targetDescriptor.fWidth = mSize.width;
targetDescriptor.fHeight = mSize.height; targetDescriptor.fHeight = mSize.height;
targetDescriptor.fConfig = GfxFormatToGrConfig(mFormat); targetDescriptor.fConfig = GfxFormatToGrConfig(mFormat);
targetDescriptor.fOrigin = kBottomLeft_GrSurfaceOrigin; targetDescriptor.fOrigin = kBottomLeft_GrSurfaceOrigin;
targetDescriptor.fSampleCnt = 0; targetDescriptor.fSampleCnt = 0;
targetDescriptor.fRenderTargetHandle = 0; // GLContext always exposes the right framebuffer as id 0
SkAutoTUnref<GrRenderTarget> target(mGrContext->wrapBackendRenderTarget(targetDescriptor)); SkAutoTUnref<GrTexture> skiaTexture(mGrContext->createUncachedTexture(targetDescriptor, NULL, 0));
SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(mGrContext.get(), target.get()));
mTexture = (uint32_t)skiaTexture->getTextureHandle();
SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(mGrContext.get(), skiaTexture->asRenderTarget()));
SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get())); SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
mCanvas = canvas.get(); mCanvas = canvas.get();
AddGLDrawTarget(this);
} }
void
DrawTargetSkia::SetCacheLimits(int aCount, int aSizeInBytes)
{
MOZ_ASSERT(mGrContext, "No GrContext!");
mGrContext->setTextureCacheLimits(aCount, aSizeInBytes);
}
#endif #endif
void void
@@ -839,6 +750,17 @@ DrawTargetSkia::SetTransform(const Matrix& aTransform)
mTransform = aTransform; mTransform = aTransform;
} }
void*
DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType)
{
if (aType == NativeSurfaceType::OPENGL_TEXTURE) {
return (void*)((uintptr_t)mTexture);
}
return nullptr;
}
TemporaryRef<PathBuilder> TemporaryRef<PathBuilder>
DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
{ {

View File

@@ -99,23 +99,15 @@ public:
virtual TemporaryRef<GradientStops> CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const; virtual TemporaryRef<GradientStops> CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const;
virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType); virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
virtual void SetTransform(const Matrix &aTransform); virtual void SetTransform(const Matrix &aTransform);
virtual void *GetNativeSurface(NativeSurfaceType aType);
bool Init(const IntSize &aSize, SurfaceFormat aFormat); bool Init(const IntSize &aSize, SurfaceFormat aFormat);
void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
#ifdef USE_SKIA_GPU #ifdef USE_SKIA_GPU
virtual GenericRefCountedBase* GetGLContext() const MOZ_OVERRIDE { return mGLContext; } void InitWithGrContext(GrContext* aGrContext,
void InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext,
GrGLInterface* aGrGLInterface,
const IntSize &aSize, const IntSize &aSize,
SurfaceFormat aFormat) MOZ_OVERRIDE; 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();
#endif #endif
operator std::string() const { operator std::string() const {
@@ -133,18 +125,8 @@ private:
SkRect SkRectCoveringWholeSurface() const; SkRect SkRectCoveringWholeSurface() const;
#ifdef USE_SKIA_GPU #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<GenericRefCountedBase> mGLContext;
SkRefPtr<GrGLInterface> mGrGLInterface;
SkRefPtr<GrContext> mGrContext; SkRefPtr<GrContext> mGrContext;
uint32_t mTexture;
static int sTextureCacheCount;
static int sTextureCacheSizeInBytes;
#endif #endif
IntSize mSize; IntSize mSize;

View File

@@ -586,30 +586,21 @@ Factory::D2DCleanup()
#ifdef USE_SKIA_GPU #ifdef USE_SKIA_GPU
TemporaryRef<DrawTarget> TemporaryRef<DrawTarget>
Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext, Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
GrGLInterface* aGrGLInterface,
const IntSize &aSize, const IntSize &aSize,
SurfaceFormat aFormat) SurfaceFormat aFormat)
{ {
DrawTargetSkia* newDrawTargetSkia = new DrawTargetSkia(); DrawTargetSkia* newDrawTargetSkia = new DrawTargetSkia();
newDrawTargetSkia->InitWithGLContextAndGrGLInterface(aGLContext, aGrGLInterface, aSize, aFormat); newDrawTargetSkia->InitWithGrContext(aGrContext, aSize, aFormat);
RefPtr<DrawTarget> newTarget = newDrawTargetSkia; RefPtr<DrawTarget> newTarget = newDrawTargetSkia;
return newTarget; return newTarget;
} }
void
Factory::SetGlobalSkiaCacheLimits(int aCount, int aSizeInBytes)
{
DrawTargetSkia::SetGlobalCacheLimits(aCount, aSizeInBytes);
}
#endif // USE_SKIA_GPU #endif // USE_SKIA_GPU
void void
Factory::PurgeAllCaches() Factory::PurgeAllCaches()
{ {
#ifdef USE_SKIA_GPU
DrawTargetSkia::PurgeAllCaches();
#endif
} }
#ifdef USE_SKIA_FREETYPE #ifdef USE_SKIA_FREETYPE

View File

@@ -96,7 +96,8 @@ MOZ_BEGIN_ENUM_CLASS(NativeSurfaceType, int8_t)
CAIRO_SURFACE, CAIRO_SURFACE,
CAIRO_CONTEXT, CAIRO_CONTEXT,
CGCONTEXT, CGCONTEXT,
CGCONTEXT_ACCELERATED CGCONTEXT_ACCELERATED,
OPENGL_TEXTURE
MOZ_END_ENUM_CLASS(NativeSurfaceType) MOZ_END_ENUM_CLASS(NativeSurfaceType)
MOZ_BEGIN_ENUM_CLASS(NativeFontType, int8_t) MOZ_BEGIN_ENUM_CLASS(NativeFontType, int8_t)

View File

@@ -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);

3
gfx/gl/GLScreenBuffer.cpp Normal file → Executable file
View File

@@ -43,6 +43,7 @@ GLScreenBuffer::Create(GLContext* gl,
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
/* On B2G, we want a Gralloc factory, and we want one right at the start */ /* On B2G, we want a Gralloc factory, and we want one right at the start */
if (!factory && if (!factory &&
caps.surfaceAllocator &&
XRE_GetProcessType() != GeckoProcessType_Default) XRE_GetProcessType() != GeckoProcessType_Default)
{ {
factory = new SurfaceFactory_Gralloc(gl, caps); factory = new SurfaceFactory_Gralloc(gl, caps);
@@ -70,7 +71,6 @@ GLScreenBuffer::Create(GLContext* gl,
GLScreenBuffer::~GLScreenBuffer() GLScreenBuffer::~GLScreenBuffer()
{ {
delete mStream;
delete mDraw; delete mDraw;
delete mRead; delete mRead;
@@ -378,7 +378,6 @@ GLScreenBuffer::Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamTyp
SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream); SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream);
MOZ_ASSERT(newStream); MOZ_ASSERT(newStream);
delete mStream;
mStream = newStream; mStream = newStream;
} }

View File

@@ -16,6 +16,7 @@
#define SCREEN_BUFFER_H_ #define SCREEN_BUFFER_H_
#include "SurfaceTypes.h" #include "SurfaceTypes.h"
#include "SurfaceStream.h"
#include "GLContextTypes.h" #include "GLContextTypes.h"
#include "GLDefs.h" #include "GLDefs.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
@@ -156,7 +157,7 @@ protected:
GLContext* const mGL; // Owns us. GLContext* const mGL; // Owns us.
SurfaceCaps mCaps; SurfaceCaps mCaps;
SurfaceFactory_GL* mFactory; // Owned by us. SurfaceFactory_GL* mFactory; // Owned by us.
SurfaceStream* mStream; // Owned by us. RefPtr<SurfaceStream> mStream;
DrawBuffer* mDraw; // Owned by us. DrawBuffer* mDraw; // Owned by us.
ReadBuffer* mRead; // Owned by us. ReadBuffer* mRead; // Owned by us.

View File

@@ -119,27 +119,33 @@ SharedSurface_GL::Copy(SharedSurface_GL* src, SharedSurface_GL* dest,
// Only {src,dest}x{texture,renderbuffer} left. // Only {src,dest}x{texture,renderbuffer} left.
if (src->AttachType() == AttachmentType::GLTexture) { if (src->AttachType() == AttachmentType::GLTexture) {
src->LockProd();
GLuint srcTex = src->Texture(); GLuint srcTex = src->Texture();
GLenum srcTarget = src->TextureTarget(); GLenum srcTarget = src->TextureTarget();
if (dest->AttachType() == AttachmentType::GLTexture) { if (dest->AttachType() == AttachmentType::GLTexture) {
dest->LockProd();
GLuint destTex = dest->Texture(); GLuint destTex = dest->Texture();
GLenum destTarget = dest->TextureTarget(); GLenum destTarget = dest->TextureTarget();
gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex, gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex,
src->Size(), dest->Size(), src->Size(), dest->Size(),
srcTarget, destTarget); srcTarget, destTarget);
src->UnlockProd();
dest->UnlockProd();
return; return;
} }
if (dest->AttachType() == AttachmentType::GLRenderbuffer) { if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
dest->LockProd();
GLuint destRB = dest->Renderbuffer(); GLuint destRB = dest->Renderbuffer();
ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(), gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(),
src->Size(), dest->Size(), srcTarget); src->Size(), dest->Size(), srcTarget);
src->UnlockProd();
dest->UnlockProd();
return; return;
} }
@@ -183,7 +189,9 @@ SharedSurface_GL::LockProd()
LockProdImpl(); LockProdImpl();
if (AttachType() == AttachmentType::Screen)
mGL->LockSurface(this); mGL->LockSurface(this);
mIsLocked = true; mIsLocked = true;
} }
@@ -195,7 +203,9 @@ SharedSurface_GL::UnlockProd()
UnlockProdImpl(); UnlockProdImpl();
if (AttachType() == AttachmentType::Screen)
mGL->UnlockSurface(this); mGL->UnlockSurface(this);
mIsLocked = false; mIsLocked = false;
} }
@@ -283,8 +293,23 @@ SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
gl, gl,
size, size,
hasAlpha) hasAlpha)
, mTex(tex) , mTex(tex), mFB(0)
{ {
mGL->MakeCurrent();
mGL->fGenFramebuffers(1, &mFB);
mGL->BindFB(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, mData = Factory::CreateDataSourceSurfaceWithStride(size, format,
GetAlignedStride<4>(size.width * BytesPerPixel(format))); GetAlignedStride<4>(size.width * BytesPerPixel(format)));
} }
@@ -294,16 +319,19 @@ SharedSurface_Basic::~SharedSurface_Basic()
if (!mGL->MakeCurrent()) if (!mGL->MakeCurrent())
return; return;
if (mFB)
mGL->fDeleteFramebuffers(1, &mFB);
mGL->fDeleteTextures(1, &mTex); mGL->fDeleteTextures(1, &mTex);
} }
void void
SharedSurface_Basic::Fence() SharedSurface_Basic::Fence()
{ {
MOZ_ASSERT(mData->GetSize() == mGL->OffscreenSize());
mGL->MakeCurrent(); mGL->MakeCurrent();
ScopedBindFramebuffer autoFB(mGL, mFB);
DataSourceSurface::MappedSurface map; DataSourceSurface::MappedSurface map;
mData->Map(DataSourceSurface::MapType::WRITE, &map); mData->Map(DataSourceSurface::MapType::WRITE, &map);
nsRefPtr<gfxImageSurface> wrappedData = nsRefPtr<gfxImageSurface> wrappedData =
@@ -311,7 +339,7 @@ SharedSurface_Basic::Fence()
ThebesIntSize(mData->GetSize()), ThebesIntSize(mData->GetSize()),
map.mStride, map.mStride,
SurfaceFormatToImageFormat(mData->GetFormat())); SurfaceFormatToImageFormat(mData->GetFormat()));
ReadScreenIntoImageSurface(mGL, wrappedData); ReadPixelsIntoImageSurface(mGL, wrappedData);
mData->Unmap(); mData->Unmap();
} }
@@ -322,15 +350,24 @@ SharedSurface_GLTexture::Create(GLContext* prodGL,
GLContext* consGL, GLContext* consGL,
const GLFormats& formats, const GLFormats& formats,
const gfx::IntSize& size, const gfx::IntSize& size,
bool hasAlpha) bool hasAlpha,
GLuint texture)
{ {
MOZ_ASSERT(prodGL); MOZ_ASSERT(prodGL);
MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL)); MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL));
prodGL->MakeCurrent(); 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() SharedSurface_GLTexture::~SharedSurface_GLTexture()
@@ -338,7 +375,9 @@ SharedSurface_GLTexture::~SharedSurface_GLTexture()
if (!mGL->MakeCurrent()) if (!mGL->MakeCurrent())
return; return;
if (mOwnsTex) {
mGL->fDeleteTextures(1, &mTex); mGL->fDeleteTextures(1, &mTex);
}
if (mSync) { if (mSync) {
mGL->fDeleteSync(mSync); mGL->fDeleteSync(mSync);

View File

@@ -6,6 +6,7 @@
#ifndef SHARED_SURFACE_GL_H_ #ifndef SHARED_SURFACE_GL_H_
#define SHARED_SURFACE_GL_H_ #define SHARED_SURFACE_GL_H_
#include "ScopedGLHelpers.h"
#include "SharedSurface.h" #include "SharedSurface.h"
#include "SurfaceFactory.h" #include "SurfaceFactory.h"
#include "SurfaceTypes.h" #include "SurfaceTypes.h"
@@ -135,6 +136,8 @@ public:
protected: protected:
const GLuint mTex; const GLuint mTex;
GLuint mFB;
RefPtr<gfx::DataSourceSurface> mData; RefPtr<gfx::DataSourceSurface> mData;
SharedSurface_Basic(GLContext* gl, SharedSurface_Basic(GLContext* gl,
@@ -192,7 +195,8 @@ public:
GLContext* consGL, GLContext* consGL,
const GLFormats& formats, const GLFormats& formats,
const gfx::IntSize& size, const gfx::IntSize& size,
bool hasAlpha); bool hasAlpha,
GLuint texture = 0);
static SharedSurface_GLTexture* Cast(SharedSurface* surf) { static SharedSurface_GLTexture* Cast(SharedSurface* surf) {
MOZ_ASSERT(surf->Type() == SharedSurfaceType::GLTextureShare); MOZ_ASSERT(surf->Type() == SharedSurfaceType::GLTextureShare);
@@ -203,6 +207,7 @@ public:
protected: protected:
GLContext* mConsGL; GLContext* mConsGL;
const GLuint mTex; const GLuint mTex;
const bool mOwnsTex;
GLsync mSync; GLsync mSync;
mutable Mutex mMutex; mutable Mutex mMutex;
@@ -210,7 +215,8 @@ protected:
GLContext* consGL, GLContext* consGL,
const gfx::IntSize& size, const gfx::IntSize& size,
bool hasAlpha, bool hasAlpha,
GLuint tex) GLuint tex,
bool ownsTex)
: SharedSurface_GL(SharedSurfaceType::GLTextureShare, : SharedSurface_GL(SharedSurfaceType::GLTextureShare,
AttachmentType::GLTexture, AttachmentType::GLTexture,
prodGL, prodGL,
@@ -218,6 +224,7 @@ protected:
hasAlpha) hasAlpha)
, mConsGL(consGL) , mConsGL(consGL)
, mTex(tex) , mTex(tex)
, mOwnsTex(ownsTex)
, mSync(0) , mSync(0)
, mMutex("SharedSurface_GLTexture mutex") , mMutex("SharedSurface_GLTexture mutex")
{ {

20
gfx/gl/GLContextSkia.cpp → gfx/gl/SkiaGLGlue.cpp Normal file → Executable file
View File

@@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "skia/GrContext.h"
#include "skia/GrGLInterface.h" #include "skia/GrGLInterface.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/ThreadLocal.h" #include "mozilla/ThreadLocal.h"
@@ -16,9 +17,11 @@
#endif #endif
#include "GLContext.h" #include "GLContext.h"
#include "SkiaGLGlue.h"
using mozilla::gl::GLContext; using mozilla::gl::GLContext;
using mozilla::gl::GLFeature; using mozilla::gl::GLFeature;
using mozilla::gl::SkiaGLGlue;
using mozilla::gfx::DrawTarget; using mozilla::gfx::DrawTarget;
static mozilla::ThreadLocal<GLContext*> sGLContext; static mozilla::ThreadLocal<GLContext*> sGLContext;
@@ -27,8 +30,8 @@ extern "C" {
void EnsureGLContext(const GrGLInterface* i) void EnsureGLContext(const GrGLInterface* i)
{ {
const DrawTarget* drawTarget = reinterpret_cast<const DrawTarget*>(i->fCallbackData); const SkiaGLGlue* contextSkia = reinterpret_cast<const SkiaGLGlue*>(i->fCallbackData);
GLContext* gl = static_cast<GLContext*>(drawTarget->GetGLContext()); GLContext* gl = contextSkia->GetGLContext();
gl->MakeCurrent(); gl->MakeCurrent();
if (!sGLContext.initialized()) { if (!sGLContext.initialized()) {
@@ -775,7 +778,7 @@ GrGLvoid glVertexPointer_mozilla(GrGLint size, GrGLenum type, GrGLsizei stride,
} // extern "C" } // extern "C"
GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
{ {
GrGLInterface* i = new GrGLInterface(); GrGLInterface* i = new GrGLInterface();
i->fCallback = EnsureGLContext; i->fCallback = EnsureGLContext;
@@ -934,3 +937,14 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
return i; return i;
} }
SkiaGLGlue::SkiaGLGlue(GLContext* context)
: mGLContext(context)
{
SkAutoTUnref<GrGLInterface> i(CreateGrGLInterfaceFromGLContext(mGLContext));
i->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(this);
mGrGLInterface = i;
SkAutoTUnref<GrContext> gr(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get()));
mGrContext = gr;
}

64
gfx/gl/SkiaGLGlue.h Executable file
View File

@@ -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<GLContext> mGLContext;
SkRefPtr<GrGLInterface> mGrGLInterface;
SkRefPtr<GrContext> 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

View File

@@ -7,6 +7,7 @@
#include "gfxPoint.h" #include "gfxPoint.h"
#include "SharedSurface.h" #include "SharedSurface.h"
#include "SharedSurfaceGL.h"
#include "SurfaceFactory.h" #include "SurfaceFactory.h"
#include "GeckoProfiler.h" #include "GeckoProfiler.h"
@@ -53,6 +54,22 @@ SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glC
return result; 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 void
SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size, SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size,
SharedSurface*& surf) SharedSurface*& surf)

View File

@@ -11,6 +11,7 @@
#include "mozilla/Monitor.h" #include "mozilla/Monitor.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/gfx/Point.h" #include "mozilla/gfx/Point.h"
#include "mozilla/GenericRefCounted.h"
#include "SurfaceTypes.h" #include "SurfaceTypes.h"
namespace mozilla { namespace mozilla {
@@ -24,7 +25,7 @@ class SharedSurface;
class SurfaceFactory; class SurfaceFactory;
// Owned by: ScreenBuffer // Owned by: ScreenBuffer
class SurfaceStream class SurfaceStream : public GenericAtomicRefCounted
{ {
public: public:
typedef enum { typedef enum {
@@ -50,6 +51,8 @@ public:
const SurfaceStreamType mType; const SurfaceStreamType mType;
mozilla::gl::GLContext* GLContext() const { return mGLContext; } mozilla::gl::GLContext* GLContext() const { return mGLContext; }
protected: protected:
// |mProd| is owned by us, but can be ripped away when // |mProd| is owned by us, but can be ripped away when
// creating a new GLStream from this one. // creating a new GLStream from this one.
@@ -121,6 +124,8 @@ public:
virtual SharedSurface* Resize(SurfaceFactory* factory, const gfx::IntSize& size); virtual SharedSurface* Resize(SurfaceFactory* factory, const gfx::IntSize& size);
virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) { MOZ_ASSERT(0); return false; }
protected: protected:
// SwapCons will return the same surface more than once, // SwapCons will return the same surface more than once,
// if nothing new has been published. // if nothing new has been published.
@@ -189,6 +194,7 @@ protected:
public: public:
SurfaceStream_TripleBuffer(SurfaceStream* prevStream); SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
virtual ~SurfaceStream_TripleBuffer(); virtual ~SurfaceStream_TripleBuffer();
virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory);
private: private:
// Common constructor code. // Common constructor code.

View File

@@ -75,9 +75,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'SharedSurfaceANGLE.cpp', 'SharedSurfaceANGLE.cpp',
] ]
if CONFIG['MOZ_ENABLE_SKIA_GPU']: if CONFIG['MOZ_ENABLE_SKIA_GPU']:
EXPORTS += ['GLContextSkia.h'] EXPORTS += ['SkiaGLGlue.h']
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
'GLContextSkia.cpp', 'SkiaGLGlue.cpp',
] ]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':

View File

@@ -32,6 +32,7 @@ namespace layers {
CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) : CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
CanvasLayer(aLayerManager, aImplData) CanvasLayer(aLayerManager, aImplData)
, mStream(nullptr)
{ {
MOZ_COUNT_CTOR(CopyableCanvasLayer); MOZ_COUNT_CTOR(CopyableCanvasLayer);
mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false); mForceReadback = Preferences::GetBool("webgl.force-layers-readback", false);
@@ -49,6 +50,7 @@ CopyableCanvasLayer::Initialize(const Data& aData)
if (aData.mGLContext) { if (aData.mGLContext) {
mGLContext = aData.mGLContext; mGLContext = aData.mGLContext;
mStream = aData.mStream;
mIsGLAlphaPremult = aData.mIsGLAlphaPremult; mIsGLAlphaPremult = aData.mIsGLAlphaPremult;
mNeedsYFlip = true; mNeedsYFlip = true;
MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen"); MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
@@ -71,7 +73,7 @@ CopyableCanvasLayer::Initialize(const Data& aData)
bool bool
CopyableCanvasLayer::IsDataValid(const Data& aData) CopyableCanvasLayer::IsDataValid(const Data& aData)
{ {
return mGLContext == aData.mGLContext; return mGLContext == aData.mGLContext && mStream == aData.mStream;
} }
void void

View File

@@ -22,6 +22,13 @@
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc #include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
namespace mozilla { namespace mozilla {
namespace gfx {
class SurfaceStream;
class SharedSurface;
class SurfaceFactory;
}
namespace layers { namespace layers {
class CanvasClientWebGL; class CanvasClientWebGL;
@@ -54,6 +61,8 @@ protected:
nsRefPtr<mozilla::gl::GLContext> mGLContext; nsRefPtr<mozilla::gl::GLContext> mGLContext;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget; mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
RefPtr<gfx::SurfaceStream> mStream;
uint32_t mCanvasFramebuffer; uint32_t mCanvasFramebuffer;
bool mIsGLAlphaPremult; bool mIsGLAlphaPremult;

View File

@@ -63,6 +63,7 @@ class GLContext;
namespace gfx { namespace gfx {
class DrawTarget; class DrawTarget;
class SurfaceStream;
} }
namespace css { namespace css {
@@ -1790,6 +1791,8 @@ public:
Data() Data()
: mDrawTarget(nullptr) : mDrawTarget(nullptr)
, mGLContext(nullptr) , mGLContext(nullptr)
, mStream(nullptr)
, mTexID(0)
, mSize(0,0) , mSize(0,0)
, mIsGLAlphaPremult(false) , mIsGLAlphaPremult(false)
{ } { }
@@ -1798,6 +1801,12 @@ public:
mozilla::gfx::DrawTarget *mDrawTarget; // a DrawTarget for the canvas contents mozilla::gfx::DrawTarget *mDrawTarget; // a DrawTarget for the canvas contents
mozilla::gl::GLContext* mGLContext; // or this, for GL. 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 // The size of the canvas content
nsIntSize mSize; nsIntSize mSize;

View File

@@ -116,7 +116,18 @@ void
CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
{ {
GLScreenBuffer* screen = aLayer->mGLContext->Screen(); 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 isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
bool bufferCreated = false; bool bufferCreated = false;
@@ -255,7 +266,15 @@ DeprecatedCanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLaye
mDeprecatedTextureClient->EnsureAllocated(aSize, gfxContentType::COLOR); mDeprecatedTextureClient->EnsureAllocated(aSize, gfxContentType::COLOR);
GLScreenBuffer* screen = aLayer->mGLContext->Screen(); 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 isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
if (isCrossProcess) { if (isCrossProcess) {

View File

@@ -41,6 +41,13 @@ ClientCanvasLayer::Initialize(const Data& aData)
if (mGLContext) { if (mGLContext) {
GLScreenBuffer* screen = mGLContext->Screen(); 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 = SurfaceStreamType streamType =
SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread, SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
screen->PreserveBuffer()); screen->PreserveBuffer());
@@ -52,11 +59,11 @@ ClientCanvasLayer::Initialize(const Data& aData)
if (!isCrossProcess) { if (!isCrossProcess) {
// [Basic/OGL Layers, OMTC] WebGL layer init. // [Basic/OGL Layers, OMTC] WebGL layer init.
factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps()); factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
} else { } else {
// [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing) // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
factory = new SurfaceFactory_Gralloc(mGLContext, screen->Caps(), ClientManager()->AsShadowForwarder()); factory = new SurfaceFactory_Gralloc(mGLContext, caps, ClientManager()->AsShadowForwarder());
#else #else
// we could do readback here maybe // we could do readback here maybe
NS_NOTREACHED("isCrossProcess but not on native B2G!"); NS_NOTREACHED("isCrossProcess but not on native B2G!");
@@ -66,19 +73,37 @@ ClientCanvasLayer::Initialize(const Data& aData)
// [Basic Layers, OMTC] WebGL layer init. // [Basic Layers, OMTC] WebGL layer init.
// Well, this *should* work... // Well, this *should* work...
#ifdef XP_MACOSX #ifdef XP_MACOSX
factory = new SurfaceFactory_IOSurface(mGLContext, screen->Caps()); factory = new SurfaceFactory_IOSurface(mGLContext, caps);
#else #else
factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, screen->Caps()); factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, caps);
#endif #endif
} }
} }
} }
if (factory) { if (factory) {
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); screen->Morph(factory, streamType);
} }
} }
} }
}
void void
ClientCanvasLayer::RenderLayer() ClientCanvasLayer::RenderLayer()

View File

@@ -33,6 +33,8 @@ public:
ClientCanvasLayer(ClientLayerManager* aLayerManager) : ClientCanvasLayer(ClientLayerManager* aLayerManager) :
CopyableCanvasLayer(aLayerManager, CopyableCanvasLayer(aLayerManager,
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST())) static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
, mTextureSurface(nullptr)
, mFactory(nullptr)
{ {
MOZ_COUNT_CTOR(ClientCanvasLayer); MOZ_COUNT_CTOR(ClientCanvasLayer);
} }
@@ -90,6 +92,9 @@ protected:
RefPtr<CanvasClient> mCanvasClient; RefPtr<CanvasClient> mCanvasClient;
gfx::SharedSurface* mTextureSurface;
gfx::SurfaceFactory* mFactory;
friend class DeprecatedCanvasClient2D; friend class DeprecatedCanvasClient2D;
friend class CanvasClient2D; friend class CanvasClient2D;
friend class DeprecatedCanvasClientSurfaceStream; friend class DeprecatedCanvasClientSurfaceStream;

View File

@@ -86,7 +86,6 @@ SharedTextureClientOGL::IsAllocated() const
StreamTextureClientOGL::StreamTextureClientOGL(TextureFlags aFlags) StreamTextureClientOGL::StreamTextureClientOGL(TextureFlags aFlags)
: TextureClient(aFlags) : TextureClient(aFlags)
, mStream(0)
, mIsLocked(false) , mIsLocked(false)
{ {
} }
@@ -131,6 +130,7 @@ StreamTextureClientOGL::InitWith(gfx::SurfaceStream* aStream)
{ {
MOZ_ASSERT(!IsAllocated()); MOZ_ASSERT(!IsAllocated());
mStream = aStream; mStream = aStream;
mGL = mStream->GLContext();
} }
bool bool

View File

@@ -97,8 +97,9 @@ public:
virtual gfx::IntSize GetSize() const { return gfx::IntSize(); } virtual gfx::IntSize GetSize() const { return gfx::IntSize(); }
protected: protected:
gfx::SurfaceStream* mStream;
bool mIsLocked; bool mIsLocked;
RefPtr<gfx::SurfaceStream> mStream;
RefPtr<gl::GLContext> mGL;
}; };
} // namespace } // namespace

View File

@@ -76,6 +76,9 @@
#ifdef USE_SKIA #ifdef USE_SKIA
#include "mozilla/Hal.h" #include "mozilla/Hal.h"
#include "skia/SkGraphics.h" #include "skia/SkGraphics.h"
#include "SkiaGLGlue.h"
#endif #endif
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
@@ -231,6 +234,8 @@ MemoryPressureObserver::Observe(nsISupports *aSubject,
{ {
NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic"); NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
Factory::PurgeAllCaches(); Factory::PurgeAllCaches();
gfxPlatform::GetPlatform()->PurgeSkiaCache();
return NS_OK; return NS_OK;
} }
@@ -298,6 +303,8 @@ gfxPlatform::gfxPlatform()
mLayersUseDeprecated = false; mLayersUseDeprecated = false;
#endif #endif
mSkiaGlue = nullptr;
Preferences::AddBoolVarCache(&mDrawLayerBorders, Preferences::AddBoolVarCache(&mDrawLayerBorders,
"layers.draw-borders", "layers.draw-borders",
false); false);
@@ -482,10 +489,6 @@ gfxPlatform::Init()
CreateCMSOutputProfile(); CreateCMSOutputProfile();
#ifdef USE_SKIA
gPlatform->InitializeSkiaCaches();
#endif
// Listen to memory pressure event so we can purge DrawTarget caches // Listen to memory pressure event so we can purge DrawTarget caches
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) { if (obs) {
@@ -892,11 +895,9 @@ gfxPlatform::UseAcceleratedSkiaCanvas()
mPreferredCanvasBackend == BackendType::SKIA; mPreferredCanvasBackend == BackendType::SKIA;
} }
void static void
gfxPlatform::InitializeSkiaCaches() 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 cacheItemLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-items", 256);
@@ -920,8 +921,41 @@ gfxPlatform::InitializeSkiaCaches()
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 #endif
Factory::SetGlobalSkiaCacheLimits(cacheItemLimit, cacheSizeLimit); context->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<mozilla::gl::GLContext> 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());
}
#endif
return mSkiaGlue;
}
void
gfxPlatform::PurgeSkiaCache()
{
#ifdef USE_SKIA_GPU
if (!mSkiaGlue)
return;
mSkiaGlue->GetGrContext()->freeGpuResources();
#endif #endif
} }

View File

@@ -40,6 +40,7 @@ struct gfxRGBA;
namespace mozilla { namespace mozilla {
namespace gl { namespace gl {
class GLContext; class GLContext;
class SkiaGLGlue;
} }
namespace gfx { namespace gfx {
class DrawTarget; class DrawTarget;
@@ -284,8 +285,6 @@ public:
virtual bool UseAcceleratedSkiaCanvas(); virtual bool UseAcceleratedSkiaCanvas();
virtual void InitializeSkiaCaches();
void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend)); aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas()); aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas());
@@ -632,6 +631,9 @@ public:
bool PreferMemoryOverShmem() const; bool PreferMemoryOverShmem() const;
bool UseDeprecatedTextures() const { return mLayersUseDeprecated; } bool UseDeprecatedTextures() const { return mLayersUseDeprecated; }
mozilla::gl::SkiaGLGlue* GetSkiaGLGlue();
void PurgeSkiaCache();
protected: protected:
gfxPlatform(); gfxPlatform();
virtual ~gfxPlatform(); virtual ~gfxPlatform();
@@ -752,6 +754,8 @@ private:
bool mDrawLayerBorders; bool mDrawLayerBorders;
bool mDrawTileBorders; bool mDrawTileBorders;
bool mDrawBigImageBorders; bool mDrawBigImageBorders;
mozilla::RefPtr<mozilla::gl::SkiaGLGlue> mSkiaGlue;
}; };
#endif /* GFX_PLATFORM_H */ #endif /* GFX_PLATFORM_H */