| 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" | 
| scroggo@google.com | 1b1bcc3 | 2013-05-21 20:31:23 +0000 | [diff] [blame^] | 12 | #include "SkData.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 13 | #include "SkDevice.h" | 
 | 14 | #include "SkGPipe.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 15 | #if SK_SUPPORT_GPU | 
| robertphillips@google.com | fe1b536 | 2013-02-07 19:45:46 +0000 | [diff] [blame] | 16 | #include "gl/GrGLDefines.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 17 | #include "SkGpuDevice.h" | 
 | 18 | #endif | 
 | 19 | #include "SkGraphics.h" | 
 | 20 | #include "SkImageEncoder.h" | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 21 | #include "SkMaskFilter.h" | 
| keyar@chromium.org | ea82695 | 2012-08-23 15:24:13 +0000 | [diff] [blame] | 22 | #include "SkMatrix.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 23 | #include "SkPicture.h" | 
| scroggo@google.com | 1b1bcc3 | 2013-05-21 20:31:23 +0000 | [diff] [blame^] | 24 | #include "SkPictureUtils.h" | 
 | 25 | #include "SkPixelRef.h" | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 26 | #include "SkRTree.h" | 
| keyar@chromium.org | ea82695 | 2012-08-23 15:24:13 +0000 | [diff] [blame] | 27 | #include "SkScalar.h" | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 28 | #include "SkStream.h" | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 29 | #include "SkString.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 30 | #include "SkTemplates.h" | 
| junov@chromium.org | 3cb834b | 2012-12-13 16:39:53 +0000 | [diff] [blame] | 31 | #include "SkTileGridPicture.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 32 | #include "SkTDArray.h" | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 33 | #include "SkThreadUtils.h" | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 34 | #include "SkTypes.h" | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 35 |  | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 36 | namespace sk_tools { | 
 | 37 |  | 
 | 38 | enum { | 
 | 39 |     kDefaultTileWidth = 256, | 
 | 40 |     kDefaultTileHeight = 256 | 
 | 41 | }; | 
 | 42 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 43 | void PictureRenderer::init(SkPicture* pict) { | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 44 |     SkASSERT(NULL == fPicture); | 
 | 45 |     SkASSERT(NULL == fCanvas.get()); | 
 | 46 |     if (fPicture != NULL || NULL != fCanvas.get()) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 47 |         return; | 
 | 48 |     } | 
 | 49 |  | 
 | 50 |     SkASSERT(pict != NULL); | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 51 |     if (NULL == pict) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 52 |         return; | 
 | 53 |     } | 
 | 54 |  | 
 | 55 |     fPicture = pict; | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 56 |     fPicture->ref(); | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 57 |     fCanvas.reset(this->setupCanvas()); | 
 | 58 | } | 
 | 59 |  | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 60 | class FlagsDrawFilter : public SkDrawFilter { | 
 | 61 | public: | 
 | 62 |     FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) : | 
 | 63 |         fFlags(flags) {} | 
 | 64 |  | 
| reed@google.com | 971aca7 | 2012-11-26 20:26:54 +0000 | [diff] [blame] | 65 |     virtual bool filter(SkPaint* paint, Type t) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 66 |         paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags); | 
| reed@google.com | 457d8a7 | 2012-12-18 18:20:44 +0000 | [diff] [blame] | 67 |         if (PictureRenderer::kBlur_DrawFilterFlag & fFlags[t]) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 68 |             SkMaskFilter* maskFilter = paint->getMaskFilter(); | 
 | 69 |             SkMaskFilter::BlurInfo blurInfo; | 
 | 70 |             if (maskFilter && maskFilter->asABlur(&blurInfo)) { | 
| reed@google.com | 457d8a7 | 2012-12-18 18:20:44 +0000 | [diff] [blame] | 71 |                 paint->setMaskFilter(NULL); | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 72 |             } | 
 | 73 |         } | 
 | 74 |         if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) { | 
 | 75 |             paint->setHinting(SkPaint::kNo_Hinting); | 
 | 76 |         } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) { | 
 | 77 |             paint->setHinting(SkPaint::kSlight_Hinting); | 
 | 78 |         } | 
| reed@google.com | 971aca7 | 2012-11-26 20:26:54 +0000 | [diff] [blame] | 79 |         return true; | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 80 |     } | 
 | 81 |  | 
 | 82 | private: | 
 | 83 |     PictureRenderer::DrawFilterFlags* fFlags; | 
 | 84 | }; | 
 | 85 |  | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 86 | static void setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 87 |     if (drawFilters && !canvas->getDrawFilter()) { | 
 | 88 |         canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref(); | 
| caryclark@google.com | e3e940c | 2012-11-07 16:42:17 +0000 | [diff] [blame] | 89 |         if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) { | 
 | 90 |             canvas->setAllowSoftClip(false); | 
 | 91 |         } | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 92 |     } | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 93 | } | 
 | 94 |  | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 95 | SkCanvas* PictureRenderer::setupCanvas() { | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 96 |     const int width = this->getViewWidth(); | 
 | 97 |     const int height = this->getViewHeight(); | 
 | 98 |     return this->setupCanvas(width, height); | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 99 | } | 
 | 100 |  | 
 | 101 | SkCanvas* PictureRenderer::setupCanvas(int width, int height) { | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 102 |     SkCanvas* canvas; | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 103 |     switch(fDeviceType) { | 
 | 104 |         case kBitmap_DeviceType: { | 
 | 105 |             SkBitmap bitmap; | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 106 |             sk_tools::setup_bitmap(&bitmap, width, height); | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 107 |             canvas = SkNEW_ARGS(SkCanvas, (bitmap)); | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 108 |         } | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 109 |         break; | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 110 | #if SK_SUPPORT_GPU | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 111 | #if SK_ANGLE | 
 | 112 |         case kAngle_DeviceType: | 
 | 113 |             // fall through | 
 | 114 | #endif | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 115 |         case kGPU_DeviceType: { | 
| commit-bot@chromium.org | ae403b9 | 2013-04-10 17:27:30 +0000 | [diff] [blame] | 116 |             SkAutoTUnref<GrSurface> target; | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 117 |             if (fGrContext) { | 
 | 118 |                 // create a render target to back the device | 
 | 119 |                 GrTextureDesc desc; | 
 | 120 |                 desc.fConfig = kSkia8888_GrPixelConfig; | 
 | 121 |                 desc.fFlags = kRenderTarget_GrTextureFlagBit; | 
 | 122 |                 desc.fWidth = width; | 
 | 123 |                 desc.fHeight = height; | 
| jvanverth@google.com | f6a9033 | 2013-05-02 12:39:37 +0000 | [diff] [blame] | 124 |                 desc.fSampleCnt = fSampleCount; | 
| commit-bot@chromium.org | ae403b9 | 2013-04-10 17:27:30 +0000 | [diff] [blame] | 125 |                 target.reset(fGrContext->createUncachedTexture(desc, NULL, 0)); | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 126 |             } | 
| commit-bot@chromium.org | ae403b9 | 2013-04-10 17:27:30 +0000 | [diff] [blame] | 127 |             if (NULL == target.get()) { | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 128 |                 SkASSERT(0); | 
 | 129 |                 return NULL; | 
 | 130 |             } | 
 | 131 |  | 
| commit-bot@chromium.org | ae403b9 | 2013-04-10 17:27:30 +0000 | [diff] [blame] | 132 |             SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target)); | 
| caryclark@google.com | a362237 | 2012-11-06 21:26:13 +0000 | [diff] [blame] | 133 |             canvas = SkNEW_ARGS(SkCanvas, (device.get())); | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 134 |             break; | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 135 |         } | 
 | 136 | #endif | 
 | 137 |         default: | 
 | 138 |             SkASSERT(0); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 139 |             return NULL; | 
| keyar@chromium.org | 4ea96c5 | 2012-08-20 15:03:29 +0000 | [diff] [blame] | 140 |     } | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 141 |     setUpFilter(canvas, fDrawFilters); | 
 | 142 |     this->scaleToScaleFactor(canvas); | 
 | 143 |     return canvas; | 
 | 144 | } | 
| keyar@chromium.org | a474ce3 | 2012-08-20 15:03:57 +0000 | [diff] [blame] | 145 |  | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 146 | void PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) { | 
 | 147 |     SkASSERT(canvas != NULL); | 
 | 148 |     if (fScaleFactor != SK_Scalar1) { | 
 | 149 |         canvas->scale(fScaleFactor, fScaleFactor); | 
 | 150 |     } | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 151 | } | 
 | 152 |  | 
 | 153 | void PictureRenderer::end() { | 
| scroggo@google.com | 08085f8 | 2013-01-28 20:40:24 +0000 | [diff] [blame] | 154 |     this->resetState(true); | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 155 |     SkSafeUnref(fPicture); | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 156 |     fPicture = NULL; | 
 | 157 |     fCanvas.reset(NULL); | 
 | 158 | } | 
 | 159 |  | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 160 | int PictureRenderer::getViewWidth() { | 
 | 161 |     SkASSERT(fPicture != NULL); | 
| robertphillips@google.com | 8ac811e | 2013-02-07 00:13:34 +0000 | [diff] [blame] | 162 |     int width = SkScalarCeilToInt(fPicture->width() * fScaleFactor); | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 163 |     if (fViewport.width() > 0) { | 
 | 164 |         width = SkMin32(width, fViewport.width()); | 
 | 165 |     } | 
 | 166 |     return width; | 
 | 167 | } | 
 | 168 |  | 
 | 169 | int PictureRenderer::getViewHeight() { | 
 | 170 |     SkASSERT(fPicture != NULL); | 
| robertphillips@google.com | 8ac811e | 2013-02-07 00:13:34 +0000 | [diff] [blame] | 171 |     int height = SkScalarCeilToInt(fPicture->height() * fScaleFactor); | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 172 |     if (fViewport.height() > 0) { | 
 | 173 |         height = SkMin32(height, fViewport.height()); | 
 | 174 |     } | 
 | 175 |     return height; | 
 | 176 | } | 
 | 177 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 178 | /** Converts fPicture to a picture that uses a BBoxHierarchy. | 
 | 179 |  *  PictureRenderer subclasses that are used to test picture playback | 
 | 180 |  *  should call this method during init. | 
 | 181 |  */ | 
 | 182 | void PictureRenderer::buildBBoxHierarchy() { | 
 | 183 |     SkASSERT(NULL != fPicture); | 
 | 184 |     if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) { | 
 | 185 |         SkPicture* newPicture = this->createPicture(); | 
 | 186 |         SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(), | 
 | 187 |                                                         this->recordFlags()); | 
 | 188 |         fPicture->draw(recorder); | 
 | 189 |         newPicture->endRecording(); | 
 | 190 |         fPicture->unref(); | 
 | 191 |         fPicture = newPicture; | 
 | 192 |     } | 
 | 193 | } | 
 | 194 |  | 
| scroggo@google.com | 08085f8 | 2013-01-28 20:40:24 +0000 | [diff] [blame] | 195 | void PictureRenderer::resetState(bool callFinish) { | 
| keyar@chromium.org | 28136b3 | 2012-08-20 15:04:15 +0000 | [diff] [blame] | 196 | #if SK_SUPPORT_GPU | 
| robertphillips@google.com | 6177e69 | 2013-02-28 20:16:25 +0000 | [diff] [blame] | 197 |     SkGLContextHelper* glContext = this->getGLContext(); | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 198 |     if (NULL == glContext) { | 
 | 199 |         SkASSERT(kBitmap_DeviceType == fDeviceType); | 
 | 200 |         return; | 
 | 201 |     } | 
| keyar@chromium.org | 28136b3 | 2012-08-20 15:04:15 +0000 | [diff] [blame] | 202 |  | 
| scroggo@google.com | 0556ea0 | 2013-02-08 19:38:21 +0000 | [diff] [blame] | 203 |     fGrContext->flush(); | 
 | 204 |     if (callFinish) { | 
 | 205 |         SK_GL(*glContext, Finish()); | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 206 |     } | 
| keyar@chromium.org | a40c20d | 2012-08-20 15:04:12 +0000 | [diff] [blame] | 207 | #endif | 
| keyar@chromium.org | 77a5522 | 2012-08-20 15:03:47 +0000 | [diff] [blame] | 208 | } | 
 | 209 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 210 | uint32_t PictureRenderer::recordFlags() { | 
| junov@chromium.org | 100b1c5 | 2013-01-16 20:12:22 +0000 | [diff] [blame] | 211 |     return ((kNone_BBoxHierarchyType == fBBoxHierarchyType) ? 0 : | 
 | 212 |         SkPicture::kOptimizeForClippedPlayback_RecordingFlag) | | 
 | 213 |         SkPicture::kUsePathBoundsForClip_RecordingFlag; | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 214 | } | 
 | 215 |  | 
| scroggo@google.com | b6e806b | 2012-10-03 17:32:33 +0000 | [diff] [blame] | 216 | /** | 
 | 217 |  * Write the canvas to the specified path. | 
 | 218 |  * @param canvas Must be non-null. Canvas to be written to a file. | 
 | 219 |  * @param path Path for the file to be written. Should have no extension; write() will append | 
 | 220 |  *             an appropriate one. Passed in by value so it can be modified. | 
 | 221 |  * @return bool True if the Canvas is written to a file. | 
 | 222 |  */ | 
 | 223 | static bool write(SkCanvas* canvas, SkString path) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 224 |     SkASSERT(canvas != NULL); | 
| scroggo@google.com | b6e806b | 2012-10-03 17:32:33 +0000 | [diff] [blame] | 225 |     if (NULL == canvas) { | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 226 |         return false; | 
 | 227 |     } | 
 | 228 |  | 
 | 229 |     SkBitmap bitmap; | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 230 |     SkISize size = canvas->getDeviceSize(); | 
 | 231 |     sk_tools::setup_bitmap(&bitmap, size.width(), size.height()); | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 232 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 233 |     canvas->readPixels(&bitmap, 0, 0); | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 234 |     sk_tools::force_all_opaque(bitmap); | 
 | 235 |  | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 236 |     // Since path is passed in by value, it is okay to modify it. | 
 | 237 |     path.append(".png"); | 
| keyar@chromium.org | 9299ede | 2012-08-21 19:05:08 +0000 | [diff] [blame] | 238 |     return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); | 
 | 239 | } | 
 | 240 |  | 
| scroggo@google.com | b6e806b | 2012-10-03 17:32:33 +0000 | [diff] [blame] | 241 | /** | 
 | 242 |  * If path is non NULL, append number to it, and call write(SkCanvas*, SkString) to write the | 
 | 243 |  * provided canvas to a file. Returns true if path is NULL or if write() succeeds. | 
 | 244 |  */ | 
 | 245 | static bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number) { | 
 | 246 |     if (NULL == path) { | 
 | 247 |         return true; | 
 | 248 |     } | 
 | 249 |     SkString pathWithNumber(*path); | 
 | 250 |     pathWithNumber.appendf("%i", number); | 
 | 251 |     return write(canvas, pathWithNumber); | 
 | 252 | } | 
 | 253 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 254 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 255 |  | 
| djsollen@google.com | fd9720c | 2012-11-06 16:54:40 +0000 | [diff] [blame] | 256 | SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { | 
 | 257 |     // defer the canvas setup until the render step | 
 | 258 |     return NULL; | 
 | 259 | } | 
 | 260 |  | 
| scroggo@google.com | 1b1bcc3 | 2013-05-21 20:31:23 +0000 | [diff] [blame^] | 261 | static SkData* encode_bitmap_to_data(size_t* offset, const SkBitmap& bm) { | 
 | 262 |     SkPixelRef* pr = bm.pixelRef(); | 
 | 263 |     if (pr != NULL) { | 
 | 264 |         SkData* data = pr->refEncodedData(); | 
 | 265 |         if (data != NULL) { | 
 | 266 |             *offset = bm.pixelRefOffset(); | 
 | 267 |             return data; | 
 | 268 |         } | 
 | 269 |     } | 
 | 270 |     *offset = 0; | 
 | 271 |     return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100); | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 272 | } | 
 | 273 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 274 | bool RecordPictureRenderer::render(const SkString* path, SkBitmap** out) { | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 275 |     SkAutoTUnref<SkPicture> replayer(this->createPicture()); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 276 |     SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->getViewHeight(), | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 277 |                                                   this->recordFlags()); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 278 |     this->scaleToScaleFactor(recorder); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 279 |     fPicture->draw(recorder); | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 280 |     replayer->endRecording(); | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 281 |     if (path != NULL) { | 
 | 282 |         // Record the new picture as a new SKP with PNG encoded bitmaps. | 
 | 283 |         SkString skpPath(*path); | 
 | 284 |         // ".skp" was removed from 'path' before being passed in here. | 
 | 285 |         skpPath.append(".skp"); | 
 | 286 |         SkFILEWStream stream(skpPath.c_str()); | 
| scroggo@google.com | 1b1bcc3 | 2013-05-21 20:31:23 +0000 | [diff] [blame^] | 287 |         replayer->serialize(&stream, &encode_bitmap_to_data); | 
| scroggo@google.com | a9e3a36 | 2012-11-07 17:52:48 +0000 | [diff] [blame] | 288 |         return true; | 
 | 289 |     } | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 290 |     return false; | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 291 | } | 
 | 292 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 293 | SkString RecordPictureRenderer::getConfigNameInternal() { | 
 | 294 |     return SkString("record"); | 
 | 295 | } | 
 | 296 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 297 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 298 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 299 | bool PipePictureRenderer::render(const SkString* path, SkBitmap** out) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 300 |     SkASSERT(fCanvas.get() != NULL); | 
 | 301 |     SkASSERT(fPicture != NULL); | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 302 |     if (NULL == fCanvas.get() || NULL == fPicture) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 303 |         return false; | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 304 |     } | 
 | 305 |  | 
 | 306 |     PipeController pipeController(fCanvas.get()); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 307 |     SkGPipeWriter writer; | 
 | 308 |     SkCanvas* pipeCanvas = writer.startRecording(&pipeController); | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 309 |     pipeCanvas->drawPicture(*fPicture); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 310 |     writer.endRecording(); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 311 |     fCanvas->flush(); | 
| borenet@google.com | 070d354 | 2012-10-26 13:26:55 +0000 | [diff] [blame] | 312 |     if (NULL != path) { | 
 | 313 |         return write(fCanvas, *path); | 
 | 314 |     } | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 315 |     if (NULL != out) { | 
 | 316 |         *out = SkNEW(SkBitmap); | 
 | 317 |         setup_bitmap(*out, fPicture->width(), fPicture->height()); | 
 | 318 |         fCanvas->readPixels(*out, 0, 0); | 
| skia.committer@gmail.com | a7d8e3e | 2012-12-19 02:01:38 +0000 | [diff] [blame] | 319 |     } | 
| borenet@google.com | 070d354 | 2012-10-26 13:26:55 +0000 | [diff] [blame] | 320 |     return true; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 321 | } | 
 | 322 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 323 | SkString PipePictureRenderer::getConfigNameInternal() { | 
 | 324 |     return SkString("pipe"); | 
 | 325 | } | 
 | 326 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 327 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 328 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 329 | void SimplePictureRenderer::init(SkPicture* picture) { | 
 | 330 |     INHERITED::init(picture); | 
 | 331 |     this->buildBBoxHierarchy(); | 
 | 332 | } | 
 | 333 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 334 | bool SimplePictureRenderer::render(const SkString* path, SkBitmap** out) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 335 |     SkASSERT(fCanvas.get() != NULL); | 
 | 336 |     SkASSERT(fPicture != NULL); | 
| keyar@chromium.org | 78a35c5 | 2012-08-20 15:03:44 +0000 | [diff] [blame] | 337 |     if (NULL == fCanvas.get() || NULL == fPicture) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 338 |         return false; | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 339 |     } | 
 | 340 |  | 
 | 341 |     fCanvas->drawPicture(*fPicture); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 342 |     fCanvas->flush(); | 
| borenet@google.com | 070d354 | 2012-10-26 13:26:55 +0000 | [diff] [blame] | 343 |     if (NULL != path) { | 
 | 344 |         return write(fCanvas, *path); | 
 | 345 |     } | 
| skia.committer@gmail.com | a7d8e3e | 2012-12-19 02:01:38 +0000 | [diff] [blame] | 346 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 347 |     if (NULL != out) { | 
 | 348 |         *out = SkNEW(SkBitmap); | 
 | 349 |         setup_bitmap(*out, fPicture->width(), fPicture->height()); | 
 | 350 |         fCanvas->readPixels(*out, 0, 0); | 
 | 351 |     } | 
 | 352 |  | 
| borenet@google.com | 070d354 | 2012-10-26 13:26:55 +0000 | [diff] [blame] | 353 |     return true; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 354 | } | 
 | 355 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 356 | SkString SimplePictureRenderer::getConfigNameInternal() { | 
 | 357 |     return SkString("simple"); | 
 | 358 | } | 
 | 359 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 360 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 361 |  | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 362 | TiledPictureRenderer::TiledPictureRenderer() | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 363 |     : fTileWidth(kDefaultTileWidth) | 
| rileya@google.com | b947b91 | 2012-08-29 17:35:07 +0000 | [diff] [blame] | 364 |     , fTileHeight(kDefaultTileHeight) | 
| rileya@google.com | a04dc02 | 2012-09-10 19:01:38 +0000 | [diff] [blame] | 365 |     , fTileWidthPercentage(0.0) | 
| rileya@google.com | b947b91 | 2012-08-29 17:35:07 +0000 | [diff] [blame] | 366 |     , fTileHeightPercentage(0.0) | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 367 |     , fTileMinPowerOf2Width(0) | 
 | 368 |     , fCurrentTileOffset(-1) | 
 | 369 |     , fTilesX(0) | 
 | 370 |     , fTilesY(0) { } | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 371 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 372 | void TiledPictureRenderer::init(SkPicture* pict) { | 
 | 373 |     SkASSERT(pict != NULL); | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 374 |     SkASSERT(0 == fTileRects.count()); | 
 | 375 |     if (NULL == pict || fTileRects.count() != 0) { | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 376 |         return; | 
 | 377 |     } | 
 | 378 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 379 |     // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not | 
 | 380 |     // used by bench_pictures. | 
 | 381 |     fPicture = pict; | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 382 |     fPicture->ref(); | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 383 |     this->buildBBoxHierarchy(); | 
| keyar@chromium.org | cc6e5ef | 2012-07-27 20:09:26 +0000 | [diff] [blame] | 384 |  | 
 | 385 |     if (fTileWidthPercentage > 0) { | 
| robertphillips@google.com | 5d8d186 | 2012-08-15 14:36:41 +0000 | [diff] [blame] | 386 |         fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100)); | 
| keyar@chromium.org | cc6e5ef | 2012-07-27 20:09:26 +0000 | [diff] [blame] | 387 |     } | 
 | 388 |     if (fTileHeightPercentage > 0) { | 
| robertphillips@google.com | 5d8d186 | 2012-08-15 14:36:41 +0000 | [diff] [blame] | 389 |         fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100)); | 
| keyar@chromium.org | cc6e5ef | 2012-07-27 20:09:26 +0000 | [diff] [blame] | 390 |     } | 
 | 391 |  | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 392 |     if (fTileMinPowerOf2Width > 0) { | 
 | 393 |         this->setupPowerOf2Tiles(); | 
 | 394 |     } else { | 
 | 395 |         this->setupTiles(); | 
 | 396 |     } | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 397 |     fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight)); | 
 | 398 |     // Initialize to -1 so that the first call to nextTile will set this up to draw tile 0 on the | 
 | 399 |     // first call to drawCurrentTile. | 
 | 400 |     fCurrentTileOffset = -1; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 401 | } | 
 | 402 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 403 | void TiledPictureRenderer::end() { | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 404 |     fTileRects.reset(); | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 405 |     this->INHERITED::end(); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 406 | } | 
 | 407 |  | 
| keyar@chromium.org | 9d696c0 | 2012-08-07 17:11:33 +0000 | [diff] [blame] | 408 | void TiledPictureRenderer::setupTiles() { | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 409 |     // Only use enough tiles to cover the viewport | 
 | 410 |     const int width = this->getViewWidth(); | 
 | 411 |     const int height = this->getViewHeight(); | 
 | 412 |  | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 413 |     fTilesX = fTilesY = 0; | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 414 |     for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) { | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 415 |         fTilesY++; | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 416 |         for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWidth) { | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 417 |             if (0 == tile_y_start) { | 
 | 418 |                 // Only count tiles in the X direction on the first pass. | 
 | 419 |                 fTilesX++; | 
 | 420 |             } | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 421 |             *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), | 
 | 422 |                                                     SkIntToScalar(tile_y_start), | 
 | 423 |                                                     SkIntToScalar(fTileWidth), | 
 | 424 |                                                     SkIntToScalar(fTileHeight)); | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 425 |         } | 
 | 426 |     } | 
 | 427 | } | 
 | 428 |  | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 429 | bool TiledPictureRenderer::tileDimensions(int &x, int &y) { | 
 | 430 |     if (fTileRects.count() == 0 || NULL == fPicture) { | 
 | 431 |         return false; | 
 | 432 |     } | 
 | 433 |     x = fTilesX; | 
 | 434 |     y = fTilesY; | 
 | 435 |     return true; | 
 | 436 | } | 
 | 437 |  | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 438 | // The goal of the powers of two tiles is to minimize the amount of wasted tile | 
 | 439 | // space in the width-wise direction and then minimize the number of tiles. The | 
 | 440 | // constraints are that every tile must have a pixel width that is a power of | 
 | 441 | // two and also be of some minimal width (that is also a power of two). | 
 | 442 | // | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 443 | // 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] | 444 | // multiple of the minimal width. The binary representation of this rounded | 
 | 445 | // value gives us the tiles we need: a bit of value one means we need a tile of | 
 | 446 | // that size. | 
 | 447 | void TiledPictureRenderer::setupPowerOf2Tiles() { | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 448 |     // Only use enough tiles to cover the viewport | 
 | 449 |     const int width = this->getViewWidth(); | 
 | 450 |     const int height = this->getViewHeight(); | 
 | 451 |  | 
 | 452 |     int rounded_value = width; | 
 | 453 |     if (width % fTileMinPowerOf2Width != 0) { | 
 | 454 |         rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerOf2Width; | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 455 |     } | 
 | 456 |  | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 457 |     int num_bits = SkScalarCeilToInt(SkScalarLog2(SkIntToScalar(width))); | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 458 |     int largest_possible_tile_size = 1 << num_bits; | 
 | 459 |  | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 460 |     fTilesX = fTilesY = 0; | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 461 |     // The tile height is constant for a particular picture. | 
| scroggo@google.com | c0d5e54 | 2012-12-13 21:40:48 +0000 | [diff] [blame] | 462 |     for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) { | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 463 |         fTilesY++; | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 464 |         int tile_x_start = 0; | 
 | 465 |         int current_width = largest_possible_tile_size; | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 466 |         // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough | 
 | 467 |         // to draw each tile. | 
 | 468 |         fTileWidth = current_width; | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 469 |  | 
 | 470 |         while (current_width >= fTileMinPowerOf2Width) { | 
 | 471 |             // It is very important this is a bitwise AND. | 
 | 472 |             if (current_width & rounded_value) { | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 473 |                 if (0 == tile_y_start) { | 
 | 474 |                     // Only count tiles in the X direction on the first pass. | 
 | 475 |                     fTilesX++; | 
 | 476 |                 } | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 477 |                 *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), | 
 | 478 |                                                         SkIntToScalar(tile_y_start), | 
 | 479 |                                                         SkIntToScalar(current_width), | 
 | 480 |                                                         SkIntToScalar(fTileHeight)); | 
| keyar@chromium.org | f4959ab | 2012-08-23 20:53:25 +0000 | [diff] [blame] | 481 |                 tile_x_start += current_width; | 
 | 482 |             } | 
 | 483 |  | 
 | 484 |             current_width >>= 1; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 485 |         } | 
 | 486 |     } | 
 | 487 | } | 
 | 488 |  | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 489 | /** | 
 | 490 |  * Draw the specified playback to the canvas translated to rectangle provided, so that this mini | 
 | 491 |  * canvas represents the rectangle's portion of the overall picture. | 
 | 492 |  * Saves and restores so that the initial clip and matrix return to their state before this function | 
 | 493 |  * is called. | 
 | 494 |  */ | 
 | 495 | template<class T> | 
 | 496 | static void DrawTileToCanvas(SkCanvas* canvas, const SkRect& tileRect, T* playback) { | 
 | 497 |     int saveCount = canvas->save(); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 498 |     // Translate so that we draw the correct portion of the picture. | 
 | 499 |     // Perform a postTranslate so that the scaleFactor does not interfere with the positioning. | 
 | 500 |     SkMatrix mat(canvas->getTotalMatrix()); | 
 | 501 |     mat.postTranslate(-tileRect.fLeft, -tileRect.fTop); | 
 | 502 |     canvas->setMatrix(mat); | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 503 |     playback->draw(canvas); | 
 | 504 |     canvas->restoreToCount(saveCount); | 
 | 505 |     canvas->flush(); | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 506 | } | 
 | 507 |  | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 508 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 509 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 510 | static void bitmapCopySubset(const SkBitmap& src, SkBitmap* dst, int xDst, | 
 | 511 |                              int yDst) { | 
 | 512 |     for (int y = 0; y <src.height() && y + yDst < dst->height() ; y++) { | 
 | 513 |         for (int x = 0; x < src.width() && x + xDst < dst->width() ; x++) { | 
 | 514 |             *dst->getAddr32(xDst + x, yDst + y) = *src.getAddr32(x, y); | 
 | 515 |         } | 
 | 516 |     } | 
 | 517 | } | 
 | 518 |  | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 519 | bool TiledPictureRenderer::nextTile(int &i, int &j) { | 
 | 520 |     if (++fCurrentTileOffset < fTileRects.count()) { | 
 | 521 |         i = fCurrentTileOffset % fTilesX; | 
 | 522 |         j = fCurrentTileOffset / fTilesX; | 
 | 523 |         return true; | 
 | 524 |     } | 
 | 525 |     return false; | 
 | 526 | } | 
 | 527 |  | 
 | 528 | void TiledPictureRenderer::drawCurrentTile() { | 
 | 529 |     SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count()); | 
 | 530 |     DrawTileToCanvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture); | 
 | 531 | } | 
 | 532 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 533 | bool TiledPictureRenderer::render(const SkString* path, SkBitmap** out) { | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 534 |     SkASSERT(fPicture != NULL); | 
 | 535 |     if (NULL == fPicture) { | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 536 |         return false; | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 537 |     } | 
 | 538 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 539 |     SkBitmap bitmap; | 
 | 540 |     if (out){ | 
 | 541 |         *out = SkNEW(SkBitmap); | 
 | 542 |         setup_bitmap(*out, fPicture->width(), fPicture->height()); | 
 | 543 |         setup_bitmap(&bitmap, fTileWidth, fTileHeight); | 
 | 544 |     } | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 545 |     bool success = true; | 
 | 546 |     for (int i = 0; i < fTileRects.count(); ++i) { | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 547 |         DrawTileToCanvas(fCanvas, fTileRects[i], fPicture); | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 548 |         if (NULL != path) { | 
| scroggo@google.com | cbcef70 | 2012-12-13 22:09:28 +0000 | [diff] [blame] | 549 |             success &= writeAppendNumber(fCanvas, path, i); | 
| scroggo@google.com | 58b4ead | 2012-08-31 16:15:22 +0000 | [diff] [blame] | 550 |         } | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 551 |         if (NULL != out) { | 
 | 552 |             if (fCanvas->readPixels(&bitmap, 0, 0)) { | 
| jvanverth@google.com | 9c4e5ac | 2013-01-07 18:41:28 +0000 | [diff] [blame] | 553 |                 bitmapCopySubset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()), | 
 | 554 |                                  SkScalarFloorToInt(fTileRects[i].top())); | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 555 |             } else { | 
 | 556 |                 success = false; | 
 | 557 |             } | 
 | 558 |         } | 
| keyar@chromium.org | 163b567 | 2012-08-01 17:53:29 +0000 | [diff] [blame] | 559 |     } | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 560 |     return success; | 
| keyar@chromium.org | 163b567 | 2012-08-01 17:53:29 +0000 | [diff] [blame] | 561 | } | 
 | 562 |  | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 563 | SkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) { | 
 | 564 |     SkCanvas* canvas = this->INHERITED::setupCanvas(width, height); | 
 | 565 |     SkASSERT(fPicture != NULL); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 566 |     // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This | 
 | 567 |     // is mostly important for tiles on the right and bottom edges as they may go over this area and | 
 | 568 |     // the picture may have some commands that draw outside of this area and so should not actually | 
 | 569 |     // be written. | 
 | 570 |     // Uses a clipRegion so that it will be unaffected by the scale factor, which may have been set | 
 | 571 |     // by INHERITED::setupCanvas. | 
 | 572 |     SkRegion clipRegion; | 
 | 573 |     clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight()); | 
 | 574 |     canvas->clipRegion(clipRegion); | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 575 |     return canvas; | 
 | 576 | } | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 577 |  | 
 | 578 | SkString TiledPictureRenderer::getConfigNameInternal() { | 
 | 579 |     SkString name; | 
 | 580 |     if (fTileMinPowerOf2Width > 0) { | 
 | 581 |         name.append("pow2tile_"); | 
 | 582 |         name.appendf("%i", fTileMinPowerOf2Width); | 
 | 583 |     } else { | 
 | 584 |         name.append("tile_"); | 
 | 585 |         if (fTileWidthPercentage > 0) { | 
 | 586 |             name.appendf("%.f%%", fTileWidthPercentage); | 
 | 587 |         } else { | 
 | 588 |             name.appendf("%i", fTileWidth); | 
 | 589 |         } | 
 | 590 |     } | 
 | 591 |     name.append("x"); | 
 | 592 |     if (fTileHeightPercentage > 0) { | 
 | 593 |         name.appendf("%.f%%", fTileHeightPercentage); | 
 | 594 |     } else { | 
 | 595 |         name.appendf("%i", fTileHeight); | 
 | 596 |     } | 
 | 597 |     return name; | 
 | 598 | } | 
 | 599 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 600 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 601 |  | 
 | 602 | // Holds all of the information needed to draw a set of tiles. | 
 | 603 | class CloneData : public SkRunnable { | 
 | 604 |  | 
 | 605 | public: | 
 | 606 |     CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end, | 
 | 607 |               SkRunnable* done) | 
 | 608 |         : fClone(clone) | 
 | 609 |         , fCanvas(canvas) | 
 | 610 |         , fPath(NULL) | 
 | 611 |         , fRects(rects) | 
 | 612 |         , fStart(start) | 
 | 613 |         , fEnd(end) | 
 | 614 |         , fSuccess(NULL) | 
 | 615 |         , fDone(done) { | 
 | 616 |         SkASSERT(fDone != NULL); | 
 | 617 |     } | 
 | 618 |  | 
 | 619 |     virtual void run() SK_OVERRIDE { | 
 | 620 |         SkGraphics::SetTLSFontCacheLimit(1024 * 1024); | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 621 |  | 
 | 622 |         SkBitmap bitmap; | 
 | 623 |         if (fBitmap != NULL) { | 
 | 624 |             // All tiles are the same size. | 
| jvanverth@google.com | 9c4e5ac | 2013-01-07 18:41:28 +0000 | [diff] [blame] | 625 |             setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScalarFloorToInt(fRects[0].height())); | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 626 |         } | 
| skia.committer@gmail.com | a7d8e3e | 2012-12-19 02:01:38 +0000 | [diff] [blame] | 627 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 628 |         for (int i = fStart; i < fEnd; i++) { | 
 | 629 |             DrawTileToCanvas(fCanvas, fRects[i], fClone); | 
 | 630 |             if (fPath != NULL && !writeAppendNumber(fCanvas, fPath, i) | 
 | 631 |                 && fSuccess != NULL) { | 
 | 632 |                 *fSuccess = false; | 
 | 633 |                 // If one tile fails to write to a file, do not continue drawing the rest. | 
 | 634 |                 break; | 
 | 635 |             } | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 636 |             if (fBitmap != NULL) { | 
 | 637 |                 if (fCanvas->readPixels(&bitmap, 0, 0)) { | 
 | 638 |                     SkAutoLockPixels alp(*fBitmap); | 
| jvanverth@google.com | 9c4e5ac | 2013-01-07 18:41:28 +0000 | [diff] [blame] | 639 |                     bitmapCopySubset(bitmap, fBitmap, SkScalarFloorToInt(fRects[i].left()), | 
 | 640 |                                      SkScalarFloorToInt(fRects[i].top())); | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 641 |                 } else { | 
 | 642 |                     *fSuccess = false; | 
 | 643 |                     // If one tile fails to read pixels, do not continue drawing the rest. | 
 | 644 |                     break; | 
 | 645 |                 } | 
 | 646 |             } | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 647 |         } | 
 | 648 |         fDone->run(); | 
 | 649 |     } | 
 | 650 |  | 
 | 651 |     void setPathAndSuccess(const SkString* path, bool* success) { | 
 | 652 |         fPath = path; | 
 | 653 |         fSuccess = success; | 
 | 654 |     } | 
 | 655 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 656 |     void setBitmap(SkBitmap* bitmap) { | 
 | 657 |         fBitmap = bitmap; | 
 | 658 |     } | 
 | 659 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 660 | private: | 
 | 661 |     // All pointers unowned. | 
 | 662 |     SkPicture*         fClone;      // Picture to draw from. Each CloneData has a unique one which | 
 | 663 |                                     // is threadsafe. | 
 | 664 |     SkCanvas*          fCanvas;     // Canvas to draw to. Reused for each tile. | 
 | 665 |     const SkString*    fPath;       // If non-null, path to write the result to as a PNG. | 
 | 666 |     SkTDArray<SkRect>& fRects;      // All tiles of the picture. | 
 | 667 |     const int          fStart;      // Range of tiles drawn by this thread. | 
 | 668 |     const int          fEnd; | 
 | 669 |     bool*              fSuccess;    // Only meaningful if path is non-null. Shared by all threads, | 
 | 670 |                                     // and only set to false upon failure to write to a PNG. | 
 | 671 |     SkRunnable*        fDone; | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 672 |     SkBitmap*          fBitmap; | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 673 | }; | 
 | 674 |  | 
 | 675 | MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) | 
 | 676 | : fNumThreads(threadCount) | 
 | 677 | , fThreadPool(threadCount) | 
 | 678 | , fCountdown(threadCount) { | 
 | 679 |     // Only need to create fNumThreads - 1 clones, since one thread will use the base | 
 | 680 |     // picture. | 
 | 681 |     fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); | 
 | 682 |     fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); | 
 | 683 | } | 
 | 684 |  | 
 | 685 | void MultiCorePictureRenderer::init(SkPicture *pict) { | 
 | 686 |     // Set fPicture and the tiles. | 
 | 687 |     this->INHERITED::init(pict); | 
 | 688 |     for (int i = 0; i < fNumThreads; ++i) { | 
 | 689 |         *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->getTileHeight()); | 
 | 690 |     } | 
 | 691 |     // Only need to create fNumThreads - 1 clones, since one thread will use the base picture. | 
 | 692 |     fPicture->clone(fPictureClones, fNumThreads - 1); | 
 | 693 |     // Populate each thread with the appropriate data. | 
 | 694 |     // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all. | 
 | 695 |     const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; | 
 | 696 |  | 
 | 697 |     for (int i = 0; i < fNumThreads; i++) { | 
 | 698 |         SkPicture* pic; | 
 | 699 |         if (i == fNumThreads-1) { | 
 | 700 |             // The last set will use the original SkPicture. | 
 | 701 |             pic = fPicture; | 
 | 702 |         } else { | 
 | 703 |             pic = &fPictureClones[i]; | 
 | 704 |         } | 
 | 705 |         const int start = i * chunkSize; | 
 | 706 |         const int end = SkMin32(start + chunkSize, fTileRects.count()); | 
 | 707 |         fCloneData[i] = SkNEW_ARGS(CloneData, | 
 | 708 |                                    (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown)); | 
 | 709 |     } | 
 | 710 | } | 
 | 711 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 712 | bool MultiCorePictureRenderer::render(const SkString *path, SkBitmap** out) { | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 713 |     bool success = true; | 
 | 714 |     if (path != NULL) { | 
 | 715 |         for (int i = 0; i < fNumThreads-1; i++) { | 
 | 716 |             fCloneData[i]->setPathAndSuccess(path, &success); | 
 | 717 |         } | 
 | 718 |     } | 
 | 719 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 720 |     if (NULL != out) { | 
 | 721 |         *out = SkNEW(SkBitmap); | 
 | 722 |         setup_bitmap(*out, fPicture->width(), fPicture->height()); | 
 | 723 |         for (int i = 0; i < fNumThreads; i++) { | 
 | 724 |             fCloneData[i]->setBitmap(*out); | 
 | 725 |         } | 
 | 726 |     } else { | 
 | 727 |         for (int i = 0; i < fNumThreads; i++) { | 
 | 728 |             fCloneData[i]->setBitmap(NULL); | 
 | 729 |         } | 
 | 730 |     } | 
 | 731 |  | 
| scroggo@google.com | a62da2f | 2012-11-02 21:28:12 +0000 | [diff] [blame] | 732 |     fCountdown.reset(fNumThreads); | 
 | 733 |     for (int i = 0; i < fNumThreads; i++) { | 
 | 734 |         fThreadPool.add(fCloneData[i]); | 
 | 735 |     } | 
 | 736 |     fCountdown.wait(); | 
 | 737 |  | 
 | 738 |     return success; | 
 | 739 | } | 
 | 740 |  | 
 | 741 | void MultiCorePictureRenderer::end() { | 
 | 742 |     for (int i = 0; i < fNumThreads - 1; i++) { | 
 | 743 |         SkDELETE(fCloneData[i]); | 
 | 744 |         fCloneData[i] = NULL; | 
 | 745 |     } | 
 | 746 |  | 
 | 747 |     fCanvasPool.unrefAll(); | 
 | 748 |  | 
 | 749 |     this->INHERITED::end(); | 
 | 750 | } | 
 | 751 |  | 
 | 752 | MultiCorePictureRenderer::~MultiCorePictureRenderer() { | 
 | 753 |     // Each individual CloneData was deleted in end. | 
 | 754 |     SkDELETE_ARRAY(fCloneData); | 
 | 755 |     SkDELETE_ARRAY(fPictureClones); | 
 | 756 | } | 
| scroggo@google.com | bcdf2ec | 2012-09-20 14:42:33 +0000 | [diff] [blame] | 757 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 758 | SkString MultiCorePictureRenderer::getConfigNameInternal() { | 
 | 759 |     SkString name = this->INHERITED::getConfigNameInternal(); | 
 | 760 |     name.appendf("_multi_%i_threads", fNumThreads); | 
 | 761 |     return name; | 
 | 762 | } | 
 | 763 |  | 
| scroggo@google.com | acfb30e | 2012-09-18 14:32:35 +0000 | [diff] [blame] | 764 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 765 |  | 
 | 766 | void PlaybackCreationRenderer::setup() { | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 767 |     fReplayer.reset(this->createPicture()); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 768 |     SkCanvas* recorder = fReplayer->beginRecording(this->getViewWidth(), this->getViewHeight(), | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 769 |                                                    this->recordFlags()); | 
| scroggo@google.com | 82ec0b0 | 2012-12-17 19:25:54 +0000 | [diff] [blame] | 770 |     this->scaleToScaleFactor(recorder); | 
| scroggo@google.com | 9a41252 | 2012-09-07 15:21:18 +0000 | [diff] [blame] | 771 |     fPicture->draw(recorder); | 
 | 772 | } | 
 | 773 |  | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 774 | bool PlaybackCreationRenderer::render(const SkString*, SkBitmap** out) { | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 775 |     fReplayer->endRecording(); | 
| scroggo@google.com | 81f9d2e | 2012-09-20 14:54:21 +0000 | [diff] [blame] | 776 |     // Since this class does not actually render, return false. | 
 | 777 |     return false; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 778 | } | 
 | 779 |  | 
| scroggo@google.com | 0a049b8 | 2012-11-02 22:01:26 +0000 | [diff] [blame] | 780 | SkString PlaybackCreationRenderer::getConfigNameInternal() { | 
 | 781 |     return SkString("playback_creation"); | 
 | 782 | } | 
 | 783 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 784 | /////////////////////////////////////////////////////////////////////////////////////////////// | 
 | 785 | // SkPicture variants for each BBoxHierarchy type | 
 | 786 |  | 
 | 787 | class RTreePicture : public SkPicture { | 
 | 788 | public: | 
 | 789 |     virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{ | 
 | 790 |         static const int kRTreeMinChildren = 6; | 
 | 791 |         static const int kRTreeMaxChildren = 11; | 
 | 792 |         SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth), | 
 | 793 |                                            SkIntToScalar(fHeight)); | 
 | 794 |         return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren, | 
 | 795 |                                aspectRatio); | 
 | 796 |     } | 
 | 797 | }; | 
 | 798 |  | 
 | 799 | SkPicture* PictureRenderer::createPicture() { | 
 | 800 |     switch (fBBoxHierarchyType) { | 
 | 801 |         case kNone_BBoxHierarchyType: | 
 | 802 |             return SkNEW(SkPicture); | 
 | 803 |         case kRTree_BBoxHierarchyType: | 
 | 804 |             return SkNEW(RTreePicture); | 
| junov@chromium.org | 7b53706 | 2012-11-06 18:58:43 +0000 | [diff] [blame] | 805 |         case kTileGrid_BBoxHierarchyType: | 
| junov@chromium.org | 29b19e5 | 2013-02-27 18:35:16 +0000 | [diff] [blame] | 806 |             return SkNEW_ARGS(SkTileGridPicture, (fPicture->width(), | 
 | 807 |                 fPicture->height(), fGridInfo)); | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 808 |     } | 
 | 809 |     SkASSERT(0); // invalid bbhType | 
 | 810 |     return NULL; | 
| keyar@chromium.org | 451bb9f | 2012-07-26 17:27:57 +0000 | [diff] [blame] | 811 | } | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 812 |  | 
| reed@google.com | fe7b1ed | 2012-11-29 21:00:39 +0000 | [diff] [blame] | 813 | /////////////////////////////////////////////////////////////////////////////// | 
 | 814 |  | 
 | 815 | class GatherRenderer : public PictureRenderer { | 
 | 816 | public: | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 817 |     virtual bool render(const SkString* path, SkBitmap** out = NULL) | 
 | 818 |             SK_OVERRIDE { | 
| reed@google.com | fe7b1ed | 2012-11-29 21:00:39 +0000 | [diff] [blame] | 819 |         SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()), | 
 | 820 |                                        SkIntToScalar(fPicture->height())); | 
 | 821 |         SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds); | 
 | 822 |         SkSafeUnref(data); | 
| skia.committer@gmail.com | c7b4be7 | 2012-12-11 02:01:20 +0000 | [diff] [blame] | 823 |  | 
| reed@google.com | fe7b1ed | 2012-11-29 21:00:39 +0000 | [diff] [blame] | 824 |         return NULL == path;    // we don't have anything to write | 
 | 825 |     } | 
| skia.committer@gmail.com | c7b4be7 | 2012-12-11 02:01:20 +0000 | [diff] [blame] | 826 |  | 
| reed@google.com | fe7b1ed | 2012-11-29 21:00:39 +0000 | [diff] [blame] | 827 | private: | 
 | 828 |     virtual SkString getConfigNameInternal() SK_OVERRIDE { | 
 | 829 |         return SkString("gather_pixelrefs"); | 
 | 830 |     } | 
 | 831 | }; | 
 | 832 |  | 
 | 833 | PictureRenderer* CreateGatherPixelRefsRenderer() { | 
 | 834 |     return SkNEW(GatherRenderer); | 
 | 835 | } | 
| skia.committer@gmail.com | c3d7d90 | 2012-11-30 02:01:24 +0000 | [diff] [blame] | 836 |  | 
| reed@google.com | 5a34fd3 | 2012-12-10 16:05:09 +0000 | [diff] [blame] | 837 | /////////////////////////////////////////////////////////////////////////////// | 
 | 838 |  | 
 | 839 | class PictureCloneRenderer : public PictureRenderer { | 
 | 840 | public: | 
| edisonn@google.com | 84f548c | 2012-12-18 22:24:03 +0000 | [diff] [blame] | 841 |     virtual bool render(const SkString* path, SkBitmap** out = NULL) | 
 | 842 |             SK_OVERRIDE { | 
| reed@google.com | 5a34fd3 | 2012-12-10 16:05:09 +0000 | [diff] [blame] | 843 |         for (int i = 0; i < 100; ++i) { | 
 | 844 |             SkPicture* clone = fPicture->clone(); | 
 | 845 |             SkSafeUnref(clone); | 
 | 846 |         } | 
| skia.committer@gmail.com | c7b4be7 | 2012-12-11 02:01:20 +0000 | [diff] [blame] | 847 |  | 
| reed@google.com | 5a34fd3 | 2012-12-10 16:05:09 +0000 | [diff] [blame] | 848 |         return NULL == path;    // we don't have anything to write | 
 | 849 |     } | 
| skia.committer@gmail.com | c7b4be7 | 2012-12-11 02:01:20 +0000 | [diff] [blame] | 850 |  | 
| reed@google.com | 5a34fd3 | 2012-12-10 16:05:09 +0000 | [diff] [blame] | 851 | private: | 
 | 852 |     virtual SkString getConfigNameInternal() SK_OVERRIDE { | 
 | 853 |         return SkString("picture_clone"); | 
 | 854 |     } | 
 | 855 | }; | 
 | 856 |  | 
 | 857 | PictureRenderer* CreatePictureCloneRenderer() { | 
 | 858 |     return SkNEW(PictureCloneRenderer); | 
 | 859 | } | 
 | 860 |  | 
| junov@chromium.org | 9313ca4 | 2012-11-02 18:11:49 +0000 | [diff] [blame] | 861 | } // namespace sk_tools |