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 #include "SkBitmapHeap.h" 10 #include "SkCanvas.h" 11 #include "SkColorFilter.h" 12 #include "SkData.h" 13 #include "SkDrawLooper.h" 14 #include "SkDevice.h" 15 #include "SkGPipe.h" 16 #include "SkGPipePriv.h" 17 #include "SkImageFilter.h" 18 #include "SkMaskFilter.h" 19 #include "SkOrderedWriteBuffer.h" 20 #include "SkPaint.h" 21 #include "SkPathEffect.h" 22 #include "SkPictureFlat.h" 23 #include "SkRasterizer.h" 24 #include "SkRRect.h" 25 #include "SkShader.h" 26 #include "SkStream.h" 27 #include "SkTSearch.h" 28 #include "SkTypeface.h" 29 #include "SkWriter32.h" 30 31 enum { 32 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector) 33 }; 34 35 static bool isCrossProcess(uint32_t flags) { 36 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag); 37 } 38 39 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { 40 SkASSERT(paintFlat < kCount_PaintFlats); 41 switch (paintFlat) { 42 case kColorFilter_PaintFlat: return paint.getColorFilter(); 43 case kDrawLooper_PaintFlat: return paint.getLooper(); 44 case kMaskFilter_PaintFlat: return paint.getMaskFilter(); 45 case kPathEffect_PaintFlat: return paint.getPathEffect(); 46 case kRasterizer_PaintFlat: return paint.getRasterizer(); 47 case kShader_PaintFlat: return paint.getShader(); 48 case kImageFilter_PaintFlat: return paint.getImageFilter(); 49 case kXfermode_PaintFlat: return paint.getXfermode(); 50 } 51 SkDEBUGFAIL("never gets here"); 52 return NULL; 53 } 54 55 static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) { 56 SkASSERT(typeface); 57 SkDynamicMemoryWStream stream; 58 typeface->serialize(&stream); 59 size_t size = stream.getOffset(); 60 if (writer) { 61 writer->write32(size); 62 SkAutoDataUnref data(stream.copyToData()); 63 writer->writePad(data->data(), size); 64 } 65 return 4 + SkAlign4(size); 66 } 67 68 /////////////////////////////////////////////////////////////////////////////// 69 70 class FlattenableHeap : public SkFlatController { 71 public: 72 FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossProcess) 73 : fNumFlatsToKeep(numFlatsToKeep) { 74 SkASSERT((isCrossProcess && fset != NULL) || (!isCrossProcess && NULL == fset)); 75 if (isCrossProcess) { 76 this->setNamedFactorySet(fset); 77 this->setWriteBufferFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag); 78 } 79 } 80 81 ~FlattenableHeap() { 82 fPointers.freeAll(); 83 } 84 85 virtual void* allocThrow(size_t bytes) SK_OVERRIDE; 86 87 virtual void unalloc(void* ptr) SK_OVERRIDE; 88 89 void setBitmapStorage(SkBitmapHeap* heap) { 90 this->setBitmapHeap(heap); 91 } 92 93 const SkFlatData* flatToReplace() const; 94 95 // Mark an SkFlatData as one that should not be returned by flatToReplace. 96 // Takes the result of SkFlatData::index() as its parameter. 97 void markFlatForKeeping(int index) { 98 *fFlatsThatMustBeKept.append() = index; 99 } 100 101 void markAllFlatsSafeToDelete() { 102 fFlatsThatMustBeKept.reset(); 103 } 104 105 private: 106 // Keep track of the indices (i.e. the result of SkFlatData::index()) of 107 // flats that must be kept, since they are on the current paint. 108 SkTDArray<int> fFlatsThatMustBeKept; 109 SkTDArray<void*> fPointers; 110 const int fNumFlatsToKeep; 111 }; 112 113 void FlattenableHeap::unalloc(void* ptr) { 114 int indexToRemove = fPointers.rfind(ptr); 115 if (indexToRemove >= 0) { 116 sk_free(ptr); 117 fPointers.remove(indexToRemove); 118 } 119 } 120 121 void* FlattenableHeap::allocThrow(size_t bytes) { 122 void* ptr = sk_malloc_throw(bytes); 123 *fPointers.append() = ptr; 124 return ptr; 125 } 126 127 const SkFlatData* FlattenableHeap::flatToReplace() const { 128 // First, determine whether we should replace one. 129 if (fPointers.count() > fNumFlatsToKeep) { 130 // Look through the flattenable heap. 131 // TODO: Return the LRU flat. 132 for (int i = 0; i < fPointers.count(); i++) { 133 SkFlatData* potential = (SkFlatData*)fPointers[i]; 134 // Make sure that it is not one that must be kept. 135 bool mustKeep = false; 136 for (int j = 0; j < fFlatsThatMustBeKept.count(); j++) { 137 if (potential->index() == fFlatsThatMustBeKept[j]) { 138 mustKeep = true; 139 break; 140 } 141 } 142 if (!mustKeep) { 143 return potential; 144 } 145 } 146 } 147 return NULL; 148 } 149 150 /////////////////////////////////////////////////////////////////////////////// 151 152 class FlatDictionary : public SkFlatDictionary<SkFlattenable> { 153 public: 154 FlatDictionary(FlattenableHeap* heap) 155 : SkFlatDictionary<SkFlattenable>(heap) { 156 fFlattenProc = &flattenFlattenableProc; 157 // No need to define fUnflattenProc since the writer will never 158 // unflatten the data. 159 } 160 static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer, 161 const void* obj) { 162 buffer.writeFlattenable((SkFlattenable*)obj); 163 } 164 165 }; 166 167 /////////////////////////////////////////////////////////////////////////////// 168 169 class SkGPipeCanvas : public SkCanvas { 170 public: 171 SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags, 172 uint32_t width, uint32_t height); 173 virtual ~SkGPipeCanvas(); 174 175 void finish() { 176 if (!fDone) { 177 if (this->needOpBytes()) { 178 this->writeOp(kDone_DrawOp); 179 this->doNotify(); 180 if (shouldFlattenBitmaps(fFlags)) { 181 // In this case, a BitmapShuttle is reffed by the SkBitmapHeap 182 // and refs this canvas. Unref the SkBitmapHeap to end the 183 // circular reference. When shouldFlattenBitmaps is false, 184 // there is no circular reference, so the SkBitmapHeap can be 185 // safely unreffed in the destructor. 186 fBitmapHeap->unref(); 187 // This eliminates a similar circular reference (Canvas owns 188 // the FlattenableHeap which holds a ref to the SkBitmapHeap). 189 fFlattenableHeap.setBitmapStorage(NULL); 190 fBitmapHeap = NULL; 191 } 192 } 193 fDone = true; 194 } 195 } 196 197 void flushRecording(bool detachCurrentBlock); 198 size_t freeMemoryIfPossible(size_t bytesToFree); 199 200 size_t storageAllocatedForRecording() { 201 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated(); 202 } 203 204 // overrides from SkCanvas 205 virtual int save(SaveFlags) SK_OVERRIDE; 206 virtual int saveLayer(const SkRect* bounds, const SkPaint*, 207 SaveFlags) SK_OVERRIDE; 208 virtual void restore() SK_OVERRIDE; 209 virtual bool isDrawingToLayer() const SK_OVERRIDE; 210 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE; 211 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE; 212 virtual bool rotate(SkScalar degrees) SK_OVERRIDE; 213 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE; 214 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE; 215 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE; 216 virtual bool clipRect(const SkRect&, SkRegion::Op op, bool doAntiAlias = false) SK_OVERRIDE; 217 virtual bool clipRRect(const SkRRect&, SkRegion::Op op, bool doAntiAlias = false) SK_OVERRIDE; 218 virtual bool clipPath(const SkPath& path, SkRegion::Op op, 219 bool doAntiAlias = false) SK_OVERRIDE; 220 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE; 221 virtual void clear(SkColor) SK_OVERRIDE; 222 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; 223 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[], 224 const SkPaint&) SK_OVERRIDE; 225 virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; 226 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE; 227 virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE; 228 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE; 229 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 230 const SkPaint*) SK_OVERRIDE; 231 virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, 232 const SkRect& dst, const SkPaint*) SK_OVERRIDE; 233 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 234 const SkPaint*) SK_OVERRIDE; 235 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 236 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE; 237 virtual void drawSprite(const SkBitmap&, int left, int top, 238 const SkPaint*) SK_OVERRIDE; 239 virtual void drawText(const void* text, size_t byteLength, SkScalar x, 240 SkScalar y, const SkPaint&) SK_OVERRIDE; 241 virtual void drawPosText(const void* text, size_t byteLength, 242 const SkPoint pos[], const SkPaint&) SK_OVERRIDE; 243 virtual void drawPosTextH(const void* text, size_t byteLength, 244 const SkScalar xpos[], SkScalar constY, 245 const SkPaint&) SK_OVERRIDE; 246 virtual void drawTextOnPath(const void* text, size_t byteLength, 247 const SkPath& path, const SkMatrix* matrix, 248 const SkPaint&) SK_OVERRIDE; 249 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE; 250 virtual void drawVertices(VertexMode, int vertexCount, 251 const SkPoint vertices[], const SkPoint texs[], 252 const SkColor colors[], SkXfermode*, 253 const uint16_t indices[], int indexCount, 254 const SkPaint&) SK_OVERRIDE; 255 virtual void drawData(const void*, size_t) SK_OVERRIDE; 256 257 /** 258 * Flatten an SkBitmap to send to the reader, where it will be referenced 259 * according to slot. 260 */ 261 bool shuttleBitmap(const SkBitmap&, int32_t slot); 262 private: 263 enum { 264 kNoSaveLayer = -1, 265 }; 266 SkNamedFactorySet* fFactorySet; 267 int fFirstSaveLayerStackLevel; 268 SkBitmapHeap* fBitmapHeap; 269 SkGPipeController* fController; 270 SkWriter32& fWriter; 271 size_t fBlockSize; // amount allocated for writer 272 size_t fBytesNotified; 273 bool fDone; 274 const uint32_t fFlags; 275 276 SkRefCntSet fTypefaceSet; 277 278 uint32_t getTypefaceID(SkTypeface*); 279 280 inline void writeOp(DrawOps op, unsigned flags, unsigned data) { 281 fWriter.write32(DrawOp_packOpFlagData(op, flags, data)); 282 } 283 284 inline void writeOp(DrawOps op) { 285 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0)); 286 } 287 288 bool needOpBytes(size_t size = 0); 289 290 inline void doNotify() { 291 if (!fDone) { 292 size_t bytes = fWriter.size() - fBytesNotified; 293 if (bytes > 0) { 294 fController->notifyWritten(bytes); 295 fBytesNotified += bytes; 296 } 297 } 298 } 299 300 // Should be called after any calls to an SkFlatDictionary::findAndReplace 301 // if a new SkFlatData was added when in cross process mode 302 void flattenFactoryNames(); 303 304 FlattenableHeap fFlattenableHeap; 305 FlatDictionary fFlatDictionary; 306 int fCurrFlatIndex[kCount_PaintFlats]; 307 int flattenToIndex(SkFlattenable* obj, PaintFlats); 308 309 // Common code used by drawBitmap*. Behaves differently depending on the 310 // type of SkBitmapHeap being used, which is determined by the flags used. 311 bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, 312 size_t opBytesNeeded, const SkPaint* paint); 313 314 SkPaint fPaint; 315 void writePaint(const SkPaint&); 316 317 class AutoPipeNotify { 318 public: 319 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {} 320 ~AutoPipeNotify() { fCanvas->doNotify(); } 321 private: 322 SkGPipeCanvas* fCanvas; 323 }; 324 friend class AutoPipeNotify; 325 326 typedef SkCanvas INHERITED; 327 }; 328 329 void SkGPipeCanvas::flattenFactoryNames() { 330 const char* name; 331 while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) { 332 size_t len = strlen(name); 333 if (this->needOpBytes(len)) { 334 this->writeOp(kDef_Factory_DrawOp); 335 fWriter.writeString(name, len); 336 } 337 } 338 } 339 340 bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) { 341 SkASSERT(shouldFlattenBitmaps(fFlags)); 342 SkOrderedWriteBuffer buffer(1024); 343 buffer.setNamedFactoryRecorder(fFactorySet); 344 bm.flatten(buffer); 345 this->flattenFactoryNames(); 346 uint32_t size = buffer.size(); 347 if (this->needOpBytes(size)) { 348 this->writeOp(kDef_Bitmap_DrawOp, 0, slot); 349 void* dst = static_cast<void*>(fWriter.reserve(size)); 350 buffer.writeToMemory(dst); 351 return true; 352 } 353 return false; 354 } 355 356 // return 0 for NULL (or unflattenable obj), or index-base-1 357 // return ~(index-base-1) if an old flattenable was replaced 358 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) { 359 SkASSERT(!fDone && fBitmapHeap != NULL); 360 if (NULL == obj) { 361 return 0; 362 } 363 364 fBitmapHeap->deferAddingOwners(); 365 bool added, replaced; 366 const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHeap.flatToReplace(), 367 &added, &replaced); 368 fBitmapHeap->endAddingOwnersDeferral(added); 369 int index = flat->index(); 370 if (added) { 371 if (isCrossProcess(fFlags)) { 372 this->flattenFactoryNames(); 373 } 374 size_t flatSize = flat->flatSize(); 375 if (this->needOpBytes(flatSize)) { 376 this->writeOp(kDef_Flattenable_DrawOp, paintflat, index); 377 fWriter.write(flat->data(), flatSize); 378 } 379 } 380 if (replaced) { 381 index = ~index; 382 } 383 return index; 384 } 385 386 /////////////////////////////////////////////////////////////////////////////// 387 388 /** 389 * If SkBitmaps are to be flattened to send to the reader, this class is 390 * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so. 391 */ 392 class BitmapShuttle : public SkBitmapHeap::ExternalStorage { 393 public: 394 BitmapShuttle(SkGPipeCanvas*); 395 396 ~BitmapShuttle(); 397 398 virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE; 399 400 private: 401 SkGPipeCanvas* fCanvas; 402 }; 403 404 /////////////////////////////////////////////////////////////////////////////// 405 406 #define MIN_BLOCK_SIZE (16 * 1024) 407 #define BITMAPS_TO_KEEP 5 408 #define FLATTENABLES_TO_KEEP 10 409 410 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, 411 SkWriter32* writer, uint32_t flags, 412 uint32_t width, uint32_t height) 413 : fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) 414 , fWriter(*writer) 415 , fFlags(flags) 416 , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags)) 417 , fFlatDictionary(&fFlattenableHeap) { 418 fController = controller; 419 fDone = false; 420 fBlockSize = 0; // need first block from controller 421 fBytesNotified = 0; 422 fFirstSaveLayerStackLevel = kNoSaveLayer; 423 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); 424 425 // we need a device to limit our clip 426 // We don't allocate pixels for the bitmap 427 SkBitmap bitmap; 428 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); 429 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap)); 430 this->setDevice(device)->unref(); 431 432 // Tell the reader the appropriate flags to use. 433 if (this->needOpBytes()) { 434 this->writeOp(kReportFlags_DrawOp, fFlags, 0); 435 } 436 437 if (shouldFlattenBitmaps(flags)) { 438 BitmapShuttle* shuttle = SkNEW_ARGS(BitmapShuttle, (this)); 439 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (shuttle, BITMAPS_TO_KEEP)); 440 shuttle->unref(); 441 } else { 442 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, 443 (BITMAPS_TO_KEEP, controller->numberOfReaders())); 444 if (this->needOpBytes(sizeof(void*))) { 445 this->writeOp(kShareBitmapHeap_DrawOp); 446 fWriter.writePtr(static_cast<void*>(fBitmapHeap)); 447 } 448 } 449 fFlattenableHeap.setBitmapStorage(fBitmapHeap); 450 this->doNotify(); 451 } 452 453 SkGPipeCanvas::~SkGPipeCanvas() { 454 this->finish(); 455 SkSafeUnref(fFactorySet); 456 SkSafeUnref(fBitmapHeap); 457 } 458 459 bool SkGPipeCanvas::needOpBytes(size_t needed) { 460 if (fDone) { 461 return false; 462 } 463 464 needed += 4; // size of DrawOp atom 465 if (fWriter.size() + needed > fBlockSize) { 466 // Before we wipe out any data that has already been written, read it 467 // out. 468 this->doNotify(); 469 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed); 470 void* block = fController->requestBlock(blockSize, &fBlockSize); 471 if (NULL == block) { 472 fDone = true; 473 return false; 474 } 475 SkASSERT(SkIsAlign4(fBlockSize)); 476 fWriter.reset(block, fBlockSize); 477 fBytesNotified = 0; 478 } 479 return true; 480 } 481 482 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { 483 uint32_t id = 0; // 0 means default/null typeface 484 if (face) { 485 id = fTypefaceSet.find(face); 486 if (0 == id) { 487 id = fTypefaceSet.add(face); 488 size_t size = writeTypeface(NULL, face); 489 if (this->needOpBytes(size)) { 490 this->writeOp(kDef_Typeface_DrawOp); 491 writeTypeface(&fWriter, face); 492 } 493 } 494 } 495 return id; 496 } 497 498 /////////////////////////////////////////////////////////////////////////////// 499 500 #define NOTIFY_SETUP(canvas) \ 501 AutoPipeNotify apn(canvas) 502 503 int SkGPipeCanvas::save(SaveFlags flags) { 504 NOTIFY_SETUP(this); 505 if (this->needOpBytes()) { 506 this->writeOp(kSave_DrawOp, 0, flags); 507 } 508 return this->INHERITED::save(flags); 509 } 510 511 int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 512 SaveFlags saveFlags) { 513 NOTIFY_SETUP(this); 514 size_t size = 0; 515 unsigned opFlags = 0; 516 517 if (bounds) { 518 opFlags |= kSaveLayer_HasBounds_DrawOpFlag; 519 size += sizeof(SkRect); 520 } 521 if (paint) { 522 opFlags |= kSaveLayer_HasPaint_DrawOpFlag; 523 this->writePaint(*paint); 524 } 525 526 if (this->needOpBytes(size)) { 527 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags); 528 if (bounds) { 529 fWriter.writeRect(*bounds); 530 } 531 } 532 533 if (kNoSaveLayer == fFirstSaveLayerStackLevel){ 534 fFirstSaveLayerStackLevel = this->getSaveCount(); 535 } 536 // we just pass on the save, so we don't create a layer 537 return this->INHERITED::save(saveFlags); 538 } 539 540 void SkGPipeCanvas::restore() { 541 NOTIFY_SETUP(this); 542 if (this->needOpBytes()) { 543 this->writeOp(kRestore_DrawOp); 544 } 545 546 this->INHERITED::restore(); 547 548 if (this->getSaveCount() == fFirstSaveLayerStackLevel){ 549 fFirstSaveLayerStackLevel = kNoSaveLayer; 550 } 551 } 552 553 bool SkGPipeCanvas::isDrawingToLayer() const { 554 return kNoSaveLayer != fFirstSaveLayerStackLevel; 555 } 556 557 bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) { 558 if (dx || dy) { 559 NOTIFY_SETUP(this); 560 if (this->needOpBytes(2 * sizeof(SkScalar))) { 561 this->writeOp(kTranslate_DrawOp); 562 fWriter.writeScalar(dx); 563 fWriter.writeScalar(dy); 564 } 565 } 566 return this->INHERITED::translate(dx, dy); 567 } 568 569 bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) { 570 if (sx || sy) { 571 NOTIFY_SETUP(this); 572 if (this->needOpBytes(2 * sizeof(SkScalar))) { 573 this->writeOp(kScale_DrawOp); 574 fWriter.writeScalar(sx); 575 fWriter.writeScalar(sy); 576 } 577 } 578 return this->INHERITED::scale(sx, sy); 579 } 580 581 bool SkGPipeCanvas::rotate(SkScalar degrees) { 582 if (degrees) { 583 NOTIFY_SETUP(this); 584 if (this->needOpBytes(sizeof(SkScalar))) { 585 this->writeOp(kRotate_DrawOp); 586 fWriter.writeScalar(degrees); 587 } 588 } 589 return this->INHERITED::rotate(degrees); 590 } 591 592 bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) { 593 if (sx || sy) { 594 NOTIFY_SETUP(this); 595 if (this->needOpBytes(2 * sizeof(SkScalar))) { 596 this->writeOp(kSkew_DrawOp); 597 fWriter.writeScalar(sx); 598 fWriter.writeScalar(sy); 599 } 600 } 601 return this->INHERITED::skew(sx, sy); 602 } 603 604 bool SkGPipeCanvas::concat(const SkMatrix& matrix) { 605 if (!matrix.isIdentity()) { 606 NOTIFY_SETUP(this); 607 if (this->needOpBytes(matrix.writeToMemory(NULL))) { 608 this->writeOp(kConcat_DrawOp); 609 fWriter.writeMatrix(matrix); 610 } 611 } 612 return this->INHERITED::concat(matrix); 613 } 614 615 void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) { 616 NOTIFY_SETUP(this); 617 if (this->needOpBytes(matrix.writeToMemory(NULL))) { 618 this->writeOp(kSetMatrix_DrawOp); 619 fWriter.writeMatrix(matrix); 620 } 621 this->INHERITED::setMatrix(matrix); 622 } 623 624 bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp, 625 bool doAntiAlias) { 626 NOTIFY_SETUP(this); 627 if (this->needOpBytes(sizeof(SkRect))) { 628 unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag; 629 this->writeOp(kClipRect_DrawOp, flags, rgnOp); 630 fWriter.writeRect(rect); 631 } 632 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias); 633 } 634 635 bool SkGPipeCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op rgnOp, 636 bool doAntiAlias) { 637 NOTIFY_SETUP(this); 638 if (this->needOpBytes(kSizeOfFlatRRect)) { 639 unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag; 640 this->writeOp(kClipRRect_DrawOp, flags, rgnOp); 641 fWriter.writeRRect(rrect); 642 } 643 return this->INHERITED::clipRRect(rrect, rgnOp, doAntiAlias); 644 } 645 646 bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp, 647 bool doAntiAlias) { 648 NOTIFY_SETUP(this); 649 if (this->needOpBytes(path.writeToMemory(NULL))) { 650 unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag; 651 this->writeOp(kClipPath_DrawOp, flags, rgnOp); 652 fWriter.writePath(path); 653 } 654 // we just pass on the bounds of the path 655 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias); 656 } 657 658 bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) { 659 NOTIFY_SETUP(this); 660 if (this->needOpBytes(region.writeToMemory(NULL))) { 661 this->writeOp(kClipRegion_DrawOp, 0, rgnOp); 662 fWriter.writeRegion(region); 663 } 664 return this->INHERITED::clipRegion(region, rgnOp); 665 } 666 667 /////////////////////////////////////////////////////////////////////////////// 668 669 void SkGPipeCanvas::clear(SkColor color) { 670 NOTIFY_SETUP(this); 671 unsigned flags = 0; 672 if (color) { 673 flags |= kClear_HasColor_DrawOpFlag; 674 } 675 if (this->needOpBytes(sizeof(SkColor))) { 676 this->writeOp(kDrawClear_DrawOp, flags, 0); 677 if (color) { 678 fWriter.write32(color); 679 } 680 } 681 } 682 683 void SkGPipeCanvas::drawPaint(const SkPaint& paint) { 684 NOTIFY_SETUP(this); 685 this->writePaint(paint); 686 if (this->needOpBytes()) { 687 this->writeOp(kDrawPaint_DrawOp); 688 } 689 } 690 691 void SkGPipeCanvas::drawPoints(PointMode mode, size_t count, 692 const SkPoint pts[], const SkPaint& paint) { 693 if (count) { 694 NOTIFY_SETUP(this); 695 this->writePaint(paint); 696 if (this->needOpBytes(4 + count * sizeof(SkPoint))) { 697 this->writeOp(kDrawPoints_DrawOp, mode, 0); 698 fWriter.write32(count); 699 fWriter.write(pts, count * sizeof(SkPoint)); 700 } 701 } 702 } 703 704 void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) { 705 NOTIFY_SETUP(this); 706 this->writePaint(paint); 707 if (this->needOpBytes(sizeof(SkRect))) { 708 this->writeOp(kDrawOval_DrawOp); 709 fWriter.writeRect(rect); 710 } 711 } 712 713 void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 714 NOTIFY_SETUP(this); 715 this->writePaint(paint); 716 if (this->needOpBytes(sizeof(SkRect))) { 717 this->writeOp(kDrawRect_DrawOp); 718 fWriter.writeRect(rect); 719 } 720 } 721 722 void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 723 NOTIFY_SETUP(this); 724 this->writePaint(paint); 725 if (this->needOpBytes(kSizeOfFlatRRect)) { 726 this->writeOp(kDrawRRect_DrawOp); 727 fWriter.writeRRect(rrect); 728 } 729 } 730 731 void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 732 NOTIFY_SETUP(this); 733 this->writePaint(paint); 734 if (this->needOpBytes(path.writeToMemory(NULL))) { 735 this->writeOp(kDrawPath_DrawOp); 736 fWriter.writePath(path); 737 } 738 } 739 740 bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op, 741 unsigned flags, 742 size_t opBytesNeeded, 743 const SkPaint* paint) { 744 if (paint != NULL) { 745 flags |= kDrawBitmap_HasPaint_DrawOpFlag; 746 this->writePaint(*paint); 747 } 748 if (this->needOpBytes(opBytesNeeded)) { 749 SkASSERT(fBitmapHeap != NULL); 750 int32_t bitmapIndex = fBitmapHeap->insert(bm); 751 if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) { 752 return false; 753 } 754 this->writeOp(op, flags, bitmapIndex); 755 return true; 756 } 757 return false; 758 } 759 760 void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top, 761 const SkPaint* paint) { 762 NOTIFY_SETUP(this); 763 size_t opBytesNeeded = sizeof(SkScalar) * 2; 764 765 if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) { 766 fWriter.writeScalar(left); 767 fWriter.writeScalar(top); 768 } 769 } 770 771 void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src, 772 const SkRect& dst, const SkPaint* paint) { 773 NOTIFY_SETUP(this); 774 size_t opBytesNeeded = sizeof(SkRect); 775 bool hasSrc = src != NULL; 776 unsigned flags; 777 if (hasSrc) { 778 flags = kDrawBitmap_HasSrcRect_DrawOpFlag; 779 opBytesNeeded += sizeof(int32_t) * 4; 780 } else { 781 flags = 0; 782 } 783 784 if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) { 785 if (hasSrc) { 786 fWriter.writeRect(*src); 787 } 788 fWriter.writeRect(dst); 789 } 790 } 791 792 void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix, 793 const SkPaint* paint) { 794 NOTIFY_SETUP(this); 795 size_t opBytesNeeded = matrix.writeToMemory(NULL); 796 797 if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) { 798 fWriter.writeMatrix(matrix); 799 } 800 } 801 802 void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center, 803 const SkRect& dst, const SkPaint* paint) { 804 NOTIFY_SETUP(this); 805 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect); 806 807 if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) { 808 fWriter.write32(center.fLeft); 809 fWriter.write32(center.fTop); 810 fWriter.write32(center.fRight); 811 fWriter.write32(center.fBottom); 812 fWriter.writeRect(dst); 813 } 814 } 815 816 void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top, 817 const SkPaint* paint) { 818 NOTIFY_SETUP(this); 819 size_t opBytesNeeded = sizeof(int32_t) * 2; 820 821 if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) { 822 fWriter.write32(left); 823 fWriter.write32(top); 824 } 825 } 826 827 void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x, 828 SkScalar y, const SkPaint& paint) { 829 if (byteLength) { 830 NOTIFY_SETUP(this); 831 this->writePaint(paint); 832 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) { 833 this->writeOp(kDrawText_DrawOp); 834 fWriter.write32(byteLength); 835 fWriter.writePad(text, byteLength); 836 fWriter.writeScalar(x); 837 fWriter.writeScalar(y); 838 } 839 } 840 } 841 842 void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength, 843 const SkPoint pos[], const SkPaint& paint) { 844 if (byteLength) { 845 NOTIFY_SETUP(this); 846 this->writePaint(paint); 847 int count = paint.textToGlyphs(text, byteLength, NULL); 848 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) { 849 this->writeOp(kDrawPosText_DrawOp); 850 fWriter.write32(byteLength); 851 fWriter.writePad(text, byteLength); 852 fWriter.write32(count); 853 fWriter.write(pos, count * sizeof(SkPoint)); 854 } 855 } 856 } 857 858 void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength, 859 const SkScalar xpos[], SkScalar constY, 860 const SkPaint& paint) { 861 if (byteLength) { 862 NOTIFY_SETUP(this); 863 this->writePaint(paint); 864 int count = paint.textToGlyphs(text, byteLength, NULL); 865 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) { 866 this->writeOp(kDrawPosTextH_DrawOp); 867 fWriter.write32(byteLength); 868 fWriter.writePad(text, byteLength); 869 fWriter.write32(count); 870 fWriter.write(xpos, count * sizeof(SkScalar)); 871 fWriter.writeScalar(constY); 872 } 873 } 874 } 875 876 void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength, 877 const SkPath& path, const SkMatrix* matrix, 878 const SkPaint& paint) { 879 if (byteLength) { 880 NOTIFY_SETUP(this); 881 unsigned flags = 0; 882 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL); 883 if (matrix) { 884 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag; 885 size += matrix->writeToMemory(NULL); 886 } 887 this->writePaint(paint); 888 if (this->needOpBytes(size)) { 889 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0); 890 891 fWriter.write32(byteLength); 892 fWriter.writePad(text, byteLength); 893 894 fWriter.writePath(path); 895 if (matrix) { 896 fWriter.writeMatrix(*matrix); 897 } 898 } 899 } 900 } 901 902 void SkGPipeCanvas::drawPicture(SkPicture& picture) { 903 // we want to playback the picture into individual draw calls 904 this->INHERITED::drawPicture(picture); 905 } 906 907 void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount, 908 const SkPoint vertices[], const SkPoint texs[], 909 const SkColor colors[], SkXfermode*, 910 const uint16_t indices[], int indexCount, 911 const SkPaint& paint) { 912 if (0 == vertexCount) { 913 return; 914 } 915 916 NOTIFY_SETUP(this); 917 size_t size = 4 + vertexCount * sizeof(SkPoint); 918 this->writePaint(paint); 919 unsigned flags = 0; 920 if (texs) { 921 flags |= kDrawVertices_HasTexs_DrawOpFlag; 922 size += vertexCount * sizeof(SkPoint); 923 } 924 if (colors) { 925 flags |= kDrawVertices_HasColors_DrawOpFlag; 926 size += vertexCount * sizeof(SkColor); 927 } 928 if (indices && indexCount > 0) { 929 flags |= kDrawVertices_HasIndices_DrawOpFlag; 930 size += 4 + SkAlign4(indexCount * sizeof(uint16_t)); 931 } 932 933 if (this->needOpBytes(size)) { 934 this->writeOp(kDrawVertices_DrawOp, flags, 0); 935 fWriter.write32(mode); 936 fWriter.write32(vertexCount); 937 fWriter.write(vertices, vertexCount * sizeof(SkPoint)); 938 if (texs) { 939 fWriter.write(texs, vertexCount * sizeof(SkPoint)); 940 } 941 if (colors) { 942 fWriter.write(colors, vertexCount * sizeof(SkColor)); 943 } 944 945 // TODO: flatten xfermode 946 947 if (indices && indexCount > 0) { 948 fWriter.write32(indexCount); 949 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); 950 } 951 } 952 } 953 954 void SkGPipeCanvas::drawData(const void* ptr, size_t size) { 955 if (size && ptr) { 956 NOTIFY_SETUP(this); 957 unsigned data = 0; 958 if (size < (1 << DRAWOPS_DATA_BITS)) { 959 data = (unsigned)size; 960 } 961 if (this->needOpBytes(4 + SkAlign4(size))) { 962 this->writeOp(kDrawData_DrawOp, 0, data); 963 if (0 == data) { 964 fWriter.write32(size); 965 } 966 fWriter.writePad(ptr, size); 967 } 968 } 969 } 970 971 void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) { 972 doNotify(); 973 if (detachCurrentBlock) { 974 // force a new block to be requested for the next recorded command 975 fBlockSize = 0; 976 } 977 } 978 979 size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) { 980 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree); 981 } 982 983 /////////////////////////////////////////////////////////////////////////////// 984 985 template <typename T> uint32_t castToU32(T value) { 986 union { 987 T fSrc; 988 uint32_t fDst; 989 } data; 990 data.fSrc = value; 991 return data.fDst; 992 } 993 994 void SkGPipeCanvas::writePaint(const SkPaint& paint) { 995 if (fDone) { 996 return; 997 } 998 SkPaint& base = fPaint; 999 uint32_t storage[32]; 1000 uint32_t* ptr = storage; 1001 1002 if (base.getFlags() != paint.getFlags()) { 1003 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags()); 1004 base.setFlags(paint.getFlags()); 1005 } 1006 if (base.getColor() != paint.getColor()) { 1007 *ptr++ = PaintOp_packOp(kColor_PaintOp); 1008 *ptr++ = paint.getColor(); 1009 base.setColor(paint.getColor()); 1010 } 1011 if (base.getStyle() != paint.getStyle()) { 1012 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle()); 1013 base.setStyle(paint.getStyle()); 1014 } 1015 if (base.getStrokeJoin() != paint.getStrokeJoin()) { 1016 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin()); 1017 base.setStrokeJoin(paint.getStrokeJoin()); 1018 } 1019 if (base.getStrokeCap() != paint.getStrokeCap()) { 1020 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap()); 1021 base.setStrokeCap(paint.getStrokeCap()); 1022 } 1023 if (base.getStrokeWidth() != paint.getStrokeWidth()) { 1024 *ptr++ = PaintOp_packOp(kWidth_PaintOp); 1025 *ptr++ = castToU32(paint.getStrokeWidth()); 1026 base.setStrokeWidth(paint.getStrokeWidth()); 1027 } 1028 if (base.getStrokeMiter() != paint.getStrokeMiter()) { 1029 *ptr++ = PaintOp_packOp(kMiter_PaintOp); 1030 *ptr++ = castToU32(paint.getStrokeMiter()); 1031 base.setStrokeMiter(paint.getStrokeMiter()); 1032 } 1033 if (base.getTextEncoding() != paint.getTextEncoding()) { 1034 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding()); 1035 base.setTextEncoding(paint.getTextEncoding()); 1036 } 1037 if (base.getHinting() != paint.getHinting()) { 1038 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting()); 1039 base.setHinting(paint.getHinting()); 1040 } 1041 if (base.getTextAlign() != paint.getTextAlign()) { 1042 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign()); 1043 base.setTextAlign(paint.getTextAlign()); 1044 } 1045 if (base.getTextSize() != paint.getTextSize()) { 1046 *ptr++ = PaintOp_packOp(kTextSize_PaintOp); 1047 *ptr++ = castToU32(paint.getTextSize()); 1048 base.setTextSize(paint.getTextSize()); 1049 } 1050 if (base.getTextScaleX() != paint.getTextScaleX()) { 1051 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp); 1052 *ptr++ = castToU32(paint.getTextScaleX()); 1053 base.setTextScaleX(paint.getTextScaleX()); 1054 } 1055 if (base.getTextSkewX() != paint.getTextSkewX()) { 1056 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp); 1057 *ptr++ = castToU32(paint.getTextSkewX()); 1058 base.setTextSkewX(paint.getTextSkewX()); 1059 } 1060 1061 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { 1062 if (isCrossProcess(fFlags)) { 1063 uint32_t id = this->getTypefaceID(paint.getTypeface()); 1064 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); 1065 } else if (this->needOpBytes(sizeof(void*))) { 1066 // Add to the set for ref counting. 1067 fTypefaceSet.add(paint.getTypeface()); 1068 // It is safe to write the typeface to the stream before the rest 1069 // of the paint unless we ever send a kReset_PaintOp, which we 1070 // currently never do. 1071 this->writeOp(kSetTypeface_DrawOp); 1072 fWriter.writePtr(paint.getTypeface()); 1073 } 1074 base.setTypeface(paint.getTypeface()); 1075 } 1076 1077 // This is a new paint, so all old flats can be safely purged, if necessary. 1078 fFlattenableHeap.markAllFlatsSafeToDelete(); 1079 for (int i = 0; i < kCount_PaintFlats; i++) { 1080 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i); 1081 bool replaced = index < 0; 1082 if (replaced) { 1083 index = ~index; 1084 } 1085 // Store the index of any flat that needs to be kept. 0 means no flat. 1086 if (index > 0) { 1087 fFlattenableHeap.markFlatForKeeping(index); 1088 } 1089 SkASSERT(index >= 0 && index <= fFlatDictionary.count()); 1090 if (index != fCurrFlatIndex[i] || replaced) { 1091 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index); 1092 fCurrFlatIndex[i] = index; 1093 } 1094 } 1095 1096 size_t size = (char*)ptr - (char*)storage; 1097 if (size && this->needOpBytes(size)) { 1098 this->writeOp(kPaintOp_DrawOp, 0, size); 1099 fWriter.write(storage, size); 1100 for (size_t i = 0; i < size/4; i++) { 1101 // SkDebugf("[%d] %08X\n", i, storage[i]); 1102 } 1103 } 1104 } 1105 1106 /////////////////////////////////////////////////////////////////////////////// 1107 1108 #include "SkGPipe.h" 1109 1110 SkGPipeController::~SkGPipeController() { 1111 SkSafeUnref(fCanvas); 1112 } 1113 1114 void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) { 1115 SkRefCnt_SafeAssign(fCanvas, canvas); 1116 } 1117 1118 /////////////////////////////////////////////////////////////////////////////// 1119 1120 SkGPipeWriter::SkGPipeWriter() 1121 : fWriter(0) { 1122 fCanvas = NULL; 1123 } 1124 1125 SkGPipeWriter::~SkGPipeWriter() { 1126 this->endRecording(); 1127 } 1128 1129 SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags, 1130 uint32_t width, uint32_t height) { 1131 if (NULL == fCanvas) { 1132 fWriter.reset(NULL, 0); 1133 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height)); 1134 } 1135 controller->setCanvas(fCanvas); 1136 return fCanvas; 1137 } 1138 1139 void SkGPipeWriter::endRecording() { 1140 if (fCanvas) { 1141 fCanvas->finish(); 1142 fCanvas->unref(); 1143 fCanvas = NULL; 1144 } 1145 } 1146 1147 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) { 1148 if (fCanvas) { 1149 fCanvas->flushRecording(detachCurrentBlock); 1150 } 1151 } 1152 1153 size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) { 1154 if (fCanvas) { 1155 return fCanvas->freeMemoryIfPossible(bytesToFree); 1156 } 1157 return 0; 1158 } 1159 1160 size_t SkGPipeWriter::storageAllocatedForRecording() const { 1161 return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording(); 1162 } 1163 1164 /////////////////////////////////////////////////////////////////////////////// 1165 1166 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { 1167 SkASSERT(canvas != NULL); 1168 fCanvas = canvas; 1169 fCanvas->ref(); 1170 } 1171 1172 BitmapShuttle::~BitmapShuttle() { 1173 fCanvas->unref(); 1174 } 1175 1176 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { 1177 return fCanvas->shuttleBitmap(bitmap, slot); 1178 } 1179