blob: 705849d01acd92348f60f506f554ccf24cf38435 [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"
scroggo@google.com58b4ead2012-08-31 16:15:22 +00009#include "picture_utils.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000010#include "SamplePipeControllers.h"
commit-bot@chromium.orga3f882c2013-12-13 20:52:36 +000011#include "SkBitmapHasher.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000012#include "SkCanvas.h"
scroggo@google.com1b1bcc32013-05-21 20:31:23 +000013#include "SkData.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000014#include "SkDevice.h"
robertphillips@google.com94d8f1e2013-12-18 17:25:33 +000015#include "SkDiscardableMemoryPool.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000016#include "SkGPipe.h"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000017#if SK_SUPPORT_GPU
robertphillips@google.comfe1b5362013-02-07 19:45:46 +000018#include "gl/GrGLDefines.h"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000019#include "SkGpuDevice.h"
20#endif
21#include "SkGraphics.h"
22#include "SkImageEncoder.h"
caryclark@google.coma3622372012-11-06 21:26:13 +000023#include "SkMaskFilter.h"
keyar@chromium.orgea826952012-08-23 15:24:13 +000024#include "SkMatrix.h"
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +000025#include "SkOSFile.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000026#include "SkPicture.h"
robertphillips@google.com770963f2014-04-18 18:04:41 +000027#include "SkPictureRecorder.h"
scroggo@google.com1b1bcc32013-05-21 20:31:23 +000028#include "SkPictureUtils.h"
29#include "SkPixelRef.h"
keyar@chromium.orgea826952012-08-23 15:24:13 +000030#include "SkScalar.h"
scroggo@google.coma9e3a362012-11-07 17:52:48 +000031#include "SkStream.h"
keyar@chromium.org9299ede2012-08-21 19:05:08 +000032#include "SkString.h"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000033#include "SkTemplates.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000034#include "SkTDArray.h"
scroggo@google.com58b4ead2012-08-31 16:15:22 +000035#include "SkThreadUtils.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000036#include "SkTypes.h"
keyar@chromium.org4ea96c52012-08-20 15:03:29 +000037
reed@google.come15b2f52013-12-18 04:59:26 +000038static inline SkScalar scalar_log2(SkScalar x) {
39 static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2));
skia.committer@gmail.com3b85deb2013-12-18 07:01:56 +000040
reed@google.come15b2f52013-12-18 04:59:26 +000041 return SkScalarLog(x) * log2_conversion_factor;
42}
43
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000044namespace sk_tools {
45
46enum {
47 kDefaultTileWidth = 256,
48 kDefaultTileHeight = 256
49};
50
mtklein2a65a232014-08-26 14:07:04 -070051void PictureRenderer::init(const SkPicture* pict,
52 const SkString* writePath,
robertphillipsce4dd3d2014-07-07 13:46:35 -070053 const SkString* mismatchPath,
mtklein2a65a232014-08-26 14:07:04 -070054 const SkString* inputFilename,
robertphillipsce4dd3d2014-07-07 13:46:35 -070055 bool useChecksumBasedFilenames) {
commit-bot@chromium.org3f045172014-05-15 15:10:48 +000056 this->CopyString(&fWritePath, writePath);
57 this->CopyString(&fMismatchPath, mismatchPath);
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +000058 this->CopyString(&fInputFilename, inputFilename);
59 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
60
keyar@chromium.org78a35c52012-08-20 15:03:44 +000061 SkASSERT(NULL == fPicture);
62 SkASSERT(NULL == fCanvas.get());
bsalomon49f085d2014-09-05 13:34:00 -070063 if (fPicture || fCanvas.get()) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +000064 return;
65 }
66
67 SkASSERT(pict != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +000068 if (NULL == pict) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +000069 return;
70 }
71
robertphillips@google.com84b18c72014-04-13 19:09:42 +000072 fPicture.reset(pict)->ref();
keyar@chromium.orga474ce32012-08-20 15:03:57 +000073 fCanvas.reset(this->setupCanvas());
74}
75
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +000076void PictureRenderer::CopyString(SkString* dest, const SkString* src) {
bsalomon49f085d2014-09-05 13:34:00 -070077 if (src) {
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +000078 dest->set(*src);
79 } else {
80 dest->reset();
81 }
82}
83
caryclark@google.coma3622372012-11-06 21:26:13 +000084class FlagsDrawFilter : public SkDrawFilter {
85public:
86 FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) :
87 fFlags(flags) {}
88
reed@google.com971aca72012-11-26 20:26:54 +000089 virtual bool filter(SkPaint* paint, Type t) {
caryclark@google.coma3622372012-11-06 21:26:13 +000090 paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags);
robertphillips@google.com49149312013-07-03 15:34:35 +000091 if (PictureRenderer::kMaskFilter_DrawFilterFlag & fFlags[t]) {
caryclark@google.coma3622372012-11-06 21:26:13 +000092 SkMaskFilter* maskFilter = paint->getMaskFilter();
bsalomon49f085d2014-09-05 13:34:00 -070093 if (maskFilter) {
reed@google.com457d8a72012-12-18 18:20:44 +000094 paint->setMaskFilter(NULL);
caryclark@google.coma3622372012-11-06 21:26:13 +000095 }
96 }
97 if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) {
98 paint->setHinting(SkPaint::kNo_Hinting);
99 } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) {
100 paint->setHinting(SkPaint::kSlight_Hinting);
101 }
reed@google.com971aca72012-11-26 20:26:54 +0000102 return true;
caryclark@google.coma3622372012-11-06 21:26:13 +0000103 }
104
105private:
106 PictureRenderer::DrawFilterFlags* fFlags;
107};
108
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000109static void setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) {
caryclark@google.coma3622372012-11-06 21:26:13 +0000110 if (drawFilters && !canvas->getDrawFilter()) {
111 canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref();
caryclark@google.come3e940c2012-11-07 16:42:17 +0000112 if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) {
113 canvas->setAllowSoftClip(false);
114 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000115 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000116}
117
keyar@chromium.orga474ce32012-08-20 15:03:57 +0000118SkCanvas* PictureRenderer::setupCanvas() {
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000119 const int width = this->getViewWidth();
120 const int height = this->getViewHeight();
121 return this->setupCanvas(width, height);
keyar@chromium.orga474ce32012-08-20 15:03:57 +0000122}
123
124SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
caryclark@google.coma3622372012-11-06 21:26:13 +0000125 SkCanvas* canvas;
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000126 switch(fDeviceType) {
127 case kBitmap_DeviceType: {
128 SkBitmap bitmap;
keyar@chromium.orga474ce32012-08-20 15:03:57 +0000129 sk_tools::setup_bitmap(&bitmap, width, height);
caryclark@google.coma3622372012-11-06 21:26:13 +0000130 canvas = SkNEW_ARGS(SkCanvas, (bitmap));
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000131 }
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000132 break;
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000133#if SK_SUPPORT_GPU
scroggo@google.com0556ea02013-02-08 19:38:21 +0000134#if SK_ANGLE
135 case kAngle_DeviceType:
136 // fall through
137#endif
rmistry@google.com6ab96732014-01-06 18:37:24 +0000138#if SK_MESA
139 case kMesa_DeviceType:
140 // fall through
141#endif
commit-bot@chromium.org0fd52702014-03-07 18:41:14 +0000142 case kGPU_DeviceType:
143 case kNVPR_DeviceType: {
commit-bot@chromium.orgae403b92013-04-10 17:27:30 +0000144 SkAutoTUnref<GrSurface> target;
scroggo@google.com0556ea02013-02-08 19:38:21 +0000145 if (fGrContext) {
146 // create a render target to back the device
147 GrTextureDesc desc;
148 desc.fConfig = kSkia8888_GrPixelConfig;
149 desc.fFlags = kRenderTarget_GrTextureFlagBit;
150 desc.fWidth = width;
151 desc.fHeight = height;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000152 desc.fSampleCnt = fSampleCount;
commit-bot@chromium.orgae403b92013-04-10 17:27:30 +0000153 target.reset(fGrContext->createUncachedTexture(desc, NULL, 0));
scroggo@google.com0556ea02013-02-08 19:38:21 +0000154 }
commit-bot@chromium.orgae403b92013-04-10 17:27:30 +0000155 if (NULL == target.get()) {
scroggo@google.com0556ea02013-02-08 19:38:21 +0000156 SkASSERT(0);
157 return NULL;
158 }
159
reed3716fd02014-09-21 09:39:55 -0700160 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target,
161 SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)));
caryclark@google.coma3622372012-11-06 21:26:13 +0000162 canvas = SkNEW_ARGS(SkCanvas, (device.get()));
scroggo@google.com0556ea02013-02-08 19:38:21 +0000163 break;
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000164 }
165#endif
166 default:
167 SkASSERT(0);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000168 return NULL;
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000169 }
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000170 setUpFilter(canvas, fDrawFilters);
171 this->scaleToScaleFactor(canvas);
commit-bot@chromium.org17cc3ea2014-01-15 14:51:25 +0000172
173 // Pictures often lie about their extent (i.e., claim to be 100x100 but
174 // only ever draw to 90x100). Clear here so the undrawn portion will have
175 // a consistent color
176 canvas->clear(SK_ColorTRANSPARENT);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000177 return canvas;
178}
keyar@chromium.orga474ce32012-08-20 15:03:57 +0000179
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000180void PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) {
181 SkASSERT(canvas != NULL);
182 if (fScaleFactor != SK_Scalar1) {
183 canvas->scale(fScaleFactor, fScaleFactor);
184 }
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000185}
186
187void PictureRenderer::end() {
scroggo@google.com08085f82013-01-28 20:40:24 +0000188 this->resetState(true);
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000189 fPicture.reset(NULL);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000190 fCanvas.reset(NULL);
191}
192
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000193int PictureRenderer::getViewWidth() {
194 SkASSERT(fPicture != NULL);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700195 int width = SkScalarCeilToInt(fPicture->cullRect().width() * fScaleFactor);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000196 if (fViewport.width() > 0) {
197 width = SkMin32(width, fViewport.width());
198 }
199 return width;
200}
201
202int PictureRenderer::getViewHeight() {
203 SkASSERT(fPicture != NULL);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700204 int height = SkScalarCeilToInt(fPicture->cullRect().height() * fScaleFactor);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000205 if (fViewport.height() > 0) {
206 height = SkMin32(height, fViewport.height());
207 }
208 return height;
209}
210
junov@chromium.org9313ca42012-11-02 18:11:49 +0000211/** Converts fPicture to a picture that uses a BBoxHierarchy.
212 * PictureRenderer subclasses that are used to test picture playback
213 * should call this method during init.
214 */
215void PictureRenderer::buildBBoxHierarchy() {
bsalomon49f085d2014-09-05 13:34:00 -0700216 SkASSERT(fPicture);
217 if (kNone_BBoxHierarchyType != fBBoxHierarchyType && fPicture) {
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000218 SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
219 SkPictureRecorder recorder;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700220 SkCanvas* canvas = recorder.beginRecording(fPicture->cullRect().width(),
221 fPicture->cullRect().height(),
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000222 factory.get(),
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000223 this->recordFlags());
robertphillipsc5ba71d2014-09-04 08:42:50 -0700224 fPicture->playback(canvas);
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000225 fPicture.reset(recorder.endRecording());
junov@chromium.org9313ca42012-11-02 18:11:49 +0000226 }
227}
228
scroggo@google.com08085f82013-01-28 20:40:24 +0000229void PictureRenderer::resetState(bool callFinish) {
keyar@chromium.org28136b32012-08-20 15:04:15 +0000230#if SK_SUPPORT_GPU
robertphillips@google.com6177e692013-02-28 20:16:25 +0000231 SkGLContextHelper* glContext = this->getGLContext();
scroggo@google.com0556ea02013-02-08 19:38:21 +0000232 if (NULL == glContext) {
233 SkASSERT(kBitmap_DeviceType == fDeviceType);
234 return;
235 }
keyar@chromium.org28136b32012-08-20 15:04:15 +0000236
scroggo@google.com0556ea02013-02-08 19:38:21 +0000237 fGrContext->flush();
commit-bot@chromium.org51c040e2014-03-11 22:58:00 +0000238 glContext->swapBuffers();
scroggo@google.com0556ea02013-02-08 19:38:21 +0000239 if (callFinish) {
240 SK_GL(*glContext, Finish());
keyar@chromium.org77a55222012-08-20 15:03:47 +0000241 }
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000242#endif
keyar@chromium.org77a55222012-08-20 15:03:47 +0000243}
244
robertphillips@google.com94d8f1e2013-12-18 17:25:33 +0000245void PictureRenderer::purgeTextures() {
246 SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool();
247
248 pool->dumpPool();
249
250#if SK_SUPPORT_GPU
251 SkGLContextHelper* glContext = this->getGLContext();
252 if (NULL == glContext) {
253 SkASSERT(kBitmap_DeviceType == fDeviceType);
254 return;
255 }
256
257 // resetState should've already done this
258 fGrContext->flush();
259
260 fGrContext->purgeAllUnlockedResources();
261#endif
262}
263
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000264/**
commit-bot@chromium.org4610a462014-04-29 19:39:22 +0000265 * Write the canvas to an image file and/or JSON summary.
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000266 *
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000267 * @param canvas Must be non-null. Canvas to be written to a file.
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000268 * @param writePath If nonempty, write the binary image to a file within this directory.
269 * @param mismatchPath If nonempty, write the binary image to a file within this directory,
270 * but only if the image does not match expectations.
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000271 * @param inputFilename If we are writing out a binary image, use this to build its filename.
commit-bot@chromium.org4610a462014-04-29 19:39:22 +0000272 * @param jsonSummaryPtr If not null, add image results (checksum) to this summary.
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000273 * @param useChecksumBasedFilenames If true, use checksum-based filenames when writing to disk.
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000274 * @param tileNumberPtr If not null, which tile number this image contains.
commit-bot@chromium.orga3f882c2013-12-13 20:52:36 +0000275 *
commit-bot@chromium.org4610a462014-04-29 19:39:22 +0000276 * @return bool True if the operation completed successfully.
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000277 */
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000278static bool write(SkCanvas* canvas, const SkString& writePath, const SkString& mismatchPath,
279 const SkString& inputFilename, ImageResultsAndExpectations *jsonSummaryPtr,
280 bool useChecksumBasedFilenames, const int* tileNumberPtr=NULL) {
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000281 SkASSERT(canvas != NULL);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000282 if (NULL == canvas) {
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000283 return false;
284 }
285
286 SkBitmap bitmap;
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000287 SkISize size = canvas->getDeviceSize();
commit-bot@chromium.org205ce482014-05-12 15:37:20 +0000288 setup_bitmap(&bitmap, size.width(), size.height());
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000289
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000290 canvas->readPixels(&bitmap, 0, 0);
commit-bot@chromium.org205ce482014-05-12 15:37:20 +0000291 force_all_opaque(bitmap);
292 BitmapAndDigest bitmapAndDigest(bitmap);
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000293
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000294 SkString escapedInputFilename(inputFilename);
295 replace_char(&escapedInputFilename, '.', '_');
296
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000297 // TODO(epoger): what about including the config type within outputFilename? That way,
298 // we could combine results of different config types without conflicting filenames.
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000299 SkString outputFilename;
300 const char *outputSubdirPtr = NULL;
301 if (useChecksumBasedFilenames) {
epoger85b438d2014-08-21 23:21:32 -0700302 ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr();
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000303 outputSubdirPtr = escapedInputFilename.c_str();
commit-bot@chromium.org205ce482014-05-12 15:37:20 +0000304 outputFilename.set(imageDigestPtr->getHashType());
305 outputFilename.append("_");
306 outputFilename.appendU64(imageDigestPtr->getHashValue());
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000307 } else {
308 outputFilename.set(escapedInputFilename);
bsalomon49f085d2014-09-05 13:34:00 -0700309 if (tileNumberPtr) {
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000310 outputFilename.append("-tile");
311 outputFilename.appendS32(*tileNumberPtr);
312 }
commit-bot@chromium.orga3f882c2013-12-13 20:52:36 +0000313 }
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000314 outputFilename.append(".png");
commit-bot@chromium.orga3f882c2013-12-13 20:52:36 +0000315
bsalomon49f085d2014-09-05 13:34:00 -0700316 if (jsonSummaryPtr) {
epoger85b438d2014-08-21 23:21:32 -0700317 ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr();
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000318 SkString outputRelativePath;
319 if (outputSubdirPtr) {
320 outputRelativePath.set(outputSubdirPtr);
321 outputRelativePath.append("/"); // always use "/", even on Windows
322 outputRelativePath.append(outputFilename);
323 } else {
324 outputRelativePath.set(outputFilename);
325 }
326
327 jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(),
commit-bot@chromium.org205ce482014-05-12 15:37:20 +0000328 *imageDigestPtr, tileNumberPtr);
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000329 if (!mismatchPath.isEmpty() &&
epoger85b438d2014-08-21 23:21:32 -0700330 !jsonSummaryPtr->getExpectation(inputFilename.c_str(),
331 tileNumberPtr).matches(*imageDigestPtr)) {
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000332 if (!write_bitmap_to_disk(bitmap, mismatchPath, outputSubdirPtr, outputFilename)) {
333 return false;
334 }
335 }
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000336 }
337
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000338 if (writePath.isEmpty()) {
commit-bot@chromium.org4610a462014-04-29 19:39:22 +0000339 return true;
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000340 } else {
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000341 return write_bitmap_to_disk(bitmap, writePath, outputSubdirPtr, outputFilename);
commit-bot@chromium.org24c568c2014-04-10 15:39:02 +0000342 }
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000343}
344
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000345///////////////////////////////////////////////////////////////////////////////////////////////
346
djsollen@google.comfd9720c2012-11-06 16:54:40 +0000347SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
348 // defer the canvas setup until the render step
349 return NULL;
350}
351
reed@google.com672588b2014-01-08 15:42:01 +0000352// the size_t* parameter is deprecated, so we ignore it
353static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
scroggo@google.com1b1bcc32013-05-21 20:31:23 +0000354 return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
scroggo@google.coma9e3a362012-11-07 17:52:48 +0000355}
356
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000357bool RecordPictureRenderer::render(SkBitmap** out) {
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000358 SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
359 SkPictureRecorder recorder;
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700360 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(this->getViewWidth()),
361 SkIntToScalar(this->getViewHeight()),
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000362 factory.get(),
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000363 this->recordFlags());
364 this->scaleToScaleFactor(canvas);
robertphillipsc5ba71d2014-09-04 08:42:50 -0700365 fPicture->playback(canvas);
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000366 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000367 if (!fWritePath.isEmpty()) {
scroggo@google.coma9e3a362012-11-07 17:52:48 +0000368 // Record the new picture as a new SKP with PNG encoded bitmaps.
tfarinaa8e2e152014-07-28 19:26:58 -0700369 SkString skpPath = SkOSPath::Join(fWritePath.c_str(), fInputFilename.c_str());
scroggo@google.coma9e3a362012-11-07 17:52:48 +0000370 SkFILEWStream stream(skpPath.c_str());
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000371 picture->serialize(&stream, &encode_bitmap_to_data);
scroggo@google.coma9e3a362012-11-07 17:52:48 +0000372 return true;
373 }
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000374 return false;
scroggo@google.com9a412522012-09-07 15:21:18 +0000375}
376
scroggo@google.com0a049b82012-11-02 22:01:26 +0000377SkString RecordPictureRenderer::getConfigNameInternal() {
378 return SkString("record");
379}
380
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000381///////////////////////////////////////////////////////////////////////////////////////////////
382
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000383bool PipePictureRenderer::render(SkBitmap** out) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000384 SkASSERT(fCanvas.get() != NULL);
385 SkASSERT(fPicture != NULL);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000386 if (NULL == fCanvas.get() || NULL == fPicture) {
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000387 return false;
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000388 }
389
390 PipeController pipeController(fCanvas.get());
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000391 SkGPipeWriter writer;
392 SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
robertphillips9b14f262014-06-04 05:40:44 -0700393 pipeCanvas->drawPicture(fPicture);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000394 writer.endRecording();
scroggo@google.com9a412522012-09-07 15:21:18 +0000395 fCanvas->flush();
bsalomon49f085d2014-09-05 13:34:00 -0700396 if (out) {
edisonn@google.com84f548c2012-12-18 22:24:03 +0000397 *out = SkNEW(SkBitmap);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700398 setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
399 SkScalarCeilToInt(fPicture->cullRect().height()));
edisonn@google.com84f548c2012-12-18 22:24:03 +0000400 fCanvas->readPixels(*out, 0, 0);
skia.committer@gmail.coma7d8e3e2012-12-19 02:01:38 +0000401 }
commit-bot@chromium.org8991c672014-05-22 00:36:05 +0000402 if (fEnableWrites) {
403 return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
404 fUseChecksumBasedFilenames);
405 } else {
406 return true;
407 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000408}
409
scroggo@google.com0a049b82012-11-02 22:01:26 +0000410SkString PipePictureRenderer::getConfigNameInternal() {
411 return SkString("pipe");
412}
413
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000414///////////////////////////////////////////////////////////////////////////////////////////////
415
robertphillipsce4dd3d2014-07-07 13:46:35 -0700416void SimplePictureRenderer::init(const SkPicture* picture, const SkString* writePath,
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000417 const SkString* mismatchPath, const SkString* inputFilename,
418 bool useChecksumBasedFilenames) {
419 INHERITED::init(picture, writePath, mismatchPath, inputFilename, useChecksumBasedFilenames);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000420 this->buildBBoxHierarchy();
421}
422
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000423bool SimplePictureRenderer::render(SkBitmap** out) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000424 SkASSERT(fCanvas.get() != NULL);
bsalomon49f085d2014-09-05 13:34:00 -0700425 SkASSERT(fPicture);
keyar@chromium.org78a35c52012-08-20 15:03:44 +0000426 if (NULL == fCanvas.get() || NULL == fPicture) {
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000427 return false;
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000428 }
429
robertphillips9b14f262014-06-04 05:40:44 -0700430 fCanvas->drawPicture(fPicture);
scroggo@google.com9a412522012-09-07 15:21:18 +0000431 fCanvas->flush();
bsalomon49f085d2014-09-05 13:34:00 -0700432 if (out) {
edisonn@google.com84f548c2012-12-18 22:24:03 +0000433 *out = SkNEW(SkBitmap);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700434 setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
435 SkScalarCeilToInt(fPicture->cullRect().height()));
edisonn@google.com84f548c2012-12-18 22:24:03 +0000436 fCanvas->readPixels(*out, 0, 0);
437 }
commit-bot@chromium.org8991c672014-05-22 00:36:05 +0000438 if (fEnableWrites) {
439 return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
440 fUseChecksumBasedFilenames);
441 } else {
442 return true;
443 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000444}
445
scroggo@google.com0a049b82012-11-02 22:01:26 +0000446SkString SimplePictureRenderer::getConfigNameInternal() {
447 return SkString("simple");
448}
449
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000450///////////////////////////////////////////////////////////////////////////////////////////////
451
krajcevskib1aded82014-08-18 07:52:17 -0700452#if SK_SUPPORT_GPU
453TiledPictureRenderer::TiledPictureRenderer(const GrContext::Options& opts)
mtklein2a65a232014-08-26 14:07:04 -0700454 : INHERITED(opts)
krajcevskib1aded82014-08-18 07:52:17 -0700455 , fTileWidth(kDefaultTileWidth)
456#else
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000457TiledPictureRenderer::TiledPictureRenderer()
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000458 : fTileWidth(kDefaultTileWidth)
krajcevskib1aded82014-08-18 07:52:17 -0700459#endif
rileya@google.comb947b912012-08-29 17:35:07 +0000460 , fTileHeight(kDefaultTileHeight)
rileya@google.coma04dc022012-09-10 19:01:38 +0000461 , fTileWidthPercentage(0.0)
rileya@google.comb947b912012-08-29 17:35:07 +0000462 , fTileHeightPercentage(0.0)
scroggo@google.comcbcef702012-12-13 22:09:28 +0000463 , fTileMinPowerOf2Width(0)
464 , fCurrentTileOffset(-1)
465 , fTilesX(0)
466 , fTilesY(0) { }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000467
robertphillipsce4dd3d2014-07-07 13:46:35 -0700468void TiledPictureRenderer::init(const SkPicture* pict, const SkString* writePath,
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000469 const SkString* mismatchPath, const SkString* inputFilename,
470 bool useChecksumBasedFilenames) {
bsalomon49f085d2014-09-05 13:34:00 -0700471 SkASSERT(pict);
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000472 SkASSERT(0 == fTileRects.count());
473 if (NULL == pict || fTileRects.count() != 0) {
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000474 return;
475 }
476
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000477 // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not
478 // used by bench_pictures.
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000479 fPicture.reset(pict)->ref();
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000480 this->CopyString(&fWritePath, writePath);
481 this->CopyString(&fMismatchPath, mismatchPath);
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000482 this->CopyString(&fInputFilename, inputFilename);
483 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000484 this->buildBBoxHierarchy();
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000485
486 if (fTileWidthPercentage > 0) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700487 fTileWidth = SkScalarCeilToInt(float(fTileWidthPercentage * fPicture->cullRect().width() / 100));
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000488 }
489 if (fTileHeightPercentage > 0) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700490 fTileHeight = SkScalarCeilToInt(float(fTileHeightPercentage * fPicture->cullRect().height() / 100));
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000491 }
492
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000493 if (fTileMinPowerOf2Width > 0) {
494 this->setupPowerOf2Tiles();
495 } else {
496 this->setupTiles();
497 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000498 fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight));
499 // Initialize to -1 so that the first call to nextTile will set this up to draw tile 0 on the
500 // first call to drawCurrentTile.
501 fCurrentTileOffset = -1;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000502}
503
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000504void TiledPictureRenderer::end() {
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000505 fTileRects.reset();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000506 this->INHERITED::end();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000507}
508
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000509void TiledPictureRenderer::setupTiles() {
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000510 // Only use enough tiles to cover the viewport
511 const int width = this->getViewWidth();
512 const int height = this->getViewHeight();
513
scroggo@google.comcbcef702012-12-13 22:09:28 +0000514 fTilesX = fTilesY = 0;
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000515 for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000516 fTilesY++;
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000517 for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWidth) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000518 if (0 == tile_y_start) {
519 // Only count tiles in the X direction on the first pass.
520 fTilesX++;
521 }
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000522 *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
523 SkIntToScalar(tile_y_start),
524 SkIntToScalar(fTileWidth),
525 SkIntToScalar(fTileHeight));
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000526 }
527 }
528}
529
scroggo@google.comcbcef702012-12-13 22:09:28 +0000530bool TiledPictureRenderer::tileDimensions(int &x, int &y) {
531 if (fTileRects.count() == 0 || NULL == fPicture) {
532 return false;
533 }
534 x = fTilesX;
535 y = fTilesY;
536 return true;
537}
538
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000539// The goal of the powers of two tiles is to minimize the amount of wasted tile
540// space in the width-wise direction and then minimize the number of tiles. The
541// constraints are that every tile must have a pixel width that is a power of
542// two and also be of some minimal width (that is also a power of two).
543//
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000544// This is solved by first taking our picture size and rounding it up to the
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000545// multiple of the minimal width. The binary representation of this rounded
546// value gives us the tiles we need: a bit of value one means we need a tile of
547// that size.
548void TiledPictureRenderer::setupPowerOf2Tiles() {
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000549 // Only use enough tiles to cover the viewport
550 const int width = this->getViewWidth();
551 const int height = this->getViewHeight();
552
553 int rounded_value = width;
554 if (width % fTileMinPowerOf2Width != 0) {
555 rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerOf2Width;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000556 }
557
reed@google.come15b2f52013-12-18 04:59:26 +0000558 int num_bits = SkScalarCeilToInt(scalar_log2(SkIntToScalar(width)));
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000559 int largest_possible_tile_size = 1 << num_bits;
560
scroggo@google.comcbcef702012-12-13 22:09:28 +0000561 fTilesX = fTilesY = 0;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000562 // The tile height is constant for a particular picture.
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000563 for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000564 fTilesY++;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000565 int tile_x_start = 0;
566 int current_width = largest_possible_tile_size;
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000567 // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough
568 // to draw each tile.
569 fTileWidth = current_width;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000570
571 while (current_width >= fTileMinPowerOf2Width) {
572 // It is very important this is a bitwise AND.
573 if (current_width & rounded_value) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000574 if (0 == tile_y_start) {
575 // Only count tiles in the X direction on the first pass.
576 fTilesX++;
577 }
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000578 *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
579 SkIntToScalar(tile_y_start),
580 SkIntToScalar(current_width),
581 SkIntToScalar(fTileHeight));
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000582 tile_x_start += current_width;
583 }
584
585 current_width >>= 1;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000586 }
587 }
588}
589
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000590/**
commit-bot@chromium.org145d1c02014-03-16 19:46:36 +0000591 * Draw the specified picture to the canvas translated to rectangle provided, so that this mini
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000592 * canvas represents the rectangle's portion of the overall picture.
593 * Saves and restores so that the initial clip and matrix return to their state before this function
594 * is called.
595 */
mtklein2a65a232014-08-26 14:07:04 -0700596static void draw_tile_to_canvas(SkCanvas* canvas,
597 const SkRect& tileRect,
robertphillipsce4dd3d2014-07-07 13:46:35 -0700598 const SkPicture* picture) {
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000599 int saveCount = canvas->save();
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000600 // Translate so that we draw the correct portion of the picture.
601 // Perform a postTranslate so that the scaleFactor does not interfere with the positioning.
602 SkMatrix mat(canvas->getTotalMatrix());
603 mat.postTranslate(-tileRect.fLeft, -tileRect.fTop);
604 canvas->setMatrix(mat);
robertphillips9b14f262014-06-04 05:40:44 -0700605 canvas->drawPicture(picture);
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000606 canvas->restoreToCount(saveCount);
607 canvas->flush();
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000608}
609
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000610///////////////////////////////////////////////////////////////////////////////////////////////
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000611
commit-bot@chromium.orga3f882c2013-12-13 20:52:36 +0000612/**
613 * Copies the entirety of the src bitmap (typically a tile) into a portion of the dst bitmap.
614 * If the src bitmap is too large to fit within the dst bitmap after the x and y
615 * offsets have been applied, any excess will be ignored (so only the top-left portion of the
616 * src bitmap will be copied).
617 *
618 * @param src source bitmap
619 * @param dst destination bitmap
620 * @param xOffset x-offset within destination bitmap
621 * @param yOffset y-offset within destination bitmap
622 */
623static void bitmapCopyAtOffset(const SkBitmap& src, SkBitmap* dst,
624 int xOffset, int yOffset) {
625 for (int y = 0; y <src.height() && y + yOffset < dst->height() ; y++) {
626 for (int x = 0; x < src.width() && x + xOffset < dst->width() ; x++) {
627 *dst->getAddr32(xOffset + x, yOffset + y) = *src.getAddr32(x, y);
edisonn@google.com84f548c2012-12-18 22:24:03 +0000628 }
629 }
630}
631
scroggo@google.comcbcef702012-12-13 22:09:28 +0000632bool TiledPictureRenderer::nextTile(int &i, int &j) {
633 if (++fCurrentTileOffset < fTileRects.count()) {
634 i = fCurrentTileOffset % fTilesX;
635 j = fCurrentTileOffset / fTilesX;
636 return true;
637 }
638 return false;
639}
640
641void TiledPictureRenderer::drawCurrentTile() {
642 SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count());
commit-bot@chromium.org145d1c02014-03-16 19:46:36 +0000643 draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture);
scroggo@google.comcbcef702012-12-13 22:09:28 +0000644}
645
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000646bool TiledPictureRenderer::render(SkBitmap** out) {
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000647 SkASSERT(fPicture != NULL);
648 if (NULL == fPicture) {
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000649 return false;
scroggo@google.comacfb30e2012-09-18 14:32:35 +0000650 }
651
edisonn@google.com84f548c2012-12-18 22:24:03 +0000652 SkBitmap bitmap;
653 if (out){
654 *out = SkNEW(SkBitmap);
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700655 setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
656 SkScalarCeilToInt(fPicture->cullRect().height()));
edisonn@google.com84f548c2012-12-18 22:24:03 +0000657 setup_bitmap(&bitmap, fTileWidth, fTileHeight);
658 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000659 bool success = true;
660 for (int i = 0; i < fTileRects.count(); ++i) {
commit-bot@chromium.org145d1c02014-03-16 19:46:36 +0000661 draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture);
commit-bot@chromium.org8991c672014-05-22 00:36:05 +0000662 if (fEnableWrites) {
663 success &= write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
664 fUseChecksumBasedFilenames, &i);
665 }
bsalomon49f085d2014-09-05 13:34:00 -0700666 if (out) {
edisonn@google.com84f548c2012-12-18 22:24:03 +0000667 if (fCanvas->readPixels(&bitmap, 0, 0)) {
commit-bot@chromium.orga3f882c2013-12-13 20:52:36 +0000668 // Add this tile to the entire bitmap.
669 bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()),
670 SkScalarFloorToInt(fTileRects[i].top()));
edisonn@google.com84f548c2012-12-18 22:24:03 +0000671 } else {
672 success = false;
673 }
674 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000675 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000676 return success;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000677}
678
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000679SkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) {
680 SkCanvas* canvas = this->INHERITED::setupCanvas(width, height);
bsalomon49f085d2014-09-05 13:34:00 -0700681 SkASSERT(fPicture);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000682 // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This
683 // is mostly important for tiles on the right and bottom edges as they may go over this area and
684 // the picture may have some commands that draw outside of this area and so should not actually
685 // be written.
686 // Uses a clipRegion so that it will be unaffected by the scale factor, which may have been set
687 // by INHERITED::setupCanvas.
688 SkRegion clipRegion;
689 clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight());
690 canvas->clipRegion(clipRegion);
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000691 return canvas;
692}
scroggo@google.com0a049b82012-11-02 22:01:26 +0000693
694SkString TiledPictureRenderer::getConfigNameInternal() {
695 SkString name;
696 if (fTileMinPowerOf2Width > 0) {
697 name.append("pow2tile_");
698 name.appendf("%i", fTileMinPowerOf2Width);
699 } else {
700 name.append("tile_");
701 if (fTileWidthPercentage > 0) {
702 name.appendf("%.f%%", fTileWidthPercentage);
703 } else {
704 name.appendf("%i", fTileWidth);
705 }
706 }
707 name.append("x");
708 if (fTileHeightPercentage > 0) {
709 name.appendf("%.f%%", fTileHeightPercentage);
710 } else {
711 name.appendf("%i", fTileHeight);
712 }
713 return name;
714}
715
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000716///////////////////////////////////////////////////////////////////////////////////////////////
717
scroggo@google.com9a412522012-09-07 15:21:18 +0000718void PlaybackCreationRenderer::setup() {
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000719 SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
720 fRecorder.reset(SkNEW(SkPictureRecorder));
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700721 SkCanvas* canvas = fRecorder->beginRecording(SkIntToScalar(this->getViewWidth()),
722 SkIntToScalar(this->getViewHeight()),
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000723 factory.get(),
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000724 this->recordFlags());
725 this->scaleToScaleFactor(canvas);
robertphillips9b14f262014-06-04 05:40:44 -0700726 canvas->drawPicture(fPicture);
scroggo@google.com9a412522012-09-07 15:21:18 +0000727}
728
commit-bot@chromium.orgf5e315c2014-03-19 17:26:07 +0000729bool PlaybackCreationRenderer::render(SkBitmap** out) {
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000730 fPicture.reset(fRecorder->endRecording());
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000731 // Since this class does not actually render, return false.
732 return false;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000733}
734
scroggo@google.com0a049b82012-11-02 22:01:26 +0000735SkString PlaybackCreationRenderer::getConfigNameInternal() {
736 return SkString("playback_creation");
737}
738
junov@chromium.org9313ca42012-11-02 18:11:49 +0000739///////////////////////////////////////////////////////////////////////////////////////////////
740// SkPicture variants for each BBoxHierarchy type
741
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000742SkBBHFactory* PictureRenderer::getFactory() {
junov@chromium.org9313ca42012-11-02 18:11:49 +0000743 switch (fBBoxHierarchyType) {
744 case kNone_BBoxHierarchyType:
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000745 return NULL;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000746 case kRTree_BBoxHierarchyType:
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000747 return SkNEW(SkRTreeFactory);
junov@chromium.org7b537062012-11-06 18:58:43 +0000748 case kTileGrid_BBoxHierarchyType:
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000749 return SkNEW_ARGS(SkTileGridFactory, (fGridInfo));
junov@chromium.org9313ca42012-11-02 18:11:49 +0000750 }
751 SkASSERT(0); // invalid bbhType
752 return NULL;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000753}
junov@chromium.org9313ca42012-11-02 18:11:49 +0000754
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000755///////////////////////////////////////////////////////////////////////////////
756
757class GatherRenderer : public PictureRenderer {
758public:
krajcevskib1aded82014-08-18 07:52:17 -0700759#if SK_SUPPORT_GPU
760 GatherRenderer(const GrContext::Options& opts) : INHERITED(opts) { }
761#endif
762
commit-bot@chromium.org8ddc26b2014-03-31 17:55:12 +0000763 virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700764 SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->cullRect().width()),
765 SkIntToScalar(fPicture->cullRect().height()));
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000766 SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
767 SkSafeUnref(data);
skia.committer@gmail.comc7b4be72012-12-11 02:01:20 +0000768
commit-bot@chromium.org3f045172014-05-15 15:10:48 +0000769 return (fWritePath.isEmpty()); // we don't have anything to write
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000770 }
skia.committer@gmail.comc7b4be72012-12-11 02:01:20 +0000771
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000772private:
773 virtual SkString getConfigNameInternal() SK_OVERRIDE {
774 return SkString("gather_pixelrefs");
775 }
krajcevskib1aded82014-08-18 07:52:17 -0700776
777 typedef PictureRenderer INHERITED;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000778};
779
krajcevskib1aded82014-08-18 07:52:17 -0700780#if SK_SUPPORT_GPU
781PictureRenderer* CreateGatherPixelRefsRenderer(const GrContext::Options& opts) {
782 return SkNEW_ARGS(GatherRenderer, (opts));
783}
784#else
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000785PictureRenderer* CreateGatherPixelRefsRenderer() {
786 return SkNEW(GatherRenderer);
787}
krajcevskib1aded82014-08-18 07:52:17 -0700788#endif
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +0000789
junov@chromium.org9313ca42012-11-02 18:11:49 +0000790} // namespace sk_tools