| /* | |
| * Copyright 2012 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SamplePipeControllers.h" | |
| #include "SkCanvas.h" | |
| #include "SkGPipe.h" | |
| #include "SkMatrix.h" | |
| PipeController::PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc) | |
| :fReader(target) { | |
| fBlock = nullptr; | |
| fBlockSize = fBytesWritten = 0; | |
| fReader.setBitmapDecoder(proc); | |
| } | |
| PipeController::~PipeController() { | |
| sk_free(fBlock); | |
| } | |
| void* PipeController::requestBlock(size_t minRequest, size_t *actual) { | |
| sk_free(fBlock); | |
| fBlockSize = minRequest; | |
| fBlock = sk_malloc_throw(fBlockSize); | |
| fBytesWritten = 0; | |
| *actual = fBlockSize; | |
| return fBlock; | |
| } | |
| void PipeController::notifyWritten(size_t bytes) { | |
| fStatus = fReader.playback(this->getData(), bytes); | |
| SkASSERT(SkGPipeReader::kError_Status != fStatus); | |
| fBytesWritten += bytes; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| TiledPipeController::TiledPipeController(const SkBitmap& bitmap, | |
| SkPicture::InstallPixelRefProc proc, | |
| const SkMatrix* initial) | |
| : INHERITED(nullptr, proc) { | |
| int32_t top = 0; | |
| int32_t bottom; | |
| int32_t height = bitmap.height() / NumberOfTiles; | |
| SkIRect rect; | |
| for (int i = 0; i < NumberOfTiles; i++) { | |
| bottom = i + 1 == NumberOfTiles ? bitmap.height() : top + height; | |
| rect.setLTRB(0, top, bitmap.width(), bottom); | |
| top = bottom; | |
| SkDEBUGCODE(bool extracted = )bitmap.extractSubset(&fBitmaps[i], rect); | |
| SkASSERT(extracted); | |
| SkCanvas* canvas = new SkCanvas(fBitmaps[i]); | |
| if (initial != nullptr) { | |
| canvas->setMatrix(*initial); | |
| } | |
| canvas->translate(SkIntToScalar(-rect.left()), | |
| SkIntToScalar(-rect.top())); | |
| if (0 == i) { | |
| fReader.setCanvas(canvas); | |
| } else { | |
| fReaders[i - 1].setCanvas(canvas); | |
| fReaders[i - 1].setBitmapDecoder(proc); | |
| } | |
| canvas->unref(); | |
| } | |
| } | |
| void TiledPipeController::notifyWritten(size_t bytes) { | |
| for (int i = 0; i < NumberOfTiles - 1; i++) { | |
| fReaders[i].playback(this->getData(), bytes); | |
| } | |
| this->INHERITED::notifyWritten(bytes); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| ThreadSafePipeController::ThreadSafePipeController(int numberOfReaders) | |
| : fAllocator(kMinBlockSize) | |
| , fNumberOfReaders(numberOfReaders) { | |
| fBlock = nullptr; | |
| fBytesWritten = 0; | |
| } | |
| void* ThreadSafePipeController::requestBlock(size_t minRequest, size_t *actual) { | |
| if (fBlock) { | |
| // Save the previous block for later | |
| PipeBlock previousBloc(fBlock, fBytesWritten); | |
| fBlockList.push(previousBloc); | |
| } | |
| int32_t blockSize = SkMax32(SkToS32(minRequest), kMinBlockSize); | |
| fBlock = fAllocator.allocThrow(blockSize); | |
| fBytesWritten = 0; | |
| *actual = blockSize; | |
| return fBlock; | |
| } | |
| void ThreadSafePipeController::notifyWritten(size_t bytes) { | |
| fBytesWritten += bytes; | |
| } | |
| void ThreadSafePipeController::draw(SkCanvas* target) { | |
| SkGPipeReader reader(target); | |
| for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) { | |
| reader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fBytes); | |
| } | |
| if (fBlock) { | |
| reader.playback(fBlock, fBytesWritten); | |
| } | |
| } |