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

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

Issue 563783003: Ensure blob typeface information survives SkGPipe serialization. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Comments + win build fix Created 6 years, 3 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkAnnotation.h" 9 #include "SkAnnotation.h"
10 #include "SkBitmapDevice.h" 10 #include "SkBitmapDevice.h"
11 #include "SkBitmapHeap.h" 11 #include "SkBitmapHeap.h"
12 #include "SkCanvas.h" 12 #include "SkCanvas.h"
13 #include "SkColorFilter.h" 13 #include "SkColorFilter.h"
14 #include "SkData.h" 14 #include "SkData.h"
15 #include "SkDrawLooper.h" 15 #include "SkDrawLooper.h"
16 #include "SkGPipe.h" 16 #include "SkGPipe.h"
17 #include "SkGPipePriv.h" 17 #include "SkGPipePriv.h"
18 #include "SkImageFilter.h" 18 #include "SkImageFilter.h"
19 #include "SkMaskFilter.h" 19 #include "SkMaskFilter.h"
20 #include "SkWriteBuffer.h" 20 #include "SkWriteBuffer.h"
21 #include "SkPaint.h" 21 #include "SkPaint.h"
22 #include "SkPatchUtils.h" 22 #include "SkPatchUtils.h"
23 #include "SkPathEffect.h" 23 #include "SkPathEffect.h"
24 #include "SkPictureFlat.h" 24 #include "SkPictureFlat.h"
25 #include "SkPtrRecorder.h"
25 #include "SkRasterizer.h" 26 #include "SkRasterizer.h"
26 #include "SkRRect.h" 27 #include "SkRRect.h"
27 #include "SkShader.h" 28 #include "SkShader.h"
28 #include "SkStream.h" 29 #include "SkStream.h"
29 #include "SkTextBlob.h" 30 #include "SkTextBlob.h"
30 #include "SkTSearch.h" 31 #include "SkTSearch.h"
31 #include "SkTypeface.h" 32 #include "SkTypeface.h"
32 #include "SkWriter32.h" 33 #include "SkWriter32.h"
33 34
34 enum { 35 enum {
35 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector) 36 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector)
36 }; 37 };
37 38
38 static bool isCrossProcess(uint32_t flags) { 39 static bool is_cross_process(uint32_t flags) {
39 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag); 40 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
40 } 41 }
41 42
42 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { 43 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
43 SkASSERT(paintFlat < kCount_PaintFlats); 44 SkASSERT(paintFlat < kCount_PaintFlats);
44 switch (paintFlat) { 45 switch (paintFlat) {
45 case kColorFilter_PaintFlat: return paint.getColorFilter(); 46 case kColorFilter_PaintFlat: return paint.getColorFilter();
46 case kDrawLooper_PaintFlat: return paint.getLooper(); 47 case kDrawLooper_PaintFlat: return paint.getLooper();
47 case kMaskFilter_PaintFlat: return paint.getMaskFilter(); 48 case kMaskFilter_PaintFlat: return paint.getMaskFilter();
48 case kPathEffect_PaintFlat: return paint.getPathEffect(); 49 case kPathEffect_PaintFlat: return paint.getPathEffect();
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 inline void doNotify() { 332 inline void doNotify() {
332 if (!fDone) { 333 if (!fDone) {
333 size_t bytes = fWriter.bytesWritten() - fBytesNotified; 334 size_t bytes = fWriter.bytesWritten() - fBytesNotified;
334 if (bytes > 0) { 335 if (bytes > 0) {
335 fController->notifyWritten(bytes); 336 fController->notifyWritten(bytes);
336 fBytesNotified += bytes; 337 fBytesNotified += bytes;
337 } 338 }
338 } 339 }
339 } 340 }
340 341
342 size_t prepareInProcessTypefaceBuffer(const SkRefCntSet& typefaceSet, void* buffer);
343 size_t prepareCrossProcessTypefaceBuffer(const SkRefCntSet& typefaceSet, voi d* buffer);
344
341 // Should be called after any calls to an SkFlatDictionary::findAndReplace 345 // Should be called after any calls to an SkFlatDictionary::findAndReplace
342 // if a new SkFlatData was added when in cross process mode 346 // if a new SkFlatData was added when in cross process mode
343 void flattenFactoryNames(); 347 void flattenFactoryNames();
344 348
345 FlattenableHeap fFlattenableHeap; 349 FlattenableHeap fFlattenableHeap;
346 FlatDictionary fFlatDictionary; 350 FlatDictionary fFlatDictionary;
347 SkAutoTUnref<BitmapShuttle> fBitmapShuttle; 351 SkAutoTUnref<BitmapShuttle> fBitmapShuttle;
348 int fCurrFlatIndex[kCount_PaintFlats]; 352 int fCurrFlatIndex[kCount_PaintFlats];
349 353
350 int flattenToIndex(SkFlattenable* obj, PaintFlats); 354 int flattenToIndex(SkFlattenable* obj, PaintFlats);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 return 0; 408 return 0;
405 } 409 }
406 410
407 fBitmapHeap->deferAddingOwners(); 411 fBitmapHeap->deferAddingOwners();
408 bool added, replaced; 412 bool added, replaced;
409 const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHe ap.flatToReplace(), 413 const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHe ap.flatToReplace(),
410 &added, &replaced); 414 &added, &replaced);
411 fBitmapHeap->endAddingOwnersDeferral(added); 415 fBitmapHeap->endAddingOwnersDeferral(added);
412 int index = flat->index(); 416 int index = flat->index();
413 if (added) { 417 if (added) {
414 if (isCrossProcess(fFlags)) { 418 if (is_cross_process(fFlags)) {
415 this->flattenFactoryNames(); 419 this->flattenFactoryNames();
416 } 420 }
417 size_t flatSize = flat->flatSize(); 421 size_t flatSize = flat->flatSize();
418 if (this->needOpBytes(flatSize)) { 422 if (this->needOpBytes(flatSize)) {
419 this->writeOp(kDef_Flattenable_DrawOp, paintflat, index); 423 this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
420 fWriter.write(flat->data(), flatSize); 424 fWriter.write(flat->data(), flatSize);
421 } 425 }
422 } 426 }
423 if (replaced) { 427 if (replaced) {
424 index = ~index; 428 index = ~index;
425 } 429 }
426 return index; 430 return index;
427 } 431 }
428 432
429 /////////////////////////////////////////////////////////////////////////////// 433 ///////////////////////////////////////////////////////////////////////////////
430 434
431 #define MIN_BLOCK_SIZE (16 * 1024) 435 #define MIN_BLOCK_SIZE (16 * 1024)
432 #define BITMAPS_TO_KEEP 5 436 #define BITMAPS_TO_KEEP 5
433 #define FLATTENABLES_TO_KEEP 10 437 #define FLATTENABLES_TO_KEEP 10
434 438
435 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, 439 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
436 SkWriter32* writer, uint32_t flags, 440 SkWriter32* writer, uint32_t flags,
437 uint32_t width, uint32_t height) 441 uint32_t width, uint32_t height)
438 : SkCanvas(width, height) 442 : SkCanvas(width, height)
439 , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) 443 , fFactorySet(is_cross_process(flags) ? SkNEW(SkNamedFactorySet) : NULL)
440 , fWriter(*writer) 444 , fWriter(*writer)
441 , fFlags(flags) 445 , fFlags(flags)
442 , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags)) 446 , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, is_cross_process(flags ))
443 , fFlatDictionary(&fFlattenableHeap) 447 , fFlatDictionary(&fFlattenableHeap)
444 { 448 {
445 fController = controller; 449 fController = controller;
446 fDone = false; 450 fDone = false;
447 fBlockSize = 0; // need first block from controller 451 fBlockSize = 0; // need first block from controller
448 fBytesNotified = 0; 452 fBytesNotified = 0;
449 fFirstSaveLayerStackLevel = kNoSaveLayer; 453 fFirstSaveLayerStackLevel = kNoSaveLayer;
450 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); 454 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
451 455
452 // Tell the reader the appropriate flags to use. 456 // Tell the reader the appropriate flags to use.
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 fWriter.writePad(text, byteLength); 935 fWriter.writePad(text, byteLength);
932 936
933 fWriter.writePath(path); 937 fWriter.writePath(path);
934 if (matrix) { 938 if (matrix) {
935 fWriter.writeMatrix(*matrix); 939 fWriter.writeMatrix(*matrix);
936 } 940 }
937 } 941 }
938 } 942 }
939 } 943 }
940 944
945 size_t SkGPipeCanvas::prepareInProcessTypefaceBuffer(const SkRefCntSet& typeface Set, void* buffer) {
946 // When in-process, we simply write out the typeface pointers.
947 typefaceSet.copyToArray((SkRefCnt**)buffer);
948
949 return typefaceSet.count() * sizeof(SkTypeface*);
950 }
951
952 size_t SkGPipeCanvas::prepareCrossProcessTypefaceBuffer(const SkRefCntSet& typef aceSet,
953 void* buffer) {
954 // For cross-process we use typeface IDs.
955 typefaceSet.copyToArray((SkRefCnt**)buffer);
mtklein 2014/09/15 22:13:14 Is there any hope for writing typefaceSet.copyIDsT
956
957 uint32_t* ids = reinterpret_cast<uint32_t*>(buffer);
958 SkTypeface** typefaces = reinterpret_cast<SkTypeface**>(buffer);
959 for (int i = 0; i < typefaceSet.count(); ++i) {
960 ids[i] = this->getTypefaceID(typefaces[i]);
961 }
962
963 return typefaceSet.count() * sizeof(uint32_t);
964 }
965
941 void SkGPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 966 void SkGPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
942 const SkPaint& paint) { 967 const SkPaint& paint) {
943 NOTIFY_SETUP(this); 968 NOTIFY_SETUP(this);
944 this->writePaint(paint); 969 this->writePaint(paint);
945 970
946 // FIXME: this is inefficient but avoids duplicating the blob serialization logic. 971 // FIXME: this is inefficient but avoids duplicating the blob serialization logic.
972 SkRefCntSet typefaceSet;
947 SkWriteBuffer blobBuffer; 973 SkWriteBuffer blobBuffer;
974 blobBuffer.setTypefaceRecorder(&typefaceSet);
948 blob->flatten(blobBuffer); 975 blob->flatten(blobBuffer);
949 976
950 size_t size = sizeof(uint32_t) + 2 * sizeof(SkScalar) + blobBuffer.bytesWrit ten(); 977 // Unlike most draw ops (which only use one paint/typeface), text blobs may reference
978 // an arbitrary number of typefaces. Since the one-paint-per-op model is not applicable,
979 // we need to serialize these explicitly.
980 SkAutoSTMalloc<128, uint8_t> storage(typefaceSet.count() * sizeof(SkTypeface *));
981 size_t typefaceSize = is_cross_process(fFlags)
982 ? this->prepareCrossProcessTypefaceBuffer(typefaceSet, storage.get())
983 : this->prepareInProcessTypefaceBuffer(typefaceSet, storage.get());
984
985 // blob byte count + typeface count + x + y + blob data + an index (cross-pr ocess)
986 // or pointer (in-process) for each typeface
987 size_t size = 2 * sizeof(uint32_t)
988 + 2 * sizeof(SkScalar)
989 + blobBuffer.bytesWritten()
990 + typefaceSize;
991
951 if (this->needOpBytes(size)) { 992 if (this->needOpBytes(size)) {
952 this->writeOp(kDrawTextBlob_DrawOp); 993 this->writeOp(kDrawTextBlob_DrawOp);
994 SkDEBUGCODE(size_t initialOffset = fWriter.bytesWritten();)
995
953 fWriter.writeScalar(x); 996 fWriter.writeScalar(x);
954 fWriter.writeScalar(y); 997 fWriter.writeScalar(y);
998
999 fWriter.write32(typefaceSet.count());
1000 fWriter.write(storage.get(), typefaceSize);
1001
955 fWriter.write32(SkToU32(blobBuffer.bytesWritten())); 1002 fWriter.write32(SkToU32(blobBuffer.bytesWritten()));
956 uint32_t* pad = fWriter.reservePad(blobBuffer.bytesWritten()); 1003 uint32_t* pad = fWriter.reservePad(blobBuffer.bytesWritten());
957 blobBuffer.writeToMemory(pad); 1004 blobBuffer.writeToMemory(pad);
1005
1006 SkASSERT(initialOffset + size == fWriter.bytesWritten());
958 } 1007 }
959 } 1008 }
960 1009
961 void SkGPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matr ix, 1010 void SkGPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matr ix,
962 const SkPaint* paint) { 1011 const SkPaint* paint) {
963 // we want to playback the picture into individual draw calls 1012 // we want to playback the picture into individual draw calls
964 // 1013 //
965 // todo: do we always have to unroll? If the pipe is not cross-process, seem s like 1014 // todo: do we always have to unroll? If the pipe is not cross-process, seem s like
966 // we could just ref the picture and move on...? <reed, scroggo> 1015 // we could just ref the picture and move on...? <reed, scroggo>
967 // 1016 //
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 *ptr++ = castToU32(paint.getTextScaleX()); 1239 *ptr++ = castToU32(paint.getTextScaleX());
1191 base.setTextScaleX(paint.getTextScaleX()); 1240 base.setTextScaleX(paint.getTextScaleX());
1192 } 1241 }
1193 if (base.getTextSkewX() != paint.getTextSkewX()) { 1242 if (base.getTextSkewX() != paint.getTextSkewX()) {
1194 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp); 1243 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
1195 *ptr++ = castToU32(paint.getTextSkewX()); 1244 *ptr++ = castToU32(paint.getTextSkewX());
1196 base.setTextSkewX(paint.getTextSkewX()); 1245 base.setTextSkewX(paint.getTextSkewX());
1197 } 1246 }
1198 1247
1199 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { 1248 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
1200 if (isCrossProcess(fFlags)) { 1249 if (is_cross_process(fFlags)) {
1201 uint32_t id = this->getTypefaceID(paint.getTypeface()); 1250 uint32_t id = this->getTypefaceID(paint.getTypeface());
1202 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); 1251 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
1203 } else if (this->needOpBytes(sizeof(void*))) { 1252 } else if (this->needOpBytes(sizeof(void*))) {
1204 // Add to the set for ref counting. 1253 // Add to the set for ref counting.
1205 fTypefaceSet.add(paint.getTypeface()); 1254 fTypefaceSet.add(paint.getTypeface());
1206 // It is safe to write the typeface to the stream before the rest 1255 // It is safe to write the typeface to the stream before the rest
1207 // of the paint unless we ever send a kReset_PaintOp, which we 1256 // of the paint unless we ever send a kReset_PaintOp, which we
1208 // currently never do. 1257 // currently never do.
1209 this->writeOp(kSetTypeface_DrawOp); 1258 this->writeOp(kSetTypeface_DrawOp);
1210 fWriter.writePtr(paint.getTypeface()); 1259 fWriter.writePtr(paint.getTypeface());
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 return fCanvas->shuttleBitmap(bitmap, slot); 1385 return fCanvas->shuttleBitmap(bitmap, slot);
1337 } 1386 }
1338 1387
1339 void BitmapShuttle::removeCanvas() { 1388 void BitmapShuttle::removeCanvas() {
1340 if (NULL == fCanvas) { 1389 if (NULL == fCanvas) {
1341 return; 1390 return;
1342 } 1391 }
1343 fCanvas->unref(); 1392 fCanvas->unref();
1344 fCanvas = NULL; 1393 fCanvas = NULL;
1345 } 1394 }
OLDNEW
« no previous file with comments | « src/pipe/SkGPipeRead.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698