Chromium Code Reviews| 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 |