blob: 46b268100f4a671268ef4dd60a871f18702b97c5 [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"
14#include "SkPicture.h"
keyar@chromium.org9299ede2012-08-21 19:05:08 +000015#include "SkString.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000016#include "SkTDArray.h"
17#include "SkTypes.h"
18#include "picture_utils.h"
19
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000020#if SK_SUPPORT_GPU
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000021#include "SkGpuDevice.h"
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000022#endif
23
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000024namespace sk_tools {
25
26enum {
27 kDefaultTileWidth = 256,
28 kDefaultTileHeight = 256
29};
30
keyar@chromium.org9d696c02012-08-07 17:11:33 +000031void PictureRenderer::init(SkPicture* pict) {
keyar@chromium.org78a35c52012-08-20 15:03:44 +000032 SkASSERT(NULL == fPicture);
33 SkASSERT(NULL == fCanvas.get());
34 if (fPicture != NULL || NULL != fCanvas.get()) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +000035 return;
36 }
37
38 SkASSERT(pict != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +000039 if (NULL == pict) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +000040 return;
41 }
42
43 fPicture = pict;
keyar@chromium.orga474ce32012-08-20 15:03:57 +000044 fCanvas.reset(this->setupCanvas());
45}
46
47SkCanvas* PictureRenderer::setupCanvas() {
48 return this->setupCanvas(fPicture->width(), fPicture->height());
49}
50
51SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000052 switch(fDeviceType) {
53 case kBitmap_DeviceType: {
54 SkBitmap bitmap;
keyar@chromium.orga474ce32012-08-20 15:03:57 +000055 sk_tools::setup_bitmap(&bitmap, width, height);
56 return SkNEW_ARGS(SkCanvas, (bitmap));
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000057 break;
58 }
59#if SK_SUPPORT_GPU
60 case kGPU_DeviceType: {
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000061 SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice,
keyar@chromium.org06125642012-08-20 15:03:33 +000062 (fGrContext, SkBitmap::kARGB_8888_Config,
keyar@chromium.orga474ce32012-08-20 15:03:57 +000063 width, height)));
64 return SkNEW_ARGS(SkCanvas, (device.get()));
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000065 break;
66 }
67#endif
68 default:
69 SkASSERT(0);
70 }
keyar@chromium.orga474ce32012-08-20 15:03:57 +000071
72 return NULL;
keyar@chromium.org9d696c02012-08-07 17:11:33 +000073}
74
75void PictureRenderer::end() {
keyar@chromium.org77a55222012-08-20 15:03:47 +000076 this->resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +000077 fPicture = NULL;
78 fCanvas.reset(NULL);
79}
80
keyar@chromium.org77a55222012-08-20 15:03:47 +000081void PictureRenderer::resetState() {
keyar@chromium.org28136b32012-08-20 15:04:15 +000082#if SK_SUPPORT_GPU
83 if (this->isUsingGpuDevice()) {
84 SkGLContext* glContext = fGrContextFactory.getGLContext(
85 GrContextFactory::kNative_GLContextType);
86 SK_GL(*glContext, Finish());
87 }
88#endif
89}
90
91void PictureRenderer::finishDraw() {
keyar@chromium.orgbffacc02012-08-20 15:04:07 +000092 SkASSERT(fCanvas.get() != NULL);
keyar@chromium.org28136b32012-08-20 15:04:15 +000093 if (NULL == fCanvas.get()) {
keyar@chromium.orgbffacc02012-08-20 15:04:07 +000094 return;
95 }
96
keyar@chromium.org77a55222012-08-20 15:03:47 +000097 fCanvas->flush();
98
keyar@chromium.orga40c20d2012-08-20 15:04:12 +000099#if SK_SUPPORT_GPU
keyar@chromium.org77a55222012-08-20 15:03:47 +0000100 if (this->isUsingGpuDevice()) {
101 SkGLContext* glContext = fGrContextFactory.getGLContext(
102 GrContextFactory::kNative_GLContextType);
keyar@chromium.org28136b32012-08-20 15:04:15 +0000103
104 SkASSERT(glContext != NULL);
105 if (NULL == glContext) {
106 return;
107 }
108
keyar@chromium.org77a55222012-08-20 15:03:47 +0000109 SK_GL(*glContext, Finish());
keyar@chromium.org77a55222012-08-20 15:03:47 +0000110 }
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000111#endif
keyar@chromium.org77a55222012-08-20 15:03:47 +0000112}
113
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000114bool PictureRenderer::write(const SkString& path) const {
115 SkASSERT(fCanvas.get() != NULL);
116 SkASSERT(fPicture != NULL);
117 if (NULL == fCanvas.get() || NULL == fPicture) {
118 return false;
119 }
120
121 SkBitmap bitmap;
122 sk_tools::setup_bitmap(&bitmap, fPicture->width(), fPicture->height());
123
124 fCanvas->readPixels(&bitmap, 0, 0);
125 sk_tools::force_all_opaque(bitmap);
126
127 return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
128}
129
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000130void PipePictureRenderer::render() {
131 SkASSERT(fCanvas.get() != NULL);
132 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000133 if (NULL == fCanvas.get() || NULL == fPicture) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000134 return;
135 }
136
137 PipeController pipeController(fCanvas.get());
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000138 SkGPipeWriter writer;
139 SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000140 pipeCanvas->drawPicture(*fPicture);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000141 writer.endRecording();
keyar@chromium.org28136b32012-08-20 15:04:15 +0000142 this->finishDraw();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000143}
144
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000145void SimplePictureRenderer::render() {
146 SkASSERT(fCanvas.get() != NULL);
147 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000148 if (NULL == fCanvas.get() || NULL == fPicture) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000149 return;
150 }
151
152 fCanvas->drawPicture(*fPicture);
keyar@chromium.org28136b32012-08-20 15:04:15 +0000153 this->finishDraw();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000154}
155
156TiledPictureRenderer::TiledPictureRenderer()
157 : fTileWidth(kDefaultTileWidth)
158 , fTileHeight(kDefaultTileHeight) {}
159
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000160void TiledPictureRenderer::init(SkPicture* pict) {
161 SkASSERT(pict != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000162 SkASSERT(0 == fTiles.count());
163 if (NULL == pict || fTiles.count() != 0) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000164 return;
165 }
166
167 this->INHERITED::init(pict);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000168
169 if (fTileWidthPercentage > 0) {
robertphillips@google.com5d8d1862012-08-15 14:36:41 +0000170 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000171 }
172 if (fTileHeightPercentage > 0) {
robertphillips@google.com5d8d1862012-08-15 14:36:41 +0000173 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000174 }
175
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000176 this->setupTiles();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000177}
178
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000179void TiledPictureRenderer::render() {
180 SkASSERT(fCanvas.get() != NULL);
181 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000182 if (NULL == fCanvas.get() || NULL == fPicture) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000183 return;
184 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000185
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000186 this->drawTiles();
187 this->copyTilesToCanvas();
keyar@chromium.org28136b32012-08-20 15:04:15 +0000188 this->finishDraw();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000189}
190
191void TiledPictureRenderer::end() {
192 this->deleteTiles();
193 this->INHERITED::end();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000194}
195
196TiledPictureRenderer::~TiledPictureRenderer() {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000197 this->deleteTiles();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000198}
199
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000200void TiledPictureRenderer::clipTile(SkCanvas* tile) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000201 SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
202 SkIntToScalar(fPicture->height()));
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000203 tile->clipRect(clip);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000204}
205
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000206void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000207 SkCanvas* tile = this->setupCanvas(fTileWidth, fTileHeight);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000208
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000209 tile->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
210 this->clipTile(tile);
211
212 fTiles.push(tile);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000213}
214
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000215void TiledPictureRenderer::setupTiles() {
216 for (int tile_y_start = 0; tile_y_start < fPicture->height();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000217 tile_y_start += fTileHeight) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000218 for (int tile_x_start = 0; tile_x_start < fPicture->width();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000219 tile_x_start += fTileWidth) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000220 this->addTile(tile_x_start, tile_y_start);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000221 }
222 }
223}
224
225void TiledPictureRenderer::deleteTiles() {
226 for (int i = 0; i < fTiles.count(); ++i) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000227 SkDELETE(fTiles[i]);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000228 }
229
230 fTiles.reset();
231}
232
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000233void TiledPictureRenderer::drawTiles() {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000234 for (int i = 0; i < fTiles.count(); ++i) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000235 fTiles[i]->drawPicture(*(fPicture));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000236 }
237}
238
keyar@chromium.org28136b32012-08-20 15:04:15 +0000239void TiledPictureRenderer::finishDraw() {
keyar@chromium.org275be532012-08-20 15:04:00 +0000240 for (int i = 0; i < fTiles.count(); ++i) {
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000241 fTiles[i]->flush();
keyar@chromium.org275be532012-08-20 15:04:00 +0000242 }
243
keyar@chromium.org28136b32012-08-20 15:04:15 +0000244#if SK_SUPPORT_GPU
245 if (this->isUsingGpuDevice()) {
246 SkGLContext* glContext = fGrContextFactory.getGLContext(
247 GrContextFactory::kNative_GLContextType);
248
249 SkASSERT(glContext != NULL);
250 if (NULL == glContext) {
251 return;
252 }
253
254 SK_GL(*glContext, Finish());
255 }
256#endif
keyar@chromium.org275be532012-08-20 15:04:00 +0000257}
258
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000259void TiledPictureRenderer::copyTilesToCanvas() {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000260 int tile_index = 0;
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000261 for (int tile_y_start = 0; tile_y_start < fPicture->height();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000262 tile_y_start += fTileHeight) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000263 for (int tile_x_start = 0; tile_x_start < fPicture->width();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000264 tile_x_start += fTileWidth) {
265 SkASSERT(tile_index < fTiles.count());
keyar@chromium.orgda652c22012-08-20 22:04:07 +0000266 SkBitmap source = fTiles[tile_index]->getDevice()->accessBitmap(false);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000267 fCanvas->drawBitmap(source,
268 SkIntToScalar(tile_x_start),
269 SkIntToScalar(tile_y_start));
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000270 ++tile_index;
271 }
272 }
273}
274
275}