Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: src/pipe/SkGPipeWrite.cpp

Issue 1568883003: remove SkGPipe (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pipe/SkGPipeRead.cpp ('k') | src/pipe/utils/SamplePipeControllers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #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 "SkGPipe.h"
16 #include "SkGPipePriv.h"
17 #include "SkImageFilter.h"
18 #include "SkMaskFilter.h"
19 #include "SkRSXform.h"
20 #include "SkWriteBuffer.h"
21 #include "SkPaint.h"
22 #include "SkPatchUtils.h"
23 #include "SkPathEffect.h"
24 #include "SkPictureFlat.h"
25 #include "SkPtrRecorder.h"
26 #include "SkRasterizer.h"
27 #include "SkRRect.h"
28 #include "SkShader.h"
29 #include "SkStream.h"
30 #include "SkTextBlob.h"
31 #include "SkTSearch.h"
32 #include "SkTypeface.h"
33 #include "SkWriter32.h"
34
35 enum {
36 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector)
37 };
38
39 static bool is_cross_process(uint32_t flags) {
40 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
41 }
42
43 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
44 SkASSERT(paintFlat < kCount_PaintFlats);
45 switch (paintFlat) {
46 case kColorFilter_PaintFlat: return paint.getColorFilter();
47 case kDrawLooper_PaintFlat: return paint.getLooper();
48 case kMaskFilter_PaintFlat: return paint.getMaskFilter();
49 case kPathEffect_PaintFlat: return paint.getPathEffect();
50 case kRasterizer_PaintFlat: return paint.getRasterizer();
51 case kShader_PaintFlat: return paint.getShader();
52 case kImageFilter_PaintFlat: return paint.getImageFilter();
53 case kXfermode_PaintFlat: return paint.getXfermode();
54 }
55 SkDEBUGFAIL("never gets here");
56 return nullptr;
57 }
58
59 static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
60 SkASSERT(typeface);
61 SkDynamicMemoryWStream stream;
62 typeface->serialize(&stream);
63 size_t size = stream.getOffset();
64 if (writer) {
65 writer->write32(SkToU32(size));
66 SkAutoDataUnref data(stream.copyToData());
67 writer->writePad(data->data(), size);
68 }
69 return 4 + SkAlign4(size);
70 }
71
72 ///////////////////////////////////////////////////////////////////////////////
73
74 class FlattenableHeap : public SkFlatController {
75 public:
76 FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossPro cess)
77 : INHERITED(isCrossProcess ? SkWriteBuffer::kCrossProcess_Flag : 0)
78 , fNumFlatsToKeep(numFlatsToKeep) {
79 SkASSERT((isCrossProcess && fset != nullptr) || (!isCrossProcess && null ptr == fset));
80 if (isCrossProcess) {
81 this->setNamedFactorySet(fset);
82 }
83 }
84
85 ~FlattenableHeap() {
86 fPointers.freeAll();
87 }
88
89 void* allocThrow(size_t bytes) override;
90
91 void unalloc(void* ptr) override;
92
93 void setBitmapStorage(SkBitmapHeap* heap) {
94 this->setBitmapHeap(heap);
95 }
96
97 const SkFlatData* flatToReplace() const;
98
99 // Mark an SkFlatData as one that should not be returned by flatToReplace.
100 // Takes the result of SkFlatData::index() as its parameter.
101 void markFlatForKeeping(int index) {
102 *fFlatsThatMustBeKept.append() = index;
103 }
104
105 void markAllFlatsSafeToDelete() {
106 fFlatsThatMustBeKept.reset();
107 }
108
109 private:
110 // Keep track of the indices (i.e. the result of SkFlatData::index()) of
111 // flats that must be kept, since they are on the current paint.
112 SkTDArray<int> fFlatsThatMustBeKept;
113 SkTDArray<void*> fPointers;
114 const int fNumFlatsToKeep;
115
116 typedef SkFlatController INHERITED;
117 };
118
119 void FlattenableHeap::unalloc(void* ptr) {
120 int indexToRemove = fPointers.rfind(ptr);
121 if (indexToRemove >= 0) {
122 sk_free(ptr);
123 fPointers.remove(indexToRemove);
124 }
125 }
126
127 void* FlattenableHeap::allocThrow(size_t bytes) {
128 void* ptr = sk_malloc_throw(bytes);
129 *fPointers.append() = ptr;
130 return ptr;
131 }
132
133 const SkFlatData* FlattenableHeap::flatToReplace() const {
134 // First, determine whether we should replace one.
135 if (fPointers.count() > fNumFlatsToKeep) {
136 // Look through the flattenable heap.
137 // TODO: Return the LRU flat.
138 for (int i = 0; i < fPointers.count(); i++) {
139 SkFlatData* potential = (SkFlatData*)fPointers[i];
140 // Make sure that it is not one that must be kept.
141 bool mustKeep = false;
142 for (int j = 0; j < fFlatsThatMustBeKept.count(); j++) {
143 if (potential->index() == fFlatsThatMustBeKept[j]) {
144 mustKeep = true;
145 break;
146 }
147 }
148 if (!mustKeep) {
149 return potential;
150 }
151 }
152 }
153 return nullptr;
154 }
155
156 ///////////////////////////////////////////////////////////////////////////////
157
158 struct SkFlattenableTraits {
159 static void Flatten(SkWriteBuffer& buffer, const SkFlattenable& flattenable) {
160 buffer.writeFlattenable(&flattenable);
161 }
162 // No need to define unflatten if we never call it.
163 };
164 typedef SkFlatDictionary<SkFlattenable, SkFlattenableTraits> FlatDictionary;
165
166 ///////////////////////////////////////////////////////////////////////////////
167
168 /**
169 * If SkBitmaps are to be flattened to send to the reader, this class is
170 * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so.
171 */
172 class BitmapShuttle : public SkBitmapHeap::ExternalStorage {
173 public:
174 BitmapShuttle(SkGPipeCanvas*);
175
176 ~BitmapShuttle();
177
178 bool insert(const SkBitmap& bitmap, int32_t slot) override;
179
180 /**
181 * Remove the SkGPipeCanvas used for insertion. After this, calls to
182 * insert will crash.
183 */
184 void removeCanvas();
185
186 private:
187 SkGPipeCanvas* fCanvas;
188 };
189
190 ///////////////////////////////////////////////////////////////////////////////
191
192 class SkGPipeCanvas : public SkCanvas {
193 public:
194 SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags,
195 uint32_t width, uint32_t height);
196 virtual ~SkGPipeCanvas();
197
198 /**
199 * Called when nothing else is to be written to the stream. Any repeated
200 * calls are ignored.
201 *
202 * @param notifyReaders Whether to send a message to the reader(s) that
203 * the writer is through sending commands. Should generally be true,
204 * unless there is an error which prevents further messages from
205 * being sent.
206 */
207 void finish(bool notifyReaders) {
208 if (fDone) {
209 return;
210 }
211 if (notifyReaders && this->needOpBytes()) {
212 this->writeOp(kDone_DrawOp);
213 this->doNotify();
214 }
215 if (shouldFlattenBitmaps(fFlags)) {
216 // The following circular references exist:
217 // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalSt orage -> fCanvas
218 // fBitmapHeap -> fExternalStorage -> fCanvas
219 // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas
220
221 // Break them all by destroying the final link to this SkGPipeCanvas .
222 fBitmapShuttle->removeCanvas();
223 }
224 fDone = true;
225 }
226
227 void flushRecording(bool detachCurrentBlock);
228 size_t freeMemoryIfPossible(size_t bytesToFree);
229
230 size_t storageAllocatedForRecording() {
231 size_t bytesAllocated = 0;
232 if (nullptr != fBitmapHeap) {
233 bytesAllocated += fBitmapHeap->bytesAllocated();
234 }
235 if (nullptr != fImageHeap) {
236 bytesAllocated += fImageHeap->bytesInCache();
237 }
238 return bytesAllocated;
239 }
240
241 /**
242 * Flatten an SkBitmap to send to the reader, where it will be referenced
243 * according to slot.
244 */
245 bool shuttleBitmap(const SkBitmap&, int32_t slot);
246
247 void resetImageHeap();
248
249 protected:
250 void willSave() override;
251 SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
252 void willRestore() override;
253
254 void didConcat(const SkMatrix&) override;
255 void didSetMatrix(const SkMatrix&) override;
256
257 void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
258 void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
259 const SkPaint&) override;
260 void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
261 const SkPaint&) override;
262 void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos [],
263 SkScalar constY, const SkPaint&) override;
264 void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& pat h,
265 const SkMatrix* matrix, const SkPaint&) override;
266 void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
267 const SkPaint& paint) override;
268 void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
269 const SkPoint texCoords[4], SkXfermode* xmode,
270 const SkPaint& paint) override;
271 void onDrawPaint(const SkPaint&) override;
272 void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPain t&) override;
273 void onDrawRect(const SkRect&, const SkPaint&) override;
274 void onDrawOval(const SkRect&, const SkPaint&) override;
275 void onDrawRRect(const SkRRect&, const SkPaint&) override;
276 void onDrawPath(const SkPath&, const SkPaint&) override;
277 void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPain t*) override;
278 void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
279 SrcRectConstraint) override;
280 void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint* ) override;
281 void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
282 const SkPaint*, SrcRectConstraint) override;
283 void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& ds t,
284 const SkPaint*) override;
285 void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
286 const SkPaint*) override;
287 void onDrawVertices(VertexMode vmode, int vertexCount,
288 const SkPoint vertices[], const SkPoint texs[],
289 const SkColor colors[], SkXfermode* xmode,
290 const uint16_t indices[], int indexCount,
291 const SkPaint&) override;
292 void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const Sk Color[],
293 int count, SkXfermode::Mode, const SkRect* cull, const SkPa int*) override;
294 void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
295 void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
296 void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
297 void onClipRegion(const SkRegion&, SkRegion::Op) override;
298
299 void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) overri de;
300
301 private:
302 void recordTranslate(const SkMatrix&);
303 void recordScale(const SkMatrix&);
304 void recordConcat(const SkMatrix&);
305
306 SkNamedFactorySet* fFactorySet;
307 SkBitmapHeap* fBitmapHeap;
308 SkImageHeap* fImageHeap;
309 SkGPipeController* fController;
310 SkWriter32& fWriter;
311 size_t fBlockSize; // amount allocated for writer
312 size_t fBytesNotified;
313 bool fDone;
314 const uint32_t fFlags;
315
316 SkRefCntSet fTypefaceSet;
317
318 uint32_t getTypefaceID(SkTypeface*);
319
320 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
321 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
322 }
323
324 inline void writeOp(DrawOps op) {
325 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
326 }
327
328 bool needOpBytes(size_t size = 0);
329
330 inline void doNotify() {
331 if (!fDone) {
332 size_t bytes = fWriter.bytesWritten() - fBytesNotified;
333 if (bytes > 0) {
334 fController->notifyWritten(bytes);
335 fBytesNotified += bytes;
336 }
337 }
338 }
339
340 typedef SkAutoSTMalloc<128, uint8_t> TypefaceBuffer;
341 size_t getInProcessTypefaces(const SkRefCntSet& typefaceSet, TypefaceBuffer* );
342 size_t getCrossProcessTypefaces(const SkRefCntSet& typefaceSet, TypefaceBuff er*);
343
344 // Should be called after any calls to an SkFlatDictionary::findAndReplace
345 // if a new SkFlatData was added when in cross process mode
346 void flattenFactoryNames();
347
348 FlattenableHeap fFlattenableHeap;
349 FlatDictionary fFlatDictionary;
350 SkAutoTUnref<BitmapShuttle> fBitmapShuttle;
351 int fCurrFlatIndex[kCount_PaintFlats];
352
353 int flattenToIndex(SkFlattenable* obj, PaintFlats);
354
355 // Common code used by drawBitmap*. Behaves differently depending on the
356 // type of SkBitmapHeap being used, which is determined by the flags used.
357 bool commonDrawBitmap(const SkBitmap&, DrawOps, unsigned flags, size_t bytes , const SkPaint*);
358 bool commonDrawImage(const SkImage*, DrawOps, unsigned flags, size_t bytes, const SkPaint*);
359
360 SkPaint fPaint;
361 void writePaint(const SkPaint&);
362
363 class AutoPipeNotify {
364 public:
365 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
366 ~AutoPipeNotify() { fCanvas->doNotify(); }
367 private:
368 SkGPipeCanvas* fCanvas;
369 };
370 friend class AutoPipeNotify;
371
372 typedef SkCanvas INHERITED;
373 };
374
375 void SkGPipeCanvas::flattenFactoryNames() {
376 const char* name;
377 while ((name = fFactorySet->getNextAddedFactoryName()) != nullptr) {
378 size_t len = strlen(name);
379 if (this->needOpBytes(SkWriter32::WriteStringSize(name, len))) {
380 this->writeOp(kDef_Factory_DrawOp);
381 fWriter.writeString(name, len);
382 }
383 }
384 }
385
386 bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) {
387 SkASSERT(shouldFlattenBitmaps(fFlags));
388 SkWriteBuffer buffer;
389 buffer.setNamedFactoryRecorder(fFactorySet);
390 buffer.writeBitmap(bm);
391 this->flattenFactoryNames();
392 size_t size = buffer.bytesWritten();
393 if (this->needOpBytes(size)) {
394 this->writeOp(kDef_Bitmap_DrawOp, 0, slot);
395 void* dst = static_cast<void*>(fWriter.reserve(size));
396 buffer.writeToMemory(dst);
397 return true;
398 }
399 return false;
400 }
401
402 // return 0 for nullptr (or unflattenable obj), or index-base-1
403 // return ~(index-base-1) if an old flattenable was replaced
404 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
405 SkASSERT(!fDone && fBitmapHeap != nullptr);
406 if (nullptr == obj) {
407 return 0;
408 }
409
410 fBitmapHeap->deferAddingOwners();
411 bool added, replaced;
412 const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHe ap.flatToReplace(),
413 &added, &replaced);
414 fBitmapHeap->endAddingOwnersDeferral(added);
415 int index = flat->index();
416 if (added) {
417 if (is_cross_process(fFlags)) {
418 this->flattenFactoryNames();
419 }
420 size_t flatSize = flat->flatSize();
421 if (this->needOpBytes(flatSize)) {
422 this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
423 fWriter.write(flat->data(), flatSize);
424 }
425 }
426 if (replaced) {
427 index = ~index;
428 }
429 return index;
430 }
431
432 ///////////////////////////////////////////////////////////////////////////////
433
434 #define MIN_BLOCK_SIZE (16 * 1024)
435 #define BITMAPS_TO_KEEP 5
436 #define FLATTENABLES_TO_KEEP 10
437
438 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
439 SkWriter32* writer,
440 uint32_t flags,
441 uint32_t width,
442 uint32_t height)
443 : SkCanvas(width, height)
444 , fFactorySet(is_cross_process(flags) ? new SkNamedFactorySet : nullptr)
445 , fWriter(*writer)
446 , fFlags(flags)
447 , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, is_cross_process(flags ))
448 , fFlatDictionary(&fFlattenableHeap) {
449 fController = controller;
450 fDone = false;
451 fBlockSize = 0; // need first block from controller
452 fBytesNotified = 0;
453 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
454
455 // Tell the reader the appropriate flags to use.
456 if (this->needOpBytes()) {
457 this->writeOp(kReportFlags_DrawOp, fFlags, 0);
458 }
459
460 if (shouldFlattenBitmaps(flags)) {
461 fBitmapShuttle.reset(new BitmapShuttle(this));
462 fBitmapHeap = new SkBitmapHeap(fBitmapShuttle.get(), BITMAPS_TO_KEEP);
463 } else {
464 fBitmapHeap = new SkBitmapHeap(BITMAPS_TO_KEEP, controller->numberOfRead ers());
465 if (this->needOpBytes(sizeof(void*))) {
466 this->writeOp(kShareBitmapHeap_DrawOp);
467 fWriter.writePtr(static_cast<void*>(fBitmapHeap));
468 }
469 }
470 fFlattenableHeap.setBitmapStorage(fBitmapHeap);
471
472 fImageHeap = new SkImageHeap;
473 if (this->needOpBytes(sizeof(void*))) {
474 this->writeOp(kShareImageHeap_DrawOp);
475 fWriter.writePtr(static_cast<void*>(fImageHeap));
476 }
477
478 this->doNotify();
479 }
480
481 SkGPipeCanvas::~SkGPipeCanvas() {
482 this->finish(true);
483 SkSafeUnref(fFactorySet);
484 SkSafeUnref(fBitmapHeap);
485 SkSafeUnref(fImageHeap);
486 }
487
488 bool SkGPipeCanvas::needOpBytes(size_t needed) {
489 if (fDone) {
490 return false;
491 }
492
493 needed += 4; // size of DrawOp atom
494 needed = SkAlign4(needed);
495 if (fWriter.bytesWritten() + needed > fBlockSize) {
496 // Before we wipe out any data that has already been written, read it ou t.
497 this->doNotify();
498
499 // If we're going to allocate a new block, allocate enough to make it wo rthwhile.
500 needed = SkTMax<size_t>(MIN_BLOCK_SIZE, needed);
501
502 void* block = fController->requestBlock(needed, &fBlockSize);
503 if (nullptr == block) {
504 // Do not notify the readers, which would call this function again.
505 this->finish(false);
506 return false;
507 }
508 SkASSERT(SkIsAlign4(fBlockSize));
509 fWriter.reset(block, fBlockSize);
510 fBytesNotified = 0;
511 }
512 return true;
513 }
514
515 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
516 uint32_t id = 0; // 0 means default/null typeface
517 if (face) {
518 id = fTypefaceSet.find(face);
519 if (0 == id) {
520 id = fTypefaceSet.add(face);
521 size_t size = writeTypeface(nullptr, face);
522 if (this->needOpBytes(size)) {
523 this->writeOp(kDef_Typeface_DrawOp);
524 writeTypeface(&fWriter, face);
525 }
526 }
527 }
528 return id;
529 }
530
531 ///////////////////////////////////////////////////////////////////////////////
532
533 #define NOTIFY_SETUP(canvas) \
534 AutoPipeNotify apn(canvas)
535
536 void SkGPipeCanvas::willSave() {
537 NOTIFY_SETUP(this);
538 if (this->needOpBytes()) {
539 this->writeOp(kSave_DrawOp);
540 }
541
542 this->INHERITED::willSave();
543 }
544
545 SkCanvas::SaveLayerStrategy SkGPipeCanvas::getSaveLayerStrategy(const SaveLayerR ec& rec) {
546 NOTIFY_SETUP(this);
547 size_t size = 0;
548 unsigned opFlags = 0;
549
550 if (rec.fBounds) {
551 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
552 size += sizeof(SkRect);
553 }
554 if (rec.fPaint) {
555 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
556 this->writePaint(*rec.fPaint);
557 }
558
559 if (this->needOpBytes(size)) {
560 this->writeOp(kSaveLayer_DrawOp, opFlags, rec.fSaveLayerFlags);
561 if (rec.fBounds) {
562 fWriter.writeRect(*rec.fBounds);
563 }
564 }
565
566 (void)this->INHERITED::getSaveLayerStrategy(rec);
567 // we don't create a layer
568 return kNoLayer_SaveLayerStrategy;
569 }
570
571 void SkGPipeCanvas::willRestore() {
572 NOTIFY_SETUP(this);
573 if (this->needOpBytes()) {
574 this->writeOp(kRestore_DrawOp);
575 }
576
577 this->INHERITED::willRestore();
578 }
579
580 void SkGPipeCanvas::recordTranslate(const SkMatrix& m) {
581 if (this->needOpBytes(2 * sizeof(SkScalar))) {
582 this->writeOp(kTranslate_DrawOp);
583 fWriter.writeScalar(m.getTranslateX());
584 fWriter.writeScalar(m.getTranslateY());
585 }
586 }
587
588 void SkGPipeCanvas::recordScale(const SkMatrix& m) {
589 if (this->needOpBytes(2 * sizeof(SkScalar))) {
590 this->writeOp(kScale_DrawOp);
591 fWriter.writeScalar(m.getScaleX());
592 fWriter.writeScalar(m.getScaleY());
593 }
594 }
595
596 void SkGPipeCanvas::recordConcat(const SkMatrix& m) {
597 if (this->needOpBytes(m.writeToMemory(nullptr))) {
598 this->writeOp(kConcat_DrawOp);
599 fWriter.writeMatrix(m);
600 }
601 }
602
603 void SkGPipeCanvas::didConcat(const SkMatrix& matrix) {
604 if (!matrix.isIdentity()) {
605 NOTIFY_SETUP(this);
606 switch (matrix.getType()) {
607 case SkMatrix::kTranslate_Mask:
608 this->recordTranslate(matrix);
609 break;
610 case SkMatrix::kScale_Mask:
611 this->recordScale(matrix);
612 break;
613 default:
614 this->recordConcat(matrix);
615 break;
616 }
617 }
618
619 this->INHERITED::didConcat(matrix);
620 }
621
622 void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
623 NOTIFY_SETUP(this);
624 if (this->needOpBytes(matrix.writeToMemory(nullptr))) {
625 this->writeOp(kSetMatrix_DrawOp);
626 fWriter.writeMatrix(matrix);
627 }
628 this->INHERITED::didSetMatrix(matrix);
629 }
630
631 void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp,
632 ClipEdgeStyle edgeStyle) {
633 NOTIFY_SETUP(this);
634 if (this->needOpBytes(sizeof(SkRect))) {
635 unsigned flags = 0;
636 if (kSoft_ClipEdgeStyle == edgeStyle) {
637 flags = kClip_HasAntiAlias_DrawOpFlag;
638 }
639 this->writeOp(kClipRect_DrawOp, flags, rgnOp);
640 fWriter.writeRect(rect);
641 }
642 this->INHERITED::onClipRect(rect, rgnOp, edgeStyle);
643 }
644
645 void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp,
646 ClipEdgeStyle edgeStyle) {
647 NOTIFY_SETUP(this);
648 if (this->needOpBytes(kSizeOfFlatRRect)) {
649 unsigned flags = 0;
650 if (kSoft_ClipEdgeStyle == edgeStyle) {
651 flags = kClip_HasAntiAlias_DrawOpFlag;
652 }
653 this->writeOp(kClipRRect_DrawOp, flags, rgnOp);
654 fWriter.writeRRect(rrect);
655 }
656 this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle);
657 }
658
659 void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp,
660 ClipEdgeStyle edgeStyle) {
661 NOTIFY_SETUP(this);
662 if (this->needOpBytes(path.writeToMemory(nullptr))) {
663 unsigned flags = 0;
664 if (kSoft_ClipEdgeStyle == edgeStyle) {
665 flags = kClip_HasAntiAlias_DrawOpFlag;
666 }
667 this->writeOp(kClipPath_DrawOp, flags, rgnOp);
668 fWriter.writePath(path);
669 }
670 // we just pass on the bounds of the path
671 this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle);
672 }
673
674 void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
675 NOTIFY_SETUP(this);
676 if (this->needOpBytes(region.writeToMemory(nullptr))) {
677 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
678 fWriter.writeRegion(region);
679 }
680 this->INHERITED::onClipRegion(region, rgnOp);
681 }
682
683 ///////////////////////////////////////////////////////////////////////////////
684
685 void SkGPipeCanvas::onDrawPaint(const SkPaint& paint) {
686 NOTIFY_SETUP(this);
687 this->writePaint(paint);
688 if (this->needOpBytes()) {
689 this->writeOp(kDrawPaint_DrawOp);
690 }
691 }
692
693 void SkGPipeCanvas::onDrawPoints(PointMode mode, size_t count,
694 const SkPoint pts[], const SkPaint& paint) {
695 if (count) {
696 NOTIFY_SETUP(this);
697 this->writePaint(paint);
698 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
699 this->writeOp(kDrawPoints_DrawOp, mode, 0);
700 fWriter.write32(SkToU32(count));
701 fWriter.write(pts, count * sizeof(SkPoint));
702 }
703 }
704 }
705
706 void SkGPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
707 NOTIFY_SETUP(this);
708 this->writePaint(paint);
709 if (this->needOpBytes(sizeof(SkRect))) {
710 this->writeOp(kDrawOval_DrawOp);
711 fWriter.writeRect(rect);
712 }
713 }
714
715 void SkGPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
716 NOTIFY_SETUP(this);
717 this->writePaint(paint);
718 if (this->needOpBytes(sizeof(SkRect))) {
719 this->writeOp(kDrawRect_DrawOp);
720 fWriter.writeRect(rect);
721 }
722 }
723
724 void SkGPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
725 NOTIFY_SETUP(this);
726 this->writePaint(paint);
727 if (this->needOpBytes(kSizeOfFlatRRect)) {
728 this->writeOp(kDrawRRect_DrawOp);
729 fWriter.writeRRect(rrect);
730 }
731 }
732
733 void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
734 const SkPaint& paint) {
735 NOTIFY_SETUP(this);
736 this->writePaint(paint);
737 if (this->needOpBytes(kSizeOfFlatRRect * 2)) {
738 this->writeOp(kDrawDRRect_DrawOp);
739 fWriter.writeRRect(outer);
740 fWriter.writeRRect(inner);
741 }
742 }
743
744 void SkGPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
745 NOTIFY_SETUP(this);
746 this->writePaint(paint);
747 if (this->needOpBytes(path.writeToMemory(nullptr))) {
748 this->writeOp(kDrawPath_DrawOp);
749 fWriter.writePath(path);
750 }
751 }
752
753 bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op,
754 unsigned flags,
755 size_t opBytesNeeded,
756 const SkPaint* paint) {
757 if (fDone) {
758 return false;
759 }
760
761 if (paint != nullptr) {
762 flags |= kDrawBitmap_HasPaint_DrawOpFlag;
763 this->writePaint(*paint);
764 }
765 // This needs to run first so its calls to needOpBytes() and its writes
766 // don't interlace with the needOpBytes() and write below.
767 SkASSERT(fBitmapHeap != nullptr);
768 int32_t bitmapIndex = fBitmapHeap->insert(bm);
769 if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) {
770 return false;
771 }
772
773 if (this->needOpBytes(opBytesNeeded)) {
774 this->writeOp(op, flags, bitmapIndex);
775 return true;
776 }
777 return false;
778 }
779
780 void SkGPipeCanvas::onDrawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top ,
781 const SkPaint* paint) {
782 NOTIFY_SETUP(this);
783 size_t opBytesNeeded = sizeof(SkScalar) * 2;
784
785 if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) {
786 fWriter.writeScalar(left);
787 fWriter.writeScalar(top);
788 }
789 }
790
791 void SkGPipeCanvas::onDrawBitmapRect(const SkBitmap& bm, const SkRect* src, cons t SkRect& dst,
792 const SkPaint* paint, SrcRectConstraint con straint) {
793 NOTIFY_SETUP(this);
794 size_t opBytesNeeded = sizeof(SkRect);
795 bool hasSrc = src != nullptr;
796 unsigned flags;
797 if (hasSrc) {
798 flags = kDrawBitmap_HasSrcRect_DrawOpFlag;
799 opBytesNeeded += sizeof(int32_t) * 4;
800 } else {
801 flags = 0;
802 }
803 if (kFast_SrcRectConstraint == constraint) {
804 flags |= kDrawBitmap_Bleed_DrawOpFlag;
805 }
806
807 if (this->commonDrawBitmap(bm, kDrawBitmapRect_DrawOp, flags, opBytesNeeded, paint)) {
808 if (hasSrc) {
809 fWriter.writeRect(*src);
810 }
811 fWriter.writeRect(dst);
812 }
813 }
814
815 void SkGPipeCanvas::onDrawBitmapNine(const SkBitmap& bm, const SkIRect& center,
816 const SkRect& dst, const SkPaint* paint) {
817 NOTIFY_SETUP(this);
818 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect);
819
820 if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, pai nt)) {
821 fWriter.write32(center.fLeft);
822 fWriter.write32(center.fTop);
823 fWriter.write32(center.fRight);
824 fWriter.write32(center.fBottom);
825 fWriter.writeRect(dst);
826 }
827 }
828
829 bool SkGPipeCanvas::commonDrawImage(const SkImage* image, DrawOps op, unsigned f lags,
830 size_t opBytesNeeded, const SkPaint* paint) {
831 if (fDone) {
832 return false;
833 }
834
835 if (paint != nullptr) {
836 flags |= kDrawBitmap_HasPaint_DrawOpFlag;
837 this->writePaint(*paint);
838 }
839 // This needs to run first so its calls to needOpBytes() and its writes
840 // don't interlace with the needOpBytes() and write below.
841 int32_t slot = fImageHeap->insert(image);
842 SkASSERT(slot != 0);
843 if (this->needOpBytes(opBytesNeeded)) {
844 this->writeOp(op, flags, slot);
845 return true;
846 }
847 return false;
848 }
849
850 void SkGPipeCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
851 const SkPaint* paint) {
852 NOTIFY_SETUP(this);
853 if (this->commonDrawImage(image, kDrawImage_DrawOp, 0, sizeof(SkScalar) * 2, paint)) {
854 fWriter.writeScalar(x);
855 fWriter.writeScalar(y);
856 }
857 }
858
859 void SkGPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, con st SkRect& dst,
860 const SkPaint* paint, SrcRectConstraint cons traint) {
861 NOTIFY_SETUP(this);
862 unsigned flags = 0;
863 size_t opBytesNeeded = sizeof(SkRect); // dst
864 if (src) {
865 flags |= kDrawBitmap_HasSrcRect_DrawOpFlag;
866 opBytesNeeded += sizeof(SkRect); // src
867 }
868 if (this->commonDrawImage(image, kDrawImageRect_DrawOp, flags, opBytesNeeded , paint)) {
869 if (src) {
870 fWriter.writeRect(*src);
871 }
872 fWriter.writeRect(dst);
873 fWriter.writeInt(constraint);
874 }
875 }
876
877 void SkGPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
878 const SkPaint* paint) {
879 NOTIFY_SETUP(this);
880 size_t opBytesNeeded = sizeof(SkIRect) + sizeof(SkRect); // center + dst
881 if (this->commonDrawImage(image, kDrawImageNine_DrawOp, 0, opBytesNeeded, pa int)) {
882 fWriter.writeIRect(center);
883 fWriter.writeRect(dst);
884 }
885 }
886
887 void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
888 const SkPaint& paint) {
889 if (byteLength) {
890 NOTIFY_SETUP(this);
891 this->writePaint(paint);
892 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
893 this->writeOp(kDrawText_DrawOp);
894 fWriter.write32(SkToU32(byteLength));
895 fWriter.writePad(text, byteLength);
896 fWriter.writeScalar(x);
897 fWriter.writeScalar(y);
898 }
899 }
900 }
901
902 void SkGPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkP oint pos[],
903 const SkPaint& paint) {
904 if (byteLength) {
905 NOTIFY_SETUP(this);
906 this->writePaint(paint);
907 int count = paint.textToGlyphs(text, byteLength, nullptr);
908 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPo int))) {
909 this->writeOp(kDrawPosText_DrawOp);
910 fWriter.write32(SkToU32(byteLength));
911 fWriter.writePad(text, byteLength);
912 fWriter.write32(count);
913 fWriter.write(pos, count * sizeof(SkPoint));
914 }
915 }
916 }
917
918 void SkGPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const Sk Scalar xpos[],
919 SkScalar constY, const SkPaint& paint) {
920 if (byteLength) {
921 NOTIFY_SETUP(this);
922 this->writePaint(paint);
923 int count = paint.textToGlyphs(text, byteLength, nullptr);
924 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkSc alar) + 4)) {
925 this->writeOp(kDrawPosTextH_DrawOp);
926 fWriter.write32(SkToU32(byteLength));
927 fWriter.writePad(text, byteLength);
928 fWriter.write32(count);
929 fWriter.write(xpos, count * sizeof(SkScalar));
930 fWriter.writeScalar(constY);
931 }
932 }
933 }
934
935 void SkGPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
936 const SkMatrix* matrix, const SkPaint& pain t) {
937 if (byteLength) {
938 NOTIFY_SETUP(this);
939 unsigned flags = 0;
940 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(nullptr);
941 if (matrix) {
942 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
943 size += matrix->writeToMemory(nullptr);
944 }
945 this->writePaint(paint);
946 if (this->needOpBytes(size)) {
947 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
948
949 fWriter.write32(SkToU32(byteLength));
950 fWriter.writePad(text, byteLength);
951
952 fWriter.writePath(path);
953 if (matrix) {
954 fWriter.writeMatrix(*matrix);
955 }
956 }
957 }
958 }
959
960 size_t SkGPipeCanvas::getInProcessTypefaces(const SkRefCntSet& typefaceSet,
961 TypefaceBuffer* buffer) {
962 // When in-process, we simply write out the typeface pointers.
963 size_t size = typefaceSet.count() * sizeof(SkTypeface*);
964 buffer->reset(size);
965 typefaceSet.copyToArray(reinterpret_cast<SkRefCnt**>(buffer->get()));
966
967 return size;
968 }
969
970 size_t SkGPipeCanvas::getCrossProcessTypefaces(const SkRefCntSet& typefaceSet,
971 TypefaceBuffer* buffer) {
972 // For cross-process we use typeface IDs.
973 size_t size = typefaceSet.count() * sizeof(uint32_t);
974 buffer->reset(size);
975
976 uint32_t* idBuffer = reinterpret_cast<uint32_t*>(buffer->get());
977 SkRefCntSet::Iter iter(typefaceSet);
978 int i = 0;
979
980 for (void* setPtr = iter.next(); setPtr; setPtr = iter.next()) {
981 idBuffer[i++] = this->getTypefaceID(reinterpret_cast<SkTypeface*>(setPtr ));
982 }
983
984 SkASSERT(i == typefaceSet.count());
985
986 return size;
987 }
988
989 void SkGPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
990 const SkPaint& paint) {
991 NOTIFY_SETUP(this);
992 this->writePaint(paint);
993
994 // FIXME: this is inefficient but avoids duplicating the blob serialization logic.
995 SkRefCntSet typefaceSet;
996 SkWriteBuffer blobBuffer;
997 blobBuffer.setTypefaceRecorder(&typefaceSet);
998 blob->flatten(blobBuffer);
999
1000 // Unlike most draw ops (which only use one paint/typeface), text blobs may reference
1001 // an arbitrary number of typefaces. Since the one-paint-per-op model is not applicable,
1002 // we need to serialize these explicitly.
1003 TypefaceBuffer typefaceBuffer;
1004 size_t typefaceSize = is_cross_process(fFlags)
1005 ? this->getCrossProcessTypefaces(typefaceSet, &typefaceBuffer)
1006 : this->getInProcessTypefaces(typefaceSet, &typefaceBuffer);
1007
1008 // blob byte count + typeface count + x + y + blob data + an index (cross-pr ocess)
1009 // or pointer (in-process) for each typeface
1010 size_t size = 2 * sizeof(uint32_t)
1011 + 2 * sizeof(SkScalar)
1012 + blobBuffer.bytesWritten()
1013 + typefaceSize;
1014
1015 if (this->needOpBytes(size)) {
1016 this->writeOp(kDrawTextBlob_DrawOp);
1017 SkDEBUGCODE(size_t initialOffset = fWriter.bytesWritten();)
1018
1019 fWriter.writeScalar(x);
1020 fWriter.writeScalar(y);
1021
1022 fWriter.write32(typefaceSet.count());
1023 fWriter.write(typefaceBuffer.get(), typefaceSize);
1024
1025 fWriter.write32(SkToU32(blobBuffer.bytesWritten()));
1026 uint32_t* pad = fWriter.reservePad(blobBuffer.bytesWritten());
1027 blobBuffer.writeToMemory(pad);
1028
1029 SkASSERT(initialOffset + size == fWriter.bytesWritten());
1030 }
1031 }
1032
1033 void SkGPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matr ix,
1034 const SkPaint* paint) {
1035 // we want to playback the picture into individual draw calls
1036 //
1037 // todo: do we always have to unroll? If the pipe is not cross-process, seem s like
1038 // we could just ref the picture and move on...? <reed, scroggo>
1039 //
1040 this->INHERITED::onDrawPicture(picture, matrix, paint);
1041 }
1042
1043 void SkGPipeCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
1044 const SkPoint vertices[], const SkPoint texs[ ],
1045 const SkColor colors[], SkXfermode* xfer,
1046 const uint16_t indices[], int indexCount,
1047 const SkPaint& paint) {
1048 if (0 == vertexCount) {
1049 return;
1050 }
1051
1052 NOTIFY_SETUP(this);
1053 this->writePaint(paint);
1054
1055 unsigned flags = 0; // packs with the op, so needs no extra space
1056
1057 size_t size = 0;
1058 size += 4; // vmode
1059 size += 4; // vertex count
1060 size += vertexCount * sizeof(SkPoint); // vertices
1061
1062 if (texs) {
1063 flags |= kDrawVertices_HasTexs_DrawOpFlag;
1064 size += vertexCount * sizeof(SkPoint);
1065 }
1066 if (colors) {
1067 flags |= kDrawVertices_HasColors_DrawOpFlag;
1068 size += vertexCount * sizeof(SkColor);
1069 }
1070 if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) {
1071 flags |= kDrawVertices_HasXfermode_DrawOpFlag;
1072 size += sizeof(int32_t); // SkXfermode::Mode
1073 }
1074 if (indices && indexCount > 0) {
1075 flags |= kDrawVertices_HasIndices_DrawOpFlag;
1076 size += 4; // index count
1077 size += SkAlign4(indexCount * sizeof(uint16_t)); // indices
1078 }
1079
1080 if (this->needOpBytes(size)) {
1081 this->writeOp(kDrawVertices_DrawOp, flags, 0);
1082 fWriter.write32(vmode);
1083 fWriter.write32(vertexCount);
1084 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
1085 if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
1086 fWriter.write(texs, vertexCount * sizeof(SkPoint));
1087 }
1088 if (flags & kDrawVertices_HasColors_DrawOpFlag) {
1089 fWriter.write(colors, vertexCount * sizeof(SkColor));
1090 }
1091 if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
1092 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
1093 SkAssertResult(xfer->asMode(&mode));
1094 fWriter.write32(mode);
1095 }
1096 if (flags & kDrawVertices_HasIndices_DrawOpFlag) {
1097 fWriter.write32(indexCount);
1098 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
1099 }
1100 }
1101 }
1102
1103 void SkGPipeCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], c onst SkRect tex[],
1104 const SkColor colors[], int count, SkXfermode::M ode mode,
1105 const SkRect* cull, const SkPaint* paint) {
1106 NOTIFY_SETUP(this);
1107 unsigned flags = 0; // packs with the op, so needs no extra space
1108
1109 if (paint) {
1110 flags |= kDrawAtlas_HasPaint_DrawOpFlag;
1111 this->writePaint(*paint);
1112 }
1113
1114 size_t size = 4; // image-slot
1115 size += 4; // count
1116 size += 4; // mode
1117 size += count * sizeof(SkRSXform); // xform
1118 size += count * sizeof(SkRect); // tex
1119 if (colors) {
1120 flags |= kDrawAtlas_HasColors_DrawOpFlag;
1121 size += count * sizeof(SkColor); // colors
1122 }
1123 if (cull) {
1124 flags |= kDrawAtlas_HasCull_DrawOpFlag;
1125 size += sizeof(SkRect); // cull
1126 }
1127
1128 if (this->needOpBytes(size)) {
1129 this->writeOp(kDrawAtlas_DrawOp, flags, 0);
1130 int32_t slot = fImageHeap->insert(atlas);
1131 fWriter.write32(slot);
1132 fWriter.write32(count);
1133 fWriter.write32(mode);
1134 fWriter.write(xform, count * sizeof(SkRSXform));
1135 fWriter.write(tex, count * sizeof(SkRect));
1136 if (colors) {
1137 fWriter.write(colors, count * sizeof(SkColor));
1138 }
1139 if (cull) {
1140 fWriter.writeRect(*cull);
1141 }
1142 }
1143 }
1144
1145 void SkGPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4 ],
1146 const SkPoint texCoords[4], SkXfermode* xmode,
1147 const SkPaint& paint) {
1148 NOTIFY_SETUP(this);
1149
1150 size_t size = SkPatchUtils::kNumCtrlPts * sizeof(SkPoint);
1151 unsigned flags = 0;
1152 if (colors) {
1153 flags |= kDrawVertices_HasColors_DrawOpFlag;
1154 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
1155 }
1156 if (texCoords) {
1157 flags |= kDrawVertices_HasTexs_DrawOpFlag;
1158 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
1159 }
1160 if (xmode) {
1161 SkXfermode::Mode mode;
1162 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
1163 flags |= kDrawVertices_HasXfermode_DrawOpFlag;
1164 size += sizeof(int32_t);
1165 }
1166 }
1167
1168 this->writePaint(paint);
1169 if (this->needOpBytes(size)) {
1170 this->writeOp(kDrawPatch_DrawOp, flags, 0);
1171
1172 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
1173
1174 if (colors) {
1175 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
1176 }
1177
1178 if (texCoords) {
1179 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint) );
1180 }
1181
1182 if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
1183 SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
1184 SkAssertResult(xmode->asMode(&mode));
1185 fWriter.write32(mode);
1186 }
1187 }
1188 }
1189
1190 void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) {
1191 this->doNotify();
1192 if (detachCurrentBlock) {
1193 // force a new block to be requested for the next recorded command
1194 fBlockSize = 0;
1195 }
1196 }
1197
1198 void SkGPipeCanvas::resetImageHeap() {
1199 if (fImageHeap) {
1200 fImageHeap->reset();
1201 }
1202 }
1203
1204 size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) {
1205 return (nullptr == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(byte sToFree);
1206 }
1207
1208 ///////////////////////////////////////////////////////////////////////////////
1209
1210 template <typename T> uint32_t castToU32(T value) {
1211 union {
1212 T fSrc;
1213 uint32_t fDst;
1214 } data;
1215 data.fSrc = value;
1216 return data.fDst;
1217 }
1218
1219 void SkGPipeCanvas::writePaint(const SkPaint& paint) {
1220 if (fDone) {
1221 return;
1222 }
1223 SkPaint& base = fPaint;
1224 uint32_t storage[32];
1225 uint32_t* ptr = storage;
1226
1227 if (base.getFlags() != paint.getFlags()) {
1228 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
1229 base.setFlags(paint.getFlags());
1230 }
1231 if (base.getColor() != paint.getColor()) {
1232 *ptr++ = PaintOp_packOp(kColor_PaintOp);
1233 *ptr++ = paint.getColor();
1234 base.setColor(paint.getColor());
1235 }
1236 if (base.getFilterQuality() != paint.getFilterQuality()) {
1237 *ptr++ = PaintOp_packOpData(kFilterLevel_PaintOp, paint.getFilterQuality ());
1238 base.setFilterQuality(paint.getFilterQuality());
1239 }
1240 if (base.getStyle() != paint.getStyle()) {
1241 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
1242 base.setStyle(paint.getStyle());
1243 }
1244 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
1245 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
1246 base.setStrokeJoin(paint.getStrokeJoin());
1247 }
1248 if (base.getStrokeCap() != paint.getStrokeCap()) {
1249 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
1250 base.setStrokeCap(paint.getStrokeCap());
1251 }
1252 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
1253 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
1254 *ptr++ = castToU32(paint.getStrokeWidth());
1255 base.setStrokeWidth(paint.getStrokeWidth());
1256 }
1257 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
1258 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
1259 *ptr++ = castToU32(paint.getStrokeMiter());
1260 base.setStrokeMiter(paint.getStrokeMiter());
1261 }
1262 if (base.getTextEncoding() != paint.getTextEncoding()) {
1263 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
1264 base.setTextEncoding(paint.getTextEncoding());
1265 }
1266 if (base.getHinting() != paint.getHinting()) {
1267 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
1268 base.setHinting(paint.getHinting());
1269 }
1270 if (base.getTextAlign() != paint.getTextAlign()) {
1271 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
1272 base.setTextAlign(paint.getTextAlign());
1273 }
1274 if (base.getTextSize() != paint.getTextSize()) {
1275 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
1276 *ptr++ = castToU32(paint.getTextSize());
1277 base.setTextSize(paint.getTextSize());
1278 }
1279 if (base.getTextScaleX() != paint.getTextScaleX()) {
1280 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
1281 *ptr++ = castToU32(paint.getTextScaleX());
1282 base.setTextScaleX(paint.getTextScaleX());
1283 }
1284 if (base.getTextSkewX() != paint.getTextSkewX()) {
1285 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
1286 *ptr++ = castToU32(paint.getTextSkewX());
1287 base.setTextSkewX(paint.getTextSkewX());
1288 }
1289
1290 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
1291 if (is_cross_process(fFlags)) {
1292 uint32_t id = this->getTypefaceID(paint.getTypeface());
1293 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
1294 } else if (this->needOpBytes(sizeof(void*))) {
1295 // Add to the set for ref counting.
1296 fTypefaceSet.add(paint.getTypeface());
1297 // It is safe to write the typeface to the stream before the rest
1298 // of the paint unless we ever send a kReset_PaintOp, which we
1299 // currently never do.
1300 this->writeOp(kSetTypeface_DrawOp);
1301 fWriter.writePtr(paint.getTypeface());
1302 }
1303 base.setTypeface(paint.getTypeface());
1304 }
1305
1306 // This is a new paint, so all old flats can be safely purged, if necessary.
1307 fFlattenableHeap.markAllFlatsSafeToDelete();
1308 for (int i = 0; i < kCount_PaintFlats; i++) {
1309 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i) ;
1310 bool replaced = index < 0;
1311 if (replaced) {
1312 index = ~index;
1313 }
1314 // Store the index of any flat that needs to be kept. 0 means no flat.
1315 if (index > 0) {
1316 fFlattenableHeap.markFlatForKeeping(index);
1317 }
1318 SkASSERT(index >= 0 && index <= fFlatDictionary.count());
1319 if (index != fCurrFlatIndex[i] || replaced) {
1320 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
1321 fCurrFlatIndex[i] = index;
1322 }
1323 }
1324
1325 size_t size = (char*)ptr - (char*)storage;
1326 if (size && this->needOpBytes(size)) {
1327 this->writeOp(kPaintOp_DrawOp, 0, SkToU32(size));
1328 fWriter.write(storage, size);
1329 for (size_t i = 0; i < size/4; i++) {
1330 // SkDebugf("[%d] %08X\n", i, storage[i]);
1331 }
1332 }
1333
1334 //
1335 // Do these after we've written kPaintOp_DrawOp
1336
1337 if (base.getAnnotation() != paint.getAnnotation()) {
1338 if (nullptr == paint.getAnnotation()) {
1339 if (this->needOpBytes()) {
1340 this->writeOp(kSetAnnotation_DrawOp, 0, 0);
1341 }
1342 } else {
1343 SkWriteBuffer buffer;
1344 paint.getAnnotation()->writeToBuffer(buffer);
1345 const size_t size = buffer.bytesWritten();
1346 if (this->needOpBytes(size)) {
1347 this->writeOp(kSetAnnotation_DrawOp, 0, SkToU32(size));
1348 buffer.writeToMemory(fWriter.reserve(size));
1349 }
1350 }
1351 base.setAnnotation(paint.getAnnotation());
1352 }
1353 }
1354
1355 ///////////////////////////////////////////////////////////////////////////////
1356
1357 #include "SkGPipe.h"
1358
1359 SkGPipeController::~SkGPipeController() {
1360 SkSafeUnref(fCanvas);
1361 }
1362
1363 void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
1364 SkRefCnt_SafeAssign(fCanvas, canvas);
1365 }
1366
1367 void SkGPipeController::purgeCaches()
1368 {
1369 fCanvas->resetImageHeap();
1370 // Other caches are self-purging with a small MRU pool
1371 // We could purge them as well, but it is not clear whether
1372 // that would be a win.
1373 }
1374
1375 ///////////////////////////////////////////////////////////////////////////////
1376
1377 SkGPipeWriter::SkGPipeWriter()
1378 : fWriter(0) {
1379 fCanvas = nullptr;
1380 }
1381
1382 SkGPipeWriter::~SkGPipeWriter() {
1383 this->endRecording();
1384 }
1385
1386 SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags,
1387 uint32_t width, uint32_t height) {
1388 if (nullptr == fCanvas) {
1389 fWriter.reset(nullptr, 0);
1390 fCanvas = new SkGPipeCanvas(controller, &fWriter, flags, width, height);
1391 }
1392 controller->setCanvas(fCanvas);
1393 return fCanvas;
1394 }
1395
1396 void SkGPipeWriter::endRecording() {
1397 if (fCanvas) {
1398 fCanvas->finish(true);
1399 fCanvas->unref();
1400 fCanvas = nullptr;
1401 }
1402 }
1403
1404 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) {
1405 if (fCanvas) {
1406 fCanvas->flushRecording(detachCurrentBlock);
1407 }
1408 }
1409
1410 size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) {
1411 if (fCanvas) {
1412 return fCanvas->freeMemoryIfPossible(bytesToFree);
1413 }
1414 return 0;
1415 }
1416
1417 size_t SkGPipeWriter::storageAllocatedForRecording() const {
1418 return nullptr == fCanvas ? 0 : fCanvas->storageAllocatedForRecording();
1419 }
1420
1421 ///////////////////////////////////////////////////////////////////////////////
1422
1423 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) {
1424 SkASSERT(canvas != nullptr);
1425 fCanvas = canvas;
1426 fCanvas->ref();
1427 }
1428
1429 BitmapShuttle::~BitmapShuttle() {
1430 this->removeCanvas();
1431 }
1432
1433 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) {
1434 SkASSERT(fCanvas != nullptr);
1435 return fCanvas->shuttleBitmap(bitmap, slot);
1436 }
1437
1438 void BitmapShuttle::removeCanvas() {
1439 if (nullptr == fCanvas) {
1440 return;
1441 }
1442 fCanvas->unref();
1443 fCanvas = nullptr;
1444 }
1445
1446 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1447
1448 SkImageHeap::SkImageHeap() : fBytesInCache (0) {}
1449
1450 SkImageHeap::~SkImageHeap() {
1451 fArray.unrefAll();
1452 }
1453
1454 void SkImageHeap::reset() {
1455 fArray.unrefAll();
1456 fArray.rewind();
1457 fBytesInCache = 0;
1458 }
1459
1460 const SkImage* SkImageHeap::get(int32_t slot) const {
1461 SkASSERT(slot > 0);
1462 return fArray[slot - 1];
1463 }
1464
1465 int32_t SkImageHeap::find(const SkImage* img) const {
1466 int index = fArray.find(img);
1467 if (index >= 0) {
1468 return index + 1; // found
1469 }
1470 return 0; // not found
1471 }
1472
1473 int32_t SkImageHeap::insert(const SkImage* img) {
1474 int32_t slot = this->find(img);
1475 if (slot) {
1476 return slot;
1477 }
1478 // TODO: SkImage does not expose bytes per pixel, 4 is just a best guess.
1479 fBytesInCache += img->width() * img->height() * 4;
1480 *fArray.append() = SkRef(img);
1481 return fArray.count(); // slot is always index+1
1482 }
1483
OLDNEW
« no previous file with comments | « src/pipe/SkGPipeRead.cpp ('k') | src/pipe/utils/SamplePipeControllers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698