1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkDeferredCanvas_DEFINED 9 #define SkDeferredCanvas_DEFINED 10 11 #include "SkCanvas.h" 12 #include "SkPixelRef.h" 13 14 class SkDeferredDevice; 15 class SkImage; 16 class SkSurface; 17 18 /** \class SkDeferredCanvas 19 Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred 20 drawing. The main difference between this class and SkPictureRecord (the 21 canvas provided by SkPicture) is that this is a full drop-in replacement 22 for SkCanvas, while SkPictureRecord only supports draw operations. 23 SkDeferredCanvas will transparently trigger the flushing of deferred 24 draw operations when an attempt is made to access the pixel data. 25 */ 26 class SK_API SkDeferredCanvas : public SkCanvas { 27 public: 28 class SK_API NotificationClient; 29 30 /** Construct a canvas with the specified surface to draw into. 31 This factory must be used for newImageSnapshot to work. 32 @param surface Specifies a surface for the canvas to draw into. 33 */ 34 static SkDeferredCanvas* Create(SkSurface* surface); 35 36 // static SkDeferredCanvas* Create(SkBaseDevice* device); 37 38 virtual ~SkDeferredCanvas(); 39 40 /** 41 * Specify the surface to be used by this canvas. Calling setSurface will 42 * release the previously set surface or device. Takes a reference on the 43 * surface. 44 * 45 * @param surface The surface that the canvas will raw into 46 * @return The surface argument, for convenience. 47 */ 48 SkSurface* setSurface(SkSurface* surface); 49 50 /** 51 * Specify a NotificationClient to be used by this canvas. Calling 52 * setNotificationClient will release the previously set 53 * NotificationClient, if any. SkDeferredCanvas does not take ownership 54 * of the notification client. Therefore user code is resposible 55 * for its destruction. The notification client must be unregistered 56 * by calling setNotificationClient(NULL) if it is destroyed before 57 * this canvas. 58 * Note: Must be called after the device is set with setDevice. 59 * 60 * @param notificationClient interface for dispatching notifications 61 * @return The notificationClient argument, for convenience. 62 */ 63 NotificationClient* setNotificationClient(NotificationClient* notificationClient); 64 65 /** 66 * Enable or disable deferred drawing. When deferral is disabled, 67 * pending draw operations are immediately flushed and from then on, 68 * the SkDeferredCanvas behaves just like a regular SkCanvas. 69 * This method must not be called while the save/restore stack is in use. 70 * @param deferred true/false 71 */ 72 void setDeferredDrawing(bool deferred); 73 74 /** 75 * Returns true if deferred drawing is currenlty enabled. 76 */ 77 bool isDeferredDrawing() const; 78 79 /** 80 * Returns true if the canvas contains a fresh frame. A frame is 81 * considered fresh when its content do not depend on the contents 82 * of the previous frame. For example, if a canvas is cleared before 83 * drawing each frame, the frames will all be considered fresh. 84 * A frame is defined as the graphics image produced by as a result 85 * of all the canvas draws operation executed between two successive 86 * calls to isFreshFrame. The result of isFreshFrame is computed 87 * conservatively, so it may report false negatives. 88 */ 89 bool isFreshFrame() const; 90 91 /** 92 * Returns canvas's size. 93 */ 94 SkISize getCanvasSize() const; 95 96 /** 97 * Returns true if the canvas has recorded draw commands that have 98 * not yet been played back. 99 */ 100 bool hasPendingCommands() const; 101 102 /** 103 * Flushes pending draw commands, if any, and returns an image of the 104 * current state of the surface pixels up to this point. Subsequent 105 * changes to the surface (by drawing into its canvas) will not be 106 * reflected in this image. Will return NULL if the deferred canvas 107 * was not constructed from an SkSurface. 108 */ 109 SkImage* newImageSnapshot(); 110 111 /** 112 * Specify the maximum number of bytes to be allocated for the purpose 113 * of recording draw commands to this canvas. The default limit, is 114 * 64MB. 115 * @param maxStorage The maximum number of bytes to be allocated. 116 */ 117 void setMaxRecordingStorage(size_t maxStorage); 118 119 /** 120 * Returns the number of bytes currently allocated for the purpose of 121 * recording draw commands. 122 */ 123 size_t storageAllocatedForRecording() const; 124 125 /** 126 * Attempt to reduce the storage allocated for recording by evicting 127 * cache resources. 128 * @param bytesToFree minimum number of bytes that should be attempted to 129 * be freed. 130 * @return number of bytes actually freed. 131 */ 132 size_t freeMemoryIfPossible(size_t bytesToFree); 133 134 /** 135 * Specifies the maximum size (in bytes) allowed for a given image to be 136 * rendered using the deferred canvas. 137 */ 138 void setBitmapSizeThreshold(size_t sizeThreshold); getBitmapSizeThreshold()139 size_t getBitmapSizeThreshold() const { return fBitmapSizeThreshold; } 140 141 /** 142 * Executes all pending commands without drawing 143 */ 144 void silentFlush(); 145 146 SkDrawFilter* setDrawFilter(SkDrawFilter* filter) override; 147 148 protected: 149 void willSave() override; 150 SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) override; 151 void willRestore() override; 152 153 void didConcat(const SkMatrix&) override; 154 void didSetMatrix(const SkMatrix&) override; 155 156 void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; 157 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 158 const SkPaint&) override; 159 virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 160 const SkPaint&) override; 161 virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 162 SkScalar constY, const SkPaint&) override; 163 virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 164 const SkMatrix* matrix, const SkPaint&) override; 165 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 166 const SkPaint& paint) override; 167 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 168 const SkPoint texCoords[4], SkXfermode* xmode, 169 const SkPaint& paint) override; 170 171 void onDrawPaint(const SkPaint&) override; 172 void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; 173 void onDrawRect(const SkRect&, const SkPaint&) override; 174 void onDrawOval(const SkRect&, const SkPaint&) override; 175 void onDrawRRect(const SkRRect&, const SkPaint&) override; 176 void onDrawPath(const SkPath&, const SkPaint&) override; 177 void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override; 178 void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*, 179 DrawBitmapRectFlags flags) override; 180 void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override; 181 void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, 182 const SkPaint*) override; 183 void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, 184 const SkPaint*) override; 185 void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override; 186 void onDrawVertices(VertexMode vmode, int vertexCount, 187 const SkPoint vertices[], const SkPoint texs[], 188 const SkColor colors[], SkXfermode* xmode, 189 const uint16_t indices[], int indexCount, 190 const SkPaint&) override; 191 192 void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override; 193 void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override; 194 void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override; 195 void onClipRegion(const SkRegion&, SkRegion::Op) override; 196 197 void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override; 198 199 public: 200 class NotificationClient { 201 public: ~NotificationClient()202 virtual ~NotificationClient() {} 203 204 /** 205 * Called before executing one or several draw commands, which means 206 * once per flush when deferred rendering is enabled. 207 */ prepareForDraw()208 virtual void prepareForDraw() {} 209 210 /** 211 * Called after a recording a draw command if additional memory 212 * had to be allocated for recording. 213 * @param newAllocatedStorage same value as would be returned by 214 * storageAllocatedForRecording(), for convenience. 215 */ storageAllocatedForRecordingChanged(size_t)216 virtual void storageAllocatedForRecordingChanged(size_t /*newAllocatedStorage*/) {} 217 218 /** 219 * Called after pending draw commands have been flushed 220 */ flushedDrawCommands()221 virtual void flushedDrawCommands() {} 222 223 /** 224 * Called after pending draw commands have been skipped, meaning 225 * that they were optimized-out because the canvas is cleared 226 * or completely overwritten by the command currently being recorded. 227 */ skippedPendingDrawCommands()228 virtual void skippedPendingDrawCommands() {} 229 }; 230 231 protected: 232 SkCanvas* canvasForDrawIter() override; 233 SkDeferredDevice* getDeferredDevice() const; 234 235 private: 236 SkDeferredCanvas(SkDeferredDevice*); 237 238 void recordedDrawCommand(); 239 SkCanvas* drawingCanvas() const; 240 SkCanvas* immediateCanvas() const; 241 bool isFullFrame(const SkRect*, const SkPaint*) const; 242 void validate() const; 243 void init(); 244 245 246 int fSaveLevel; 247 int fFirstSaveLayerIndex; 248 size_t fBitmapSizeThreshold; 249 bool fDeferredDrawing; 250 251 mutable SkISize fCachedCanvasSize; 252 mutable bool fCachedCanvasSizeDirty; 253 254 friend class SkDeferredCanvasTester; // for unit testing 255 typedef SkCanvas INHERITED; 256 }; 257 258 259 #endif 260