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