PictureRenderer.cpp revision b3fb7c1f467c4d43dff0d98683d3043f0176e07c
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 8#include "PictureRenderer.h" 9#include "SamplePipeControllers.h" 10#include "SkCanvas.h" 11#include "SkDevice.h" 12#include "SkGPipe.h" 13#include "SkPicture.h" 14#include "SkTDArray.h" 15#include "SkTypes.h" 16#include "picture_utils.h" 17 18#if SK_SUPPORT_GPU 19#include "SkGpuDevice.h" 20#endif 21 22namespace sk_tools { 23 24enum { 25 kDefaultTileWidth = 256, 26 kDefaultTileHeight = 256 27}; 28 29void PictureRenderer::init(SkPicture* pict) { 30 SkASSERT(NULL == fPicture); 31 SkASSERT(NULL == fCanvas.get()); 32 if (fPicture != NULL || NULL != fCanvas.get()) { 33 return; 34 } 35 36 SkASSERT(pict != NULL); 37 if (NULL == pict) { 38 return; 39 } 40 41 fPicture = pict; 42 fCanvas.reset(this->setupCanvas()); 43} 44 45SkCanvas* PictureRenderer::setupCanvas() { 46 return this->setupCanvas(fPicture->width(), fPicture->height()); 47} 48 49SkCanvas* PictureRenderer::setupCanvas(int width, int height) { 50 switch(fDeviceType) { 51 case kBitmap_DeviceType: { 52 SkBitmap bitmap; 53 sk_tools::setup_bitmap(&bitmap, width, height); 54 return SkNEW_ARGS(SkCanvas, (bitmap)); 55 break; 56 } 57#if SK_SUPPORT_GPU 58 case kGPU_DeviceType: { 59 SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice, 60 (fGrContext, SkBitmap::kARGB_8888_Config, 61 width, height))); 62 return SkNEW_ARGS(SkCanvas, (device.get())); 63 break; 64 } 65#endif 66 default: 67 SkASSERT(0); 68 } 69 70 return NULL; 71} 72 73void PictureRenderer::end() { 74 this->resetState(); 75 fPicture = NULL; 76 fCanvas.reset(NULL); 77} 78 79void PictureRenderer::resetState() { 80#if SK_SUPPORT_GPU 81 if (this->isUsingGpuDevice()) { 82 SkGLContext* glContext = fGrContextFactory.getGLContext( 83 GrContextFactory::kNative_GLContextType); 84 SK_GL(*glContext, Finish()); 85 } 86#endif 87} 88 89void PictureRenderer::finishDraw() { 90 SkASSERT(fCanvas.get() != NULL); 91 if (NULL == fCanvas.get()) { 92 return; 93 } 94 95 fCanvas->flush(); 96 97#if SK_SUPPORT_GPU 98 if (this->isUsingGpuDevice()) { 99 SkGLContext* glContext = fGrContextFactory.getGLContext( 100 GrContextFactory::kNative_GLContextType); 101 102 SkASSERT(glContext != NULL); 103 if (NULL == glContext) { 104 return; 105 } 106 107 SK_GL(*glContext, Finish()); 108 } 109#endif 110} 111 112void PipePictureRenderer::render() { 113 SkASSERT(fCanvas.get() != NULL); 114 SkASSERT(fPicture != NULL); 115 if (NULL == fCanvas.get() || NULL == fPicture) { 116 return; 117 } 118 119 PipeController pipeController(fCanvas.get()); 120 SkGPipeWriter writer; 121 SkCanvas* pipeCanvas = writer.startRecording(&pipeController); 122 pipeCanvas->drawPicture(*fPicture); 123 writer.endRecording(); 124 this->finishDraw(); 125} 126 127void SimplePictureRenderer::render() { 128 SkASSERT(fCanvas.get() != NULL); 129 SkASSERT(fPicture != NULL); 130 if (NULL == fCanvas.get() || NULL == fPicture) { 131 return; 132 } 133 134 fCanvas->drawPicture(*fPicture); 135 this->finishDraw(); 136} 137 138TiledPictureRenderer::TiledPictureRenderer() 139 : fTileWidth(kDefaultTileWidth) 140 , fTileHeight(kDefaultTileHeight) {} 141 142void TiledPictureRenderer::init(SkPicture* pict) { 143 SkASSERT(pict != NULL); 144 SkASSERT(0 == fTiles.count()); 145 if (NULL == pict || fTiles.count() != 0) { 146 return; 147 } 148 149 this->INHERITED::init(pict); 150 151 if (fTileWidthPercentage > 0) { 152 fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100)); 153 } 154 if (fTileHeightPercentage > 0) { 155 fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100)); 156 } 157 158 this->setupTiles(); 159} 160 161void TiledPictureRenderer::render() { 162 SkASSERT(fCanvas.get() != NULL); 163 SkASSERT(fPicture != NULL); 164 if (NULL == fCanvas.get() || NULL == fPicture) { 165 return; 166 } 167 168 this->drawTiles(); 169 this->copyTilesToCanvas(); 170 this->finishDraw(); 171} 172 173void TiledPictureRenderer::end() { 174 this->deleteTiles(); 175 this->INHERITED::end(); 176} 177 178TiledPictureRenderer::~TiledPictureRenderer() { 179 this->deleteTiles(); 180} 181 182void TiledPictureRenderer::clipTile(const TileInfo& tile) { 183 SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()), 184 SkIntToScalar(fPicture->height())); 185 tile.fCanvas->clipRect(clip); 186} 187 188void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) { 189 TileInfo* tile = fTiles.push(); 190 191 tile->fCanvas = this->setupCanvas(fTileWidth, fTileHeight); 192 tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start)); 193 this->clipTile(*tile); 194} 195 196void TiledPictureRenderer::setupTiles() { 197 for (int tile_y_start = 0; tile_y_start < fPicture->height(); 198 tile_y_start += fTileHeight) { 199 for (int tile_x_start = 0; tile_x_start < fPicture->width(); 200 tile_x_start += fTileWidth) { 201 this->addTile(tile_x_start, tile_y_start); 202 } 203 } 204} 205 206void TiledPictureRenderer::deleteTiles() { 207 for (int i = 0; i < fTiles.count(); ++i) { 208 SkDELETE(fTiles[i].fCanvas); 209 } 210 211 fTiles.reset(); 212} 213 214void TiledPictureRenderer::drawTiles() { 215 for (int i = 0; i < fTiles.count(); ++i) { 216 fTiles[i].fCanvas->drawPicture(*(fPicture)); 217 } 218} 219 220void TiledPictureRenderer::finishDraw() { 221 for (int i = 0; i < fTiles.count(); ++i) { 222 fTiles[i].fCanvas->flush(); 223 } 224 225#if SK_SUPPORT_GPU 226 if (this->isUsingGpuDevice()) { 227 SkGLContext* glContext = fGrContextFactory.getGLContext( 228 GrContextFactory::kNative_GLContextType); 229 230 SkASSERT(glContext != NULL); 231 if (NULL == glContext) { 232 return; 233 } 234 235 SK_GL(*glContext, Finish()); 236 } 237#endif 238} 239 240void TiledPictureRenderer::copyTilesToCanvas() { 241 int tile_index = 0; 242 for (int tile_y_start = 0; tile_y_start < fPicture->height(); 243 tile_y_start += fTileHeight) { 244 for (int tile_x_start = 0; tile_x_start < fPicture->width(); 245 tile_x_start += fTileWidth) { 246 SkASSERT(tile_index < fTiles.count()); 247 SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false); 248 fCanvas->drawBitmap(source, 249 SkIntToScalar(tile_x_start), 250 SkIntToScalar(tile_y_start)); 251 ++tile_index; 252 } 253 } 254} 255 256} 257