/*
* 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 bool isDrawingToLayer() 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 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() {}
};
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;}
/**
* Returns true if an opaque draw operation covering the entire canvas
* was performed since the last call to isFreshFrame().
*/
bool isFreshFrame();
void flushPending();
void contentsCleared();
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 const SkBitmap& 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;
bool fFreshFrame;
};
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