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 "SkBitmapDevice.h" 11 #include "SkCanvas.h" 12 #include "SkGPipe.h" 13 #include "SkMatrix.h" 14 15 PipeController::PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc) 16 :fReader(target) { 17 fBlock = NULL; 18 fBlockSize = fBytesWritten = 0; 19 fReader.setBitmapDecoder(proc); 20 } 21 22 PipeController::~PipeController() { 23 sk_free(fBlock); 24 } 25 26 void* 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 35 void 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 43 TiledPipeController::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 SkBaseDevice* device = new SkBitmapDevice(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 76 void 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 85 ThreadSafePipeController::ThreadSafePipeController(int numberOfReaders) 86 : fAllocator(kMinBlockSize) 87 , fNumberOfReaders(numberOfReaders) { 88 fBlock = NULL; 89 fBytesWritten = 0; 90 } 91 92 void* 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 105 void ThreadSafePipeController::notifyWritten(size_t bytes) { 106 fBytesWritten += bytes; 107 } 108 109 void 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