PictureRenderer.cpp revision 9c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254
1b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org/* 2b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * Copyright 2012 Google Inc. 3b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * 4b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * Use of this source code is governed by a BSD-style license that can be 5b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org * found in the LICENSE file. 6b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org */ 7b3fb7c1f467c4d43dff0d98683d3043f0176e07ckeyar@chromium.org 8451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "PictureRenderer.h" 958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "picture_utils.h" 10451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SamplePipeControllers.h" 11451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkCanvas.h" 12451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkDevice.h" 13451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkGPipe.h" 1458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#if SK_SUPPORT_GPU 1558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkGpuDevice.h" 1658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#endif 1758b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkGraphics.h" 1858b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkImageEncoder.h" 19a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com#include "SkMaskFilter.h" 20ea82695325e2afc68f646fcc23fcae8b1bff6dc1keyar@chromium.org#include "SkMatrix.h" 21451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkPicture.h" 229313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org#include "SkRTree.h" 23ea82695325e2afc68f646fcc23fcae8b1bff6dc1keyar@chromium.org#include "SkScalar.h" 24a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com#include "SkStream.h" 259299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org#include "SkString.h" 2658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkTemplates.h" 273cb834bd27a16cc60ff30adae96659558c2dc91fjunov@chromium.org#include "SkTileGridPicture.h" 28451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkTDArray.h" 2958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkThreadUtils.h" 30451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkTypes.h" 31fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkData.h" 32fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkPictureUtils.h" 334ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org 34451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgnamespace sk_tools { 35451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 36451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgenum { 37451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org kDefaultTileWidth = 256, 38451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org kDefaultTileHeight = 256 39451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}; 40451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 419d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid PictureRenderer::init(SkPicture* pict) { 4278a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org SkASSERT(NULL == fPicture); 4378a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org SkASSERT(NULL == fCanvas.get()); 4478a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org if (fPicture != NULL || NULL != fCanvas.get()) { 459d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org return; 469d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org } 479d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 489d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org SkASSERT(pict != NULL); 4978a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org if (NULL == pict) { 509d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org return; 519d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org } 529d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 539d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org fPicture = pict; 549313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fPicture->ref(); 55a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org fCanvas.reset(this->setupCanvas()); 56a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org} 57a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org 58a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comclass FlagsDrawFilter : public SkDrawFilter { 59a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.compublic: 60a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) : 61a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com fFlags(flags) {} 62a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com 63971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com virtual bool filter(SkPaint* paint, Type t) { 64a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags); 65457d8a77bed0160519fc5dfb67d0e02f9c3950a2reed@google.com if (PictureRenderer::kBlur_DrawFilterFlag & fFlags[t]) { 66a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com SkMaskFilter* maskFilter = paint->getMaskFilter(); 67a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com SkMaskFilter::BlurInfo blurInfo; 68a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com if (maskFilter && maskFilter->asABlur(&blurInfo)) { 69457d8a77bed0160519fc5dfb67d0e02f9c3950a2reed@google.com paint->setMaskFilter(NULL); 70a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com } 71a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com } 72a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) { 73a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com paint->setHinting(SkPaint::kNo_Hinting); 74a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) { 75a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com paint->setHinting(SkPaint::kSlight_Hinting); 76a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com } 77971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com return true; 78a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com } 79a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com 80a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comprivate: 81a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com PictureRenderer::DrawFilterFlags* fFlags; 82a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com}; 83a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com 8482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comstatic void setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) { 85a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com if (drawFilters && !canvas->getDrawFilter()) { 86a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref(); 87e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) { 88e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com canvas->setAllowSoftClip(false); 89e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com } 90a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com } 91a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com} 92a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com 93a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas() { 94c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com const int width = this->getViewWidth(); 95c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com const int height = this->getViewHeight(); 96c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com return this->setupCanvas(width, height); 97a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org} 98a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org 99a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas(int width, int height) { 100a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com SkCanvas* canvas; 1014ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org switch(fDeviceType) { 1024ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org case kBitmap_DeviceType: { 1034ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org SkBitmap bitmap; 104a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org sk_tools::setup_bitmap(&bitmap, width, height); 105a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com canvas = SkNEW_ARGS(SkCanvas, (bitmap)); 1064ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org } 10782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com break; 1084ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#if SK_SUPPORT_GPU 1094ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org case kGPU_DeviceType: { 1104ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice, 1110612564bb76ec533d26d87e03368fd81ef97831ekeyar@chromium.org (fGrContext, SkBitmap::kARGB_8888_Config, 112a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org width, height))); 113a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com canvas = SkNEW_ARGS(SkCanvas, (device.get())); 1144ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org } 11582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com break; 1164ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#endif 1174ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org default: 1184ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org SkASSERT(0); 11982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com return NULL; 1204ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org } 12182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com setUpFilter(canvas, fDrawFilters); 12282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com this->scaleToScaleFactor(canvas); 12382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com return canvas; 12482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com} 125a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org 12682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comvoid PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) { 12782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com SkASSERT(canvas != NULL); 12882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com if (fScaleFactor != SK_Scalar1) { 12982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com canvas->scale(fScaleFactor, fScaleFactor); 13082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com } 1319d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org} 1329d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 1339d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid PictureRenderer::end() { 13477a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org this->resetState(); 1359313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkSafeUnref(fPicture); 1369d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org fPicture = NULL; 1379d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org fCanvas.reset(NULL); 1389d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org} 1399d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 140c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewWidth() { 141c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com SkASSERT(fPicture != NULL); 142c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com int width = fPicture->width(); 143c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com if (fViewport.width() > 0) { 144c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com width = SkMin32(width, fViewport.width()); 145c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com } 146c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com return width; 147c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com} 148c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com 149c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewHeight() { 150c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com SkASSERT(fPicture != NULL); 151c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com int height = fPicture->height(); 152c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com if (fViewport.height() > 0) { 153c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com height = SkMin32(height, fViewport.height()); 154c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com } 155c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com return height; 156c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com} 157c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com 1589313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org/** Converts fPicture to a picture that uses a BBoxHierarchy. 1599313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org * PictureRenderer subclasses that are used to test picture playback 1609313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org * should call this method during init. 1619313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org */ 1629313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgvoid PictureRenderer::buildBBoxHierarchy() { 1639313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkASSERT(NULL != fPicture); 1649313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) { 1659313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkPicture* newPicture = this->createPicture(); 1669313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(), 1679313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org this->recordFlags()); 1689313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fPicture->draw(recorder); 1699313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org newPicture->endRecording(); 1709313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fPicture->unref(); 1719313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fPicture = newPicture; 1729313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org } 1739313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} 1749313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org 17577a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.orgvoid PictureRenderer::resetState() { 17628136b308fe467da113983cfee332faea133cd8akeyar@chromium.org#if SK_SUPPORT_GPU 17728136b308fe467da113983cfee332faea133cd8akeyar@chromium.org if (this->isUsingGpuDevice()) { 17828136b308fe467da113983cfee332faea133cd8akeyar@chromium.org SkGLContext* glContext = fGrContextFactory.getGLContext( 17928136b308fe467da113983cfee332faea133cd8akeyar@chromium.org GrContextFactory::kNative_GLContextType); 18028136b308fe467da113983cfee332faea133cd8akeyar@chromium.org 18128136b308fe467da113983cfee332faea133cd8akeyar@chromium.org SkASSERT(glContext != NULL); 18228136b308fe467da113983cfee332faea133cd8akeyar@chromium.org if (NULL == glContext) { 18328136b308fe467da113983cfee332faea133cd8akeyar@chromium.org return; 18428136b308fe467da113983cfee332faea133cd8akeyar@chromium.org } 18528136b308fe467da113983cfee332faea133cd8akeyar@chromium.org 1869a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com fGrContext->flush(); 18777a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org SK_GL(*glContext, Finish()); 18877a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org } 189a40c20df0e4c5d04acb0841d70127778c0a779eckeyar@chromium.org#endif 19077a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org} 19177a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org 1929313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orguint32_t PictureRenderer::recordFlags() { 1939313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org return kNone_BBoxHierarchyType == fBBoxHierarchyType ? 0 : 1949313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkPicture::kOptimizeForClippedPlayback_RecordingFlag; 1959313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} 1969313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org 197b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com/** 198b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * Write the canvas to the specified path. 199b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @param canvas Must be non-null. Canvas to be written to a file. 200b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @param path Path for the file to be written. Should have no extension; write() will append 201b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * an appropriate one. Passed in by value so it can be modified. 202b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @return bool True if the Canvas is written to a file. 203b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com */ 204b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.comstatic bool write(SkCanvas* canvas, SkString path) { 20581f9d2e05be4902993345dac93337158345c660bscroggo@google.com SkASSERT(canvas != NULL); 206b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com if (NULL == canvas) { 2079299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org return false; 2089299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org } 2099299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org 2109299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org SkBitmap bitmap; 21181f9d2e05be4902993345dac93337158345c660bscroggo@google.com SkISize size = canvas->getDeviceSize(); 21281f9d2e05be4902993345dac93337158345c660bscroggo@google.com sk_tools::setup_bitmap(&bitmap, size.width(), size.height()); 2139299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org 21481f9d2e05be4902993345dac93337158345c660bscroggo@google.com canvas->readPixels(&bitmap, 0, 0); 2159299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org sk_tools::force_all_opaque(bitmap); 2169299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org 21781f9d2e05be4902993345dac93337158345c660bscroggo@google.com // Since path is passed in by value, it is okay to modify it. 21881f9d2e05be4902993345dac93337158345c660bscroggo@google.com path.append(".png"); 2199299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); 2209299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org} 2219299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org 222b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com/** 223b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * If path is non NULL, append number to it, and call write(SkCanvas*, SkString) to write the 224b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * provided canvas to a file. Returns true if path is NULL or if write() succeeds. 225b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com */ 226b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.comstatic bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number) { 227b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com if (NULL == path) { 228b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com return true; 229b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com } 230b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com SkString pathWithNumber(*path); 231b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com pathWithNumber.appendf("%i", number); 232b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com return write(canvas, pathWithNumber); 233b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com} 234b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com 235acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 236acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com 237fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.comSkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) { 238fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com // defer the canvas setup until the render step 239fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com return NULL; 240fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com} 241fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com 242a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.comstatic bool PNGEncodeBitmapToStream(SkWStream* wStream, const SkBitmap& bm) { 243a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com return SkImageEncoder::EncodeStream(wStream, bm, SkImageEncoder::kPNG_Type, 100); 244a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com} 245a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com 24684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool RecordPictureRenderer::render(const SkString* path, SkBitmap** out) { 2479313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkAutoTUnref<SkPicture> replayer(this->createPicture()); 24882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->getViewHeight(), 2499313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org this->recordFlags()); 25082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com this->scaleToScaleFactor(recorder); 2519a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com fPicture->draw(recorder); 2529313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org replayer->endRecording(); 253a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com if (path != NULL) { 254a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com // Record the new picture as a new SKP with PNG encoded bitmaps. 255a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com SkString skpPath(*path); 256a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com // ".skp" was removed from 'path' before being passed in here. 257a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com skpPath.append(".skp"); 258a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com SkFILEWStream stream(skpPath.c_str()); 259a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com replayer->serialize(&stream, &PNGEncodeBitmapToStream); 260a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com return true; 261a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com } 26281f9d2e05be4902993345dac93337158345c660bscroggo@google.com return false; 2639a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com} 2649a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com 2650a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString RecordPictureRenderer::getConfigNameInternal() { 2660a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com return SkString("record"); 2670a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com} 2680a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 269acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 270acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com 27184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool PipePictureRenderer::render(const SkString* path, SkBitmap** out) { 2729d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org SkASSERT(fCanvas.get() != NULL); 2739d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org SkASSERT(fPicture != NULL); 27478a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org if (NULL == fCanvas.get() || NULL == fPicture) { 27581f9d2e05be4902993345dac93337158345c660bscroggo@google.com return false; 2769d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org } 2779d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 2789d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org PipeController pipeController(fCanvas.get()); 279451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org SkGPipeWriter writer; 280451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org SkCanvas* pipeCanvas = writer.startRecording(&pipeController); 2819d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org pipeCanvas->drawPicture(*fPicture); 282451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org writer.endRecording(); 2839a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com fCanvas->flush(); 284070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com if (NULL != path) { 285070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com return write(fCanvas, *path); 286070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com } 28784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (NULL != out) { 28884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com *out = SkNEW(SkBitmap); 28984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com setup_bitmap(*out, fPicture->width(), fPicture->height()); 29084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com fCanvas->readPixels(*out, 0, 0); 291a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com } 292070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com return true; 293451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 294451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 2950a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PipePictureRenderer::getConfigNameInternal() { 2960a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com return SkString("pipe"); 2970a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com} 2980a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 299acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 300acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com 3019313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgvoid SimplePictureRenderer::init(SkPicture* picture) { 3029313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org INHERITED::init(picture); 3039313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org this->buildBBoxHierarchy(); 3049313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} 3059313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org 30684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool SimplePictureRenderer::render(const SkString* path, SkBitmap** out) { 3079d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org SkASSERT(fCanvas.get() != NULL); 3089d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org SkASSERT(fPicture != NULL); 30978a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org if (NULL == fCanvas.get() || NULL == fPicture) { 31081f9d2e05be4902993345dac93337158345c660bscroggo@google.com return false; 3119d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org } 3129d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 3139d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org fCanvas->drawPicture(*fPicture); 3149a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com fCanvas->flush(); 315070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com if (NULL != path) { 316070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com return write(fCanvas, *path); 317070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com } 318a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com 31984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (NULL != out) { 32084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com *out = SkNEW(SkBitmap); 32184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com setup_bitmap(*out, fPicture->width(), fPicture->height()); 32284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com fCanvas->readPixels(*out, 0, 0); 32384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 32484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com 325070d354d51dac52a70f07d4b102392b89f2da5d7borenet@google.com return true; 326451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 327451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 3280a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString SimplePictureRenderer::getConfigNameInternal() { 3290a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com return SkString("simple"); 3300a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com} 3310a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 332acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 333acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com 334451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgTiledPictureRenderer::TiledPictureRenderer() 335a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com : fTileWidth(kDefaultTileWidth) 336b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com , fTileHeight(kDefaultTileHeight) 337a04dc02b118363fedf3a7b11cfcdab886d368f8arileya@google.com , fTileWidthPercentage(0.0) 338b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com , fTileHeightPercentage(0.0) 339cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com , fTileMinPowerOf2Width(0) 340cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com , fCurrentTileOffset(-1) 341cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com , fTilesX(0) 342cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com , fTilesY(0) { } 343451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 3449d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::init(SkPicture* pict) { 3459d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org SkASSERT(pict != NULL); 346acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkASSERT(0 == fTileRects.count()); 347acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com if (NULL == pict || fTileRects.count() != 0) { 3489d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org return; 3499d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org } 3509d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org 351acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not 352acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com // used by bench_pictures. 353acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com fPicture = pict; 3549313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fPicture->ref(); 355a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com this->buildBBoxHierarchy(); 356cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org 357cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org if (fTileWidthPercentage > 0) { 3585d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100)); 359cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org } 360cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org if (fTileHeightPercentage > 0) { 3615d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100)); 362cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org } 363cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org 364f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org if (fTileMinPowerOf2Width > 0) { 365f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org this->setupPowerOf2Tiles(); 366f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org } else { 367f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org this->setupTiles(); 368f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org } 369cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight)); 370cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com // Initialize to -1 so that the first call to nextTile will set this up to draw tile 0 on the 371cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com // first call to drawCurrentTile. 372cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fCurrentTileOffset = -1; 373451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 374451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 3759d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::end() { 376bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com fTileRects.reset(); 3779d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org this->INHERITED::end(); 378451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 379451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 3809d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::setupTiles() { 381c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com // Only use enough tiles to cover the viewport 382c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com const int width = this->getViewWidth(); 383c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com const int height = this->getViewHeight(); 384c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com 385cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fTilesX = fTilesY = 0; 386c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) { 387cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fTilesY++; 388c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWidth) { 389cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com if (0 == tile_y_start) { 390cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com // Only count tiles in the X direction on the first pass. 391cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fTilesX++; 392cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com } 393acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), 394acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkIntToScalar(tile_y_start), 395acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkIntToScalar(fTileWidth), 396acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkIntToScalar(fTileHeight)); 397f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org } 398f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org } 399f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org} 400f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org 401cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::tileDimensions(int &x, int &y) { 402cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com if (fTileRects.count() == 0 || NULL == fPicture) { 403cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com return false; 404cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com } 405cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com x = fTilesX; 406cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com y = fTilesY; 407cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com return true; 408cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com} 409cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com 410f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// The goal of the powers of two tiles is to minimize the amount of wasted tile 411f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// space in the width-wise direction and then minimize the number of tiles. The 412f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// constraints are that every tile must have a pixel width that is a power of 413f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// two and also be of some minimal width (that is also a power of two). 414f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// 41558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com// This is solved by first taking our picture size and rounding it up to the 416f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// multiple of the minimal width. The binary representation of this rounded 417f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// value gives us the tiles we need: a bit of value one means we need a tile of 418f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// that size. 419f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.orgvoid TiledPictureRenderer::setupPowerOf2Tiles() { 420c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com // Only use enough tiles to cover the viewport 421c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com const int width = this->getViewWidth(); 422c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com const int height = this->getViewHeight(); 423c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com 424c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com int rounded_value = width; 425c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com if (width % fTileMinPowerOf2Width != 0) { 426c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerOf2Width; 427f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org } 428f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org 429c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com int num_bits = SkScalarCeilToInt(SkScalarLog2(SkIntToScalar(width))); 430f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org int largest_possible_tile_size = 1 << num_bits; 431f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org 432cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fTilesX = fTilesY = 0; 433f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org // The tile height is constant for a particular picture. 434c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) { 435cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fTilesY++; 436f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org int tile_x_start = 0; 437f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org int current_width = largest_possible_tile_size; 438acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough 439acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com // to draw each tile. 440acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com fTileWidth = current_width; 441f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org 442f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org while (current_width >= fTileMinPowerOf2Width) { 443f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org // It is very important this is a bitwise AND. 444f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org if (current_width & rounded_value) { 445cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com if (0 == tile_y_start) { 446cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com // Only count tiles in the X direction on the first pass. 447cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com fTilesX++; 448cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com } 449acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), 450acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkIntToScalar(tile_y_start), 451acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkIntToScalar(current_width), 452acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com SkIntToScalar(fTileHeight)); 453f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org tile_x_start += current_width; 454f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org } 455f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org 456f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org current_width >>= 1; 457451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org } 458451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org } 459451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 460451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 461bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com/** 462bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * Draw the specified playback to the canvas translated to rectangle provided, so that this mini 463bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * canvas represents the rectangle's portion of the overall picture. 464bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * Saves and restores so that the initial clip and matrix return to their state before this function 465bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * is called. 466bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com */ 467bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.comtemplate<class T> 468bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.comstatic void DrawTileToCanvas(SkCanvas* canvas, const SkRect& tileRect, T* playback) { 469bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com int saveCount = canvas->save(); 47082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // Translate so that we draw the correct portion of the picture. 47182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // Perform a postTranslate so that the scaleFactor does not interfere with the positioning. 47282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com SkMatrix mat(canvas->getTotalMatrix()); 47382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com mat.postTranslate(-tileRect.fLeft, -tileRect.fTop); 47482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com canvas->setMatrix(mat); 475bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com playback->draw(canvas); 476bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com canvas->restoreToCount(saveCount); 477bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com canvas->flush(); 478451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 479451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 48058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 481bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com 48284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.comstatic void bitmapCopySubset(const SkBitmap& src, SkBitmap* dst, int xDst, 48384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com int yDst) { 48484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com for (int y = 0; y <src.height() && y + yDst < dst->height() ; y++) { 48584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com for (int x = 0; x < src.width() && x + xDst < dst->width() ; x++) { 48684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com *dst->getAddr32(xDst + x, yDst + y) = *src.getAddr32(x, y); 48784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 48884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 48984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com} 49084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com 491cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::nextTile(int &i, int &j) { 492cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com if (++fCurrentTileOffset < fTileRects.count()) { 493cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com i = fCurrentTileOffset % fTilesX; 494cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com j = fCurrentTileOffset / fTilesX; 495cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com return true; 496cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com } 497cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com return false; 498cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com} 499cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com 500cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.comvoid TiledPictureRenderer::drawCurrentTile() { 501cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count()); 502cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com DrawTileToCanvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture); 503cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com} 504cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com 50584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool TiledPictureRenderer::render(const SkString* path, SkBitmap** out) { 506a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkASSERT(fPicture != NULL); 507a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com if (NULL == fPicture) { 508a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com return false; 509bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com } 510bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com 51184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com SkBitmap bitmap; 51284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (out){ 51384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com *out = SkNEW(SkBitmap); 51484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com setup_bitmap(*out, fPicture->width(), fPicture->height()); 51584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com setup_bitmap(&bitmap, fTileWidth, fTileHeight); 51684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 517a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com bool success = true; 518a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = 0; i < fTileRects.count(); ++i) { 519cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com DrawTileToCanvas(fCanvas, fTileRects[i], fPicture); 520a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com if (NULL != path) { 521cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com success &= writeAppendNumber(fCanvas, path, i); 522b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com } 52384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (NULL != out) { 52484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (fCanvas->readPixels(&bitmap, 0, 0)) { 5259c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com bitmapCopySubset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()), 5269c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com SkScalarFloorToInt(fTileRects[i].top())); 52784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } else { 52884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com success = false; 52984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 53084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 531bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com } 532a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com return success; 533bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com} 53458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com 535a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comSkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) { 536a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkCanvas* canvas = this->INHERITED::setupCanvas(width, height); 537a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkASSERT(fPicture != NULL); 53882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This 53982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // is mostly important for tiles on the right and bottom edges as they may go over this area and 54082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // the picture may have some commands that draw outside of this area and so should not actually 54182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // be written. 54282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // Uses a clipRegion so that it will be unaffected by the scale factor, which may have been set 54382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com // by INHERITED::setupCanvas. 54482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com SkRegion clipRegion; 54582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight()); 54682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com canvas->clipRegion(clipRegion); 547a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com return canvas; 548a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com} 5490a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 5500a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString TiledPictureRenderer::getConfigNameInternal() { 5510a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com SkString name; 5520a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com if (fTileMinPowerOf2Width > 0) { 5530a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.append("pow2tile_"); 5540a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.appendf("%i", fTileMinPowerOf2Width); 5550a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com } else { 5560a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.append("tile_"); 5570a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com if (fTileWidthPercentage > 0) { 5580a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.appendf("%.f%%", fTileWidthPercentage); 5590a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com } else { 5600a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.appendf("%i", fTileWidth); 5610a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com } 5620a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com } 5630a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.append("x"); 5640a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com if (fTileHeightPercentage > 0) { 5650a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.appendf("%.f%%", fTileHeightPercentage); 5660a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com } else { 5670a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.appendf("%i", fTileHeight); 5680a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com } 5690a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com return name; 5700a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com} 5710a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 57258b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 57358b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com 574a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com// Holds all of the information needed to draw a set of tiles. 575a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comclass CloneData : public SkRunnable { 576a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 577a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.compublic: 578a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end, 579a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkRunnable* done) 580a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com : fClone(clone) 581a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fCanvas(canvas) 582a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fPath(NULL) 583a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fRects(rects) 584a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fStart(start) 585a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fEnd(end) 586a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fSuccess(NULL) 587a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com , fDone(done) { 588a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkASSERT(fDone != NULL); 589a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } 590a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 591a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com virtual void run() SK_OVERRIDE { 592a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkGraphics::SetTLSFontCacheLimit(1024 * 1024); 59384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com 59484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com SkBitmap bitmap; 59584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (fBitmap != NULL) { 59684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com // All tiles are the same size. 5979c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScalarFloorToInt(fRects[0].height())); 59884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 599a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com 600a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = fStart; i < fEnd; i++) { 601a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com DrawTileToCanvas(fCanvas, fRects[i], fClone); 602a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com if (fPath != NULL && !writeAppendNumber(fCanvas, fPath, i) 603a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com && fSuccess != NULL) { 604a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com *fSuccess = false; 605a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // If one tile fails to write to a file, do not continue drawing the rest. 606a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com break; 607a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } 60884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (fBitmap != NULL) { 60984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (fCanvas->readPixels(&bitmap, 0, 0)) { 61084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com SkAutoLockPixels alp(*fBitmap); 6119c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com bitmapCopySubset(bitmap, fBitmap, SkScalarFloorToInt(fRects[i].left()), 6129c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com SkScalarFloorToInt(fRects[i].top())); 61384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } else { 61484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com *fSuccess = false; 61584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com // If one tile fails to read pixels, do not continue drawing the rest. 61684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com break; 61784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 61884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 619a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } 620a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fDone->run(); 621a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } 622bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com 623a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com void setPathAndSuccess(const SkString* path, bool* success) { 624a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fPath = path; 625a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fSuccess = success; 626a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } 627bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com 62884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com void setBitmap(SkBitmap* bitmap) { 62984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com fBitmap = bitmap; 63084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 63184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com 632a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comprivate: 633a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // All pointers unowned. 634a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkPicture* fClone; // Picture to draw from. Each CloneData has a unique one which 635a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // is threadsafe. 636a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkCanvas* fCanvas; // Canvas to draw to. Reused for each tile. 637a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com const SkString* fPath; // If non-null, path to write the result to as a PNG. 638a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkTDArray<SkRect>& fRects; // All tiles of the picture. 639a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com const int fStart; // Range of tiles drawn by this thread. 640a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com const int fEnd; 641a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com bool* fSuccess; // Only meaningful if path is non-null. Shared by all threads, 642a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // and only set to false upon failure to write to a PNG. 643a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkRunnable* fDone; 64484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com SkBitmap* fBitmap; 64558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com}; 64658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com 647a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comMultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount) 648a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com: fNumThreads(threadCount) 649a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com, fThreadPool(threadCount) 650a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com, fCountdown(threadCount) { 651a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // Only need to create fNumThreads - 1 clones, since one thread will use the base 652a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // picture. 653a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1); 654a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads); 655a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com} 656a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 657a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comvoid MultiCorePictureRenderer::init(SkPicture *pict) { 658a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // Set fPicture and the tiles. 659a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com this->INHERITED::init(pict); 660a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = 0; i < fNumThreads; ++i) { 661a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->getTileHeight()); 662a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } 663a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // Only need to create fNumThreads - 1 clones, since one thread will use the base picture. 664a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fPicture->clone(fPictureClones, fNumThreads - 1); 665a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // Populate each thread with the appropriate data. 666a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all. 667a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads; 668a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 669a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = 0; i < fNumThreads; i++) { 670a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkPicture* pic; 671a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com if (i == fNumThreads-1) { 672a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // The last set will use the original SkPicture. 673a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com pic = fPicture; 674a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com } else { 675a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com pic = &fPictureClones[i]; 676b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com } 677a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com const int start = i * chunkSize; 678a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com const int end = SkMin32(start + chunkSize, fTileRects.count()); 679a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCloneData[i] = SkNEW_ARGS(CloneData, 680a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown)); 681bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com } 682bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com} 68358b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com 68484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool MultiCorePictureRenderer::render(const SkString *path, SkBitmap** out) { 685a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com bool success = true; 686a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com if (path != NULL) { 687a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = 0; i < fNumThreads-1; i++) { 688a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCloneData[i]->setPathAndSuccess(path, &success); 689bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com } 690bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com } 691bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com 69284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com if (NULL != out) { 69384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com *out = SkNEW(SkBitmap); 69484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com setup_bitmap(*out, fPicture->width(), fPicture->height()); 69584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com for (int i = 0; i < fNumThreads; i++) { 69684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com fCloneData[i]->setBitmap(*out); 69784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 69884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } else { 69984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com for (int i = 0; i < fNumThreads; i++) { 70084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com fCloneData[i]->setBitmap(NULL); 70184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 70284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com } 70384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com 704a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCountdown.reset(fNumThreads); 705a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = 0; i < fNumThreads; i++) { 706a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fThreadPool.add(fCloneData[i]); 707acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com } 708a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCountdown.wait(); 709acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com 710a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com return success; 711a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com} 712a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 713a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comvoid MultiCorePictureRenderer::end() { 714a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com for (int i = 0; i < fNumThreads - 1; i++) { 715a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkDELETE(fCloneData[i]); 716a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCloneData[i] = NULL; 717163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org } 718a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 719a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com fCanvasPool.unrefAll(); 720a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com 721a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com this->INHERITED::end(); 722163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org} 723163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org 724a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comMultiCorePictureRenderer::~MultiCorePictureRenderer() { 725a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com // Each individual CloneData was deleted in end. 726a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkDELETE_ARRAY(fCloneData); 727a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com SkDELETE_ARRAY(fPictureClones); 728bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com} 729bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com 7300a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString MultiCorePictureRenderer::getConfigNameInternal() { 7310a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com SkString name = this->INHERITED::getConfigNameInternal(); 7320a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com name.appendf("_multi_%i_threads", fNumThreads); 7330a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com return name; 7340a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com} 7350a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 736acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com/////////////////////////////////////////////////////////////////////////////////////////////// 7379a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com 7389a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.comvoid PlaybackCreationRenderer::setup() { 7399313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fReplayer.reset(this->createPicture()); 74082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com SkCanvas* recorder = fReplayer->beginRecording(this->getViewWidth(), this->getViewHeight(), 7419313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org this->recordFlags()); 74282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com this->scaleToScaleFactor(recorder); 7439a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com fPicture->draw(recorder); 7449a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com} 7459a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com 74684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.combool PlaybackCreationRenderer::render(const SkString*, SkBitmap** out) { 7479313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org fReplayer->endRecording(); 74881f9d2e05be4902993345dac93337158345c660bscroggo@google.com // Since this class does not actually render, return false. 74981f9d2e05be4902993345dac93337158345c660bscroggo@google.com return false; 750451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 751451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org 7520a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PlaybackCreationRenderer::getConfigNameInternal() { 7530a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com return SkString("playback_creation"); 7540a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com} 7550a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com 7569313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org/////////////////////////////////////////////////////////////////////////////////////////////// 7579313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org// SkPicture variants for each BBoxHierarchy type 7589313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org 7599313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgclass RTreePicture : public SkPicture { 7609313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgpublic: 7619313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{ 7629313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org static const int kRTreeMinChildren = 6; 7639313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org static const int kRTreeMaxChildren = 11; 7649313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth), 7659313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkIntToScalar(fHeight)); 7669313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren, 7679313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org aspectRatio); 7689313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org } 7699313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}; 7709313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org 7719313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgSkPicture* PictureRenderer::createPicture() { 7729313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org switch (fBBoxHierarchyType) { 7739313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org case kNone_BBoxHierarchyType: 7749313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org return SkNEW(SkPicture); 7759313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org case kRTree_BBoxHierarchyType: 7769313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org return SkNEW(RTreePicture); 7777b53706a7d596a2d8dce6cfe5b543264e5a37239junov@chromium.org case kTileGrid_BBoxHierarchyType: 7783cb834bd27a16cc60ff30adae96659558c2dc91fjunov@chromium.org return SkNEW_ARGS(SkTileGridPicture, (fGridWidth, fGridHeight, fPicture->width(), 7793cb834bd27a16cc60ff30adae96659558c2dc91fjunov@chromium.org fPicture->height())); 7809313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org } 7819313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org SkASSERT(0); // invalid bbhType 7829313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org return NULL; 783451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org} 7849313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org 785fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com/////////////////////////////////////////////////////////////////////////////// 786fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com 787fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comclass GatherRenderer : public PictureRenderer { 788fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.compublic: 78984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com virtual bool render(const SkString* path, SkBitmap** out = NULL) 79084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com SK_OVERRIDE { 791fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()), 792fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com SkIntToScalar(fPicture->height())); 793fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds); 794fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com SkSafeUnref(data); 795c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com 796fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com return NULL == path; // we don't have anything to write 797fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com } 798c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com 799fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comprivate: 800fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com virtual SkString getConfigNameInternal() SK_OVERRIDE { 801fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com return SkString("gather_pixelrefs"); 802fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com } 803fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com}; 804fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com 805fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comPictureRenderer* CreateGatherPixelRefsRenderer() { 806fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com return SkNEW(GatherRenderer); 807fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com} 808c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 8095a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 8105a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com 8115a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comclass PictureCloneRenderer : public PictureRenderer { 8125a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.compublic: 81384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com virtual bool render(const SkString* path, SkBitmap** out = NULL) 81484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com SK_OVERRIDE { 8155a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com for (int i = 0; i < 100; ++i) { 8165a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com SkPicture* clone = fPicture->clone(); 8175a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com SkSafeUnref(clone); 8185a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com } 819c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com 8205a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com return NULL == path; // we don't have anything to write 8215a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com } 822c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com 8235a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comprivate: 8245a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com virtual SkString getConfigNameInternal() SK_OVERRIDE { 8255a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com return SkString("picture_clone"); 8265a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com } 8275a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com}; 8285a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com 8295a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comPictureRenderer* CreatePictureCloneRenderer() { 8305a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com return SkNEW(PictureCloneRenderer); 8315a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com} 8325a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com 8339313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} // namespace sk_tools 834