PictureRenderer.cpp revision a40c20df0e4c5d04acb0841d70127778c0a779ec
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 SK_SUPPORT_GPU
82    if (this->isUsingGpuDevice()) {
83        SkGLContext* glContext = fGrContextFactory.getGLContext(
84            GrContextFactory::kNative_GLContextType);
85        SK_GL(*glContext, Finish());
86        fGrContext->freeGpuResources();
87    }
88#endif
89}
90
91void PipePictureRenderer::render() {
92    SkASSERT(fCanvas.get() != NULL);
93    SkASSERT(fPicture != NULL);
94    if (NULL == fCanvas.get() || NULL == fPicture) {
95        return;
96    }
97
98    PipeController pipeController(fCanvas.get());
99    SkGPipeWriter writer;
100    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
101    pipeCanvas->drawPicture(*fPicture);
102    writer.endRecording();
103}
104
105void SimplePictureRenderer::render() {
106    SkASSERT(fCanvas.get() != NULL);
107    SkASSERT(fPicture != NULL);
108    if (NULL == fCanvas.get() || NULL == fPicture) {
109        return;
110    }
111
112    fCanvas->drawPicture(*fPicture);
113}
114
115TiledPictureRenderer::TiledPictureRenderer()
116    : fTileWidth(kDefaultTileWidth)
117    , fTileHeight(kDefaultTileHeight) {}
118
119void TiledPictureRenderer::init(SkPicture* pict) {
120    SkASSERT(pict != NULL);
121    SkASSERT(0 == fTiles.count());
122    if (NULL == pict || fTiles.count() != 0) {
123        return;
124    }
125
126    this->INHERITED::init(pict);
127
128    if (fTileWidthPercentage > 0) {
129        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
130    }
131    if (fTileHeightPercentage > 0) {
132        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
133    }
134
135    this->setupTiles();
136}
137
138void TiledPictureRenderer::render() {
139    SkASSERT(fCanvas.get() != NULL);
140    SkASSERT(fPicture != NULL);
141    if (NULL == fCanvas.get() || NULL == fPicture) {
142        return;
143    }
144
145    this->drawTiles();
146    this->copyTilesToCanvas();
147}
148
149void TiledPictureRenderer::end() {
150    this->deleteTiles();
151    this->INHERITED::end();
152}
153
154TiledPictureRenderer::~TiledPictureRenderer() {
155    this->deleteTiles();
156}
157
158void TiledPictureRenderer::clipTile(const TileInfo& tile) {
159    SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
160                                 SkIntToScalar(fPicture->height()));
161    tile.fCanvas->clipRect(clip);
162}
163
164void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
165    TileInfo* tile = fTiles.push();
166
167    tile->fCanvas = this->setupCanvas(fTileWidth, fTileHeight);
168    tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
169    this->clipTile(*tile);
170}
171
172void TiledPictureRenderer::setupTiles() {
173    for (int tile_y_start = 0; tile_y_start < fPicture->height();
174         tile_y_start += fTileHeight) {
175        for (int tile_x_start = 0; tile_x_start < fPicture->width();
176             tile_x_start += fTileWidth) {
177            this->addTile(tile_x_start, tile_y_start);
178        }
179    }
180}
181
182void TiledPictureRenderer::deleteTiles() {
183    for (int i = 0; i < fTiles.count(); ++i) {
184        SkDELETE(fTiles[i].fCanvas);
185    }
186
187    fTiles.reset();
188}
189
190void TiledPictureRenderer::drawTiles() {
191    for (int i = 0; i < fTiles.count(); ++i) {
192        fTiles[i].fCanvas->drawPicture(*(fPicture));
193    }
194}
195
196void TiledPictureRenderer::resetState() {
197    SkASSERT(fCanvas.get() != NULL);
198    SkASSERT(fPicture != NULL);
199    if (NULL == fCanvas.get() || NULL == fPicture) {
200        return;
201    }
202
203    for (int i = 0; i < fTiles.count(); ++i) {
204        fTiles[i].fCanvas->flush();
205    }
206
207    this->INHERITED::resetState();
208}
209
210void TiledPictureRenderer::copyTilesToCanvas() {
211    int tile_index = 0;
212    for (int tile_y_start = 0; tile_y_start < fPicture->height();
213         tile_y_start += fTileHeight) {
214        for (int tile_x_start = 0; tile_x_start < fPicture->width();
215             tile_x_start += fTileWidth) {
216            SkASSERT(tile_index < fTiles.count());
217            SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false);
218            fCanvas->drawBitmap(source,
219                                SkIntToScalar(tile_x_start),
220                                SkIntToScalar(tile_y_start));
221            ++tile_index;
222        }
223    }
224}
225
226}
227