210ae2a426
*** SKP format breaking change *** Adding a couple of culling primitives: pushCull(SkRect) & popCull(). These are currently only plumbed for SKP playback quickreject. At record time, we perform a couple of optimizations to trim down the number of redundant culls: * collapse empty pushCull/popCull pairs * skip pushCull/popCull pairs nested within an identical cull rect Things still missing/to consider: * use an inlineable, simplified quickreject (Mike's old prototype) * debugger visualization for cull boxes * BBH integration: the initial prototype had some minimal BBH support, but since the optimizations required expensive rewinds and culling is expected to be a BBH alternative, it got dropped. R=bsalomon@google.com, reed@google.com, robertphillips@google.com, caryclark@google.com, tomhudson@google.com, iancottrell@google.com Author: fmalita@chromium.org Review URL: https://codereview.chromium.org/138013009 git-svn-id: http://skia.googlecode.com/svn/trunk@13611 2bbb7eff-a529-9590-31e7-b0007b416f81
300 lines
12 KiB
C++
300 lines
12 KiB
C++
|
|
/*
|
|
* Copyright 2007 The Android Open Source Project
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
|
|
#ifndef SkPicture_DEFINED
|
|
#define SkPicture_DEFINED
|
|
|
|
#include "SkBitmap.h"
|
|
#include "SkImageDecoder.h"
|
|
#include "SkRefCnt.h"
|
|
|
|
class SkBBoxHierarchy;
|
|
class SkCanvas;
|
|
class SkDrawPictureCallback;
|
|
class SkData;
|
|
class SkPicturePlayback;
|
|
class SkPictureRecord;
|
|
class SkStream;
|
|
class SkWStream;
|
|
|
|
struct SkPictInfo;
|
|
|
|
/** \class SkPicture
|
|
|
|
The SkPicture class records the drawing commands made to a canvas, to
|
|
be played back at a later time.
|
|
*/
|
|
class SK_API SkPicture : public SkRefCnt {
|
|
public:
|
|
SK_DECLARE_INST_COUNT(SkPicture)
|
|
|
|
/** The constructor prepares the picture to record.
|
|
@param width the width of the virtual device the picture records.
|
|
@param height the height of the virtual device the picture records.
|
|
*/
|
|
SkPicture();
|
|
/** Make a copy of the contents of src. If src records more drawing after
|
|
this call, those elements will not appear in this picture.
|
|
*/
|
|
SkPicture(const SkPicture& src);
|
|
|
|
/**
|
|
* Function signature defining a function that sets up an SkBitmap from encoded data. On
|
|
* success, the SkBitmap should have its Config, width, height, rowBytes and pixelref set.
|
|
* If the installed pixelref has decoded the data into pixels, then the src buffer need not be
|
|
* copied. If the pixelref defers the actual decode until its lockPixels() is called, then it
|
|
* must make a copy of the src buffer.
|
|
* @param src Encoded data.
|
|
* @param length Size of the encoded data, in bytes.
|
|
* @param dst SkBitmap to install the pixel ref on.
|
|
* @param bool Whether or not a pixel ref was successfully installed.
|
|
*/
|
|
typedef bool (*InstallPixelRefProc)(const void* src, size_t length, SkBitmap* dst);
|
|
|
|
/**
|
|
* Recreate a picture that was serialized into a stream.
|
|
* @param SkStream Serialized picture data.
|
|
* @param proc Function pointer for installing pixelrefs on SkBitmaps representing the
|
|
* encoded bitmap data from the stream.
|
|
* @return A new SkPicture representing the serialized data, or NULL if the stream is
|
|
* invalid.
|
|
*/
|
|
static SkPicture* CreateFromStream(SkStream*,
|
|
InstallPixelRefProc proc = &SkImageDecoder::DecodeMemory);
|
|
|
|
/**
|
|
* Recreate a picture that was serialized into a buffer. If the creation requires bitmap
|
|
* decoding, the decoder must be set on the SkReadBuffer parameter by calling
|
|
* SkReadBuffer::setBitmapDecoder() before calling SkPicture::CreateFromBuffer().
|
|
* @param SkReadBuffer Serialized picture data.
|
|
* @return A new SkPicture representing the serialized data, or NULL if the buffer is
|
|
* invalid.
|
|
*/
|
|
static SkPicture* CreateFromBuffer(SkReadBuffer&);
|
|
|
|
virtual ~SkPicture();
|
|
|
|
/**
|
|
* Swap the contents of the two pictures. Guaranteed to succeed.
|
|
*/
|
|
void swap(SkPicture& other);
|
|
|
|
/**
|
|
* Creates a thread-safe clone of the picture that is ready for playback.
|
|
*/
|
|
SkPicture* clone() const;
|
|
|
|
/**
|
|
* Creates multiple thread-safe clones of this picture that are ready for
|
|
* playback. The resulting clones are stored in the provided array of
|
|
* SkPictures.
|
|
*/
|
|
void clone(SkPicture* pictures, int count) const;
|
|
|
|
enum RecordingFlags {
|
|
/* This flag specifies that when clipPath() is called, the path will
|
|
be faithfully recorded, but the recording canvas' current clip will
|
|
only see the path's bounds. This speeds up the recording process
|
|
without compromising the fidelity of the playback. The only side-
|
|
effect for recording is that calling getTotalClip() or related
|
|
clip-query calls will reflect the path's bounds, not the actual
|
|
path.
|
|
*/
|
|
kUsePathBoundsForClip_RecordingFlag = 0x01,
|
|
/* This flag causes the picture to compute bounding boxes and build
|
|
up a spatial hierarchy (currently an R-Tree), plus a tree of Canvas'
|
|
usually stack-based clip/etc state. This requires an increase in
|
|
recording time (often ~2x; likely more for very complex pictures),
|
|
but allows us to perform much faster culling at playback time, and
|
|
completely avoid some unnecessary clips and other operations. This
|
|
is ideal for tiled rendering, or any other situation where you're
|
|
drawing a fraction of a large scene into a smaller viewport.
|
|
|
|
In most cases the record cost is offset by the playback improvement
|
|
after a frame or two of tiled rendering (and complex pictures that
|
|
induce the worst record times will generally get the largest
|
|
speedups at playback time).
|
|
|
|
Note: Currently this is not serializable, the bounding data will be
|
|
discarded if you serialize into a stream and then deserialize.
|
|
*/
|
|
kOptimizeForClippedPlayback_RecordingFlag = 0x02,
|
|
/*
|
|
This flag disables all the picture recording optimizations (i.e.,
|
|
those in SkPictureRecord). It is mainly intended for testing the
|
|
existing optimizations (i.e., to actually have the pattern
|
|
appear in an .skp we have to disable the optimization). This
|
|
option doesn't affect the optimizations controlled by
|
|
'kOptimizeForClippedPlayback_RecordingFlag'.
|
|
*/
|
|
kDisableRecordOptimizations_RecordingFlag = 0x04
|
|
};
|
|
|
|
/** Returns the canvas that records the drawing commands.
|
|
@param width the base width for the picture, as if the recording
|
|
canvas' bitmap had this width.
|
|
@param height the base width for the picture, as if the recording
|
|
canvas' bitmap had this height.
|
|
@param recordFlags optional flags that control recording.
|
|
@return the picture canvas.
|
|
*/
|
|
SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);
|
|
|
|
/** Returns the recording canvas if one is active, or NULL if recording is
|
|
not active. This does not alter the refcnt on the canvas (if present).
|
|
*/
|
|
SkCanvas* getRecordingCanvas() const;
|
|
/** Signal that the caller is done recording. This invalidates the canvas
|
|
returned by beginRecording/getRecordingCanvas, and prepares the picture
|
|
for drawing. Note: this happens implicitly the first time the picture
|
|
is drawn.
|
|
*/
|
|
void endRecording();
|
|
|
|
/** Replays the drawing commands on the specified canvas. This internally
|
|
calls endRecording() if that has not already been called.
|
|
@param canvas the canvas receiving the drawing commands.
|
|
*/
|
|
void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL);
|
|
|
|
/** Return the width of the picture's recording canvas. This
|
|
value reflects what was passed to setSize(), and does not necessarily
|
|
reflect the bounds of what has been recorded into the picture.
|
|
@return the width of the picture's recording canvas
|
|
*/
|
|
int width() const { return fWidth; }
|
|
|
|
/** Return the height of the picture's recording canvas. This
|
|
value reflects what was passed to setSize(), and does not necessarily
|
|
reflect the bounds of what has been recorded into the picture.
|
|
@return the height of the picture's recording canvas
|
|
*/
|
|
int height() const { return fHeight; }
|
|
|
|
/**
|
|
* Function to encode an SkBitmap to an SkData. A function with this
|
|
* signature can be passed to serialize() and SkWriteBuffer.
|
|
* Returning NULL will tell the SkWriteBuffer to use
|
|
* SkBitmap::flatten() to store the bitmap.
|
|
*
|
|
* @param pixelRefOffset DEPRECATED -- caller assumes it will return 0.
|
|
* @return SkData If non-NULL, holds encoded data representing the passed
|
|
* in bitmap. The caller is responsible for calling unref().
|
|
*/
|
|
typedef SkData* (*EncodeBitmap)(size_t* pixelRefOffset, const SkBitmap& bm);
|
|
|
|
/**
|
|
* Serialize to a stream. If non NULL, encoder will be used to encode
|
|
* any bitmaps in the picture.
|
|
* encoder will never be called with a NULL pixelRefOffset.
|
|
*/
|
|
void serialize(SkWStream*, EncodeBitmap encoder = NULL) const;
|
|
|
|
/**
|
|
* Serialize to a buffer.
|
|
*/
|
|
void flatten(SkWriteBuffer&) const;
|
|
|
|
/**
|
|
* Returns true if any bitmaps may be produced when this SkPicture
|
|
* is replayed.
|
|
* Returns false if called while still recording.
|
|
*/
|
|
bool willPlayBackBitmaps() const;
|
|
|
|
#ifdef SK_BUILD_FOR_ANDROID
|
|
/** Signals that the caller is prematurely done replaying the drawing
|
|
commands. This can be called from a canvas virtual while the picture
|
|
is drawing. Has no effect if the picture is not drawing.
|
|
@deprecated preserving for legacy purposes
|
|
*/
|
|
void abortPlayback();
|
|
#endif
|
|
|
|
protected:
|
|
// V2 : adds SkPixelRef's generation ID.
|
|
// V3 : PictInfo tag at beginning, and EOF tag at the end
|
|
// V4 : move SkPictInfo to be the header
|
|
// V5 : don't read/write FunctionPtr on cross-process (we can detect that)
|
|
// V6 : added serialization of SkPath's bounds (and packed its flags tighter)
|
|
// V7 : changed drawBitmapRect(IRect) to drawBitmapRectToRect(Rect)
|
|
// V8 : Add an option for encoding bitmaps
|
|
// V9 : Allow the reader and writer of an SKP disagree on whether to support
|
|
// SK_SUPPORT_HINTING_SCALE_FACTOR
|
|
// V10: add drawRRect, drawOval, clipRRect
|
|
// V11: modify how readBitmap and writeBitmap store their info.
|
|
// V12: add conics to SkPath, use new SkPathRef flattening
|
|
// V13: add flag to drawBitmapRectToRect
|
|
// parameterize blurs by sigma rather than radius
|
|
// V14: Add flags word to PathRef serialization
|
|
// V15: Remove A1 bitmpa config (and renumber remaining configs)
|
|
// V16: Move SkPath's isOval flag to SkPathRef
|
|
// V17: SkPixelRef now writes SkImageInfo
|
|
// V18: SkBitmap now records x,y for its pixelref origin, instead of offset.
|
|
// V19: encode matrices and regions into the ops stream
|
|
// V20: added bool to SkPictureImageFilter's serialization (to allow SkPicture serialization)
|
|
// V21: add pushCull, popCull
|
|
|
|
// Note: If the picture version needs to be increased then please follow the
|
|
// steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw
|
|
|
|
// Only SKPs within the min/current picture version range (inclusive) can be read.
|
|
static const uint32_t MIN_PICTURE_VERSION = 19;
|
|
static const uint32_t CURRENT_PICTURE_VERSION = 21;
|
|
|
|
// fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
|
|
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived
|
|
// recorders and set the picture size
|
|
SkPicturePlayback* fPlayback;
|
|
SkPictureRecord* fRecord;
|
|
int fWidth, fHeight;
|
|
|
|
// Create a new SkPicture from an existing SkPicturePlayback. Ref count of
|
|
// playback is unchanged.
|
|
SkPicture(SkPicturePlayback*, int width, int height);
|
|
|
|
// For testing. Derived classes may instantiate an alternate
|
|
// SkBBoxHierarchy implementation
|
|
virtual SkBBoxHierarchy* createBBoxHierarchy() const;
|
|
|
|
// Return true if the SkStream represents a serialized picture, and fills out
|
|
// SkPictInfo. After this function returns, the SkStream is not rewound; it
|
|
// will be ready to be parsed to create an SkPicturePlayback.
|
|
// If false is returned, SkPictInfo is unmodified.
|
|
static bool StreamIsSKP(SkStream*, SkPictInfo*);
|
|
static bool BufferIsSKP(SkReadBuffer&, SkPictInfo*);
|
|
private:
|
|
void createHeader(void* header) const;
|
|
|
|
friend class SkFlatPicture;
|
|
friend class SkPicturePlayback;
|
|
|
|
typedef SkRefCnt INHERITED;
|
|
};
|
|
|
|
/**
|
|
* Subclasses of this can be passed to canvas.drawPicture. During the drawing
|
|
* of the picture, this callback will periodically be invoked. If its
|
|
* abortDrawing() returns true, then picture playback will be interrupted.
|
|
*
|
|
* The resulting drawing is undefined, as there is no guarantee how often the
|
|
* callback will be invoked. If the abort happens inside some level of nested
|
|
* calls to save(), restore will automatically be called to return the state
|
|
* to the same level it was before the drawPicture call was made.
|
|
*/
|
|
class SK_API SkDrawPictureCallback {
|
|
public:
|
|
SkDrawPictureCallback() {}
|
|
virtual ~SkDrawPictureCallback() {}
|
|
|
|
virtual bool abortDrawing() = 0;
|
|
};
|
|
|
|
#endif
|