Avoid unnecessary InvalidateFrame calls from CanvasRenderingContext2D - bug 447836 r=vlad
authorEric Butler <ebutler@mozilla.com>
Mon, 04 Aug 2008 10:38:09 -0700
changeset 16362 2b66c4c351f78e5ab8cb11d7d1bd99fa9f55a25c
parent 16361 0d0a155411ddc4a4f9fdddeaf1151e373b59b2bd
child 16364 232db16ff3a28a6126e666e886ca278ca420ac02
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs447836
milestone1.9.1a2pre
Avoid unnecessary InvalidateFrame calls from CanvasRenderingContext2D - bug 447836 r=vlad
content/canvas/src/nsCanvasRenderingContext2D.cpp
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -371,16 +371,22 @@ protected:
 
     // yay thebes
     nsRefPtr<gfxContext> mThebes;
     nsRefPtr<gfxASurface> mSurface;
 
     PRUint32 mSaveCount;
 
     /**
+     * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
+     * Redraw is called, reset to false when Render is called.
+     */
+    PRBool mIsFrameInvalid;
+
+    /**
      * Draws a rectangle in the given style; used by FillRect and StrokeRect.
      */
     nsresult DrawRect(const gfxRect& rect, Style style);
 
     // text
     enum TextAlign {
         TEXT_ALIGN_START,
         TEXT_ALIGN_END,
@@ -546,31 +552,32 @@ NS_NewCanvasRenderingContext2D(nsIDOMCan
         return NS_ERROR_OUT_OF_MEMORY;
 
     *aResult = ctx.forget().get();
     return NS_OK;
 }
 
 nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
     : mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
-      mSaveCount(0), mStyleStack(20)
+      mSaveCount(0), mIsFrameInvalid(PR_FALSE), mStyleStack(20)
 {
 }
 
 nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
 {
     Destroy();
 }
 
 void
 nsCanvasRenderingContext2D::Destroy()
 {
     mSurface = nsnull;
     mThebes = nsnull;
     mValid = PR_FALSE;
+    mIsFrameInvalid = PR_FALSE;
 }
 
 nsresult
 nsCanvasRenderingContext2D::SetStyleFromVariant(nsIVariant* aStyle, Style aWhichStyle)
 {
     nsresult rv;
     nscolor color;
 
@@ -732,17 +739,22 @@ nsCanvasRenderingContext2D::ApplyStyle(S
 }
 
 nsresult
 nsCanvasRenderingContext2D::Redraw()
 {
     if (!mCanvasElement)
         return NS_OK;
 
-    return mCanvasElement->InvalidateFrame();
+    if (!mIsFrameInvalid) {
+        mIsFrameInvalid = PR_TRUE;
+        return mCanvasElement->InvalidateFrame();
+    }
+
+    return NS_OK;
 }
 
 void
 nsCanvasRenderingContext2D::SetThebesColor(nscolor c)
 {
     gfxRGBA color(c);
     color.a *= CurrentState().globalAlpha;
 
@@ -850,16 +862,17 @@ nsCanvasRenderingContext2D::Render(gfxCo
     // pixel alignment for this stuff!
     ctx->NewPath();
     ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
     ctx->Fill();
 
     if (mOpaque)
         ctx->SetOperator(op);
 
+    mIsFrameInvalid = PR_FALSE;
     return rv;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::GetInputStream(const char *aMimeType,
                                            const PRUnichar *aEncoderOptions,
                                            nsIInputStream **aStream)
 {
@@ -1373,17 +1386,17 @@ nsCanvasRenderingContext2D::Stroke()
     mThebes->Stroke();
     return Redraw();
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::Clip()
 {
     mThebes->Clip();
-    return Redraw();
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::MoveTo(float x, float y)
 {
     if (!FloatValidate(x,y))
         return NS_ERROR_DOM_SYNTAX_ERR;