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