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"
11a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org#include "SkBitmapHasher.h"
12451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkCanvas.h"
131b1bcc3ceac9b4adbb4de68429903a5f721ffe62scroggo@google.com#include "SkData.h"
14451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkDevice.h"
1594d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com#include "SkDiscardableMemoryPool.h"
16451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkGPipe.h"
1758b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#if SK_SUPPORT_GPU
18fe1b536bb7af523995549b64ad19de6685e11411robertphillips@google.com#include "gl/GrGLDefines.h"
1958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkGpuDevice.h"
2058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#endif
2158b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkGraphics.h"
2258b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkImageEncoder.h"
23a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com#include "SkMaskFilter.h"
24ea82695325e2afc68f646fcc23fcae8b1bff6dc1keyar@chromium.org#include "SkMatrix.h"
2524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org#include "SkOSFile.h"
26451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkPicture.h"
27770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "SkPictureRecorder.h"
281b1bcc3ceac9b4adbb4de68429903a5f721ffe62scroggo@google.com#include "SkPictureUtils.h"
291b1bcc3ceac9b4adbb4de68429903a5f721ffe62scroggo@google.com#include "SkPixelRef.h"
30ea82695325e2afc68f646fcc23fcae8b1bff6dc1keyar@chromium.org#include "SkScalar.h"
31a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com#include "SkStream.h"
329299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org#include "SkString.h"
3358b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkTemplates.h"
34451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkTDArray.h"
3558b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com#include "SkThreadUtils.h"
36451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org#include "SkTypes.h"
374ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org
38e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.comstatic inline SkScalar scalar_log2(SkScalar x) {
39e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.com    static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2));
403b85deb9c3c0889152ccbff02cf4417df161fe33skia.committer@gmail.com
41e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.com    return SkScalarLog(x) * log2_conversion_factor;
42e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.com}
43e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.com
44451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgnamespace sk_tools {
45451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
46451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgenum {
47451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    kDefaultTileWidth = 256,
48451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    kDefaultTileHeight = 256
49451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org};
50451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
512a65a238b0e688356aee09d08f3f8a317359b4d2mtkleinvoid PictureRenderer::init(const SkPicture* pict,
522a65a238b0e688356aee09d08f3f8a317359b4d2mtklein                           const SkString* writePath,
53ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                           const SkString* mismatchPath,
542a65a238b0e688356aee09d08f3f8a317359b4d2mtklein                           const SkString* inputFilename,
55ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                           bool useChecksumBasedFilenames) {
563f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fWritePath, writePath);
573f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fMismatchPath, mismatchPath);
58f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    this->CopyString(&fInputFilename, inputFilename);
59f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    fUseChecksumBasedFilenames = useChecksumBasedFilenames;
60f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
6178a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    SkASSERT(NULL == fPicture);
6278a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    SkASSERT(NULL == fCanvas.get());
6349f085dddff10473b6ebf832a974288300224e60bsalomon    if (fPicture || fCanvas.get()) {
649d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
659d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
669d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
679d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(pict != NULL);
6878a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == pict) {
699d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
709d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
719d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
7284b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(pict)->ref();
73a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org    fCanvas.reset(this->setupCanvas());
74a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org}
75a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
76f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgvoid PictureRenderer::CopyString(SkString* dest, const SkString* src) {
7749f085dddff10473b6ebf832a974288300224e60bsalomon    if (src) {
78f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        dest->set(*src);
79f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    } else {
80f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        dest->reset();
81f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    }
82f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org}
83f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
84a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comclass FlagsDrawFilter : public SkDrawFilter {
85a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.compublic:
86a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) :
87a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        fFlags(flags) {}
88a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
89971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com    virtual bool filter(SkPaint* paint, Type t) {
90a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags);
91491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        if (PictureRenderer::kMaskFilter_DrawFilterFlag & fFlags[t]) {
92a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            SkMaskFilter* maskFilter = paint->getMaskFilter();
9349f085dddff10473b6ebf832a974288300224e60bsalomon            if (maskFilter) {
94457d8a77bed0160519fc5dfb67d0e02f9c3950a2reed@google.com                paint->setMaskFilter(NULL);
95a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            }
96a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        }
97a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) {
98a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            paint->setHinting(SkPaint::kNo_Hinting);
99a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) {
100a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            paint->setHinting(SkPaint::kSlight_Hinting);
101a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        }
102971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        return true;
103a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    }
104a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
105a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comprivate:
106a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    PictureRenderer::DrawFilterFlags* fFlags;
107a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com};
108a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
10982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comstatic void setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) {
110a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    if (drawFilters && !canvas->getDrawFilter()) {
111a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref();
112e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com        if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) {
113e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com            canvas->setAllowSoftClip(false);
114e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com        }
115a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    }
116a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com}
117a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
118a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas() {
119c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
120c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
121c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return this->setupCanvas(width, height);
122a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org}
123a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
124a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas(int width, int height) {
125a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    SkCanvas* canvas;
1264ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org    switch(fDeviceType) {
1274ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        case kBitmap_DeviceType: {
1284ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkBitmap bitmap;
129a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org            sk_tools::setup_bitmap(&bitmap, width, height);
130a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            canvas = SkNEW_ARGS(SkCanvas, (bitmap));
1314ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        }
13282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        break;
1334ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#if SK_SUPPORT_GPU
1340556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com#if SK_ANGLE
1350556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        case kAngle_DeviceType:
1360556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            // fall through
1370556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com#endif
1386ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com#if SK_MESA
1396ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com        case kMesa_DeviceType:
1406ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com            // fall through
1416ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com#endif
1420fd5270ad69f5b99852d544158c989d2deda2c11commit-bot@chromium.org        case kGPU_DeviceType:
1430fd5270ad69f5b99852d544158c989d2deda2c11commit-bot@chromium.org        case kNVPR_DeviceType: {
144ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org            SkAutoTUnref<GrSurface> target;
1450556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            if (fGrContext) {
1460556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                // create a render target to back the device
1470556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                GrTextureDesc desc;
1480556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fConfig = kSkia8888_GrPixelConfig;
1490556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fFlags = kRenderTarget_GrTextureFlagBit;
1500556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fWidth = width;
1510556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fHeight = height;
152f6a90332ae21414cf19630764d4371ffd24ac0ccjvanverth@google.com                desc.fSampleCnt = fSampleCount;
153ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org                target.reset(fGrContext->createUncachedTexture(desc, NULL, 0));
1540556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            }
155ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org            if (NULL == target.get()) {
1560556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                SkASSERT(0);
1570556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                return NULL;
1580556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            }
1590556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com
1604a8126e7f81384526629b1e21bf89b632ea13cd9reed            SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target,
1614a8126e7f81384526629b1e21bf89b632ea13cd9reed                                         SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)));
162a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            canvas = SkNEW_ARGS(SkCanvas, (device.get()));
1630556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            break;
1644ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        }
1654ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#endif
1664ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        default:
1674ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkASSERT(0);
16882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com            return NULL;
1694ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org    }
17082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    setUpFilter(canvas, fDrawFilters);
17182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    this->scaleToScaleFactor(canvas);
17217cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org
17317cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    // Pictures often lie about their extent (i.e., claim to be 100x100 but
17417cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    // only ever draw to 90x100). Clear here so the undrawn portion will have
17517cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    // a consistent color
17617cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    canvas->clear(SK_ColorTRANSPARENT);
17782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    return canvas;
17882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com}
179a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
18082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comvoid PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) {
18182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkASSERT(canvas != NULL);
18282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    if (fScaleFactor != SK_Scalar1) {
18382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        canvas->scale(fScaleFactor, fScaleFactor);
18482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    }
1859d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org}
1869d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
1879d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid PictureRenderer::end() {
18808085f808b808bfb14fcb247bb8cb1a5e8d43dccscroggo@google.com    this->resetState(true);
18984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(NULL);
1909d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    fCanvas.reset(NULL);
1919d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org}
1929d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
193c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewWidth() {
194c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    SkASSERT(fPicture != NULL);
195a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    int width = SkScalarCeilToInt(fPicture->cullRect().width() * fScaleFactor);
196c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (fViewport.width() > 0) {
197c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        width = SkMin32(width, fViewport.width());
198c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    }
199c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return width;
200c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com}
201c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
202c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewHeight() {
203c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    SkASSERT(fPicture != NULL);
204a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    int height = SkScalarCeilToInt(fPicture->cullRect().height() * fScaleFactor);
205c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (fViewport.height() > 0) {
206c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        height = SkMin32(height, fViewport.height());
207c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    }
208c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return height;
209c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com}
210c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
2119313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org/** Converts fPicture to a picture that uses a BBoxHierarchy.
2129313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org *  PictureRenderer subclasses that are used to test picture playback
2139313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org *  should call this method during init.
2149313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org */
2159313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgvoid PictureRenderer::buildBBoxHierarchy() {
21649f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(fPicture);
21749f085dddff10473b6ebf832a974288300224e60bsalomon    if (kNone_BBoxHierarchyType != fBBoxHierarchyType && fPicture) {
2185fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org        SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
2195fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org        SkPictureRecorder recorder;
220a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkCanvas* canvas = recorder.beginRecording(fPicture->cullRect().width(),
221a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                   fPicture->cullRect().height(),
2225fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                   factory.get(),
22384b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                                                   this->recordFlags());
224c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips        fPicture->playback(canvas);
22584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com        fPicture.reset(recorder.endRecording());
2269313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
2279313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
2289313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
22908085f808b808bfb14fcb247bb8cb1a5e8d43dccscroggo@google.comvoid PictureRenderer::resetState(bool callFinish) {
23028136b308fe467da113983cfee332faea133cd8akeyar@chromium.org#if SK_SUPPORT_GPU
2316177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com    SkGLContextHelper* glContext = this->getGLContext();
2320556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    if (NULL == glContext) {
2330556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        SkASSERT(kBitmap_DeviceType == fDeviceType);
2340556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        return;
2350556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    }
23628136b308fe467da113983cfee332faea133cd8akeyar@chromium.org
2370556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    fGrContext->flush();
23851c040ed1e8c50bec4297bbe25242f644b40b0b7commit-bot@chromium.org    glContext->swapBuffers();
2390556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    if (callFinish) {
2400556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        SK_GL(*glContext, Finish());
24177a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org    }
242a40c20df0e4c5d04acb0841d70127778c0a779eckeyar@chromium.org#endif
24377a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org}
24477a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org
24594d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.comvoid PictureRenderer::purgeTextures() {
24694d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool();
24794d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
24894d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    pool->dumpPool();
24994d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
25094d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com#if SK_SUPPORT_GPU
25194d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    SkGLContextHelper* glContext = this->getGLContext();
25294d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    if (NULL == glContext) {
25394d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com        SkASSERT(kBitmap_DeviceType == fDeviceType);
25494d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com        return;
25594d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    }
25694d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
25794d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    // resetState should've already done this
25894d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    fGrContext->flush();
25994d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
26094d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    fGrContext->purgeAllUnlockedResources();
26194d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com#endif
26294d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com}
26394d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
264b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com/**
2654610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org * Write the canvas to an image file and/or JSON summary.
266f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org *
267b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @param canvas Must be non-null. Canvas to be written to a file.
2683f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org * @param writePath If nonempty, write the binary image to a file within this directory.
2693f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org * @param mismatchPath If nonempty, write the binary image to a file within this directory,
2703f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org *     but only if the image does not match expectations.
271f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org * @param inputFilename If we are writing out a binary image, use this to build its filename.
2724610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org * @param jsonSummaryPtr If not null, add image results (checksum) to this summary.
273f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org * @param useChecksumBasedFilenames If true, use checksum-based filenames when writing to disk.
27424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org * @param tileNumberPtr If not null, which tile number this image contains.
275a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org *
2764610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org * @return bool True if the operation completed successfully.
277b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com */
2783f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.orgstatic bool write(SkCanvas* canvas, const SkString& writePath, const SkString& mismatchPath,
2793f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                  const SkString& inputFilename, ImageResultsAndExpectations *jsonSummaryPtr,
2803f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                  bool useChecksumBasedFilenames, const int* tileNumberPtr=NULL) {
28181f9d2e05be4902993345dac93337158345c660bscroggo@google.com    SkASSERT(canvas != NULL);
282b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    if (NULL == canvas) {
2839299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org        return false;
2849299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    }
2859299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
2869299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    SkBitmap bitmap;
28781f9d2e05be4902993345dac93337158345c660bscroggo@google.com    SkISize size = canvas->getDeviceSize();
288205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    setup_bitmap(&bitmap, size.width(), size.height());
289f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
29081f9d2e05be4902993345dac93337158345c660bscroggo@google.com    canvas->readPixels(&bitmap, 0, 0);
291205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    force_all_opaque(bitmap);
292205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    BitmapAndDigest bitmapAndDigest(bitmap);
2939299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
29424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    SkString escapedInputFilename(inputFilename);
29524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    replace_char(&escapedInputFilename, '.', '_');
29624c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org
297f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    // TODO(epoger): what about including the config type within outputFilename?  That way,
298f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    // we could combine results of different config types without conflicting filenames.
29924c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    SkString outputFilename;
30024c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    const char *outputSubdirPtr = NULL;
30124c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    if (useChecksumBasedFilenames) {
30285b438dfab7f6ec1fd46dbc19215ccf2171ad6aeepoger        ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr();
30324c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        outputSubdirPtr = escapedInputFilename.c_str();
304205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        outputFilename.set(imageDigestPtr->getHashType());
305205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        outputFilename.append("_");
306205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        outputFilename.appendU64(imageDigestPtr->getHashValue());
30724c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    } else {
30824c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        outputFilename.set(escapedInputFilename);
30949f085dddff10473b6ebf832a974288300224e60bsalomon        if (tileNumberPtr) {
31024c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputFilename.append("-tile");
31124c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputFilename.appendS32(*tileNumberPtr);
31224c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        }
313f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    }
31424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    outputFilename.append(".png");
3159299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
31649f085dddff10473b6ebf832a974288300224e60bsalomon    if (jsonSummaryPtr) {
31785b438dfab7f6ec1fd46dbc19215ccf2171ad6aeepoger        ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr();
31824c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        SkString outputRelativePath;
31924c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        if (outputSubdirPtr) {
32024c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.set(outputSubdirPtr);
32124c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.append("/");  // always use "/", even on Windows
32224c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.append(outputFilename);
32324c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        } else {
32424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.set(outputFilename);
32524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        }
32624c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org
32724c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(),
328205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org                            *imageDigestPtr, tileNumberPtr);
3293f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        if (!mismatchPath.isEmpty() &&
33085b438dfab7f6ec1fd46dbc19215ccf2171ad6aeepoger            !jsonSummaryPtr->getExpectation(inputFilename.c_str(),
33185b438dfab7f6ec1fd46dbc19215ccf2171ad6aeepoger                                            tileNumberPtr).matches(*imageDigestPtr)) {
3323f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org            if (!write_bitmap_to_disk(bitmap, mismatchPath, outputSubdirPtr, outputFilename)) {
3333f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                return false;
3343f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org            }
3353f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        }
336b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    }
337f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
3383f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    if (writePath.isEmpty()) {
3394610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org        return true;
34024c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    } else {
3413f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        return write_bitmap_to_disk(bitmap, writePath, outputSubdirPtr, outputFilename);
34224c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    }
343b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com}
344b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com
345acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
346acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
347fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.comSkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
348fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com    // defer the canvas setup until the render step
349fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com    return NULL;
350fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com}
351fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com
352672588b684d484dce6ae251e9e163e4a46924322reed@google.com// the size_t* parameter is deprecated, so we ignore it
353672588b684d484dce6ae251e9e163e4a46924322reed@google.comstatic SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
3541b1bcc3ceac9b4adbb4de68429903a5f721ffe62scroggo@google.com    return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
355a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com}
356a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com
357f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool RecordPictureRenderer::render(SkBitmap** out) {
3585fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
3595fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkPictureRecorder recorder;
360a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(this->getViewWidth()),
361a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                               SkIntToScalar(this->getViewHeight()),
3625fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                               factory.get(),
36384b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                                               this->recordFlags());
36484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    this->scaleToScaleFactor(canvas);
365c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    fPicture->playback(canvas);
36684b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
3673f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    if (!fWritePath.isEmpty()) {
368a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        // Record the new picture as a new SKP with PNG encoded bitmaps.
369a8e2e1504b9af6ba791637f228debaa23953064atfarina        SkString skpPath = SkOSPath::Join(fWritePath.c_str(), fInputFilename.c_str());
370a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        SkFILEWStream stream(skpPath.c_str());
37184b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com        picture->serialize(&stream, &encode_bitmap_to_data);
372a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        return true;
373a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com    }
37481f9d2e05be4902993345dac93337158345c660bscroggo@google.com    return false;
3759a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com}
3769a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
3770a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString RecordPictureRenderer::getConfigNameInternal() {
3780a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("record");
3790a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
3800a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
381acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
382acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
383f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool PipePictureRenderer::render(SkBitmap** out) {
3849d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fCanvas.get() != NULL);
3859d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fPicture != NULL);
38678a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == fCanvas.get() || NULL == fPicture) {
38781f9d2e05be4902993345dac93337158345c660bscroggo@google.com        return false;
3889d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
3899d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
3909d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    PipeController pipeController(fCanvas.get());
391451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    SkGPipeWriter writer;
392451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
3939b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    pipeCanvas->drawPicture(fPicture);
394451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    writer.endRecording();
3959a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fCanvas->flush();
39649f085dddff10473b6ebf832a974288300224e60bsalomon    if (out) {
39784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
398a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
399a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                           SkScalarCeilToInt(fPicture->cullRect().height()));
40084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fCanvas->readPixels(*out, 0, 0);
401a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com    }
4028991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    if (fEnableWrites) {
4038991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
4048991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                     fUseChecksumBasedFilenames);
4058991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    } else {
4068991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return true;
4078991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    }
408451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
409451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4100a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PipePictureRenderer::getConfigNameInternal() {
4110a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("pipe");
4120a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
4130a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
414acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
415acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
416ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipsvoid SimplePictureRenderer::init(const SkPicture* picture, const SkString* writePath,
4173f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                 const SkString* mismatchPath, const SkString* inputFilename,
4183f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                 bool useChecksumBasedFilenames) {
4193f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    INHERITED::init(picture, writePath, mismatchPath, inputFilename, useChecksumBasedFilenames);
4209313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    this->buildBBoxHierarchy();
4219313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
4229313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
423f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool SimplePictureRenderer::render(SkBitmap** out) {
4249d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fCanvas.get() != NULL);
42549f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(fPicture);
42678a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == fCanvas.get() || NULL == fPicture) {
42781f9d2e05be4902993345dac93337158345c660bscroggo@google.com        return false;
4289d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
4299d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
4309b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    fCanvas->drawPicture(fPicture);
4319a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fCanvas->flush();
43249f085dddff10473b6ebf832a974288300224e60bsalomon    if (out) {
43384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
434a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
435a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                           SkScalarCeilToInt(fPicture->cullRect().height()));
43684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fCanvas->readPixels(*out, 0, 0);
43784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
4388991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    if (fEnableWrites) {
4398991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
4408991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                     fUseChecksumBasedFilenames);
4418991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    } else {
4428991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return true;
4438991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    }
444451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
445451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4460a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString SimplePictureRenderer::getConfigNameInternal() {
4470a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("simple");
4480a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
4490a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
450acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
451acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
452b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#if SK_SUPPORT_GPU
453b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevskiTiledPictureRenderer::TiledPictureRenderer(const GrContext::Options& opts)
4542a65a238b0e688356aee09d08f3f8a317359b4d2mtklein    : INHERITED(opts)
455b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski    , fTileWidth(kDefaultTileWidth)
456b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#else
457451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgTiledPictureRenderer::TiledPictureRenderer()
458a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    : fTileWidth(kDefaultTileWidth)
459b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#endif
460b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com    , fTileHeight(kDefaultTileHeight)
461a04dc02b118363fedf3a7b11cfcdab886d368f8arileya@google.com    , fTileWidthPercentage(0.0)
462b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com    , fTileHeightPercentage(0.0)
463cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTileMinPowerOf2Width(0)
464cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fCurrentTileOffset(-1)
465cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTilesX(0)
466cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTilesY(0) { }
467451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
468ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillipsvoid TiledPictureRenderer::init(const SkPicture* pict, const SkString* writePath,
4693f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                const SkString* mismatchPath, const SkString* inputFilename,
4703f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                bool useChecksumBasedFilenames) {
47149f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(pict);
472acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    SkASSERT(0 == fTileRects.count());
473acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    if (NULL == pict || fTileRects.count() != 0) {
4749d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
4759d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
4769d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
477acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not
478acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    // used by bench_pictures.
47984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(pict)->ref();
4803f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fWritePath, writePath);
4813f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fMismatchPath, mismatchPath);
482f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    this->CopyString(&fInputFilename, inputFilename);
483f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    fUseChecksumBasedFilenames = useChecksumBasedFilenames;
484a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    this->buildBBoxHierarchy();
485cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org
486cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    if (fTileWidthPercentage > 0) {
487a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        fTileWidth = SkScalarCeilToInt(float(fTileWidthPercentage * fPicture->cullRect().width() / 100));
488cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    }
489cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    if (fTileHeightPercentage > 0) {
490a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        fTileHeight = SkScalarCeilToInt(float(fTileHeightPercentage * fPicture->cullRect().height() / 100));
491cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    }
492cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org
493f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    if (fTileMinPowerOf2Width > 0) {
494f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        this->setupPowerOf2Tiles();
495f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    } else {
496f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        this->setupTiles();
497f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
498cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight));
499cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    // Initialize to -1 so that the first call to nextTile will set this up to draw tile 0 on the
500cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    // first call to drawCurrentTile.
501cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fCurrentTileOffset = -1;
502451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
503451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
5049d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::end() {
505bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    fTileRects.reset();
5069d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    this->INHERITED::end();
507451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
508451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
5099d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::setupTiles() {
510c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    // Only use enough tiles to cover the viewport
511c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
512c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
513c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
514cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fTilesX = fTilesY = 0;
515c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
516cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        fTilesY++;
517c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWidth) {
518cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            if (0 == tile_y_start) {
519cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                // Only count tiles in the X direction on the first pass.
520cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                fTilesX++;
521cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            }
522acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com            *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
523acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(tile_y_start),
524acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(fTileWidth),
525acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(fTileHeight));
526f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        }
527f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
528f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org}
529f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
530cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::tileDimensions(int &x, int &y) {
531cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    if (fTileRects.count() == 0 || NULL == fPicture) {
532cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        return false;
533cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    }
534cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    x = fTilesX;
535cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    y = fTilesY;
536cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    return true;
537cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
538cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
539f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// The goal of the powers of two tiles is to minimize the amount of wasted tile
540f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// space in the width-wise direction and then minimize the number of tiles. The
541f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// constraints are that every tile must have a pixel width that is a power of
542f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// two and also be of some minimal width (that is also a power of two).
543f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org//
54458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com// This is solved by first taking our picture size and rounding it up to the
545f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// multiple of the minimal width. The binary representation of this rounded
546f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// value gives us the tiles we need: a bit of value one means we need a tile of
547f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// that size.
548f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.orgvoid TiledPictureRenderer::setupPowerOf2Tiles() {
549c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    // Only use enough tiles to cover the viewport
550c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
551c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
552c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
553c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    int rounded_value = width;
554c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (width % fTileMinPowerOf2Width != 0) {
555c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerOf2Width;
556f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
557f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
558e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.com    int num_bits = SkScalarCeilToInt(scalar_log2(SkIntToScalar(width)));
559f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    int largest_possible_tile_size = 1 << num_bits;
560f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
561cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fTilesX = fTilesY = 0;
562f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    // The tile height is constant for a particular picture.
563c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
564cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        fTilesY++;
565f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        int tile_x_start = 0;
566f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        int current_width = largest_possible_tile_size;
567acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough
568acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        // to draw each tile.
569acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        fTileWidth = current_width;
570f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
571f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        while (current_width >= fTileMinPowerOf2Width) {
572f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            // It is very important this is a bitwise AND.
573f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            if (current_width & rounded_value) {
574cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                if (0 == tile_y_start) {
575cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                    // Only count tiles in the X direction on the first pass.
576cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                    fTilesX++;
577cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                }
578acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
579acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(tile_y_start),
580acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(current_width),
581acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(fTileHeight));
582f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org                tile_x_start += current_width;
583f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            }
584f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
585f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            current_width >>= 1;
586451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org        }
587451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    }
588451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
589451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
590bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com/**
591145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org * Draw the specified picture to the canvas translated to rectangle provided, so that this mini
592bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * canvas represents the rectangle's portion of the overall picture.
593bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * Saves and restores so that the initial clip and matrix return to their state before this function
594bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * is called.
595bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com */
5962a65a238b0e688356aee09d08f3f8a317359b4d2mtkleinstatic void draw_tile_to_canvas(SkCanvas* canvas,
5972a65a238b0e688356aee09d08f3f8a317359b4d2mtklein                                const SkRect& tileRect,
598ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips                                const SkPicture* picture) {
599bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    int saveCount = canvas->save();
60082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Translate so that we draw the correct portion of the picture.
60182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Perform a postTranslate so that the scaleFactor does not interfere with the positioning.
60282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkMatrix mat(canvas->getTotalMatrix());
60382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    mat.postTranslate(-tileRect.fLeft, -tileRect.fTop);
60482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    canvas->setMatrix(mat);
6059b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas->drawPicture(picture);
606bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    canvas->restoreToCount(saveCount);
607bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    canvas->flush();
608451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
609451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
61058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
611bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
612a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org/**
613a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * Copies the entirety of the src bitmap (typically a tile) into a portion of the dst bitmap.
614a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * If the src bitmap is too large to fit within the dst bitmap after the x and y
615a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * offsets have been applied, any excess will be ignored (so only the top-left portion of the
616a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * src bitmap will be copied).
617a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org *
618a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param src source bitmap
619a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param dst destination bitmap
620a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param xOffset x-offset within destination bitmap
621a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param yOffset y-offset within destination bitmap
622a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org */
623a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.orgstatic void bitmapCopyAtOffset(const SkBitmap& src, SkBitmap* dst,
624a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                               int xOffset, int yOffset) {
625a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org    for (int y = 0; y <src.height() && y + yOffset < dst->height() ; y++) {
626a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org        for (int x = 0; x < src.width() && x + xOffset < dst->width() ; x++) {
627a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org            *dst->getAddr32(xOffset + x, yOffset + y) = *src.getAddr32(x, y);
62884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
62984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
63084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com}
63184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
632cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::nextTile(int &i, int &j) {
633cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    if (++fCurrentTileOffset < fTileRects.count()) {
634cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        i = fCurrentTileOffset % fTilesX;
635cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        j = fCurrentTileOffset / fTilesX;
636cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        return true;
637cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    }
638cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    return false;
639cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
640cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
641cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.comvoid TiledPictureRenderer::drawCurrentTile() {
642cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count());
643145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture);
644cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
645cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
646f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool TiledPictureRenderer::render(SkBitmap** out) {
647a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkASSERT(fPicture != NULL);
648a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    if (NULL == fPicture) {
649a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        return false;
650bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
651bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
65284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    SkBitmap bitmap;
65384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (out){
65484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
655a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
656a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                           SkScalarCeilToInt(fPicture->cullRect().height()));
65784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(&bitmap, fTileWidth, fTileHeight);
65884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
659a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool success = true;
660a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fTileRects.count(); ++i) {
661145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture);
6628991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        if (fEnableWrites) {
6638991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org            success &= write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
6648991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                             fUseChecksumBasedFilenames, &i);
6658991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        }
66649f085dddff10473b6ebf832a974288300224e60bsalomon        if (out) {
66784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            if (fCanvas->readPixels(&bitmap, 0, 0)) {
668a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                // Add this tile to the entire bitmap.
669a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()),
670a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                                   SkScalarFloorToInt(fTileRects[i].top()));
67184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            } else {
67284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                success = false;
67384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            }
67484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
675bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
676a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return success;
677bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
67858b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
679a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comSkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) {
680a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkCanvas* canvas = this->INHERITED::setupCanvas(width, height);
68149f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(fPicture);
68282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This
68382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // is mostly important for tiles on the right and bottom edges as they may go over this area and
68482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // the picture may have some commands that draw outside of this area and so should not actually
68582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // be written.
68682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Uses a clipRegion so that it will be unaffected by the scale factor, which may have been set
68782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // by INHERITED::setupCanvas.
68882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkRegion clipRegion;
68982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight());
69082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    canvas->clipRegion(clipRegion);
691a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return canvas;
692a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
6930a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
6940a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString TiledPictureRenderer::getConfigNameInternal() {
6950a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    SkString name;
6960a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    if (fTileMinPowerOf2Width > 0) {
6970a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.append("pow2tile_");
6980a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%i", fTileMinPowerOf2Width);
6990a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    } else {
7000a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.append("tile_");
7010a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        if (fTileWidthPercentage > 0) {
7020a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com            name.appendf("%.f%%", fTileWidthPercentage);
7030a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        } else {
7040a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com            name.appendf("%i", fTileWidth);
7050a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        }
7060a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    }
7070a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    name.append("x");
7080a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    if (fTileHeightPercentage > 0) {
7090a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%.f%%", fTileHeightPercentage);
7100a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    } else {
7110a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%i", fTileHeight);
7120a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    }
7130a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return name;
7140a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
7150a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
71658b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
71758b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
7189a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.comvoid PlaybackCreationRenderer::setup() {
7195fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
7205fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    fRecorder.reset(SkNEW(SkPictureRecorder));
721a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkCanvas* canvas = fRecorder->beginRecording(SkIntToScalar(this->getViewWidth()),
722a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 SkIntToScalar(this->getViewHeight()),
7235fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                 factory.get(),
72484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                                                 this->recordFlags());
72584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    this->scaleToScaleFactor(canvas);
7269b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas->drawPicture(fPicture);
7279a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com}
7289a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
729f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool PlaybackCreationRenderer::render(SkBitmap** out) {
73084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(fRecorder->endRecording());
73181f9d2e05be4902993345dac93337158345c660bscroggo@google.com    // Since this class does not actually render, return false.
73281f9d2e05be4902993345dac93337158345c660bscroggo@google.com    return false;
733451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
734451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
7350a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PlaybackCreationRenderer::getConfigNameInternal() {
7360a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("playback_creation");
7370a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
7380a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
7399313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org///////////////////////////////////////////////////////////////////////////////////////////////
7409313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org// SkPicture variants for each BBoxHierarchy type
7419313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
7425fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.orgSkBBHFactory* PictureRenderer::getFactory() {
7439313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    switch (fBBoxHierarchyType) {
7449313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        case kNone_BBoxHierarchyType:
74584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com            return NULL;
7469313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        case kRTree_BBoxHierarchyType:
7475fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org            return SkNEW(SkRTreeFactory);
7487b53706a7d596a2d8dce6cfe5b543264e5a37239junov@chromium.org        case kTileGrid_BBoxHierarchyType:
7495fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org            return SkNEW_ARGS(SkTileGridFactory, (fGridInfo));
7509313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
7519313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkASSERT(0); // invalid bbhType
7529313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    return NULL;
753451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
7549313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
755fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com///////////////////////////////////////////////////////////////////////////////
756fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
757fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comclass GatherRenderer : public PictureRenderer {
758fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.compublic:
759b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#if SK_SUPPORT_GPU
760b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski    GatherRenderer(const GrContext::Options& opts) : INHERITED(opts) { }
761b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#endif
762b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski
7638ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE {
764a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->cullRect().width()),
765a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                       SkIntToScalar(fPicture->cullRect().height()));
766fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
767fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkSafeUnref(data);
768c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
7693f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        return (fWritePath.isEmpty());    // we don't have anything to write
770fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
771c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
772fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comprivate:
773fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual SkString getConfigNameInternal() SK_OVERRIDE {
774fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        return SkString("gather_pixelrefs");
775fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
776b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski
777b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski    typedef PictureRenderer INHERITED;
778fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com};
779fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
780b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#if SK_SUPPORT_GPU
781b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevskiPictureRenderer* CreateGatherPixelRefsRenderer(const GrContext::Options& opts) {
782b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski    return SkNEW_ARGS(GatherRenderer, (opts));
783b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski}
784b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#else
785fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comPictureRenderer* CreateGatherPixelRefsRenderer() {
786fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    return SkNEW(GatherRenderer);
787fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com}
788b1aded8edd1d809cded20ff546c6e9218b43cda4krajcevski#endif
789c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com
7909313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} // namespace sk_tools
791