OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |