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" |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 } | 160 } |
161 static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer, | 161 static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer, |
162 const void* obj) { | 162 const void* obj) { |
163 buffer.writeFlattenable((SkFlattenable*)obj); | 163 buffer.writeFlattenable((SkFlattenable*)obj); |
164 } | 164 } |
165 | 165 |
166 }; | 166 }; |
167 | 167 |
168 /////////////////////////////////////////////////////////////////////////////// | 168 /////////////////////////////////////////////////////////////////////////////// |
169 | 169 |
| 170 /** |
| 171 * If SkBitmaps are to be flattened to send to the reader, this class is |
| 172 * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so. |
| 173 */ |
| 174 class BitmapShuttle : public SkBitmapHeap::ExternalStorage { |
| 175 public: |
| 176 BitmapShuttle(SkGPipeCanvas*); |
| 177 |
| 178 ~BitmapShuttle(); |
| 179 |
| 180 virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE; |
| 181 |
| 182 /** |
| 183 * Remove the SkGPipeCanvas used for insertion. After this, calls to |
| 184 * insert will crash. |
| 185 */ |
| 186 void removeCanvas(); |
| 187 |
| 188 private: |
| 189 SkGPipeCanvas* fCanvas; |
| 190 }; |
| 191 |
| 192 /////////////////////////////////////////////////////////////////////////////// |
| 193 |
170 class SkGPipeCanvas : public SkCanvas { | 194 class SkGPipeCanvas : public SkCanvas { |
171 public: | 195 public: |
172 SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags, | 196 SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags, |
173 uint32_t width, uint32_t height); | 197 uint32_t width, uint32_t height); |
174 virtual ~SkGPipeCanvas(); | 198 virtual ~SkGPipeCanvas(); |
175 | 199 |
176 void finish() { | 200 /** |
177 if (!fDone) { | 201 * Called when nothing else is to be written to the stream. Any repeated |
178 if (this->needOpBytes()) { | 202 * calls are ignored. |
179 this->writeOp(kDone_DrawOp); | 203 * |
180 this->doNotify(); | 204 * @param notifyReaders Whether to send a message to the reader(s) that |
181 if (shouldFlattenBitmaps(fFlags)) { | 205 * the writer is through sending commands. Should generally be true, |
182 // In this case, a BitmapShuttle is reffed by the SkBitmapHe
ap | 206 * unless there is an error which prevents further messages from |
183 // and refs this canvas. Unref the SkBitmapHeap to end the | 207 * being sent. |
184 // circular reference. When shouldFlattenBitmaps is false, | 208 */ |
185 // there is no circular reference, so the SkBitmapHeap can b
e | 209 void finish(bool notifyReaders) { |
186 // safely unreffed in the destructor. | 210 if (fDone) { |
187 fBitmapHeap->unref(); | 211 return; |
188 // This eliminates a similar circular reference (Canvas owns | |
189 // the FlattenableHeap which holds a ref to the SkBitmapHeap
). | |
190 fFlattenableHeap.setBitmapStorage(NULL); | |
191 fBitmapHeap = NULL; | |
192 } | |
193 } | |
194 fDone = true; | |
195 } | 212 } |
| 213 if (notifyReaders && this->needOpBytes()) { |
| 214 this->writeOp(kDone_DrawOp); |
| 215 this->doNotify(); |
| 216 } |
| 217 if (shouldFlattenBitmaps(fFlags)) { |
| 218 // The following circular references exist: |
| 219 // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalSt
orage -> fCanvas |
| 220 // fBitmapHeap -> fExternalStorage -> fCanvas |
| 221 // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas |
| 222 |
| 223 // Break them all by destroying the final link to this SkGPipeCanvas
. |
| 224 fBitmapShuttle->removeCanvas(); |
| 225 } |
| 226 fDone = true; |
196 } | 227 } |
197 | 228 |
198 void flushRecording(bool detachCurrentBlock); | 229 void flushRecording(bool detachCurrentBlock); |
199 size_t freeMemoryIfPossible(size_t bytesToFree); | 230 size_t freeMemoryIfPossible(size_t bytesToFree); |
200 | 231 |
201 size_t storageAllocatedForRecording() { | 232 size_t storageAllocatedForRecording() { |
202 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated(); | 233 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated(); |
203 } | 234 } |
204 | 235 |
205 // overrides from SkCanvas | 236 // overrides from SkCanvas |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 fController->notifyWritten(bytes); | 330 fController->notifyWritten(bytes); |
300 fBytesNotified += bytes; | 331 fBytesNotified += bytes; |
301 } | 332 } |
302 } | 333 } |
303 } | 334 } |
304 | 335 |
305 // Should be called after any calls to an SkFlatDictionary::findAndReplace | 336 // Should be called after any calls to an SkFlatDictionary::findAndReplace |
306 // if a new SkFlatData was added when in cross process mode | 337 // if a new SkFlatData was added when in cross process mode |
307 void flattenFactoryNames(); | 338 void flattenFactoryNames(); |
308 | 339 |
309 FlattenableHeap fFlattenableHeap; | 340 FlattenableHeap fFlattenableHeap; |
310 FlatDictionary fFlatDictionary; | 341 FlatDictionary fFlatDictionary; |
311 int fCurrFlatIndex[kCount_PaintFlats]; | 342 SkAutoTUnref<BitmapShuttle> fBitmapShuttle; |
| 343 int fCurrFlatIndex[kCount_PaintFlats]; |
| 344 |
312 int flattenToIndex(SkFlattenable* obj, PaintFlats); | 345 int flattenToIndex(SkFlattenable* obj, PaintFlats); |
313 | 346 |
314 // Common code used by drawBitmap*. Behaves differently depending on the | 347 // Common code used by drawBitmap*. Behaves differently depending on the |
315 // type of SkBitmapHeap being used, which is determined by the flags used. | 348 // type of SkBitmapHeap being used, which is determined by the flags used. |
316 bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, | 349 bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, |
317 size_t opBytesNeeded, const SkPaint* paint); | 350 size_t opBytesNeeded, const SkPaint* paint); |
318 | 351 |
319 SkPaint fPaint; | 352 SkPaint fPaint; |
320 void writePaint(const SkPaint&); | 353 void writePaint(const SkPaint&); |
321 | 354 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 } | 416 } |
384 } | 417 } |
385 if (replaced) { | 418 if (replaced) { |
386 index = ~index; | 419 index = ~index; |
387 } | 420 } |
388 return index; | 421 return index; |
389 } | 422 } |
390 | 423 |
391 /////////////////////////////////////////////////////////////////////////////// | 424 /////////////////////////////////////////////////////////////////////////////// |
392 | 425 |
393 /** | |
394 * If SkBitmaps are to be flattened to send to the reader, this class is | |
395 * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so. | |
396 */ | |
397 class BitmapShuttle : public SkBitmapHeap::ExternalStorage { | |
398 public: | |
399 BitmapShuttle(SkGPipeCanvas*); | |
400 | |
401 ~BitmapShuttle(); | |
402 | |
403 virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE; | |
404 | |
405 private: | |
406 SkGPipeCanvas* fCanvas; | |
407 }; | |
408 | |
409 /////////////////////////////////////////////////////////////////////////////// | |
410 | |
411 #define MIN_BLOCK_SIZE (16 * 1024) | 426 #define MIN_BLOCK_SIZE (16 * 1024) |
412 #define BITMAPS_TO_KEEP 5 | 427 #define BITMAPS_TO_KEEP 5 |
413 #define FLATTENABLES_TO_KEEP 10 | 428 #define FLATTENABLES_TO_KEEP 10 |
414 | 429 |
415 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, | 430 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, |
416 SkWriter32* writer, uint32_t flags, | 431 SkWriter32* writer, uint32_t flags, |
417 uint32_t width, uint32_t height) | 432 uint32_t width, uint32_t height) |
418 : fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) | 433 : fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) |
419 , fWriter(*writer) | 434 , fWriter(*writer) |
420 , fFlags(flags) | 435 , fFlags(flags) |
(...skipping 12 matching lines...) Expand all Loading... |
433 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); | 448 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); |
434 SkBaseDevice* device = SkNEW_ARGS(SkBitmapDevice, (bitmap)); | 449 SkBaseDevice* device = SkNEW_ARGS(SkBitmapDevice, (bitmap)); |
435 this->setDevice(device)->unref(); | 450 this->setDevice(device)->unref(); |
436 | 451 |
437 // Tell the reader the appropriate flags to use. | 452 // Tell the reader the appropriate flags to use. |
438 if (this->needOpBytes()) { | 453 if (this->needOpBytes()) { |
439 this->writeOp(kReportFlags_DrawOp, fFlags, 0); | 454 this->writeOp(kReportFlags_DrawOp, fFlags, 0); |
440 } | 455 } |
441 | 456 |
442 if (shouldFlattenBitmaps(flags)) { | 457 if (shouldFlattenBitmaps(flags)) { |
443 BitmapShuttle* shuttle = SkNEW_ARGS(BitmapShuttle, (this)); | 458 fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this))); |
444 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (shuttle, BITMAPS_TO_KEEP)); | 459 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO
_KEEP)); |
445 shuttle->unref(); | |
446 } else { | 460 } else { |
447 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, | 461 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, |
448 (BITMAPS_TO_KEEP, controller->numberOfReaders()
)); | 462 (BITMAPS_TO_KEEP, controller->numberOfReaders()
)); |
449 if (this->needOpBytes(sizeof(void*))) { | 463 if (this->needOpBytes(sizeof(void*))) { |
450 this->writeOp(kShareBitmapHeap_DrawOp); | 464 this->writeOp(kShareBitmapHeap_DrawOp); |
451 fWriter.writePtr(static_cast<void*>(fBitmapHeap)); | 465 fWriter.writePtr(static_cast<void*>(fBitmapHeap)); |
452 } | 466 } |
453 } | 467 } |
454 fFlattenableHeap.setBitmapStorage(fBitmapHeap); | 468 fFlattenableHeap.setBitmapStorage(fBitmapHeap); |
455 this->doNotify(); | 469 this->doNotify(); |
456 } | 470 } |
457 | 471 |
458 SkGPipeCanvas::~SkGPipeCanvas() { | 472 SkGPipeCanvas::~SkGPipeCanvas() { |
459 this->finish(); | 473 this->finish(true); |
460 SkSafeUnref(fFactorySet); | 474 SkSafeUnref(fFactorySet); |
461 SkSafeUnref(fBitmapHeap); | 475 SkSafeUnref(fBitmapHeap); |
462 } | 476 } |
463 | 477 |
464 bool SkGPipeCanvas::needOpBytes(size_t needed) { | 478 bool SkGPipeCanvas::needOpBytes(size_t needed) { |
465 if (fDone) { | 479 if (fDone) { |
466 return false; | 480 return false; |
467 } | 481 } |
468 | 482 |
469 needed += 4; // size of DrawOp atom | 483 needed += 4; // size of DrawOp atom |
470 if (fWriter.bytesWritten() + needed > fBlockSize) { | 484 if (fWriter.bytesWritten() + needed > fBlockSize) { |
471 // Before we wipe out any data that has already been written, read it | 485 // Before we wipe out any data that has already been written, read it |
472 // out. | 486 // out. |
473 this->doNotify(); | 487 this->doNotify(); |
474 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed); | 488 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed); |
475 void* block = fController->requestBlock(blockSize, &fBlockSize); | 489 void* block = fController->requestBlock(blockSize, &fBlockSize); |
476 if (NULL == block) { | 490 if (NULL == block) { |
477 fDone = true; | 491 // Do not notify the readers, which would call this function again. |
| 492 this->finish(false); |
478 return false; | 493 return false; |
479 } | 494 } |
480 SkASSERT(SkIsAlign4(fBlockSize)); | 495 SkASSERT(SkIsAlign4(fBlockSize)); |
481 fWriter.reset(block, fBlockSize); | 496 fWriter.reset(block, fBlockSize); |
482 fBytesNotified = 0; | 497 fBytesNotified = 0; |
483 } | 498 } |
484 return true; | 499 return true; |
485 } | 500 } |
486 | 501 |
487 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { | 502 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1172 if (NULL == fCanvas) { | 1187 if (NULL == fCanvas) { |
1173 fWriter.reset(NULL, 0); | 1188 fWriter.reset(NULL, 0); |
1174 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width,
height)); | 1189 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width,
height)); |
1175 } | 1190 } |
1176 controller->setCanvas(fCanvas); | 1191 controller->setCanvas(fCanvas); |
1177 return fCanvas; | 1192 return fCanvas; |
1178 } | 1193 } |
1179 | 1194 |
1180 void SkGPipeWriter::endRecording() { | 1195 void SkGPipeWriter::endRecording() { |
1181 if (fCanvas) { | 1196 if (fCanvas) { |
1182 fCanvas->finish(); | 1197 fCanvas->finish(true); |
1183 fCanvas->unref(); | 1198 fCanvas->unref(); |
1184 fCanvas = NULL; | 1199 fCanvas = NULL; |
1185 } | 1200 } |
1186 } | 1201 } |
1187 | 1202 |
1188 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) { | 1203 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) { |
1189 if (fCanvas) { | 1204 if (fCanvas) { |
1190 fCanvas->flushRecording(detachCurrentBlock); | 1205 fCanvas->flushRecording(detachCurrentBlock); |
1191 } | 1206 } |
1192 } | 1207 } |
(...skipping 11 matching lines...) Expand all Loading... |
1204 | 1219 |
1205 /////////////////////////////////////////////////////////////////////////////// | 1220 /////////////////////////////////////////////////////////////////////////////// |
1206 | 1221 |
1207 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { | 1222 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { |
1208 SkASSERT(canvas != NULL); | 1223 SkASSERT(canvas != NULL); |
1209 fCanvas = canvas; | 1224 fCanvas = canvas; |
1210 fCanvas->ref(); | 1225 fCanvas->ref(); |
1211 } | 1226 } |
1212 | 1227 |
1213 BitmapShuttle::~BitmapShuttle() { | 1228 BitmapShuttle::~BitmapShuttle() { |
1214 fCanvas->unref(); | 1229 this->removeCanvas(); |
1215 } | 1230 } |
1216 | 1231 |
1217 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { | 1232 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { |
| 1233 SkASSERT(fCanvas != NULL); |
1218 return fCanvas->shuttleBitmap(bitmap, slot); | 1234 return fCanvas->shuttleBitmap(bitmap, slot); |
1219 } | 1235 } |
| 1236 |
| 1237 void BitmapShuttle::removeCanvas() { |
| 1238 if (NULL == fCanvas) { |
| 1239 return; |
| 1240 } |
| 1241 fCanvas->unref(); |
| 1242 fCanvas = NULL; |
| 1243 } |
OLD | NEW |