1/* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SamplePipeControllers.h" 9 10#include "SkCanvas.h" 11#include "SkDevice.h" 12#include "SkGPipe.h" 13#include "SkMatrix.h" 14 15PipeController::PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc) 16:fReader(target) { 17 fBlock = NULL; 18 fBlockSize = fBytesWritten = 0; 19 fReader.setBitmapDecoder(proc); 20} 21 22PipeController::~PipeController() { 23 sk_free(fBlock); 24} 25 26void* PipeController::requestBlock(size_t minRequest, size_t *actual) { 27 sk_free(fBlock); 28 fBlockSize = minRequest * 4; 29 fBlock = sk_malloc_throw(fBlockSize); 30 fBytesWritten = 0; 31 *actual = fBlockSize; 32 return fBlock; 33} 34 35void PipeController::notifyWritten(size_t bytes) { 36 fStatus = fReader.playback(this->getData(), bytes); 37 SkASSERT(SkGPipeReader::kError_Status != fStatus); 38 fBytesWritten += bytes; 39} 40 41//////////////////////////////////////////////////////////////////////////////// 42 43TiledPipeController::TiledPipeController(const SkBitmap& bitmap, 44 SkPicture::InstallPixelRefProc proc, 45 const SkMatrix* initial) 46: INHERITED(NULL, proc) { 47 int32_t top = 0; 48 int32_t bottom; 49 int32_t height = bitmap.height() / NumberOfTiles; 50 SkIRect rect; 51 for (int i = 0; i < NumberOfTiles; i++) { 52 bottom = i + 1 == NumberOfTiles ? bitmap.height() : top + height; 53 rect.setLTRB(0, top, bitmap.width(), bottom); 54 top = bottom; 55 56 SkDEBUGCODE(bool extracted = )bitmap.extractSubset(&fBitmaps[i], rect); 57 SkASSERT(extracted); 58 SkDevice* device = new SkDevice(fBitmaps[i]); 59 SkCanvas* canvas = new SkCanvas(device); 60 device->unref(); 61 if (initial != NULL) { 62 canvas->setMatrix(*initial); 63 } 64 canvas->translate(SkIntToScalar(-rect.left()), 65 SkIntToScalar(-rect.top())); 66 if (0 == i) { 67 fReader.setCanvas(canvas); 68 } else { 69 fReaders[i - 1].setCanvas(canvas); 70 fReaders[i - 1].setBitmapDecoder(proc); 71 } 72 canvas->unref(); 73 } 74} 75 76void TiledPipeController::notifyWritten(size_t bytes) { 77 for (int i = 0; i < NumberOfTiles - 1; i++) { 78 fReaders[i].playback(this->getData(), bytes); 79 } 80 this->INHERITED::notifyWritten(bytes); 81} 82 83//////////////////////////////////////////////////////////////////////////////// 84 85ThreadSafePipeController::ThreadSafePipeController(int numberOfReaders) 86: fAllocator(kMinBlockSize) 87, fNumberOfReaders(numberOfReaders) { 88 fBlock = NULL; 89 fBytesWritten = 0; 90} 91 92void* ThreadSafePipeController::requestBlock(size_t minRequest, size_t *actual) { 93 if (fBlock) { 94 // Save the previous block for later 95 PipeBlock previousBloc(fBlock, fBytesWritten); 96 fBlockList.push(previousBloc); 97 } 98 int32_t blockSize = SkMax32(SkToS32(minRequest), kMinBlockSize); 99 fBlock = fAllocator.allocThrow(blockSize); 100 fBytesWritten = 0; 101 *actual = blockSize; 102 return fBlock; 103} 104 105void ThreadSafePipeController::notifyWritten(size_t bytes) { 106 fBytesWritten += bytes; 107} 108 109void ThreadSafePipeController::draw(SkCanvas* target) { 110 SkGPipeReader reader(target); 111 for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) { 112 reader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fBytes); 113 } 114 115 if (fBlock) { 116 reader.playback(fBlock, fBytesWritten); 117 } 118} 119