Bug 1167235 - Part 3: Switch CanvasRenderingContext2D to use the new BufferProvider API. r=nical

This commit is contained in:
Bas Schouten 2015-06-19 01:07:21 +02:00
Родитель 4ed616c712
Коммит 7801f65a75
3 изменённых файлов: 101 добавлений и 31 удалений

Просмотреть файл

@ -87,6 +87,7 @@
#include "mozilla/gfx/PatternHelpers.h" #include "mozilla/gfx/PatternHelpers.h"
#include "mozilla/ipc/DocumentRendererParent.h" #include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/PDocumentRendererParent.h" #include "mozilla/ipc/PDocumentRendererParent.h"
#include "mozilla/layers/PersistentBufferProvider.h"
#include "mozilla/MathAlgorithms.h" #include "mozilla/MathAlgorithms.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
@ -820,6 +821,7 @@ public:
// 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();
context->ReturnTarget();
} }
static void DidTransactionCallback(void* aData) static void DidTransactionCallback(void* aData)
@ -1034,7 +1036,9 @@ CanvasRenderingContext2D::Reset()
gCanvasAzureMemoryUsed -= mWidth * mHeight * 4; gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
} }
ReturnTarget();
mTarget = nullptr; mTarget = nullptr;
mBufferProvider = nullptr;
// reset hit regions // reset hit regions
mHitRegionsOptions.ClearAndRetainStorage(); mHitRegionsOptions.ClearAndRetainStorage();
@ -1186,9 +1190,18 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
} }
#endif #endif
RefPtr<SourceSurface> snapshot = mTarget->Snapshot(); RefPtr<SourceSurface> snapshot;
RefPtr<DrawTarget> oldTarget = mTarget; Matrix transform;
if (mTarget) {
snapshot = mTarget->Snapshot();
transform = mTarget->GetTransform();
} else {
MOZ_ASSERT(mBufferProvider);
snapshot = mBufferProvider->GetSnapshot();
}
mTarget = nullptr; mTarget = nullptr;
mBufferProvider = nullptr;
mResetLayer = true; mResetLayer = true;
// Recreate target using the new rendering mode // Recreate target using the new rendering mode
@ -1208,7 +1221,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
mTarget->PushClip(CurrentState().clipsPushed[i]); mTarget->PushClip(CurrentState().clipsPushed[i]);
} }
mTarget->SetTransform(oldTarget->GetTransform()); mTarget->SetTransform(transform);
return true; return true;
} }
@ -1332,6 +1345,15 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
return mRenderingMode; return mRenderingMode;
} }
if (mBufferProvider && mode == mRenderingMode) {
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), IntSize(mWidth, mHeight)));
if (mTarget) {
return mRenderingMode;
} else {
mBufferProvider = nullptr;
}
}
// Check that the dimensions are sane // Check that the dimensions are sane
IntSize size(mWidth, mHeight); IntSize size(mWidth, mHeight);
if (size.width <= gfxPrefs::MaxCanvasSize() && if (size.width <= gfxPrefs::MaxCanvasSize() &&
@ -1355,6 +1377,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() && gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() &&
CheckSizeForSkiaGL(size)) { CheckSizeForSkiaGL(size)) {
DemoteOldestContextIfNecessary(); DemoteOldestContextIfNecessary();
mBufferProvider = nullptr;
#if USE_SKIA_GPU #if USE_SKIA_GPU
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
@ -1369,14 +1392,16 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
} }
} }
#endif #endif
if (!mTarget) {
mTarget = layerManager->CreateDrawTarget(size, format);
} }
} else {
mTarget = layerManager->CreateDrawTarget(size, format); if (!mBufferProvider) {
mode = RenderingMode::SoftwareBackendMode; mBufferProvider = layerManager->CreatePersistentBufferProvider(size, format);
} }
} else { }
if (mBufferProvider) {
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), IntSize(mWidth, mHeight)));
} else if (!mTarget) {
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format); mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
mode = RenderingMode::SoftwareBackendMode; mode = RenderingMode::SoftwareBackendMode;
} }
@ -1496,6 +1521,17 @@ CanvasRenderingContext2D::ClearTarget()
} }
} }
void
CanvasRenderingContext2D::ReturnTarget()
{
if (mTarget && mBufferProvider) {
CurrentState().transform = mTarget->GetTransform();
DrawTarget* oldDT = mTarget;
mTarget = nullptr;
mBufferProvider->ReturnAndUseDT(oldDT);
}
}
NS_IMETHODIMP NS_IMETHODIMP
CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell, CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell,
gfxASurface *surface, gfxASurface *surface,
@ -2382,9 +2418,7 @@ void
CanvasRenderingContext2D::ClearRect(double x, double y, double w, CanvasRenderingContext2D::ClearRect(double x, double y, double w,
double h) double h)
{ {
if (!mTarget) { EnsureTarget();
return;
}
mTarget->ClearRect(mgfx::Rect(x, y, w, h)); mTarget->ClearRect(mgfx::Rect(x, y, w, h));
@ -2545,6 +2579,7 @@ CanvasRenderingContext2D::BeginPath()
void void
CanvasRenderingContext2D::Fill(const CanvasWindingRule& winding) CanvasRenderingContext2D::Fill(const CanvasWindingRule& winding)
{ {
EnsureTarget();
EnsureUserSpacePath(winding); EnsureUserSpacePath(winding);
if (!mPath) { if (!mPath) {
@ -2590,6 +2625,7 @@ void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingR
void void
CanvasRenderingContext2D::Stroke() CanvasRenderingContext2D::Stroke()
{ {
EnsureTarget();
EnsureUserSpacePath(); EnsureUserSpacePath();
if (!mPath) { if (!mPath) {
@ -2725,6 +2761,8 @@ bool CanvasRenderingContext2D::DrawCustomFocusRing(mozilla::dom::Element& aEleme
void void
CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding) CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding)
{ {
EnsureTarget();
EnsureUserSpacePath(winding); EnsureUserSpacePath(winding);
if (!mPath) { if (!mPath) {
@ -5156,6 +5194,7 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY, bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
int32_t dirtyWidth, int32_t dirtyHeight) int32_t dirtyWidth, int32_t dirtyHeight)
{ {
EnsureTarget();
if (mDrawObserver) { if (mDrawObserver) {
mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::PutImageData); mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::PutImageData);
} }
@ -5347,6 +5386,9 @@ static uint8_t g2DContextLayerUserData;
uint32_t uint32_t
CanvasRenderingContext2D::SkiaGLTex() const CanvasRenderingContext2D::SkiaGLTex() const
{ {
if (!mTarget) {
return 0;
}
MOZ_ASSERT(IsTargetValid()); MOZ_ASSERT(IsTargetValid());
return (uint32_t)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE); return (uint32_t)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
} }
@ -5359,6 +5401,26 @@ void CanvasRenderingContext2D::RemoveDrawObserver()
} }
} }
PersistentBufferProvider*
CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
{
if (mBufferProvider) {
return mBufferProvider;
}
if (!mTarget) {
return nullptr;
}
mBufferProvider = aManager->CreatePersistentBufferProvider(mTarget->GetSize(), mTarget->GetFormat());
RefPtr<SourceSurface> surf = mTarget->Snapshot();
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), mTarget->GetSize()));
mTarget->CopySurface(surf, IntRect(IntPoint(), mTarget->GetSize()), IntPoint());
return mBufferProvider;
}
already_AddRefed<CanvasLayer> already_AddRefed<CanvasLayer>
CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder, CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
@ -5375,15 +5437,13 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
// we have nothing to paint and there is no need to create a surface just // we have nothing to paint and there is no need to create a surface just
// to paint nothing. Also, EnsureTarget() can cause creation of a persistent // to paint nothing. Also, EnsureTarget() can cause creation of a persistent
// layer manager which must NOT happen during a paint. // layer manager which must NOT happen during a paint.
if (!mTarget || !IsTargetValid()) { if ((!mBufferProvider && !mTarget) || !IsTargetValid()) {
// No DidTransactionCallback will be received, so mark the context clean // No DidTransactionCallback will be received, so mark the context clean
// now so future invalidations will be dispatched. // now so future invalidations will be dispatched.
MarkContextClean(); MarkContextClean();
return nullptr; return nullptr;
} }
mTarget->Flush();
if (!mResetLayer && aOldLayer) { if (!mResetLayer && aOldLayer) {
CanvasRenderingContext2DUserData* userData = CanvasRenderingContext2DUserData* userData =
static_cast<CanvasRenderingContext2DUserData*>( static_cast<CanvasRenderingContext2DUserData*>(
@ -5399,7 +5459,8 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
data.mGLContext = glue->GetGLContext(); data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex; data.mFrontbufferGLTex = skiaGLTex;
} else { } else {
data.mDrawTarget = mTarget; PersistentBufferProvider *provider = GetBufferProvider(aManager);
data.mBufferProvider = provider;
} }
if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) { if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) {
@ -5437,18 +5498,19 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
data.mSize = nsIntSize(mWidth, mHeight); data.mSize = nsIntSize(mWidth, mHeight);
data.mHasAlpha = !mOpaque; data.mHasAlpha = !mOpaque;
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
canvasLayer->SetPreTransactionCallback( canvasLayer->SetPreTransactionCallback(
CanvasRenderingContext2DUserData::PreTransactionCallback, userData); CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue(); SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue); MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext(); data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex; data.mFrontbufferGLTex = skiaGLTex;
} else { } else {
data.mDrawTarget = mTarget; PersistentBufferProvider *provider = GetBufferProvider(aManager);
data.mBufferProvider = provider;
} }
canvasLayer->Initialize(data); canvasLayer->Initialize(data);

Просмотреть файл

@ -27,6 +27,7 @@
#include "mozilla/EnumeratedArray.h" #include "mozilla/EnumeratedArray.h"
#include "FilterSupport.h" #include "FilterSupport.h"
#include "nsSVGEffects.h" #include "nsSVGEffects.h"
#include "Layers.h"
class nsGlobalWindow; class nsGlobalWindow;
class nsXULElement; class nsXULElement;
@ -456,6 +457,7 @@ public:
NS_IMETHOD SetIsOpaque(bool isOpaque) override; NS_IMETHOD SetIsOpaque(bool isOpaque) override;
bool GetIsOpaque() override { return mOpaque; } bool GetIsOpaque() override { return mOpaque; }
NS_IMETHOD Reset() override; NS_IMETHOD Reset() override;
mozilla::layers::PersistentBufferProvider* GetBufferProvider(mozilla::layers::LayerManager* aManager);
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder, already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer, CanvasLayer *aOldLayer,
LayerManager *aManager) override; LayerManager *aManager) override;
@ -637,11 +639,17 @@ protected:
*/ */
void ClearTarget(); void ClearTarget();
/*
* Returns the target to the buffer provider. i.e. this will queue a frame for
* rendering.
*/
void ReturnTarget();
/** /**
* Check if the target is valid after calling EnsureTarget. * Check if the target is valid after calling EnsureTarget.
*/ */
bool IsTargetValid() const { bool IsTargetValid() const {
return mTarget != sErrorTarget && mTarget != nullptr; return (sErrorTarget == nullptr || mTarget != sErrorTarget) && (mBufferProvider != nullptr || mTarget);
} }
/** /**
@ -715,6 +723,8 @@ protected:
// sErrorTarget. // sErrorTarget.
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget; mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
mozilla::RefPtr<mozilla::layers::PersistentBufferProvider> mBufferProvider;
uint32_t SkiaGLTex() const; uint32_t SkiaGLTex() const;
// This observes our draw calls at the beginning of the canvas // This observes our draw calls at the beginning of the canvas

Просмотреть файл

@ -48,10 +48,8 @@ public:
*/ */
virtual bool ReturnAndUseDT(gfx::DrawTarget* aDT) = 0; virtual bool ReturnAndUseDT(gfx::DrawTarget* aDT) = 0;
protected:
friend class CopyableCanvasLayer;
virtual TemporaryRef<gfx::SourceSurface> GetSnapshot() = 0; virtual TemporaryRef<gfx::SourceSurface> GetSnapshot() = 0;
protected:
}; };
class PersistentBufferProviderBasic : public PersistentBufferProvider class PersistentBufferProviderBasic : public PersistentBufferProvider