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/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/PDocumentRendererParent.h"
#include "mozilla/layers/PersistentBufferProvider.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
@ -820,6 +821,7 @@ public:
// Since SkiaGL default to store drawing command until flush
// We will have to flush it before present.
context->mTarget->Flush();
context->ReturnTarget();
}
static void DidTransactionCallback(void* aData)
@ -1034,7 +1036,9 @@ CanvasRenderingContext2D::Reset()
gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
}
ReturnTarget();
mTarget = nullptr;
mBufferProvider = nullptr;
// reset hit regions
mHitRegionsOptions.ClearAndRetainStorage();
@ -1186,9 +1190,18 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
}
#endif
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
RefPtr<DrawTarget> oldTarget = mTarget;
RefPtr<SourceSurface> snapshot;
Matrix transform;
if (mTarget) {
snapshot = mTarget->Snapshot();
transform = mTarget->GetTransform();
} else {
MOZ_ASSERT(mBufferProvider);
snapshot = mBufferProvider->GetSnapshot();
}
mTarget = nullptr;
mBufferProvider = nullptr;
mResetLayer = true;
// Recreate target using the new rendering mode
@ -1208,7 +1221,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
mTarget->PushClip(CurrentState().clipsPushed[i]);
}
mTarget->SetTransform(oldTarget->GetTransform());
mTarget->SetTransform(transform);
return true;
}
@ -1332,6 +1345,15 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
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
IntSize size(mWidth, mHeight);
if (size.width <= gfxPrefs::MaxCanvasSize() &&
@ -1350,11 +1372,12 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
}
if (layerManager) {
if (layerManager) {
if (mode == RenderingMode::OpenGLBackendMode &&
gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() &&
CheckSizeForSkiaGL(size)) {
DemoteOldestContextIfNecessary();
mBufferProvider = nullptr;
#if USE_SKIA_GPU
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
@ -1369,17 +1392,19 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
}
}
#endif
if (!mTarget) {
mTarget = layerManager->CreateDrawTarget(size, format);
}
} else {
mTarget = layerManager->CreateDrawTarget(size, format);
mode = RenderingMode::SoftwareBackendMode;
}
} else {
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
mode = RenderingMode::SoftwareBackendMode;
}
if (!mBufferProvider) {
mBufferProvider = layerManager->CreatePersistentBufferProvider(size, format);
}
}
if (mBufferProvider) {
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), IntSize(mWidth, mHeight)));
} else if (!mTarget) {
mTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(size, format);
mode = RenderingMode::SoftwareBackendMode;
}
}
if (mTarget) {
@ -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
CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell,
gfxASurface *surface,
@ -2382,9 +2418,7 @@ void
CanvasRenderingContext2D::ClearRect(double x, double y, double w,
double h)
{
if (!mTarget) {
return;
}
EnsureTarget();
mTarget->ClearRect(mgfx::Rect(x, y, w, h));
@ -2545,6 +2579,7 @@ CanvasRenderingContext2D::BeginPath()
void
CanvasRenderingContext2D::Fill(const CanvasWindingRule& winding)
{
EnsureTarget();
EnsureUserSpacePath(winding);
if (!mPath) {
@ -2590,6 +2625,7 @@ void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingR
void
CanvasRenderingContext2D::Stroke()
{
EnsureTarget();
EnsureUserSpacePath();
if (!mPath) {
@ -2725,6 +2761,8 @@ bool CanvasRenderingContext2D::DrawCustomFocusRing(mozilla::dom::Element& aEleme
void
CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding)
{
EnsureTarget();
EnsureUserSpacePath(winding);
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,
int32_t dirtyWidth, int32_t dirtyHeight)
{
EnsureTarget();
if (mDrawObserver) {
mDrawObserver->DidDrawCall(CanvasDrawObserver::DrawCallType::PutImageData);
}
@ -5347,8 +5386,11 @@ static uint8_t g2DContextLayerUserData;
uint32_t
CanvasRenderingContext2D::SkiaGLTex() const
{
MOZ_ASSERT(IsTargetValid());
return (uint32_t)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
if (!mTarget) {
return 0;
}
MOZ_ASSERT(IsTargetValid());
return (uint32_t)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
}
void CanvasRenderingContext2D::RemoveDrawObserver()
@ -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>
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
// to paint nothing. Also, EnsureTarget() can cause creation of a persistent
// 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
// now so future invalidations will be dispatched.
MarkContextClean();
return nullptr;
}
mTarget->Flush();
if (!mResetLayer && aOldLayer) {
CanvasRenderingContext2DUserData* userData =
static_cast<CanvasRenderingContext2DUserData*>(
@ -5399,7 +5459,8 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
} else {
data.mDrawTarget = mTarget;
PersistentBufferProvider *provider = GetBufferProvider(aManager);
data.mBufferProvider = provider;
}
if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) {
@ -5437,18 +5498,19 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
data.mSize = nsIntSize(mWidth, mHeight);
data.mHasAlpha = !mOpaque;
canvasLayer->SetPreTransactionCallback(
CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
canvasLayer->SetPreTransactionCallback(
CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
} else {
data.mDrawTarget = mTarget;
PersistentBufferProvider *provider = GetBufferProvider(aManager);
data.mBufferProvider = provider;
}
canvasLayer->Initialize(data);

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

@ -27,6 +27,7 @@
#include "mozilla/EnumeratedArray.h"
#include "FilterSupport.h"
#include "nsSVGEffects.h"
#include "Layers.h"
class nsGlobalWindow;
class nsXULElement;
@ -456,6 +457,7 @@ public:
NS_IMETHOD SetIsOpaque(bool isOpaque) override;
bool GetIsOpaque() override { return mOpaque; }
NS_IMETHOD Reset() override;
mozilla::layers::PersistentBufferProvider* GetBufferProvider(mozilla::layers::LayerManager* aManager);
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
LayerManager *aManager) override;
@ -637,11 +639,17 @@ protected:
*/
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.
*/
bool IsTargetValid() const {
return mTarget != sErrorTarget && mTarget != nullptr;
return (sErrorTarget == nullptr || mTarget != sErrorTarget) && (mBufferProvider != nullptr || mTarget);
}
/**
@ -715,6 +723,8 @@ protected:
// sErrorTarget.
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
mozilla::RefPtr<mozilla::layers::PersistentBufferProvider> mBufferProvider;
uint32_t SkiaGLTex() const;
// This observes our draw calls at the beginning of the canvas

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

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