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
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;
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        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
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