| keyar@chromium.org | b3fb7c1 | 2012-08-20 21:02:49 +0000 | [diff] [blame] | 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 |  | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 8 | #include "PictureRenderer.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 9 | #include "picture_utils.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 10 | #include "SamplePipeControllers.h" | 
 | 11 | #include "SkCanvas.h" | 
 | 12 | #include "SkDevice.h" | 
 | 13 | #include "SkGPipe.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 14 | #if SK_SUPPORT_GPU | 
 | 15 | #include "SkGpuDevice.h" | 
 | 16 | #endif | 
 | 17 | #include "SkGraphics.h" | 
 | 18 | #include "SkImageEncoder.h" | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 19 | #include "SkMaskFilter.h" | 
| keyar@chromium.org | ea82695 | 2012-08-23 15:24:13 +0000 | [diff] [blame] | 20 | #include "SkMatrix.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 21 | #include "SkPicture.h" | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 22 | #include "SkRTree.h" | 
| keyar@chromium.org | ea82695 | 2012-08-23 15:24:13 +0000 | [diff] [blame] | 23 | #include "SkScalar.h" | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 24 | #include "SkStream.h" | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 25 | #include "SkString.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 26 | #include "SkTemplates.h" | 
| junov@chromium.org | 7b53706 | 2012-11-06 18:58:43 +0000 | [diff] [blame] | 27 | #include "SkTileGrid.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 28 | #include "SkTDArray.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 29 | #include "SkThreadUtils.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 30 | #include "SkTypes.h" | 
| reed@google.com | fe7b1ed | 2012-11-29 21:00:39 +0000 | [diff] [blame^] | 31 | #include "SkData.h" | 
 | 32 | #include "SkPictureUtils.h" | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 33 |  | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 34 | namespace sk_tools { | 
 | 35 |  | 
 | 36 | enum { | 
 | 37 |     kDefaultTileWidth = 256, | 
 | 38 |     kDefaultTileHeight = 256 | 
 | 39 | }; | 
 | 40 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 41 | void PictureRenderer::init(SkPicture* pict) { | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 42 |     SkASSERT(NULL == fPicture); | 
 | 43 |     SkASSERT(NULL == fCanvas.get()); | 
 | 44 |     if (fPicture != NULL || NULL != fCanvas.get()) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 45 |         return; | 
 | 46 |     } | 
 | 47 |  | 
 | 48 |     SkASSERT(pict != NULL); | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 49 |     if (NULL == pict) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 50 |         return; | 
 | 51 |     } | 
 | 52 |  | 
 | 53 |     fPicture = pict; | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 54 |     fPicture->ref(); | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 55 |     fCanvas.reset(this->setupCanvas()); | 
 | 56 | } | 
 | 57 |  | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 58 | class FlagsDrawFilter : public SkDrawFilter { | 
 | 59 | public: | 
 | 60 |     FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) : | 
 | 61 |         fFlags(flags) {} | 
 | 62 |  | 
| reed@google.com | 971aca7 | 2012-11-26 20:26:54 +0000 | [diff] [blame] | 63 |     virtual bool filter(SkPaint* paint, Type t) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 64 |         paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags); | 
| caryclark@google.com | e3e940c | 2012-11-07 16:42:17 +0000 | [diff] [blame] | 65 |         if ((PictureRenderer::kBlur_DrawFilterFlag | PictureRenderer::kLowBlur_DrawFilterFlag) | 
 | 66 |                 & fFlags[t]) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 67 |             SkMaskFilter* maskFilter = paint->getMaskFilter(); | 
 | 68 |             SkMaskFilter::BlurInfo blurInfo; | 
 | 69 |             if (maskFilter && maskFilter->asABlur(&blurInfo)) { | 
| caryclark@google.com | e3e940c | 2012-11-07 16:42:17 +0000 | [diff] [blame] | 70 |                 if (PictureRenderer::kBlur_DrawFilterFlag & fFlags[t]) { | 
 | 71 |                     paint->setMaskFilter(NULL); | 
 | 72 |                 } else { | 
 | 73 |                     blurInfo.fHighQuality = false; | 
 | 74 |                     maskFilter->setAsABlur(blurInfo); | 
 | 75 |                 } | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 76 |             } | 
 | 77 |         } | 
 | 78 |         if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) { | 
 | 79 |             paint->setHinting(SkPaint::kNo_Hinting); | 
 | 80 |         } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) { | 
 | 81 |             paint->setHinting(SkPaint::kSlight_Hinting); | 
 | 82 |         } | 
| reed@google.com | 971aca7 | 2012-11-26 20:26:54 +0000 | [diff] [blame] | 83 |         return true; | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 84 |     } | 
 | 85 |  | 
 | 86 | private: | 
 | 87 |     PictureRenderer::DrawFilterFlags* fFlags; | 
 | 88 | }; | 
 | 89 |  | 
 | 90 | static SkCanvas* setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) { | 
 | 91 |     if (drawFilters && !canvas->getDrawFilter()) { | 
 | 92 |         canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref(); | 
| caryclark@google.com | e3e940c | 2012-11-07 16:42:17 +0000 | [diff] [blame] | 93 |         if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) { | 
 | 94 |             canvas->setAllowSoftClip(false); | 
 | 95 |         } | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 96 |     } | 
 | 97 |     return canvas; | 
 | 98 | } | 
 | 99 |  | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 100 | SkCanvas* PictureRenderer::setupCanvas() { | 
 | 101 |     return this->setupCanvas(fPicture->width(), fPicture->height()); | 
 | 102 | } | 
 | 103 |  | 
 | 104 | SkCanvas* PictureRenderer::setupCanvas(int width, int height) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 105 |     SkCanvas* canvas; | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 106 |     switch(fDeviceType) { | 
 | 107 |         case kBitmap_DeviceType: { | 
 | 108 |             SkBitmap bitmap; | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 109 |             sk_tools::setup_bitmap(&bitmap, width, height); | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 110 |             canvas = SkNEW_ARGS(SkCanvas, (bitmap)); | 
 | 111 |             return setUpFilter(canvas, fDrawFilters); | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 112 |         } | 
 | 113 | #if SK_SUPPORT_GPU | 
 | 114 |         case kGPU_DeviceType: { | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 115 |             SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice, | 
| keyar@chromium.org | 0612564 | 2012-08-20 15:03:33 +0000 | [diff] [blame] | 116 |                                                     (fGrContext, SkBitmap::kARGB_8888_Config, | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 117 |                                                     width, height))); | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 118 |             canvas = SkNEW_ARGS(SkCanvas, (device.get())); | 
 | 119 |             return setUpFilter(canvas, fDrawFilters); | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 120 |         } | 
 | 121 | #endif | 
 | 122 |         default: | 
 | 123 |             SkASSERT(0); | 
 | 124 |     } | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 125 |  | 
 | 126 |     return NULL; | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 127 | } | 
 | 128 |  | 
 | 129 | void PictureRenderer::end() { | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 130 |     this->resetState(); | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 131 |     SkSafeUnref(fPicture); | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 132 |     fPicture = NULL; | 
 | 133 |     fCanvas.reset(NULL); | 
 | 134 | } | 
 | 135 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 136 | /** Converts fPicture to a picture that uses a BBoxHierarchy. | 
 | 137 |  *  PictureRenderer subclasses that are used to test picture playback | 
 | 138 |  *  should call this method during init. | 
 | 139 |  */ | 
 | 140 | void PictureRenderer::buildBBoxHierarchy() { | 
 | 141 |     SkASSERT(NULL != fPicture); | 
 | 142 |     if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) { | 
 | 143 |         SkPicture* newPicture = this->createPicture(); | 
 | 144 |         SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(), | 
 | 145 |                                                         this->recordFlags()); | 
 | 146 |         fPicture->draw(recorder); | 
 | 147 |         newPicture->endRecording(); | 
 | 148 |         fPicture->unref(); | 
 | 149 |         fPicture = newPicture; | 
 | 150 |     } | 
 | 151 | } | 
 | 152 |  | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 153 | void PictureRenderer::resetState() { | 
| keyar@chromium.org | 28136b3 | 2012-08-20 15:04:15 +0000 | [diff] [blame] | 154 | #if SK_SUPPORT_GPU | 
 | 155 |     if (this->isUsingGpuDevice()) { | 
 | 156 |         SkGLContext* glContext = fGrContextFactory.getGLContext( | 
 | 157 |             GrContextFactory::kNative_GLContextType); | 
| keyar@chromium.org | 28136b3 | 2012-08-20 15:04:15 +0000 | [diff] [blame] | 158 |  | 
 | 159 |         SkASSERT(glContext != NULL); | 
 | 160 |         if (NULL == glContext) { | 
 | 161 |             return; | 
 | 162 |         } | 
 | 163 |  | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 164 |         fGrContext->flush(); | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 165 |         SK_GL(*glContext, Finish()); | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 166 |     } | 
| keyar@chromium.org | a40c20d | 2012-08-20 15:04:12 +0000 | [diff] [blame] | 167 | #endif | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 168 | } | 
 | 169 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 170 | uint32_t PictureRenderer::recordFlags() { | 
 | 171 |     return kNone_BBoxHierarchyType == fBBoxHierarchyType ? 0 : | 
 | 172 |         SkPicture::kOptimizeForClippedPlayback_RecordingFlag; | 
 | 173 | } | 
 | 174 |  | 
| scroggo@google.com | b6e806b | 2012-10-03 17:32:33 +0000 | [diff] [blame] | 175 | /** | 
 | 176 |  * Write the canvas to the specified path. | 
 | 177 |  * @param canvas Must be non-null. Canvas to be written to a file. | 
 | 178 |  * @param path Path for the file to be written. Should have no extension; write() will append | 
 | 179 |  *             an appropriate one. Passed in by value so it can be modified. | 
 | 180 |  * @return bool True if the Canvas is written to a file. | 
 | 181 |  */ | 
 | 182 | static bool write(SkCanvas* canvas, SkString path) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 183 |     SkASSERT(canvas != NULL); | 
| scroggo@google.com | b6e806b | 2012-10-03 17:32:33 +0000 | [diff] [blame] | 184 |     if (NULL == canvas) { | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 185 |         return false; | 
 | 186 |     } | 
 | 187 |  | 
 | 188 |     SkBitmap bitmap; | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 189 |     SkISize size = canvas->getDeviceSize(); | 
 | 190 |     sk_tools::setup_bitmap(&bitmap, size.width(), size.height()); | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 191 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 192 |     canvas->readPixels(&bitmap, 0, 0); | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 193 |     sk_tools::force_all_opaque(bitmap); | 
 | 194 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 195 |     // Since path is passed in by value, it is okay to modify it. | 
 | 196 |     path.append(".png"); | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 197 |     return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); | 
 | 198 | } | 
 | 199 |  | 
| scroggo@google.com | b6e806b | 2012-10-03 17:32:33 +0000 | [diff] [blame] | 200 | /** | 
 | 201 |  * If path is non NULL, append number to it, and call write(SkCanvas*, SkString) to write the | 
 | 202 |  * provided canvas to a file. Returns true if path is NULL or if write() succeeds. | 
 | 203 |  */ | 
 | 204 | static bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number) { | 
 | 205 |     if (NULL == path) { | 
 | 206 |         return true; | 
 | 207 |     } | 
 | 208 |     SkString pathWithNumber(*path); | 
 | 209 |     pathWithNumber.appendf("%i", number); | 
 | 210 |     return write(canvas, pathWithNumber); | 
 | 211 | } | 
 | 212 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 213 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 214 |  | 
| djsollen@google.com | fd9720c | 2012-11-06 16:54:40 +0000 | [diff] [blame] | 215 | SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { | 
 | 216 |     // defer the canvas setup until the render step | 
 | 217 |     return NULL; | 
 | 218 | } | 
 | 219 |  | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 220 | static bool PNGEncodeBitmapToStream(SkWStream* wStream, const SkBitmap& bm) { | 
 | 221 |     return SkImageEncoder::EncodeStream(wStream, bm, SkImageEncoder::kPNG_Type, 100); | 
 | 222 | } | 
 | 223 |  | 
 | 224 | bool RecordPictureRenderer::render(const SkString* path) { | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 225 |     SkAutoTUnref<SkPicture> replayer(this->createPicture()); | 
 | 226 |     SkCanvas* recorder = replayer->beginRecording(fPicture->width(), fPicture->height(), | 
 | 227 |                                                   this->recordFlags()); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 228 |     fPicture->draw(recorder); | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 229 |     replayer->endRecording(); | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 230 |     if (path != NULL) { | 
 | 231 |         // Record the new picture as a new SKP with PNG encoded bitmaps. | 
 | 232 |         SkString skpPath(*path); | 
 | 233 |         // ".skp" was removed from 'path' before being passed in here. | 
 | 234 |         skpPath.append(".skp"); | 
 | 235 |         SkFILEWStream stream(skpPath.c_str()); | 
 | 236 |         replayer->serialize(&stream, &PNGEncodeBitmapToStream); | 
 | 237 |         return true; | 
 | 238 |     } | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 239 |     return false; | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 240 | } | 
 | 241 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 242 | SkString RecordPictureRenderer::getConfigNameInternal() { | 
 | 243 |     return SkString("record"); | 
 | 244 | } | 
 | 245 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 246 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 247 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 248 | bool PipePictureRenderer::render(const SkString* path) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 249 |     SkASSERT(fCanvas.get() != NULL); | 
 | 250 |     SkASSERT(fPicture != NULL); | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 251 |     if (NULL == fCanvas.get() || NULL == fPicture) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 252 |         return false; | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 253 |     } | 
 | 254 |  | 
 | 255 |     PipeController pipeController(fCanvas.get()); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 256 |     SkGPipeWriter writer; | 
 | 257 |     SkCanvas* pipeCanvas = writer.startRecording(&pipeController); | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 258 |     pipeCanvas->drawPicture(*fPicture); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 259 |     writer.endRecording(); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 260 |     fCanvas->flush(); | 
| borenet@google.com | 070d354 | 2012-10-26 13:26:55 +0000 | [diff] [blame] | 261 |     if (NULL != path) { | 
 | 262 |         return write(fCanvas, *path); | 
 | 263 |     } | 
 | 264 |     return true; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 265 | } | 
 | 266 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 267 | SkString PipePictureRenderer::getConfigNameInternal() { | 
 | 268 |     return SkString("pipe"); | 
 | 269 | } | 
 | 270 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 271 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 272 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 273 | void SimplePictureRenderer::init(SkPicture* picture) { | 
 | 274 |     INHERITED::init(picture); | 
 | 275 |     this->buildBBoxHierarchy(); | 
 | 276 | } | 
 | 277 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 278 | bool SimplePictureRenderer::render(const SkString* path) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 279 |     SkASSERT(fCanvas.get() != NULL); | 
 | 280 |     SkASSERT(fPicture != NULL); | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 281 |     if (NULL == fCanvas.get() || NULL == fPicture) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 282 |         return false; | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 283 |     } | 
 | 284 |  | 
 | 285 |     fCanvas->drawPicture(*fPicture); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 286 |     fCanvas->flush(); | 
| borenet@google.com | 070d354 | 2012-10-26 13:26:55 +0000 | [diff] [blame] | 287 |     if (NULL != path) { | 
 | 288 |         return write(fCanvas, *path); | 
 | 289 |     } | 
 | 290 |     return true; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 291 | } | 
 | 292 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 293 | SkString SimplePictureRenderer::getConfigNameInternal() { | 
 | 294 |     return SkString("simple"); | 
 | 295 | } | 
 | 296 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 297 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 298 |  | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 299 | TiledPictureRenderer::TiledPictureRenderer() | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 300 |     : fTileWidth(kDefaultTileWidth) | 
| rileya@google.com | b947b91 | 2012-08-29 17:35:07 +0000 | [diff] [blame] | 301 |     , fTileHeight(kDefaultTileHeight) | 
| rileya@google.com | a04dc02 | 2012-09-10 19:01:38 +0000 | [diff] [blame] | 302 |     , fTileWidthPercentage(0.0) | 
| rileya@google.com | b947b91 | 2012-08-29 17:35:07 +0000 | [diff] [blame] | 303 |     , fTileHeightPercentage(0.0) | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 304 |     , fTileMinPowerOf2Width(0) { } | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 305 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 306 | void TiledPictureRenderer::init(SkPicture* pict) { | 
 | 307 |     SkASSERT(pict != NULL); | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 308 |     SkASSERT(0 == fTileRects.count()); | 
 | 309 |     if (NULL == pict || fTileRects.count() != 0) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 310 |         return; | 
 | 311 |     } | 
 | 312 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 313 |     // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not | 
 | 314 |     // used by bench_pictures. | 
 | 315 |     fPicture = pict; | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 316 |     fPicture->ref(); | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 317 |     this->buildBBoxHierarchy(); | 
| keyar@chromium.org | cc6e5ef | 2012-07-27 20:09:26 +0000 | [diff] [blame] | 318 |  | 
 | 319 |     if (fTileWidthPercentage > 0) { | 
| robertphillips@google.com | 5d8d186 | 2012-08-15 14:36:41 +0000 | [diff] [blame] | 320 |         fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100)); | 
| keyar@chromium.org | cc6e5ef | 2012-07-27 20:09:26 +0000 | [diff] [blame] | 321 |     } | 
 | 322 |     if (fTileHeightPercentage > 0) { | 
| robertphillips@google.com | 5d8d186 | 2012-08-15 14:36:41 +0000 | [diff] [blame] | 323 |         fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100)); | 
| keyar@chromium.org | cc6e5ef | 2012-07-27 20:09:26 +0000 | [diff] [blame] | 324 |     } | 
 | 325 |  | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 326 |     if (fTileMinPowerOf2Width > 0) { | 
 | 327 |         this->setupPowerOf2Tiles(); | 
 | 328 |     } else { | 
 | 329 |         this->setupTiles(); | 
 | 330 |     } | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 331 | } | 
 | 332 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 333 | void TiledPictureRenderer::end() { | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 334 |     fTileRects.reset(); | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 335 |     this->INHERITED::end(); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 336 | } | 
 | 337 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 338 | void TiledPictureRenderer::setupTiles() { | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 339 |     for (int tile_y_start = 0; tile_y_start < fPicture->height(); tile_y_start += fTileHeight) { | 
 | 340 |         for (int tile_x_start = 0; tile_x_start < fPicture->width(); tile_x_start += fTileWidth) { | 
 | 341 |             *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), | 
 | 342 |                                                     SkIntToScalar(tile_y_start), | 
 | 343 |                                                     SkIntToScalar(fTileWidth), | 
 | 344 |                                                     SkIntToScalar(fTileHeight)); | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 345 |         } | 
 | 346 |     } | 
 | 347 | } | 
 | 348 |  | 
 | 349 | // The goal of the powers of two tiles is to minimize the amount of wasted tile | 
 | 350 | // space in the width-wise direction and then minimize the number of tiles. The | 
 | 351 | // constraints are that every tile must have a pixel width that is a power of | 
 | 352 | // two and also be of some minimal width (that is also a power of two). | 
 | 353 | // | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 354 | // This is solved by first taking our picture size and rounding it up to the | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 355 | // multiple of the minimal width. The binary representation of this rounded | 
 | 356 | // value gives us the tiles we need: a bit of value one means we need a tile of | 
 | 357 | // that size. | 
 | 358 | void TiledPictureRenderer::setupPowerOf2Tiles() { | 
 | 359 |     int rounded_value = fPicture->width(); | 
 | 360 |     if (fPicture->width() % fTileMinPowerOf2Width != 0) { | 
 | 361 |         rounded_value = fPicture->width() - (fPicture->width() % fTileMinPowerOf2Width) | 
 | 362 |             + fTileMinPowerOf2Width; | 
 | 363 |     } | 
 | 364 |  | 
| robertphillips@google.com | 94acc70 | 2012-09-06 18:43:21 +0000 | [diff] [blame] | 365 |     int num_bits = SkScalarCeilToInt(SkScalarLog2(SkIntToScalar(fPicture->width()))); | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 366 |     int largest_possible_tile_size = 1 << num_bits; | 
 | 367 |  | 
 | 368 |     // The tile height is constant for a particular picture. | 
 | 369 |     for (int tile_y_start = 0; tile_y_start < fPicture->height(); tile_y_start += fTileHeight) { | 
 | 370 |         int tile_x_start = 0; | 
 | 371 |         int current_width = largest_possible_tile_size; | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 372 |         // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough | 
 | 373 |         // to draw each tile. | 
 | 374 |         fTileWidth = current_width; | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 375 |  | 
 | 376 |         while (current_width >= fTileMinPowerOf2Width) { | 
 | 377 |             // It is very important this is a bitwise AND. | 
 | 378 |             if (current_width & rounded_value) { | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 379 |                 *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), | 
 | 380 |                                                         SkIntToScalar(tile_y_start), | 
 | 381 |                                                         SkIntToScalar(current_width), | 
 | 382 |                                                         SkIntToScalar(fTileHeight)); | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 383 |                 tile_x_start += current_width; | 
 | 384 |             } | 
 | 385 |  | 
 | 386 |             current_width >>= 1; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 387 |         } | 
 | 388 |     } | 
 | 389 | } | 
 | 390 |  | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 391 | /** | 
 | 392 |  * Draw the specified playback to the canvas translated to rectangle provided, so that this mini | 
 | 393 |  * canvas represents the rectangle's portion of the overall picture. | 
 | 394 |  * Saves and restores so that the initial clip and matrix return to their state before this function | 
 | 395 |  * is called. | 
 | 396 |  */ | 
 | 397 | template<class T> | 
 | 398 | static void DrawTileToCanvas(SkCanvas* canvas, const SkRect& tileRect, T* playback) { | 
 | 399 |     int saveCount = canvas->save(); | 
 | 400 |     // Translate so that we draw the correct portion of the picture | 
 | 401 |     canvas->translate(-tileRect.fLeft, -tileRect.fTop); | 
 | 402 |     playback->draw(canvas); | 
 | 403 |     canvas->restoreToCount(saveCount); | 
 | 404 |     canvas->flush(); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 405 | } | 
 | 406 |  | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 407 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 408 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 409 | bool TiledPictureRenderer::render(const SkString* path) { | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 410 |     SkASSERT(fPicture != NULL); | 
 | 411 |     if (NULL == fPicture) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 412 |         return false; | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 413 |     } | 
 | 414 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 415 |     // Reuse one canvas for all tiles. | 
 | 416 |     SkCanvas* canvas = this->setupCanvas(fTileWidth, fTileHeight); | 
 | 417 |     SkAutoUnref aur(canvas); | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 418 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 419 |     bool success = true; | 
 | 420 |     for (int i = 0; i < fTileRects.count(); ++i) { | 
 | 421 |         DrawTileToCanvas(canvas, fTileRects[i], fPicture); | 
 | 422 |         if (NULL != path) { | 
 | 423 |             success &= writeAppendNumber(canvas, path, i); | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 424 |         } | 
| keyar@chromium.org | 163b567 | 2012-08-01 17:53:29 +0000 | [diff] [blame] | 425 |     } | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 426 |     return success; | 
| keyar@chromium.org | 163b567 | 2012-08-01 17:53:29 +0000 | [diff] [blame] | 427 | } | 
 | 428 |  | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 429 | SkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) { | 
 | 430 |     SkCanvas* canvas = this->INHERITED::setupCanvas(width, height); | 
 | 431 |     SkASSERT(fPicture != NULL); | 
 | 432 |     // Clip the tile to an area that is completely in what the SkPicture says is the | 
 | 433 |     // drawn-to area. This is mostly important for tiles on the right and bottom edges | 
 | 434 |     // as they may go over this area and the picture may have some commands that | 
 | 435 |     // draw outside of this area and so should not actually be written. | 
 | 436 |     SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()), | 
 | 437 |                                  SkIntToScalar(fPicture->height())); | 
 | 438 |     canvas->clipRect(clip); | 
 | 439 |     return canvas; | 
 | 440 | } | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 441 |  | 
 | 442 | SkString TiledPictureRenderer::getConfigNameInternal() { | 
 | 443 |     SkString name; | 
 | 444 |     if (fTileMinPowerOf2Width > 0) { | 
 | 445 |         name.append("pow2tile_"); | 
 | 446 |         name.appendf("%i", fTileMinPowerOf2Width); | 
 | 447 |     } else { | 
 | 448 |         name.append("tile_"); | 
 | 449 |         if (fTileWidthPercentage > 0) { | 
 | 450 |             name.appendf("%.f%%", fTileWidthPercentage); | 
 | 451 |         } else { | 
 | 452 |             name.appendf("%i", fTileWidth); | 
 | 453 |         } | 
 | 454 |     } | 
 | 455 |     name.append("x"); | 
 | 456 |     if (fTileHeightPercentage > 0) { | 
 | 457 |         name.appendf("%.f%%", fTileHeightPercentage); | 
 | 458 |     } else { | 
 | 459 |         name.appendf("%i", fTileHeight); | 
 | 460 |     } | 
 | 461 |     return name; | 
 | 462 | } | 
 | 463 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 464 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 465 |  | 
 | 466 | // Holds all of the information needed to draw a set of tiles. | 
 | 467 | class CloneData : public SkRunnable { | 
 | 468 |  | 
 | 469 | public: | 
 | 470 |     CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end, | 
 | 471 |               SkRunnable* done) | 
 | 472 |         : fClone(clone) | 
 | 473 |         , fCanvas(canvas) | 
 | 474 |         , fPath(NULL) | 
 | 475 |         , fRects(rects) | 
 | 476 |         , fStart(start) | 
 | 477 |         , fEnd(end) | 
 | 478 |         , fSuccess(NULL) | 
 | 479 |         , fDone(done) { | 
 | 480 |         SkASSERT(fDone != NULL); | 
 | 481 |     } | 
 | 482 |  | 
 | 483 |     virtual void run() SK_OVERRIDE { | 
 | 484 |         SkGraphics::SetTLSFontCacheLimit(1024 * 1024); | 
 | 485 |         for (int i = fStart; i < fEnd; i++) { | 
 | 486 |             DrawTileToCanvas(fCanvas, fRects[i], fClone); | 
 | 487 |             if (fPath != NULL && !writeAppendNumber(fCanvas, fPath, i) | 
 | 488 |                 && fSuccess != NULL) { | 
 | 489 |                 *fSuccess = false; | 
 | 490 |                 // If one tile fails to write to a file, do not continue drawing the rest. | 
 | 491 |                 break; | 
 | 492 |             } | 
 | 493 |         } | 
 | 494 |         fDone->run(); | 
 | 495 |     } | 
 | 496 |  | 
 | 497 |     void setPathAndSuccess(const SkString* path, bool* success) { | 
 | 498 |         fPath = path; | 
 | 499 |         fSuccess = success; | 
 | 500 |     } | 
 | 501 |  | 
 | 502 | private: | 
 | 503 |     // All pointers unowned. | 
 | 504 |     SkPicture*         fClone;      // Picture to draw from. Each CloneData has a unique one which | 
 | 505 |                                     // is threadsafe. | 
 | 506 |     SkCanvas*          fCanvas;     // Canvas to draw to. Reused for each tile. | 
 | 507 |     const SkString*    fPath;       // If non-null, path to write the result to as a PNG. | 
 | 508 |     SkTDArray<SkRect>& fRects;      // All tiles of the picture. | 
 | 509 |     const int          fStart;      // Range of tiles drawn by this thread. | 
 | 510 |     const int          fEnd; | 
 | 511 |     bool*              fSuccess;    // Only meaningful if path is non-null. Shared by all threads, | 
 | 512 |                                     // and only set to false upon failure to write to a PNG. | 
 | 513 |     SkRunnable*        fDone; | 
 | 514 | }; | 
 | 515 |  | 
 | 516 | MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) | 
 | 517 | : fNumThreads(threadCount) | 
 | 518 | , fThreadPool(threadCount) | 
 | 519 | , fCountdown(threadCount) { | 
 | 520 |     // Only need to create fNumThreads - 1 clones, since one thread will use the base | 
 | 521 |     // picture. | 
 | 522 |     fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); | 
 | 523 |     fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); | 
 | 524 | } | 
 | 525 |  | 
 | 526 | void MultiCorePictureRenderer::init(SkPicture *pict) { | 
 | 527 |     // Set fPicture and the tiles. | 
 | 528 |     this->INHERITED::init(pict); | 
 | 529 |     for (int i = 0; i < fNumThreads; ++i) { | 
 | 530 |         *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->getTileHeight()); | 
 | 531 |     } | 
 | 532 |     // Only need to create fNumThreads - 1 clones, since one thread will use the base picture. | 
 | 533 |     fPicture->clone(fPictureClones, fNumThreads - 1); | 
 | 534 |     // Populate each thread with the appropriate data. | 
 | 535 |     // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all. | 
 | 536 |     const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; | 
 | 537 |  | 
 | 538 |     for (int i = 0; i < fNumThreads; i++) { | 
 | 539 |         SkPicture* pic; | 
 | 540 |         if (i == fNumThreads-1) { | 
 | 541 |             // The last set will use the original SkPicture. | 
 | 542 |             pic = fPicture; | 
 | 543 |         } else { | 
 | 544 |             pic = &fPictureClones[i]; | 
 | 545 |         } | 
 | 546 |         const int start = i * chunkSize; | 
 | 547 |         const int end = SkMin32(start + chunkSize, fTileRects.count()); | 
 | 548 |         fCloneData[i] = SkNEW_ARGS(CloneData, | 
 | 549 |                                    (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown)); | 
 | 550 |     } | 
 | 551 | } | 
 | 552 |  | 
 | 553 | bool MultiCorePictureRenderer::render(const SkString *path) { | 
 | 554 |     bool success = true; | 
 | 555 |     if (path != NULL) { | 
 | 556 |         for (int i = 0; i < fNumThreads-1; i++) { | 
 | 557 |             fCloneData[i]->setPathAndSuccess(path, &success); | 
 | 558 |         } | 
 | 559 |     } | 
 | 560 |  | 
 | 561 |     fCountdown.reset(fNumThreads); | 
 | 562 |     for (int i = 0; i < fNumThreads; i++) { | 
 | 563 |         fThreadPool.add(fCloneData[i]); | 
 | 564 |     } | 
 | 565 |     fCountdown.wait(); | 
 | 566 |  | 
 | 567 |     return success; | 
 | 568 | } | 
 | 569 |  | 
 | 570 | void MultiCorePictureRenderer::end() { | 
 | 571 |     for (int i = 0; i < fNumThreads - 1; i++) { | 
 | 572 |         SkDELETE(fCloneData[i]); | 
 | 573 |         fCloneData[i] = NULL; | 
 | 574 |     } | 
 | 575 |  | 
 | 576 |     fCanvasPool.unrefAll(); | 
 | 577 |  | 
 | 578 |     this->INHERITED::end(); | 
 | 579 | } | 
 | 580 |  | 
 | 581 | MultiCorePictureRenderer::~MultiCorePictureRenderer() { | 
 | 582 |     // Each individual CloneData was deleted in end. | 
 | 583 |     SkDELETE_ARRAY(fCloneData); | 
 | 584 |     SkDELETE_ARRAY(fPictureClones); | 
 | 585 | } | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 586 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 587 | SkString MultiCorePictureRenderer::getConfigNameInternal() { | 
 | 588 |     SkString name = this->INHERITED::getConfigNameInternal(); | 
 | 589 |     name.appendf("_multi_%i_threads", fNumThreads); | 
 | 590 |     return name; | 
 | 591 | } | 
 | 592 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 593 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 594 |  | 
 | 595 | void PlaybackCreationRenderer::setup() { | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 596 |     fReplayer.reset(this->createPicture()); | 
 | 597 |     SkCanvas* recorder = fReplayer->beginRecording(fPicture->width(), fPicture->height(), | 
 | 598 |                                                    this->recordFlags()); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 599 |     fPicture->draw(recorder); | 
 | 600 | } | 
 | 601 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 602 | bool PlaybackCreationRenderer::render(const SkString*) { | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 603 |     fReplayer->endRecording(); | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 604 |     // Since this class does not actually render, return false. | 
 | 605 |     return false; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 606 | } | 
 | 607 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 608 | SkString PlaybackCreationRenderer::getConfigNameInternal() { | 
 | 609 |     return SkString("playback_creation"); | 
 | 610 | } | 
 | 611 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 612 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 613 | // SkPicture variants for each BBoxHierarchy type | 
 | 614 |  | 
 | 615 | class RTreePicture : public SkPicture { | 
 | 616 | public: | 
 | 617 |     virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{ | 
 | 618 |         static const int kRTreeMinChildren = 6; | 
 | 619 |         static const int kRTreeMaxChildren = 11; | 
 | 620 |         SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth), | 
 | 621 |                                            SkIntToScalar(fHeight)); | 
 | 622 |         return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren, | 
 | 623 |                                aspectRatio); | 
 | 624 |     } | 
 | 625 | }; | 
 | 626 |  | 
| junov@chromium.org | 7b53706 | 2012-11-06 18:58:43 +0000 | [diff] [blame] | 627 | class TileGridPicture : public SkPicture { | 
 | 628 | public: | 
 | 629 |     TileGridPicture(int tileWidth, int tileHeight, int xTileCount, int yTileCount) { | 
 | 630 |         fTileWidth = tileWidth; | 
 | 631 |         fTileHeight = tileHeight; | 
 | 632 |         fXTileCount = xTileCount; | 
 | 633 |         fYTileCount = yTileCount; | 
 | 634 |     } | 
 | 635 |  | 
 | 636 |     virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{ | 
 | 637 |         return SkNEW_ARGS(SkTileGrid, (fTileWidth, fTileHeight, fXTileCount, fYTileCount)); | 
 | 638 |     } | 
 | 639 | private: | 
 | 640 |     int fTileWidth, fTileHeight, fXTileCount, fYTileCount; | 
 | 641 | }; | 
 | 642 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 643 | SkPicture* PictureRenderer::createPicture() { | 
 | 644 |     switch (fBBoxHierarchyType) { | 
 | 645 |         case kNone_BBoxHierarchyType: | 
 | 646 |             return SkNEW(SkPicture); | 
 | 647 |         case kRTree_BBoxHierarchyType: | 
 | 648 |             return SkNEW(RTreePicture); | 
| junov@chromium.org | 7b53706 | 2012-11-06 18:58:43 +0000 | [diff] [blame] | 649 |         case kTileGrid_BBoxHierarchyType: | 
 | 650 |             { | 
 | 651 |                 int xTileCount = fPicture->width() / fGridWidth + | 
 | 652 |                     ((fPicture->width() % fGridWidth) ? 1 : 0); | 
 | 653 |                 int yTileCount = fPicture->height() / fGridHeight + | 
 | 654 |                     ((fPicture->height() % fGridHeight) ? 1 : 0); | 
 | 655 |                 return SkNEW_ARGS(TileGridPicture, (fGridWidth, fGridHeight, xTileCount, | 
 | 656 |                                                     yTileCount)); | 
 | 657 |             } | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 658 |     } | 
 | 659 |     SkASSERT(0); // invalid bbhType | 
 | 660 |     return NULL; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 661 | } | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 662 |  | 
| reed@google.com | fe7b1ed | 2012-11-29 21:00:39 +0000 | [diff] [blame^] | 663 | /////////////////////////////////////////////////////////////////////////////// | 
 | 664 |  | 
 | 665 | class GatherRenderer : public PictureRenderer { | 
 | 666 | public: | 
 | 667 |     virtual bool render(const SkString* path) SK_OVERRIDE { | 
 | 668 |         SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()), | 
 | 669 |                                        SkIntToScalar(fPicture->height())); | 
 | 670 |         SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds); | 
 | 671 |         SkSafeUnref(data); | 
 | 672 |          | 
 | 673 |         return NULL == path;    // we don't have anything to write | 
 | 674 |     } | 
 | 675 |  | 
 | 676 | private: | 
 | 677 |     virtual SkString getConfigNameInternal() SK_OVERRIDE { | 
 | 678 |         return SkString("gather_pixelrefs"); | 
 | 679 |     } | 
 | 680 | }; | 
 | 681 |  | 
 | 682 | PictureRenderer* CreateGatherPixelRefsRenderer() { | 
 | 683 |     return SkNEW(GatherRenderer); | 
 | 684 | } | 
 | 685 |      | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 686 | } // namespace sk_tools |