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
PipeController(SkCanvas * target,SkPicture::InstallPixelRefProc proc)15 PipeController::PipeController(SkCanvas* target, SkPicture::InstallPixelRefProc proc)
16 :fReader(target) {
17 fBlock = NULL;
18 fBlockSize = fBytesWritten = 0;
19 fReader.setBitmapDecoder(proc);
20 }
21
~PipeController()22 PipeController::~PipeController() {
23 sk_free(fBlock);
24 }
25
requestBlock(size_t minRequest,size_t * actual)26 void* PipeController::requestBlock(size_t minRequest, size_t *actual) {
27 sk_free(fBlock);
28 fBlockSize = minRequest;
29 fBlock = sk_malloc_throw(fBlockSize);
30 fBytesWritten = 0;
31 *actual = fBlockSize;
32 return fBlock;
33 }
34
notifyWritten(size_t bytes)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
TiledPipeController(const SkBitmap & bitmap,SkPicture::InstallPixelRefProc proc,const SkMatrix * initial)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
notifyWritten(size_t bytes)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
ThreadSafePipeController(int numberOfReaders)85 ThreadSafePipeController::ThreadSafePipeController(int numberOfReaders)
86 : fAllocator(kMinBlockSize)
87 , fNumberOfReaders(numberOfReaders) {
88 fBlock = NULL;
89 fBytesWritten = 0;
90 }
91
requestBlock(size_t minRequest,size_t * actual)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
notifyWritten(size_t bytes)105 void ThreadSafePipeController::notifyWritten(size_t bytes) {
106 fBytesWritten += bytes;
107 }
108
draw(SkCanvas * target)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