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