BitmapHolder::BitmapHolder(SkReader32* reader, uint32_t op32, SkGPipeState* state) { const unsigned flags = state->getFlags(); const unsigned index = DrawOp_unpackData(op32); if (shouldFlattenBitmaps(flags)) { fHeapEntry = NULL; fBitmap = state->getBitmap(index); } else { SkBitmapHeapEntry* entry = state->getSharedHeap()->getEntry(index); if (SkToBool(flags & SkGPipeWriter::kSimultaneousReaders_Flag)) { // Make a shallow copy for thread safety. Each thread will point to the same SkPixelRef, // which is thread safe. fBitmapStorage = *entry->getBitmap(); fBitmap = &fBitmapStorage; // Release the ref on the bitmap now, since we made our own copy. entry->releaseRef(); fHeapEntry = NULL; } else { SkASSERT(!shouldFlattenBitmaps(flags)); SkASSERT(!SkToBool(flags & SkGPipeWriter::kSimultaneousReaders_Flag)); fHeapEntry = entry; fBitmap = fHeapEntry->getBitmap(); } } }
SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, SkWriter32* writer, uint32_t flags, uint32_t width, uint32_t height) : SkCanvas(width, height) , fFactorySet(is_cross_process(flags) ? SkNEW(SkNamedFactorySet) : NULL) , fWriter(*writer) , fFlags(flags) , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, is_cross_process(flags)) , fFlatDictionary(&fFlattenableHeap) { fController = controller; fDone = false; fBlockSize = 0; // need first block from controller fBytesNotified = 0; sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); // Tell the reader the appropriate flags to use. if (this->needOpBytes()) { this->writeOp(kReportFlags_DrawOp, fFlags, 0); } if (shouldFlattenBitmaps(flags)) { fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this))); fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO_KEEP)); } else { fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (BITMAPS_TO_KEEP, controller->numberOfReaders())); if (this->needOpBytes(sizeof(void*))) { this->writeOp(kShareBitmapHeap_DrawOp); fWriter.writePtr(static_cast<void*>(fBitmapHeap)); } } fFlattenableHeap.setBitmapStorage(fBitmapHeap); this->doNotify(); }
/** * Add a bitmap to the array of bitmaps, or replace an existing one. * This is only used when in cross process mode without a shared heap. */ void addBitmap(int index) { SkASSERT(shouldFlattenBitmaps(fFlags)); SkBitmap* bm; if(fBitmaps.count() == index) { bm = SkNEW(SkBitmap); *fBitmaps.append() = bm; } else { bm = fBitmaps[index]; } fReader->readBitmap(bm); }
bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) { SkASSERT(shouldFlattenBitmaps(fFlags)); SkWriteBuffer buffer; buffer.setNamedFactoryRecorder(fFactorySet); buffer.writeBitmap(bm); this->flattenFactoryNames(); size_t size = buffer.bytesWritten(); if (this->needOpBytes(size)) { this->writeOp(kDef_Bitmap_DrawOp, 0, slot); void* dst = static_cast<void*>(fWriter.reserve(size)); buffer.writeToMemory(dst); return true; } return false; }
/** * Called when nothing else is to be written to the stream. Any repeated * calls are ignored. * * @param notifyReaders Whether to send a message to the reader(s) that * the writer is through sending commands. Should generally be true, * unless there is an error which prevents further messages from * being sent. */ void finish(bool notifyReaders) { if (fDone) { return; } if (notifyReaders && this->needOpBytes()) { this->writeOp(kDone_DrawOp); this->doNotify(); } if (shouldFlattenBitmaps(fFlags)) { // The following circular references exist: // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalStorage -> fCanvas // fBitmapHeap -> fExternalStorage -> fCanvas // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas // Break them all by destroying the final link to this SkGPipeCanvas. fBitmapShuttle->removeCanvas(); } fDone = true; }
void updateReader() { if (NULL == fReader) { return; } bool crossProcess = SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag); fReader->setFlags(SkSetClearMask(fReader->getFlags(), crossProcess, SkReadBuffer::kCrossProcess_Flag)); if (crossProcess) { fReader->setFactoryArray(&fFactoryArray); } else { fReader->setFactoryArray(NULL); } if (shouldFlattenBitmaps(fFlags)) { fReader->setBitmapStorage(this); } else { fReader->setBitmapStorage(fSharedHeap); } }
/** * Access the shared heap. Only used in the case when bitmaps are not * flattened. */ SkBitmapHeap* getSharedHeap() const { SkASSERT(!shouldFlattenBitmaps(fFlags)); return fSharedHeap; }
void setSharedHeap(SkBitmapHeap* heap) { SkASSERT(!shouldFlattenBitmaps(fFlags) || NULL == heap); SkRefCnt_SafeAssign(fSharedHeap, heap); this->updateReader(); }
/** * Override of SkBitmapHeapReader, so that SkReadBuffer can use * these SkBitmaps for bitmap shaders. Used only in cross process mode * without a shared heap. */ SkBitmap* getBitmap(int32_t index) const override { SkASSERT(shouldFlattenBitmaps(fFlags)); return fBitmaps[index]; }