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