Adding class SkDeferredCanvas for deferred rendering.

TEST=added a new pass to gm, so all gm tests are run through SkDeferredCanvas
REVIEW=http://codereview.appspot.com/5430058/



git-svn-id: http://skia.googlecode.com/svn/trunk@3059 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h
new file mode 100644
index 0000000..14951d9
--- /dev/null
+++ b/include/utils/SkDeferredCanvas.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredCanvas_DEFINED
+#define SkDeferredCanvas_DEFINED
+
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkPicture.h"
+#include "SkPixelRef.h"
+
+/** \class SkDeferredCanvas
+    Subclass of SkCanvas that encapsulates an SkPicture for deferred drawing.
+    The main difference between this class and SkPictureRecord (the canvas
+    provided by SkPicture) is that this is a full drop-in replacement for
+    SkCanvas, while SkPictureRecord only supports draw operations.
+    SkDeferredCanvas will transparently trigger the flushing of deferred
+    draw operations when an attempt is made to access the pixel data.  
+*/
+class SK_API SkDeferredCanvas : public SkCanvas {
+public:
+    class DeviceContext;
+
+    SkDeferredCanvas();
+
+    /** Construct a canvas with the specified device to draw into.
+        Equivalent to calling default constructor, then setDevice.
+        @param device Specifies a device for the canvas to draw into.
+    */
+    explicit SkDeferredCanvas(SkDevice* device);
+
+    /** Construct a canvas with the specified device to draw into, and
+     *  a device context. Equivalent to calling default constructor, then
+     *  setDevice.
+     *  @param device Specifies a device for the canvas to draw into.
+     *  @param deviceContext interface for the device's the graphics context
+     */
+    explicit SkDeferredCanvas(SkDevice* device, DeviceContext* deviceContext);
+
+    virtual ~SkDeferredCanvas();
+
+    /**
+     *  Specify a device to be used by this canvas. Calling setDevice will
+     *  release the previously set device, if any.
+     *
+     *  @param device The device that the canvas will raw into
+     *  @return The device argument, for convenience.
+     */
+    virtual SkDevice* setDevice(SkDevice* device);
+
+    /**
+     *  Specify a deviceContext to be used by this canvas. Calling 
+     *  setDeviceContext will release the previously set deviceContext, if any.
+     *  A deviceContext must be specified if the device uses a graphics context
+     *  that requires some form of state initialization prior to drawing 
+     *  and/or explicit flushing to synchronize the execution of rendering
+     *  operations. 
+     *  Note: Must be called after the device is set with setDevice.
+     *
+     *  @deviceContext interface for the device's the graphics context
+     *  @return The deviceContext argument, for convenience.
+     */
+    DeviceContext* setDeviceContext(DeviceContext* deviceContext);
+
+    /**
+     *  Enable or disable deferred drawing. When deferral is disabled,
+     *  pending draw operations are immediately flushed and from then on,
+     *  the SkDeferredCanvas behaves just like a regular SkCanvas.
+     *  This method must not be called while the save/restore stack is in use.
+     *  @param deferred true/false
+     */
+    void setDeferredDrawing(bool deferred);
+
+    // Overrides of the SkCanvas interface
+    virtual int save(SaveFlags flags) SK_OVERRIDE;
+    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+                          SaveFlags flags) SK_OVERRIDE;
+    virtual void restore() SK_OVERRIDE;
+    virtual int getSaveCount() const SK_OVERRIDE;
+    virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+    virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+    virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+    virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+    virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
+    virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+    virtual const SkMatrix& getTotalMatrix() const SK_OVERRIDE;
+    virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
+                          bool doAntiAlias) SK_OVERRIDE;
+    virtual bool clipPath(const SkPath& path, SkRegion::Op op,
+                          bool doAntiAlias) SK_OVERRIDE;
+    virtual bool clipRegion(const SkRegion& deviceRgn,
+                            SkRegion::Op op) SK_OVERRIDE;
+    virtual void clear(SkColor) SK_OVERRIDE;
+    virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                            const SkPaint& paint) SK_OVERRIDE;
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint)
+                          SK_OVERRIDE;
+    virtual void drawPath(const SkPath& path, const SkPaint& paint)
+                          SK_OVERRIDE;
+    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, 
+                            SkScalar top, const SkPaint* paint)
+                            SK_OVERRIDE;
+    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+                                const SkRect& dst, const SkPaint* paint)
+                                SK_OVERRIDE;
+
+    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+                                  const SkPaint* paint) SK_OVERRIDE;
+    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+                                const SkRect& dst, const SkPaint* paint)
+                                SK_OVERRIDE;
+    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+                            const SkPaint* paint) SK_OVERRIDE;
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint) SK_OVERRIDE;
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint) 
+                             SK_OVERRIDE;
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint) SK_OVERRIDE;
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint) SK_OVERRIDE;
+    virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
+    virtual void drawVertices(VertexMode vmode, int vertexCount,
+                              const SkPoint vertices[], const SkPoint texs[],
+                              const SkColor colors[], SkXfermode* xmode,
+                              const uint16_t indices[], int indexCount,
+                              const SkPaint& paint) SK_OVERRIDE;
+    virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
+    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
+
+private:
+    void flushIfNeeded(const SkBitmap& bitmap);
+
+public:
+    class DeviceContext : public SkRefCnt {
+    public:
+        virtual void prepareForDraw() {}
+        virtual void flush() {}
+    };
+
+public:
+    class DeferredDevice : public SkDevice {
+    public:
+        /**
+         *  Constructor
+         *  @param immediateDevice device to be drawn to when flushing
+         *      deferred operations
+         *  @param deviceContext callback interface for managing graphics
+         *      context state, can be NULL.
+         */
+        DeferredDevice(SkDevice* immediateDevice,
+            DeviceContext* deviceContext = NULL);
+        ~DeferredDevice();
+
+        /**
+         *  Sets the device context to be use with the device.
+         *  @param deviceContext callback interface for managing graphics
+         *      context state, can be NULL.
+         */
+        void setDeviceContext(DeviceContext* deviceContext);
+
+        /**
+         *  Returns the recording canvas.
+         */
+        SkCanvas* recordingCanvas() const {return fRecordingCanvas;}
+
+        /**
+         *  Returns the immediate (non deferred) canvas.
+         */
+        SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
+
+        /**
+         *  Returns the immediate (non deferred) device.
+         */
+        SkDevice* immediateDevice() const {return fImmediateDevice;}
+
+        void flushPending();
+        void flushContext();
+        void purgePending();
+        void flushIfNeeded(const SkBitmap& bitmap);
+
+        virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
+        virtual int width() const SK_OVERRIDE;
+        virtual int height() const SK_OVERRIDE;
+        virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
+
+        virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, 
+                                                   int width, int height, 
+                                                   bool isOpaque,
+                                                   Usage usage) SK_OVERRIDE;
+
+        virtual void writePixels(const SkBitmap& bitmap, int x, int y,
+                                 SkCanvas::Config8888 config8888) SK_OVERRIDE;
+
+    protected:
+        virtual void onAccessBitmap(SkBitmap*) SK_OVERRIDE;
+        virtual bool onReadPixels(const SkBitmap& bitmap,
+                                  int x, int y,
+                                  SkCanvas::Config8888 config8888) SK_OVERRIDE;
+
+        // The following methods are no-ops on a deferred device
+        virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) 
+            SK_OVERRIDE
+            {return false;}
+        virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
+                                   const SkClipStack&) SK_OVERRIDE
+            {}
+        virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&,
+                               const SkClipStack&) SK_OVERRIDE
+            {}
+
+        // None of the following drawing methods should ever get called on the
+        // deferred device
+        virtual void clear(SkColor color)
+            {SkASSERT(0);}
+        virtual void drawPaint(const SkDraw&, const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
+                                size_t count, const SkPoint[],
+                                const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawRect(const SkDraw&, const SkRect& r,
+                              const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawPath(const SkDraw&, const SkPath& path,
+                              const SkPaint& paint,
+                              const SkMatrix* prePathMatrix = NULL,
+                              bool pathIsMutable = false)
+            {SkASSERT(0);}
+        virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+                                const SkIRect* srcRectOrNull,
+                                const SkMatrix& matrix, const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
+                                int x, int y, const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawText(const SkDraw&, const void* text, size_t len,
+                              SkScalar x, SkScalar y, const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawPosText(const SkDraw&, const void* text, size_t len,
+                                 const SkScalar pos[], SkScalar constY,
+                                 int scalarsPerPos, const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawTextOnPath(const SkDraw&, const void* text,
+                                    size_t len, const SkPath& path,
+                                    const SkMatrix* matrix,
+                                    const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
+                                       size_t len, const SkPoint pos[],
+                                       const SkPaint& paint,
+                                       const SkPath& path, 
+                                       const SkMatrix* matrix)
+            {SkASSERT(0);}
+        virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, 
+                                  int vertexCount, const SkPoint verts[],
+                                  const SkPoint texs[], const SkColor colors[],
+                                  SkXfermode* xmode, const uint16_t indices[],
+                                  int indexCount, const SkPaint& paint)
+            {SkASSERT(0);}
+        virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
+                                const SkPaint&)
+            {SkASSERT(0);}
+    private:
+        virtual void flush();
+
+        SkPicture fPicture;
+        SkDevice* fImmediateDevice;
+        SkCanvas* fImmediateCanvas;
+        SkCanvas* fRecordingCanvas;
+        DeviceContext* fDeviceContext;
+    };
+
+    DeferredDevice* getDeferredDevice() const;
+
+protected:
+    virtual SkCanvas* canvasForDrawIter();
+
+private:
+    SkCanvas* drawingCanvas() const;
+    bool isFullFrame(const SkRect*, const SkPaint*) const;
+    void validate() const;
+    void init();
+    bool            fDeferredDrawing;
+
+    typedef SkCanvas INHERITED;
+};
+
+
+#endif