From 4ffb1a14bf5784ccfbd91a8491d18a6cededbd4f Mon Sep 17 00:00:00 2001 From: James Willcox Date: Fri, 23 Aug 2013 09:52:32 -0400 Subject: [PATCH] Bug 902651 - Restore the DrawTarget transform and clip when demoting r=mattwoodrow,bz --HG-- rename : browser/config/mozconfigs/win64/common-opt => browser/config/mozconfigs/win64/nightly extra : rebase_source : 1f1438d54fb97935c9186b69afc37a5d17028dbb --- .../canvas/src/CanvasRenderingContext2D.cpp | 35 ++++++++++----- content/canvas/src/CanvasRenderingContext2D.h | 8 ++-- content/canvas/test/Makefile.in | 1 + content/canvas/test/test_bug902651.html | 44 +++++++++++++++++++ dom/webidl/CanvasRenderingContext2D.webidl | 6 +++ 5 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 content/canvas/test/test_bug902651.html diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index 052d99c9002..dcebbcc2d35 100644 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -547,7 +547,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D() sNumLivingContexts++; SetIsDOMBinding(); -#if USE_SKIA_GPU +#ifdef USE_SKIA_GPU mForceSoftware = false; #endif } @@ -564,10 +564,8 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() NS_IF_RELEASE(sErrorTarget); } -#if USE_SKIA_GPU - std::vector::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), this); - if (iter != DemotableContexts().end()) - DemotableContexts().erase(iter); +#ifdef USE_SKIA_GPU + RemoveDemotableContext(this); #endif } @@ -746,13 +744,14 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& r) Redraw(newr); } -#if USE_SKIA_GPU - void CanvasRenderingContext2D::Demote() { +#ifdef USE_SKIA_GPU if (!IsTargetValid() || mForceSoftware) return; + RemoveDemotableContext(this); + RefPtr snapshot = mTarget->Snapshot(); RefPtr oldTarget = mTarget; mTarget = nullptr; @@ -764,11 +763,21 @@ void CanvasRenderingContext2D::Demote() if (!IsTargetValid()) return; - // Put back the content from the old DrawTarget + // Restore the content from the old DrawTarget mgfx::Rect r(0, 0, mWidth, mHeight); mTarget->DrawSurface(snapshot, r, r); + + // Restore the clips and transform + for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) { + mTarget->PushClip(CurrentState().clipsPushed[i]); + } + + mTarget->SetTransform(oldTarget->GetTransform()); +#endif } +#ifdef USE_SKIA_GPU + std::vector& CanvasRenderingContext2D::DemotableContexts() { @@ -790,8 +799,6 @@ CanvasRenderingContext2D::DemoteOldestContextIfNecessary() return; CanvasRenderingContext2D* oldest = contexts.front(); - contexts.erase(contexts.begin()); - oldest->Demote(); } @@ -805,6 +812,14 @@ CanvasRenderingContext2D::AddDemotableContext(CanvasRenderingContext2D* context) DemotableContexts().push_back(context); } +void +CanvasRenderingContext2D::RemoveDemotableContext(CanvasRenderingContext2D* context) +{ + std::vector::iterator iter = std::find(DemotableContexts().begin(), DemotableContexts().end(), context); + if (iter != DemotableContexts().end()) + DemotableContexts().erase(iter); +} + #define MIN_SKIA_GL_DIMENSION 16 bool diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index 28929f5a656..dc78180a080 100644 --- a/content/canvas/src/CanvasRenderingContext2D.h +++ b/content/canvas/src/CanvasRenderingContext2D.h @@ -367,6 +367,8 @@ public: double h, const nsAString& bgColor, uint32_t flags, mozilla::ErrorResult& error); + void Demote(); + nsresult Redraw(); // nsICanvasRenderingContextInternal @@ -567,13 +569,11 @@ protected: } #if USE_SKIA_GPU - - // Recreate the DrawTarget in software mode - void Demote(); - static std::vector& DemotableContexts(); static void DemoteOldestContextIfNecessary(); + static void AddDemotableContext(CanvasRenderingContext2D* context); + static void RemoveDemotableContext(CanvasRenderingContext2D* context); // Do not use GL bool mForceSoftware; diff --git a/content/canvas/test/Makefile.in b/content/canvas/test/Makefile.in index 63c825bed0a..2af137464d6 100644 --- a/content/canvas/test/Makefile.in +++ b/content/canvas/test/Makefile.in @@ -88,6 +88,7 @@ MOCHITEST_FILES = \ file_drawImage_document_domain.html \ test_windingRuleUndefined.html \ test_strokeText_throw.html \ + test_bug902651.html \ $(NULL) # SkiaGL on Android/Gonk does not implement these composite ops yet diff --git a/content/canvas/test/test_bug902651.html b/content/canvas/test/test_bug902651.html new file mode 100644 index 00000000000..9ddb2960993 --- /dev/null +++ b/content/canvas/test/test_bug902651.html @@ -0,0 +1,44 @@ + +Canvas test: canvas demotion + + + + +

FAIL (fallback content)

+ + diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl index 34f8f1f30e9..02d8fd1d320 100644 --- a/dom/webidl/CanvasRenderingContext2D.webidl +++ b/dom/webidl/CanvasRenderingContext2D.webidl @@ -207,6 +207,12 @@ interface CanvasRenderingContext2D { void asyncDrawXULElement(XULElement elem, double x, double y, double w, double h, DOMString bgColor, optional unsigned long flags = 0); + /** + * This causes a context that is currently using a hardware-accelerated + * backend to fallback to a software one. All state should be preserved. + */ + [ChromeOnly] + void demote(); }; CanvasRenderingContext2D implements CanvasDrawingStyles; CanvasRenderingContext2D implements CanvasPathMethods;