PictureRenderer.cpp revision bffacc01d62416a18aef79ddc42606ed626eca31
1#include "PictureRenderer.h"
2#include "SamplePipeControllers.h"
3#include "SkCanvas.h"
4#include "SkDevice.h"
5#include "SkGPipe.h"
6#include "SkPicture.h"
7#include "SkTDArray.h"
8#include "SkTypes.h"
9#include "picture_utils.h"
10
11#if SK_SUPPORT_GPU
12#include "SkGpuDevice.h"
13#endif
14
15namespace sk_tools {
16
17enum {
18    kDefaultTileWidth = 256,
19    kDefaultTileHeight = 256
20};
21
22void PictureRenderer::init(SkPicture* pict) {
23    SkASSERT(NULL == fPicture);
24    SkASSERT(NULL == fCanvas.get());
25    if (fPicture != NULL || NULL != fCanvas.get()) {
26        return;
27    }
28
29    SkASSERT(pict != NULL);
30    if (NULL == pict) {
31        return;
32    }
33
34    fPicture = pict;
35    fCanvas.reset(this->setupCanvas());
36}
37
38SkCanvas* PictureRenderer::setupCanvas() {
39    return this->setupCanvas(fPicture->width(), fPicture->height());
40}
41
42SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
43    switch(fDeviceType) {
44        case kBitmap_DeviceType: {
45            SkBitmap bitmap;
46            sk_tools::setup_bitmap(&bitmap, width, height);
47            return SkNEW_ARGS(SkCanvas, (bitmap));
48            break;
49        }
50#if SK_SUPPORT_GPU
51        case kGPU_DeviceType: {
52            SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
53                                                    (fGrContext, SkBitmap::kARGB_8888_Config,
54                                                    width, height)));
55            return SkNEW_ARGS(SkCanvas, (device.get()));
56            break;
57        }
58#endif
59        default:
60            SkASSERT(0);
61    }
62
63    return NULL;
64}
65
66void PictureRenderer::end() {
67    this->resetState();
68    fPicture = NULL;
69    fCanvas.reset(NULL);
70}
71
72void PictureRenderer::resetState() {
73    SkASSERT(fCanvas.get() != NULL);
74    SkASSERT(fPicture != NULL);
75    if (NULL == fCanvas.get() || NULL == fPicture) {
76        return;
77    }
78
79    fCanvas->flush();
80
81    if (this->isUsingGpuDevice()) {
82        SkGLContext* glContext = fGrContextFactory.getGLContext(
83            GrContextFactory::kNative_GLContextType);
84        SK_GL(*glContext, Finish());
85        fGrContext->freeGpuResources();
86    }
87}
88
89void PipePictureRenderer::render() {
90    SkASSERT(fCanvas.get() != NULL);
91    SkASSERT(fPicture != NULL);
92    if (NULL == fCanvas.get() || NULL == fPicture) {
93        return;
94    }
95
96    PipeController pipeController(fCanvas.get());
97    SkGPipeWriter writer;
98    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
99    pipeCanvas->drawPicture(*fPicture);
100    writer.endRecording();
101}
102
103void SimplePictureRenderer::render() {
104    SkASSERT(fCanvas.get() != NULL);
105    SkASSERT(fPicture != NULL);
106    if (NULL == fCanvas.get() || NULL == fPicture) {
107        return;
108    }
109
110    fCanvas->drawPicture(*fPicture);
111}
112
113TiledPictureRenderer::TiledPictureRenderer()
114    : fTileWidth(kDefaultTileWidth)
115    , fTileHeight(kDefaultTileHeight) {}
116
117void TiledPictureRenderer::init(SkPicture* pict) {
118    SkASSERT(pict != NULL);
119    SkASSERT(0 == fTiles.count());
120    if (NULL == pict || fTiles.count() != 0) {
121        return;
122    }
123
124    this->INHERITED::init(pict);
125
126    if (fTileWidthPercentage > 0) {
127        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
128    }
129    if (fTileHeightPercentage > 0) {
130        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
131    }
132
133    this->setupTiles();
134}
135
136void TiledPictureRenderer::render() {
137    SkASSERT(fCanvas.get() != NULL);
138    SkASSERT(fPicture != NULL);
139    if (NULL == fCanvas.get() || NULL == fPicture) {
140        return;
141    }
142
143    this->drawTiles();
144    this->copyTilesToCanvas();
145}
146
147void TiledPictureRenderer::end() {
148    this->deleteTiles();
149    this->INHERITED::end();
150}
151
152TiledPictureRenderer::~TiledPictureRenderer() {
153    this->deleteTiles();
154}
155
156void TiledPictureRenderer::clipTile(const TileInfo& tile) {
157    SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
158                                 SkIntToScalar(fPicture->height()));
159    tile.fCanvas->clipRect(clip);
160}
161
162void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
163    TileInfo* tile = fTiles.push();
164
165    tile->fCanvas = this->setupCanvas(fTileWidth, fTileHeight);
166    tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
167    this->clipTile(*tile);
168}
169
170void TiledPictureRenderer::setupTiles() {
171    for (int tile_y_start = 0; tile_y_start < fPicture->height();
172         tile_y_start += fTileHeight) {
173        for (int tile_x_start = 0; tile_x_start < fPicture->width();
174             tile_x_start += fTileWidth) {
175            this->addTile(tile_x_start, tile_y_start);
176        }
177    }
178}
179
180void TiledPictureRenderer::deleteTiles() {
181    for (int i = 0; i < fTiles.count(); ++i) {
182        SkDELETE(fTiles[i].fCanvas);
183    }
184
185    fTiles.reset();
186}
187
188void TiledPictureRenderer::drawTiles() {
189    for (int i = 0; i < fTiles.count(); ++i) {
190        fTiles[i].fCanvas->drawPicture(*(fPicture));
191    }
192}
193
194void TiledPictureRenderer::resetState() {
195    SkASSERT(fCanvas.get() != NULL);
196    SkASSERT(fPicture != NULL);
197    if (NULL == fCanvas.get() || NULL == fPicture) {
198        return;
199    }
200
201    for (int i = 0; i < fTiles.count(); ++i) {
202        fTiles[i].fCanvas->flush();
203    }
204
205    this->INHERITED::resetState();
206}
207
208void TiledPictureRenderer::copyTilesToCanvas() {
209    int tile_index = 0;
210    for (int tile_y_start = 0; tile_y_start < fPicture->height();
211         tile_y_start += fTileHeight) {
212        for (int tile_x_start = 0; tile_x_start < fPicture->width();
213             tile_x_start += fTileWidth) {
214            SkASSERT(tile_index < fTiles.count());
215            SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false);
216            fCanvas->drawBitmap(source,
217                                SkIntToScalar(tile_x_start),
218                                SkIntToScalar(tile_y_start));
219            ++tile_index;
220        }
221    }
222}
223
224}
225