| OLD | NEW |
| (Empty) |
| 1 | |
| 2 /* | |
| 3 * Copyright 2011 Google Inc. | |
| 4 * | |
| 5 * Use of this source code is governed by a BSD-style license that can be | |
| 6 * found in the LICENSE file. | |
| 7 */ | |
| 8 | |
| 9 #ifndef SkPicturePlayback_DEFINED | |
| 10 #define SkPicturePlayback_DEFINED | |
| 11 | |
| 12 #include "SkBitmap.h" | |
| 13 #include "SkPathHeap.h" | |
| 14 #include "SkPicture.h" | |
| 15 #include "SkPictureFlat.h" | |
| 16 | |
| 17 #ifdef SK_BUILD_FOR_ANDROID | |
| 18 #include "SkThread.h" | |
| 19 #endif | |
| 20 | |
| 21 class SkData; | |
| 22 class SkPictureRecord; | |
| 23 class SkReader32; | |
| 24 class SkStream; | |
| 25 class SkWStream; | |
| 26 class SkBBoxHierarchy; | |
| 27 class SkMatrix; | |
| 28 class SkPaint; | |
| 29 class SkPath; | |
| 30 class SkPictureStateTree; | |
| 31 class SkReadBuffer; | |
| 32 class SkRegion; | |
| 33 | |
| 34 struct SkPictInfo { | |
| 35 enum Flags { | |
| 36 kCrossProcess_Flag = 1 << 0, | |
| 37 kScalarIsFloat_Flag = 1 << 1, | |
| 38 kPtrIs64Bit_Flag = 1 << 2, | |
| 39 }; | |
| 40 | |
| 41 char fMagic[8]; | |
| 42 uint32_t fVersion; | |
| 43 uint32_t fWidth; | |
| 44 uint32_t fHeight; | |
| 45 uint32_t fFlags; | |
| 46 }; | |
| 47 | |
| 48 #define SK_PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd') | |
| 49 #define SK_PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't') | |
| 50 #define SK_PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c') | |
| 51 #define SK_PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r') | |
| 52 | |
| 53 // This tag specifies the size of the ReadBuffer, needed for the following tags | |
| 54 #define SK_PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y') | |
| 55 // these are all inside the ARRAYS tag | |
| 56 #define SK_PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p') | |
| 57 #define SK_PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ') | |
| 58 #define SK_PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ') | |
| 59 | |
| 60 // Always write this guy last (with no length field afterwards) | |
| 61 #define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ') | |
| 62 | |
| 63 // SkPictureContentInfo is not serialized! It is intended solely for use | |
| 64 // with suitableForGpuRasterization. | |
| 65 class SkPictureContentInfo { | |
| 66 public: | |
| 67 SkPictureContentInfo() { this->reset(); } | |
| 68 | |
| 69 SkPictureContentInfo(const SkPictureContentInfo& src) { this->set(src); } | |
| 70 | |
| 71 void set(const SkPictureContentInfo& src) { | |
| 72 fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses; | |
| 73 fNumFastPathDashEffects = src.fNumFastPathDashEffects; | |
| 74 fNumAAConcavePaths = src.fNumAAConcavePaths; | |
| 75 fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths; | |
| 76 } | |
| 77 | |
| 78 void reset() { | |
| 79 fNumPaintWithPathEffectUses = 0; | |
| 80 fNumFastPathDashEffects = 0; | |
| 81 fNumAAConcavePaths = 0; | |
| 82 fNumAAHairlineConcavePaths = 0; | |
| 83 } | |
| 84 | |
| 85 void swap(SkPictureContentInfo* other) { | |
| 86 SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses)
; | |
| 87 SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects); | |
| 88 SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths); | |
| 89 SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths); | |
| 90 } | |
| 91 | |
| 92 void incPaintWithPathEffectUses() { ++fNumPaintWithPathEffectUses; } | |
| 93 int numPaintWithPathEffectUses() const { return fNumPaintWithPathEffectUses;
} | |
| 94 | |
| 95 void incFastPathDashEffects() { ++fNumFastPathDashEffects; } | |
| 96 int numFastPathDashEffects() const { return fNumFastPathDashEffects; } | |
| 97 | |
| 98 void incAAConcavePaths() { ++fNumAAConcavePaths; } | |
| 99 int numAAConcavePaths() const { return fNumAAConcavePaths; } | |
| 100 | |
| 101 void incAAHairlineConcavePaths() { | |
| 102 ++fNumAAHairlineConcavePaths; | |
| 103 SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths); | |
| 104 } | |
| 105 int numAAHairlineConcavePaths() const { return fNumAAHairlineConcavePaths; } | |
| 106 | |
| 107 private: | |
| 108 // This field is incremented every time a paint with a path effect is | |
| 109 // used (i.e., it is not a de-duplicated count) | |
| 110 int fNumPaintWithPathEffectUses; | |
| 111 // This field is incremented every time a paint with a path effect that is | |
| 112 // dashed, we are drawing a line, and we can use the gpu fast path | |
| 113 int fNumFastPathDashEffects; | |
| 114 // This field is incremented every time an anti-aliased drawPath call is | |
| 115 // issued with a concave path | |
| 116 int fNumAAConcavePaths; | |
| 117 // This field is incremented every time a drawPath call is | |
| 118 // issued for a hairline stroked concave path. | |
| 119 int fNumAAHairlineConcavePaths; | |
| 120 }; | |
| 121 | |
| 122 #ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE | |
| 123 /** | |
| 124 * Container for data that is needed to deep copy a SkPicture. The container | |
| 125 * enables the data to be generated once and reused for subsequent copies. | |
| 126 */ | |
| 127 struct SkPictCopyInfo { | |
| 128 SkPictCopyInfo() : initialized(false), controller(1024) {} | |
| 129 | |
| 130 bool initialized; | |
| 131 SkChunkFlatController controller; | |
| 132 SkTDArray<SkFlatData*> paintData; | |
| 133 }; | |
| 134 #endif | |
| 135 | |
| 136 class SkPicturePlayback { | |
| 137 public: | |
| 138 #ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE | |
| 139 SkPicturePlayback(const SkPicturePlayback& src, | |
| 140 SkPictCopyInfo* deepCopyInfo = NULL); | |
| 141 #else | |
| 142 SkPicturePlayback(const SkPicturePlayback& src); | |
| 143 #endif | |
| 144 SkPicturePlayback(const SkPictureRecord& record, const SkPictInfo&, bool dee
pCopyOps); | |
| 145 static SkPicturePlayback* CreateFromStream(SkStream*, | |
| 146 const SkPictInfo&, | |
| 147 SkPicture::InstallPixelRefProc); | |
| 148 static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&, | |
| 149 const SkPictInfo&); | |
| 150 | |
| 151 virtual ~SkPicturePlayback(); | |
| 152 | |
| 153 const SkPicture::OperationList& getActiveOps(const SkIRect& queryRect); | |
| 154 | |
| 155 void setUseBBH(bool useBBH) { fUseBBH = useBBH; } | |
| 156 | |
| 157 void draw(SkCanvas& canvas, SkDrawPictureCallback*); | |
| 158 | |
| 159 void serialize(SkWStream*, SkPicture::EncodeBitmap) const; | |
| 160 void flatten(SkWriteBuffer&) const; | |
| 161 | |
| 162 void dumpSize() const; | |
| 163 | |
| 164 bool containsBitmaps() const; | |
| 165 | |
| 166 #ifdef SK_BUILD_FOR_ANDROID | |
| 167 // Can be called in the middle of playback (the draw() call). WIll abort the | |
| 168 // drawing and return from draw() after the "current" op code is done | |
| 169 void abort() { fAbortCurrentPlayback = true; } | |
| 170 #endif | |
| 171 | |
| 172 size_t curOpID() const { return fCurOffset; } | |
| 173 void resetOpID() { fCurOffset = 0; } | |
| 174 | |
| 175 protected: | |
| 176 explicit SkPicturePlayback(const SkPictInfo& info); | |
| 177 | |
| 178 bool parseStream(SkStream*, SkPicture::InstallPixelRefProc); | |
| 179 bool parseBuffer(SkReadBuffer& buffer); | |
| 180 #ifdef SK_DEVELOPER | |
| 181 virtual bool preDraw(int opIndex, int type); | |
| 182 virtual void postDraw(int opIndex); | |
| 183 #endif | |
| 184 | |
| 185 private: | |
| 186 class TextContainer { | |
| 187 public: | |
| 188 size_t length() { return fByteLength; } | |
| 189 const void* text() { return (const void*) fText; } | |
| 190 size_t fByteLength; | |
| 191 const char* fText; | |
| 192 }; | |
| 193 | |
| 194 const SkBitmap& getBitmap(SkReader32& reader) { | |
| 195 const int index = reader.readInt(); | |
| 196 if (SkBitmapHeap::INVALID_SLOT == index) { | |
| 197 #ifdef SK_DEBUG | |
| 198 SkDebugf("An invalid bitmap was recorded!\n"); | |
| 199 #endif | |
| 200 return fBadBitmap; | |
| 201 } | |
| 202 return (*fBitmaps)[index]; | |
| 203 } | |
| 204 | |
| 205 void getMatrix(SkReader32& reader, SkMatrix* matrix) { | |
| 206 reader.readMatrix(matrix); | |
| 207 } | |
| 208 | |
| 209 const SkPath& getPath(SkReader32& reader) { | |
| 210 int index = reader.readInt() - 1; | |
| 211 return (*fPathHeap.get())[index]; | |
| 212 } | |
| 213 | |
| 214 const SkPicture* getPicture(SkReader32& reader) { | |
| 215 int index = reader.readInt(); | |
| 216 SkASSERT(index > 0 && index <= fPictureCount); | |
| 217 return fPictureRefs[index - 1]; | |
| 218 } | |
| 219 | |
| 220 const SkPaint* getPaint(SkReader32& reader) { | |
| 221 int index = reader.readInt(); | |
| 222 if (index == 0) { | |
| 223 return NULL; | |
| 224 } | |
| 225 return &(*fPaints)[index - 1]; | |
| 226 } | |
| 227 | |
| 228 const SkRect* getRectPtr(SkReader32& reader) { | |
| 229 if (reader.readBool()) { | |
| 230 return &reader.skipT<SkRect>(); | |
| 231 } else { | |
| 232 return NULL; | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 const SkIRect* getIRectPtr(SkReader32& reader) { | |
| 237 if (reader.readBool()) { | |
| 238 return &reader.skipT<SkIRect>(); | |
| 239 } else { | |
| 240 return NULL; | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void getRegion(SkReader32& reader, SkRegion* region) { | |
| 245 reader.readRegion(region); | |
| 246 } | |
| 247 | |
| 248 void getText(SkReader32& reader, TextContainer* text) { | |
| 249 size_t length = text->fByteLength = reader.readInt(); | |
| 250 text->fText = (const char*)reader.skip(length); | |
| 251 } | |
| 252 | |
| 253 void init(); | |
| 254 | |
| 255 #ifdef SK_DEBUG_SIZE | |
| 256 public: | |
| 257 int size(size_t* sizePtr); | |
| 258 int bitmaps(size_t* size); | |
| 259 int paints(size_t* size); | |
| 260 int paths(size_t* size); | |
| 261 #endif | |
| 262 | |
| 263 #ifdef SK_DEBUG_DUMP | |
| 264 private: | |
| 265 void dumpBitmap(const SkBitmap& bitmap) const; | |
| 266 void dumpMatrix(const SkMatrix& matrix) const; | |
| 267 void dumpPaint(const SkPaint& paint) const; | |
| 268 void dumpPath(const SkPath& path) const; | |
| 269 void dumpPicture(const SkPicture& picture) const; | |
| 270 void dumpRegion(const SkRegion& region) const; | |
| 271 int dumpDrawType(char* bufferPtr, char* buffer, DrawType drawType); | |
| 272 int dumpInt(char* bufferPtr, char* buffer, char* name); | |
| 273 int dumpRect(char* bufferPtr, char* buffer, char* name); | |
| 274 int dumpPoint(char* bufferPtr, char* buffer, char* name); | |
| 275 void dumpPointArray(char** bufferPtrPtr, char* buffer, int count); | |
| 276 int dumpPtr(char* bufferPtr, char* buffer, char* name, void* ptr); | |
| 277 int dumpRectPtr(char* bufferPtr, char* buffer, char* name); | |
| 278 int dumpScalar(char* bufferPtr, char* buffer, char* name); | |
| 279 void dumpText(char** bufferPtrPtr, char* buffer); | |
| 280 void dumpStream(); | |
| 281 | |
| 282 public: | |
| 283 void dump() const; | |
| 284 #endif | |
| 285 | |
| 286 #if SK_SUPPORT_GPU | |
| 287 /** | |
| 288 * sampleCount is the number of samples-per-pixel or zero if non-MSAA. | |
| 289 * It is defaulted to be zero. | |
| 290 */ | |
| 291 bool suitableForGpuRasterization(GrContext* context, const char **reason, | |
| 292 int sampleCount = 0) const; | |
| 293 | |
| 294 /** | |
| 295 * Calls getRecommendedSampleCount with GrPixelConfig and dpi to calculate s
ampleCount | |
| 296 * and then calls the above version of suitableForGpuRasterization | |
| 297 */ | |
| 298 bool suitableForGpuRasterization(GrContext* context, const char **reason, | |
| 299 GrPixelConfig config, SkScalar dpi) const; | |
| 300 #endif | |
| 301 | |
| 302 private: // these help us with reading/writing | |
| 303 bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, SkPicture::Insta
llPixelRefProc); | |
| 304 bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size); | |
| 305 void flattenToBuffer(SkWriteBuffer&) const; | |
| 306 | |
| 307 private: | |
| 308 friend class SkPicture; | |
| 309 friend class SkGpuDevice; // for access to setDrawLimits & setReplacements | |
| 310 | |
| 311 // Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_
SLOT. This empty | |
| 312 // bitmap allows playback to draw nothing and move on. | |
| 313 SkBitmap fBadBitmap; | |
| 314 | |
| 315 SkAutoTUnref<SkBitmapHeap> fBitmapHeap; | |
| 316 | |
| 317 SkTRefArray<SkBitmap>* fBitmaps; | |
| 318 SkTRefArray<SkPaint>* fPaints; | |
| 319 | |
| 320 SkData* fOpData; // opcodes and parameters | |
| 321 | |
| 322 SkAutoTUnref<const SkPathHeap> fPathHeap; // reference counted | |
| 323 | |
| 324 const SkPicture** fPictureRefs; | |
| 325 int fPictureCount; | |
| 326 | |
| 327 SkBBoxHierarchy* fBoundingHierarchy; | |
| 328 SkPictureStateTree* fStateTree; | |
| 329 | |
| 330 SkPictureContentInfo fContentInfo; | |
| 331 | |
| 332 // Limit the opcode playback to be between the offsets 'start' and 'stop'. | |
| 333 // The opcode at 'start' should be a saveLayer while the opcode at | |
| 334 // 'stop' should be a restore. Neither of those commands will be issued. | |
| 335 // Set both start & stop to 0 to disable draw limiting | |
| 336 // Draw limiting cannot be enabled at the same time as draw replacing | |
| 337 void setDrawLimits(size_t start, size_t stop) { | |
| 338 SkASSERT(NULL == fReplacements); | |
| 339 fStart = start; | |
| 340 fStop = stop; | |
| 341 } | |
| 342 | |
| 343 // PlaybackReplacements collects op ranges that can be replaced with | |
| 344 // a single drawBitmap call (using a precomputed bitmap). | |
| 345 class PlaybackReplacements { | |
| 346 public: | |
| 347 // All the operations between fStart and fStop (inclusive) will be repla
ced with | |
| 348 // a single drawBitmap call using fPos, fBM and fPaint. | |
| 349 // fPaint will be NULL if the picture's paint wasn't copyable | |
| 350 struct ReplacementInfo { | |
| 351 size_t fStart; | |
| 352 size_t fStop; | |
| 353 SkIPoint fPos; | |
| 354 SkBitmap* fBM; // fBM is allocated so ReplacementInfo can
remain POD | |
| 355 const SkPaint* fPaint; // Note: this object doesn't own the paint | |
| 356 | |
| 357 SkIRect fSrcRect; | |
| 358 }; | |
| 359 | |
| 360 ~PlaybackReplacements() { this->freeAll(); } | |
| 361 | |
| 362 // Add a new replacement range. The replacement ranges should be | |
| 363 // sorted in increasing order and non-overlapping (esp. no nested | |
| 364 // saveLayers). | |
| 365 ReplacementInfo* push(); | |
| 366 | |
| 367 private: | |
| 368 friend class SkPicturePlayback; // for access to lookupByStart | |
| 369 | |
| 370 // look up a replacement range by its start offset | |
| 371 ReplacementInfo* lookupByStart(size_t start); | |
| 372 | |
| 373 void freeAll(); | |
| 374 | |
| 375 #ifdef SK_DEBUG | |
| 376 void validate() const; | |
| 377 #endif | |
| 378 | |
| 379 SkTDArray<ReplacementInfo> fReplacements; | |
| 380 }; | |
| 381 | |
| 382 // Replace all the draw ops in the replacement ranges in 'replacements' with | |
| 383 // the associated drawBitmap call | |
| 384 // Draw replacing cannot be enabled at the same time as draw limiting | |
| 385 void setReplacements(PlaybackReplacements* replacements) { | |
| 386 SkASSERT(fStart == 0 && fStop == 0); | |
| 387 fReplacements = replacements; | |
| 388 } | |
| 389 | |
| 390 bool fUseBBH; | |
| 391 size_t fStart; | |
| 392 size_t fStop; | |
| 393 PlaybackReplacements* fReplacements; | |
| 394 | |
| 395 class CachedOperationList : public SkPicture::OperationList { | |
| 396 public: | |
| 397 CachedOperationList() { | |
| 398 fCacheQueryRect.setEmpty(); | |
| 399 } | |
| 400 | |
| 401 virtual bool valid() const { return true; } | |
| 402 virtual int numOps() const SK_OVERRIDE { return fOps.count(); } | |
| 403 virtual uint32_t offset(int index) const SK_OVERRIDE; | |
| 404 virtual const SkMatrix& matrix(int index) const SK_OVERRIDE; | |
| 405 | |
| 406 // The query rect for which the cached active ops are valid | |
| 407 SkIRect fCacheQueryRect; | |
| 408 | |
| 409 // The operations which are active within 'fCachedQueryRect' | |
| 410 SkTDArray<void*> fOps; | |
| 411 | |
| 412 private: | |
| 413 typedef SkPicture::OperationList INHERITED; | |
| 414 }; | |
| 415 | |
| 416 CachedOperationList* fCachedActiveOps; | |
| 417 | |
| 418 SkTypefacePlayback fTFPlayback; | |
| 419 SkFactoryPlayback* fFactoryPlayback; | |
| 420 | |
| 421 // The offset of the current operation when within the draw method | |
| 422 size_t fCurOffset; | |
| 423 | |
| 424 const SkPictInfo fInfo; | |
| 425 | |
| 426 static void WriteFactories(SkWStream* stream, const SkFactorySet& rec); | |
| 427 static void WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec); | |
| 428 | |
| 429 void initForPlayback() const; | |
| 430 | |
| 431 #ifdef SK_BUILD_FOR_ANDROID | |
| 432 SkMutex fDrawMutex; | |
| 433 bool fAbortCurrentPlayback; | |
| 434 #endif | |
| 435 }; | |
| 436 | |
| 437 #endif | |
| OLD | NEW |