blob: ab7f7b9fc950f868c44877befd89719a6dda43cf [file] [log] [blame]
keyar@chromium.orgb3fb7c12012-08-20 21:02:49 +00001/*
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
keyar@chromium.org451bb9f2012-07-26 17:27:57 +00008#include "PictureRenderer.h"
9#include "SamplePipeControllers.h"
10#include "SkCanvas.h"
11#include "SkDevice.h"
keyar@chromium.org9299ede2012-08-21 19:05:08 +000012#include "SkImageEncoder.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000013#include "SkGPipe.h"
keyar@chromium.orgea826952012-08-23 15:24:13 +000014#include "SkMatrix.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000015#include "SkPicture.h"
keyar@chromium.orgea826952012-08-23 15:24:13 +000016#include "SkScalar.h"
keyar@chromium.org9299ede2012-08-21 19:05:08 +000017#include "SkString.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000018#include "SkTDArray.h"
19#include "SkTypes.h"
20#include "picture_utils.h"
21
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000022#if SK_SUPPORT_GPU
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000023#include "SkGpuDevice.h"
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000024#endif
25
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000026namespace sk_tools {
27
28enum {
29 kDefaultTileWidth = 256,
30 kDefaultTileHeight = 256
31};
32
keyar@chromium.org9d696c02012-08-07 17:11:33 +000033void PictureRenderer::init(SkPicture* pict) {
keyar@chromium.org78a35c52012-08-20 15:03:44 +000034 SkASSERT(NULL == fPicture);
35 SkASSERT(NULL == fCanvas.get());
36 if (fPicture != NULL || NULL != fCanvas.get()) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +000037 return;
38 }
39
40 SkASSERT(pict != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +000041 if (NULL == pict) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +000042 return;
43 }
44
45 fPicture = pict;
keyar@chromium.orga474ce32012-08-20 15:03:57 +000046 fCanvas.reset(this->setupCanvas());
47}
48
49SkCanvas* PictureRenderer::setupCanvas() {
50 return this->setupCanvas(fPicture->width(), fPicture->height());
51}
52
53SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000054 switch(fDeviceType) {
55 case kBitmap_DeviceType: {
56 SkBitmap bitmap;
keyar@chromium.orga474ce32012-08-20 15:03:57 +000057 sk_tools::setup_bitmap(&bitmap, width, height);
58 return SkNEW_ARGS(SkCanvas, (bitmap));
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000059 break;
60 }
61#if SK_SUPPORT_GPU
62 case kGPU_DeviceType: {
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000063 SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
keyar@chromium.org06125642012-08-20 15:03:33 +000064 (fGrContext, SkBitmap::kARGB_8888_Config,
keyar@chromium.orga474ce32012-08-20 15:03:57 +000065 width, height)));
66 return SkNEW_ARGS(SkCanvas, (device.get()));
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000067 break;
68 }
69#endif
70 default:
71 SkASSERT(0);
72 }
keyar@chromium.orga474ce32012-08-20 15:03:57 +000073
74 return NULL;
keyar@chromium.org9d696c02012-08-07 17:11:33 +000075}
76
77void PictureRenderer::end() {
keyar@chromium.org77a55222012-08-20 15:03:47 +000078 this->resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +000079 fPicture = NULL;
80 fCanvas.reset(NULL);
81}
82
keyar@chromium.org77a55222012-08-20 15:03:47 +000083void PictureRenderer::resetState() {
keyar@chromium.org28136b32012-08-20 15:04:15 +000084#if SK_SUPPORT_GPU
85 if (this->isUsingGpuDevice()) {
86 SkGLContext* glContext = fGrContextFactory.getGLContext(
87 GrContextFactory::kNative_GLContextType);
88 SK_GL(*glContext, Finish());
89 }
90#endif
91}
92
93void PictureRenderer::finishDraw() {
keyar@chromium.orgbffacc02012-08-20 15:04:07 +000094 SkASSERT(fCanvas.get() != NULL);
keyar@chromium.org28136b32012-08-20 15:04:15 +000095 if (NULL == fCanvas.get()) {
keyar@chromium.orgbffacc02012-08-20 15:04:07 +000096 return;
97 }
98
keyar@chromium.org77a55222012-08-20 15:03:47 +000099 fCanvas->flush();
100
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000101#if SK_SUPPORT_GPU
keyar@chromium.org77a55222012-08-20 15:03:47 +0000102 if (this->isUsingGpuDevice()) {
103 SkGLContext* glContext = fGrContextFactory.getGLContext(
104 GrContextFactory::kNative_GLContextType);
keyar@chromium.org28136b32012-08-20 15:04:15 +0000105
106 SkASSERT(glContext != NULL);
107 if (NULL == glContext) {
108 return;
109 }
110
keyar@chromium.org77a55222012-08-20 15:03:47 +0000111 SK_GL(*glContext, Finish());
keyar@chromium.org77a55222012-08-20 15:03:47 +0000112 }
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000113#endif
keyar@chromium.org77a55222012-08-20 15:03:47 +0000114}
115
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000116bool PictureRenderer::write(const SkString& path) const {
117 SkASSERT(fCanvas.get() != NULL);
118 SkASSERT(fPicture != NULL);
119 if (NULL == fCanvas.get() || NULL == fPicture) {
120 return false;
121 }
122
123 SkBitmap bitmap;
124 sk_tools::setup_bitmap(&bitmap, fPicture->width(), fPicture->height());
125
126 fCanvas->readPixels(&bitmap, 0, 0);
127 sk_tools::force_all_opaque(bitmap);
128
129 return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
130}
131
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000132void PipePictureRenderer::render() {
133 SkASSERT(fCanvas.get() != NULL);
134 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000135 if (NULL == fCanvas.get() || NULL == fPicture) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000136 return;
137 }
138
139 PipeController pipeController(fCanvas.get());
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000140 SkGPipeWriter writer;
141 SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000142 pipeCanvas->drawPicture(*fPicture);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000143 writer.endRecording();
keyar@chromium.org28136b32012-08-20 15:04:15 +0000144 this->finishDraw();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000145}
146
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000147void SimplePictureRenderer::render() {
148 SkASSERT(fCanvas.get() != NULL);
149 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000150 if (NULL == fCanvas.get() || NULL == fPicture) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000151 return;
152 }
153
154 fCanvas->drawPicture(*fPicture);
keyar@chromium.org28136b32012-08-20 15:04:15 +0000155 this->finishDraw();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000156}
157
158TiledPictureRenderer::TiledPictureRenderer()
159 : fTileWidth(kDefaultTileWidth)
160 , fTileHeight(kDefaultTileHeight) {}
161
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000162void TiledPictureRenderer::init(SkPicture* pict) {
163 SkASSERT(pict != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000164 SkASSERT(0 == fTiles.count());
165 if (NULL == pict || fTiles.count() != 0) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000166 return;
167 }
168
169 this->INHERITED::init(pict);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000170
171 if (fTileWidthPercentage > 0) {
robertphillips@google.com5d8d1862012-08-15 14:36:41 +0000172 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000173 }
174 if (fTileHeightPercentage > 0) {
robertphillips@google.com5d8d1862012-08-15 14:36:41 +0000175 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000176 }
177
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000178 this->setupTiles();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000179}
180
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000181void TiledPictureRenderer::render() {
182 SkASSERT(fCanvas.get() != NULL);
183 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000184 if (NULL == fCanvas.get() || NULL == fPicture) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000185 return;
186 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000187
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000188 this->drawTiles();
189 this->copyTilesToCanvas();
keyar@chromium.org28136b32012-08-20 15:04:15 +0000190 this->finishDraw();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000191}
192
193void TiledPictureRenderer::end() {
194 this->deleteTiles();
195 this->INHERITED::end();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000196}
197
198TiledPictureRenderer::~TiledPictureRenderer() {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000199 this->deleteTiles();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000200}
201
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000202void TiledPictureRenderer::clipTile(SkCanvas* tile) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000203 SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
204 SkIntToScalar(fPicture->height()));
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000205 tile->clipRect(clip);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000206}
207
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000208void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000209 SkCanvas* tile = this->setupCanvas(fTileWidth, fTileHeight);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000210
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000211 tile->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
212 this->clipTile(tile);
213
214 fTiles.push(tile);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000215}
216
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000217void TiledPictureRenderer::setupTiles() {
218 for (int tile_y_start = 0; tile_y_start < fPicture->height();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000219 tile_y_start += fTileHeight) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000220 for (int tile_x_start = 0; tile_x_start < fPicture->width();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000221 tile_x_start += fTileWidth) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000222 this->addTile(tile_x_start, tile_y_start);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000223 }
224 }
225}
226
227void TiledPictureRenderer::deleteTiles() {
228 for (int i = 0; i < fTiles.count(); ++i) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000229 SkDELETE(fTiles[i]);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000230 }
231
232 fTiles.reset();
233}
234
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000235void TiledPictureRenderer::drawTiles() {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000236 for (int i = 0; i < fTiles.count(); ++i) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000237 fTiles[i]->drawPicture(*(fPicture));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000238 }
239}
240
keyar@chromium.org28136b32012-08-20 15:04:15 +0000241void TiledPictureRenderer::finishDraw() {
keyar@chromium.org275be532012-08-20 15:04:00 +0000242 for (int i = 0; i < fTiles.count(); ++i) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000243 fTiles[i]->flush();
keyar@chromium.org275be532012-08-20 15:04:00 +0000244 }
245
keyar@chromium.org28136b32012-08-20 15:04:15 +0000246#if SK_SUPPORT_GPU
247 if (this->isUsingGpuDevice()) {
248 SkGLContext* glContext = fGrContextFactory.getGLContext(
249 GrContextFactory::kNative_GLContextType);
250
251 SkASSERT(glContext != NULL);
252 if (NULL == glContext) {
253 return;
254 }
255
256 SK_GL(*glContext, Finish());
257 }
258#endif
keyar@chromium.org275be532012-08-20 15:04:00 +0000259}
260
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000261void TiledPictureRenderer::copyTilesToCanvas() {
keyar@chromium.orgea826952012-08-23 15:24:13 +0000262 for (int i = 0; i < fTiles.count(); ++i) {
263 // Since SkPicture performs a save and restore when being drawn to a
264 // canvas, we can be confident that the transform matrix of the canvas
265 // is what we set when creating the tiles.
266 SkMatrix matrix = fTiles[i]->getTotalMatrix();
267 SkScalar tile_x_start = matrix.getTranslateX();
268 SkScalar tile_y_start = matrix.getTranslateY();
269
270 SkBitmap source = fTiles[i]->getDevice()->accessBitmap(false);
271
272 fCanvas->drawBitmap(source, -tile_x_start, -tile_y_start);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000273 }
274}
275
276}