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
513f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.orgvoid PictureRenderer::init(SkPicture* pict, const SkString* writePath, const SkString* mismatchPath,
52f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org                           const SkString* inputFilename, bool useChecksumBasedFilenames) {
533f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fWritePath, writePath);
543f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fMismatchPath, mismatchPath);
55f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    this->CopyString(&fInputFilename, inputFilename);
56f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    fUseChecksumBasedFilenames = useChecksumBasedFilenames;
57f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
5878a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    SkASSERT(NULL == fPicture);
5978a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    SkASSERT(NULL == fCanvas.get());
6084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    if (NULL != fPicture || NULL != fCanvas.get()) {
619d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
629d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
639d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
649d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(pict != NULL);
6578a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == pict) {
669d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
679d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
689d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
6984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(pict)->ref();
70a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org    fCanvas.reset(this->setupCanvas());
71a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org}
72a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
73f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgvoid PictureRenderer::CopyString(SkString* dest, const SkString* src) {
74f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    if (NULL != src) {
75f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        dest->set(*src);
76f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    } else {
77f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        dest->reset();
78f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    }
79f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org}
80f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
81a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comclass FlagsDrawFilter : public SkDrawFilter {
82a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.compublic:
83a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    FlagsDrawFilter(PictureRenderer::DrawFilterFlags* flags) :
84a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        fFlags(flags) {}
85a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
86971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com    virtual bool filter(SkPaint* paint, Type t) {
87a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags);
88491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com        if (PictureRenderer::kMaskFilter_DrawFilterFlag & fFlags[t]) {
89a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            SkMaskFilter* maskFilter = paint->getMaskFilter();
90491493119c11206c5823b76eb6420a705be243a1robertphillips@google.com            if (NULL != maskFilter) {
91457d8a77bed0160519fc5dfb67d0e02f9c3950a2reed@google.com                paint->setMaskFilter(NULL);
92a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            }
93a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        }
94a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) {
95a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            paint->setHinting(SkPaint::kNo_Hinting);
96a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) {
97a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            paint->setHinting(SkPaint::kSlight_Hinting);
98a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        }
99971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        return true;
100a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    }
101a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
102a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.comprivate:
103a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    PictureRenderer::DrawFilterFlags* fFlags;
104a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com};
105a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
10682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comstatic void setUpFilter(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* drawFilters) {
107a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    if (drawFilters && !canvas->getDrawFilter()) {
108a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com        canvas->setDrawFilter(SkNEW_ARGS(FlagsDrawFilter, (drawFilters)))->unref();
109e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com        if (drawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) {
110e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com            canvas->setAllowSoftClip(false);
111e3e940cf81dc46d872002ded98c1bd39c2daf1b0caryclark@google.com        }
112a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    }
113a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com}
114a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com
115a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas() {
116c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
117c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
118c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return this->setupCanvas(width, height);
119a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org}
120a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
121a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.orgSkCanvas* PictureRenderer::setupCanvas(int width, int height) {
122a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com    SkCanvas* canvas;
1234ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org    switch(fDeviceType) {
1244ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        case kBitmap_DeviceType: {
1254ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkBitmap bitmap;
126a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org            sk_tools::setup_bitmap(&bitmap, width, height);
127a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            canvas = SkNEW_ARGS(SkCanvas, (bitmap));
1284ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        }
12982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        break;
1304ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#if SK_SUPPORT_GPU
1310556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com#if SK_ANGLE
1320556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        case kAngle_DeviceType:
1330556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            // fall through
1340556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com#endif
1356ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com#if SK_MESA
1366ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com        case kMesa_DeviceType:
1376ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com            // fall through
1386ab96733b85cebac99b378f998cd7dc10b286395rmistry@google.com#endif
1390fd5270ad69f5b99852d544158c989d2deda2c11commit-bot@chromium.org        case kGPU_DeviceType:
1400fd5270ad69f5b99852d544158c989d2deda2c11commit-bot@chromium.org        case kNVPR_DeviceType: {
141ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org            SkAutoTUnref<GrSurface> target;
1420556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            if (fGrContext) {
1430556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                // create a render target to back the device
1440556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                GrTextureDesc desc;
1450556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fConfig = kSkia8888_GrPixelConfig;
1460556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fFlags = kRenderTarget_GrTextureFlagBit;
1470556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fWidth = width;
1480556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                desc.fHeight = height;
149f6a90332ae21414cf19630764d4371ffd24ac0ccjvanverth@google.com                desc.fSampleCnt = fSampleCount;
150ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org                target.reset(fGrContext->createUncachedTexture(desc, NULL, 0));
1510556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            }
152ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org            if (NULL == target.get()) {
1530556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                SkASSERT(0);
1540556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com                return NULL;
1550556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            }
1560556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com
157ae403b94967aa73fe0fd9f0afb612d5773aeafbfcommit-bot@chromium.org            SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target));
158a36223764466c964ed1035bf6f152ba55168f61ecaryclark@google.com            canvas = SkNEW_ARGS(SkCanvas, (device.get()));
1590556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com            break;
1604ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        }
1614ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org#endif
1624ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org        default:
1634ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org            SkASSERT(0);
16482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com            return NULL;
1654ea96c5e5449248780acfeb3cef4ec812f955d74keyar@chromium.org    }
16682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    setUpFilter(canvas, fDrawFilters);
16782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    this->scaleToScaleFactor(canvas);
16817cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org
16917cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    // Pictures often lie about their extent (i.e., claim to be 100x100 but
17017cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    // only ever draw to 90x100). Clear here so the undrawn portion will have
17117cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    // a consistent color
17217cc3eaeafd507a78b7f713f8981a6ed67569964commit-bot@chromium.org    canvas->clear(SK_ColorTRANSPARENT);
17382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    return canvas;
17482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com}
175a474ce3c0b7f72539e20a57b583b99046dfb7706keyar@chromium.org
17682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.comvoid PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) {
17782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkASSERT(canvas != NULL);
17882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    if (fScaleFactor != SK_Scalar1) {
17982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com        canvas->scale(fScaleFactor, fScaleFactor);
18082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    }
1819d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org}
1829d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
1839d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid PictureRenderer::end() {
18408085f808b808bfb14fcb247bb8cb1a5e8d43dccscroggo@google.com    this->resetState(true);
18584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(NULL);
1869d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    fCanvas.reset(NULL);
1879d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org}
1889d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
189c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewWidth() {
190c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    SkASSERT(fPicture != NULL);
1918ac811e1604d7bddff33f4f52c00ada10b19c59arobertphillips@google.com    int width = SkScalarCeilToInt(fPicture->width() * fScaleFactor);
192c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (fViewport.width() > 0) {
193c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        width = SkMin32(width, fViewport.width());
194c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    }
195c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return width;
196c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com}
197c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
198c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.comint PictureRenderer::getViewHeight() {
199c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    SkASSERT(fPicture != NULL);
2008ac811e1604d7bddff33f4f52c00ada10b19c59arobertphillips@google.com    int height = SkScalarCeilToInt(fPicture->height() * fScaleFactor);
201c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (fViewport.height() > 0) {
202c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        height = SkMin32(height, fViewport.height());
203c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    }
204c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    return height;
205c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com}
206c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
2079313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org/** Converts fPicture to a picture that uses a BBoxHierarchy.
2089313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org *  PictureRenderer subclasses that are used to test picture playback
2099313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org *  should call this method during init.
2109313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org */
2119313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.orgvoid PictureRenderer::buildBBoxHierarchy() {
2129313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkASSERT(NULL != fPicture);
2139313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) {
2145fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org        SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
2155fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org        SkPictureRecorder recorder;
21684b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com        SkCanvas* canvas = recorder.beginRecording(fPicture->width(), fPicture->height(),
2175fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                   factory.get(),
21884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                                                   this->recordFlags());
21984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com        fPicture->draw(canvas);
22084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com        fPicture.reset(recorder.endRecording());
2219313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
2229313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
2239313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
22408085f808b808bfb14fcb247bb8cb1a5e8d43dccscroggo@google.comvoid PictureRenderer::resetState(bool callFinish) {
22528136b308fe467da113983cfee332faea133cd8akeyar@chromium.org#if SK_SUPPORT_GPU
2266177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com    SkGLContextHelper* glContext = this->getGLContext();
2270556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    if (NULL == glContext) {
2280556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        SkASSERT(kBitmap_DeviceType == fDeviceType);
2290556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        return;
2300556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    }
23128136b308fe467da113983cfee332faea133cd8akeyar@chromium.org
2320556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    fGrContext->flush();
23351c040ed1e8c50bec4297bbe25242f644b40b0b7commit-bot@chromium.org    glContext->swapBuffers();
2340556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com    if (callFinish) {
2350556ea0ede7066b9b3ed9f03f5a6eb72cd718897scroggo@google.com        SK_GL(*glContext, Finish());
23677a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org    }
237a40c20df0e4c5d04acb0841d70127778c0a779eckeyar@chromium.org#endif
23877a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org}
23977a5522d0e4437ef2b856acd7b135b6afda64ceekeyar@chromium.org
24094d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.comvoid PictureRenderer::purgeTextures() {
24194d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool();
24294d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
24394d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    pool->dumpPool();
24494d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
24594d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com#if SK_SUPPORT_GPU
24694d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    SkGLContextHelper* glContext = this->getGLContext();
24794d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    if (NULL == glContext) {
24894d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com        SkASSERT(kBitmap_DeviceType == fDeviceType);
24994d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com        return;
25094d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    }
25194d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
25294d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    // resetState should've already done this
25394d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    fGrContext->flush();
25494d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
25594d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com    fGrContext->purgeAllUnlockedResources();
25694d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com#endif
25794d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com}
25894d8f1ed6116780346ffa39ed683f1977786434arobertphillips@google.com
259b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com/**
2604610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org * Write the canvas to an image file and/or JSON summary.
261f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org *
262b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com * @param canvas Must be non-null. Canvas to be written to a file.
2633f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org * @param writePath If nonempty, write the binary image to a file within this directory.
2643f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org * @param mismatchPath If nonempty, write the binary image to a file within this directory,
2653f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org *     but only if the image does not match expectations.
266f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org * @param inputFilename If we are writing out a binary image, use this to build its filename.
2674610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org * @param jsonSummaryPtr If not null, add image results (checksum) to this summary.
268f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org * @param useChecksumBasedFilenames If true, use checksum-based filenames when writing to disk.
26924c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org * @param tileNumberPtr If not null, which tile number this image contains.
270a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org *
2714610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org * @return bool True if the operation completed successfully.
272b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com */
2733f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.orgstatic bool write(SkCanvas* canvas, const SkString& writePath, const SkString& mismatchPath,
2743f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                  const SkString& inputFilename, ImageResultsAndExpectations *jsonSummaryPtr,
2753f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                  bool useChecksumBasedFilenames, const int* tileNumberPtr=NULL) {
27681f9d2e05be4902993345dac93337158345c660bscroggo@google.com    SkASSERT(canvas != NULL);
277b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    if (NULL == canvas) {
2789299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org        return false;
2799299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    }
2809299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
2819299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org    SkBitmap bitmap;
28281f9d2e05be4902993345dac93337158345c660bscroggo@google.com    SkISize size = canvas->getDeviceSize();
283205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    setup_bitmap(&bitmap, size.width(), size.height());
284f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
28581f9d2e05be4902993345dac93337158345c660bscroggo@google.com    canvas->readPixels(&bitmap, 0, 0);
286205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    force_all_opaque(bitmap);
287205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    BitmapAndDigest bitmapAndDigest(bitmap);
2889299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
28924c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    SkString escapedInputFilename(inputFilename);
29024c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    replace_char(&escapedInputFilename, '.', '_');
29124c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org
292f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    // TODO(epoger): what about including the config type within outputFilename?  That way,
293f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    // we could combine results of different config types without conflicting filenames.
29424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    SkString outputFilename;
29524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    const char *outputSubdirPtr = NULL;
29624c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    if (useChecksumBasedFilenames) {
297661832cadebab4ebc81885355077d71978d275fbcommit-bot@chromium.org        const ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr();
29824c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        outputSubdirPtr = escapedInputFilename.c_str();
299205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        outputFilename.set(imageDigestPtr->getHashType());
300205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        outputFilename.append("_");
301205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        outputFilename.appendU64(imageDigestPtr->getHashValue());
30224c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    } else {
30324c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        outputFilename.set(escapedInputFilename);
30424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        if (NULL != tileNumberPtr) {
30524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputFilename.append("-tile");
30624c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputFilename.appendS32(*tileNumberPtr);
30724c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        }
308f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    }
30924c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    outputFilename.append(".png");
3109299eded3838a7997235ff033aa3b9a8d4c6d4d4keyar@chromium.org
31124c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    if (NULL != jsonSummaryPtr) {
312205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org        const ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr();
31324c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        SkString outputRelativePath;
31424c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        if (outputSubdirPtr) {
31524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.set(outputSubdirPtr);
31624c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.append("/");  // always use "/", even on Windows
31724c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.append(outputFilename);
31824c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        } else {
31924c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org            outputRelativePath.set(outputFilename);
32024c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        }
32124c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org
32224c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org        jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(),
323205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org                            *imageDigestPtr, tileNumberPtr);
3243f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        if (!mismatchPath.isEmpty() &&
3253f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org            !jsonSummaryPtr->matchesExpectation(inputFilename.c_str(), *imageDigestPtr,
3263f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                                tileNumberPtr)) {
3273f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org            if (!write_bitmap_to_disk(bitmap, mismatchPath, outputSubdirPtr, outputFilename)) {
3283f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                return false;
3293f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org            }
3303f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        }
331b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com    }
332f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org
3333f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    if (writePath.isEmpty()) {
3344610a465b61f27ea5de2254a0e0b79ea2f327617commit-bot@chromium.org        return true;
33524c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    } else {
3363f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        return write_bitmap_to_disk(bitmap, writePath, outputSubdirPtr, outputFilename);
33724c568c1597de9f54df8cea3b46f2e93028a5aeccommit-bot@chromium.org    }
338b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com}
339b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com
340acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
341acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
342fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.comSkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
343fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com    // defer the canvas setup until the render step
344fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com    return NULL;
345fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com}
346fd9720cfec6bc50fa77d40ffdf2f6cb4b5150d4edjsollen@google.com
347672588b684d484dce6ae251e9e163e4a46924322reed@google.com// the size_t* parameter is deprecated, so we ignore it
348672588b684d484dce6ae251e9e163e4a46924322reed@google.comstatic SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
3491b1bcc3ceac9b4adbb4de68429903a5f721ffe62scroggo@google.com    return SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, 100);
350a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com}
351a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com
352f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool RecordPictureRenderer::render(SkBitmap** out) {
3535fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
3545fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkPictureRecorder recorder;
35584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkCanvas* canvas = recorder.beginRecording(this->getViewWidth(), this->getViewHeight(),
3565fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                               factory.get(),
35784b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                                               this->recordFlags());
35884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    this->scaleToScaleFactor(canvas);
35984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture->draw(canvas);
36084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
3613f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    if (!fWritePath.isEmpty()) {
362a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        // Record the new picture as a new SKP with PNG encoded bitmaps.
3633f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        SkString skpPath = SkOSPath::SkPathJoin(fWritePath.c_str(), fInputFilename.c_str());
364a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        SkFILEWStream stream(skpPath.c_str());
36584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com        picture->serialize(&stream, &encode_bitmap_to_data);
366a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com        return true;
367a9e3a369c18c6d5f41724e837e3ba0fa87d8c559scroggo@google.com    }
36881f9d2e05be4902993345dac93337158345c660bscroggo@google.com    return false;
3699a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com}
3709a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
3710a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString RecordPictureRenderer::getConfigNameInternal() {
3720a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("record");
3730a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
3740a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
375acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
376acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
377f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool PipePictureRenderer::render(SkBitmap** out) {
3789d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fCanvas.get() != NULL);
3799d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fPicture != NULL);
38078a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == fCanvas.get() || NULL == fPicture) {
38181f9d2e05be4902993345dac93337158345c660bscroggo@google.com        return false;
3829d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
3839d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
3849d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    PipeController pipeController(fCanvas.get());
385451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    SkGPipeWriter writer;
386451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
3879b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    pipeCanvas->drawPicture(fPicture);
388451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    writer.endRecording();
3899a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fCanvas->flush();
39084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (NULL != out) {
39184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
39284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
39384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fCanvas->readPixels(*out, 0, 0);
394a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com    }
3958991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    if (fEnableWrites) {
3968991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
3978991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                     fUseChecksumBasedFilenames);
3988991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    } else {
3998991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return true;
4008991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    }
401451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
402451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4030a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PipePictureRenderer::getConfigNameInternal() {
4040a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("pipe");
4050a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
4060a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
407acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
408acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
4093f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.orgvoid SimplePictureRenderer::init(SkPicture* picture, const SkString* writePath,
4103f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                 const SkString* mismatchPath, const SkString* inputFilename,
4113f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                 bool useChecksumBasedFilenames) {
4123f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    INHERITED::init(picture, writePath, mismatchPath, inputFilename, useChecksumBasedFilenames);
4139313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    this->buildBBoxHierarchy();
4149313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org}
4159313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
416f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool SimplePictureRenderer::render(SkBitmap** out) {
4179d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    SkASSERT(fCanvas.get() != NULL);
41884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkASSERT(NULL != fPicture);
41978a35c5f1dcc00b2b442069a94f9e7c996f8d7f9keyar@chromium.org    if (NULL == fCanvas.get() || NULL == fPicture) {
42081f9d2e05be4902993345dac93337158345c660bscroggo@google.com        return false;
4219d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
4229d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
4239b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    fCanvas->drawPicture(fPicture);
4249a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com    fCanvas->flush();
42584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (NULL != out) {
42684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
42784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
42884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fCanvas->readPixels(*out, 0, 0);
42984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
4308991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    if (fEnableWrites) {
4318991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
4328991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                     fUseChecksumBasedFilenames);
4338991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    } else {
4348991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        return true;
4358991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    }
436451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
437451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4380a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString SimplePictureRenderer::getConfigNameInternal() {
4390a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("simple");
4400a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
4410a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
442acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
443acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
444451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.orgTiledPictureRenderer::TiledPictureRenderer()
445a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    : fTileWidth(kDefaultTileWidth)
446b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com    , fTileHeight(kDefaultTileHeight)
447a04dc02b118363fedf3a7b11cfcdab886d368f8arileya@google.com    , fTileWidthPercentage(0.0)
448b947b91794f47cc92b17c83e570536f5e315a118rileya@google.com    , fTileHeightPercentage(0.0)
449cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTileMinPowerOf2Width(0)
450cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fCurrentTileOffset(-1)
451cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTilesX(0)
452cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    , fTilesY(0) { }
453451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4543f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.orgvoid TiledPictureRenderer::init(SkPicture* pict, const SkString* writePath,
4553f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                const SkString* mismatchPath, const SkString* inputFilename,
4563f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                bool useChecksumBasedFilenames) {
45784b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkASSERT(NULL != pict);
458acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    SkASSERT(0 == fTileRects.count());
459acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    if (NULL == pict || fTileRects.count() != 0) {
4609d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org        return;
4619d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    }
4629d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org
463acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not
464acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    // used by bench_pictures.
46584b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(pict)->ref();
4663f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fWritePath, writePath);
4673f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->CopyString(&fMismatchPath, mismatchPath);
468f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    this->CopyString(&fInputFilename, inputFilename);
469f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    fUseChecksumBasedFilenames = useChecksumBasedFilenames;
470a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    this->buildBBoxHierarchy();
471cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org
472cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    if (fTileWidthPercentage > 0) {
4735d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com        fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100));
474cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    }
475cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    if (fTileHeightPercentage > 0) {
4765d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com        fTileHeight = sk_float_ceil2int(float(fTileHeightPercentage * fPicture->height() / 100));
477cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org    }
478cc6e5efe03bfeda903d67d2bacd9ed0be58572bakeyar@chromium.org
479f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    if (fTileMinPowerOf2Width > 0) {
480f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        this->setupPowerOf2Tiles();
481f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    } else {
482f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        this->setupTiles();
483f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
484cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight));
485cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    // Initialize to -1 so that the first call to nextTile will set this up to draw tile 0 on the
486cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    // first call to drawCurrentTile.
487cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fCurrentTileOffset = -1;
488451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
489451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4909d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::end() {
491bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    fTileRects.reset();
4929d696c0d04548520af08252e577d2ca88012a239keyar@chromium.org    this->INHERITED::end();
493451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
494451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
4959d696c0d04548520af08252e577d2ca88012a239keyar@chromium.orgvoid TiledPictureRenderer::setupTiles() {
496c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    // Only use enough tiles to cover the viewport
497c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
498c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
499c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
500cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fTilesX = fTilesY = 0;
501c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
502cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        fTilesY++;
503c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWidth) {
504cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            if (0 == tile_y_start) {
505cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                // Only count tiles in the X direction on the first pass.
506cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                fTilesX++;
507cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com            }
508acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com            *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
509acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(tile_y_start),
510acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(fTileWidth),
511acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                    SkIntToScalar(fTileHeight));
512f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        }
513f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
514f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org}
515f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
516cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::tileDimensions(int &x, int &y) {
517cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    if (fTileRects.count() == 0 || NULL == fPicture) {
518cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        return false;
519cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    }
520cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    x = fTilesX;
521cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    y = fTilesY;
522cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    return true;
523cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
524cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
525f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// The goal of the powers of two tiles is to minimize the amount of wasted tile
526f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// space in the width-wise direction and then minimize the number of tiles. The
527f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// constraints are that every tile must have a pixel width that is a power of
528f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// two and also be of some minimal width (that is also a power of two).
529f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org//
53058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com// This is solved by first taking our picture size and rounding it up to the
531f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// multiple of the minimal width. The binary representation of this rounded
532f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// value gives us the tiles we need: a bit of value one means we need a tile of
533f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org// that size.
534f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.orgvoid TiledPictureRenderer::setupPowerOf2Tiles() {
535c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    // Only use enough tiles to cover the viewport
536c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int width = this->getViewWidth();
537c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    const int height = this->getViewHeight();
538c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com
539c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    int rounded_value = width;
540c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    if (width % fTileMinPowerOf2Width != 0) {
541c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com        rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerOf2Width;
542f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    }
543f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
544e15b2f5296a65c92be477a71ddf9eae9d95eddcereed@google.com    int num_bits = SkScalarCeilToInt(scalar_log2(SkIntToScalar(width)));
545f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    int largest_possible_tile_size = 1 << num_bits;
546f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
547cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    fTilesX = fTilesY = 0;
548f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org    // The tile height is constant for a particular picture.
549c0d5e549ab8d594a5da8db417db39622e9491fffscroggo@google.com    for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeight) {
550cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        fTilesY++;
551f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        int tile_x_start = 0;
552f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        int current_width = largest_possible_tile_size;
553acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough
554acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        // to draw each tile.
555acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com        fTileWidth = current_width;
556f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
557f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org        while (current_width >= fTileMinPowerOf2Width) {
558f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            // It is very important this is a bitwise AND.
559f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            if (current_width & rounded_value) {
560cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                if (0 == tile_y_start) {
561cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                    // Only count tiles in the X direction on the first pass.
562cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                    fTilesX++;
563cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com                }
564acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start),
565acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(tile_y_start),
566acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(current_width),
567acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com                                                        SkIntToScalar(fTileHeight));
568f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org                tile_x_start += current_width;
569f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            }
570f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org
571f4959ab11827bef99e8985031feb457cae1f987akeyar@chromium.org            current_width >>= 1;
572451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org        }
573451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org    }
574451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
575451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
576bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com/**
577145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org * Draw the specified picture to the canvas translated to rectangle provided, so that this mini
578bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * canvas represents the rectangle's portion of the overall picture.
579bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * Saves and restores so that the initial clip and matrix return to their state before this function
580bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com * is called.
581bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com */
582145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.orgstatic void draw_tile_to_canvas(SkCanvas* canvas, const SkRect& tileRect, SkPicture* picture) {
583bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    int saveCount = canvas->save();
58482ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Translate so that we draw the correct portion of the picture.
58582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Perform a postTranslate so that the scaleFactor does not interfere with the positioning.
58682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkMatrix mat(canvas->getTotalMatrix());
58782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    mat.postTranslate(-tileRect.fLeft, -tileRect.fTop);
58882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    canvas->setMatrix(mat);
5899b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas->drawPicture(picture);
590bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    canvas->restoreToCount(saveCount);
591bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    canvas->flush();
592451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
593451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
59458b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
595bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
596a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org/**
597a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * Copies the entirety of the src bitmap (typically a tile) into a portion of the dst bitmap.
598a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * If the src bitmap is too large to fit within the dst bitmap after the x and y
599a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * offsets have been applied, any excess will be ignored (so only the top-left portion of the
600a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * src bitmap will be copied).
601a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org *
602a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param src source bitmap
603a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param dst destination bitmap
604a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param xOffset x-offset within destination bitmap
605a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org * @param yOffset y-offset within destination bitmap
606a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org */
607a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.orgstatic void bitmapCopyAtOffset(const SkBitmap& src, SkBitmap* dst,
608a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                               int xOffset, int yOffset) {
609a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org    for (int y = 0; y <src.height() && y + yOffset < dst->height() ; y++) {
610a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org        for (int x = 0; x < src.width() && x + xOffset < dst->width() ; x++) {
611a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org            *dst->getAddr32(xOffset + x, yOffset + y) = *src.getAddr32(x, y);
61284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
61384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
61484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com}
61584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
616cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.combool TiledPictureRenderer::nextTile(int &i, int &j) {
617cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    if (++fCurrentTileOffset < fTileRects.count()) {
618cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        i = fCurrentTileOffset % fTilesX;
619cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        j = fCurrentTileOffset / fTilesX;
620cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com        return true;
621cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    }
622cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    return false;
623cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
624cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
625cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.comvoid TiledPictureRenderer::drawCurrentTile() {
626cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com    SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count());
627145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture);
628cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com}
629cbcef708914f3b5e9bb63ad3d87261378026e29bscroggo@google.com
630f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool TiledPictureRenderer::render(SkBitmap** out) {
631a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkASSERT(fPicture != NULL);
632a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    if (NULL == fPicture) {
633a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        return false;
634bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
635bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
63684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    SkBitmap bitmap;
63784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (out){
63884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
63984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
64084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(&bitmap, fTileWidth, fTileHeight);
64184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
642a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool success = true;
643a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fTileRects.count(); ++i) {
644145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture);
6458991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        if (fEnableWrites) {
6468991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org            success &= write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
6478991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                             fUseChecksumBasedFilenames, &i);
6488991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        }
64984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        if (NULL != out) {
65084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            if (fCanvas->readPixels(&bitmap, 0, 0)) {
651a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                // Add this tile to the entire bitmap.
652a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()),
653a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                                   SkScalarFloorToInt(fTileRects[i].top()));
65484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            } else {
65584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                success = false;
65684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            }
65784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
658bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
659a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return success;
660bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
66158b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
662a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comSkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) {
663a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkCanvas* canvas = this->INHERITED::setupCanvas(width, height);
6648ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    SkASSERT(NULL != fPicture);
66582ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This
66682ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // is mostly important for tiles on the right and bottom edges as they may go over this area and
66782ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // the picture may have some commands that draw outside of this area and so should not actually
66882ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // be written.
66982ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // Uses a clipRegion so that it will be unaffected by the scale factor, which may have been set
67082ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    // by INHERITED::setupCanvas.
67182ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    SkRegion clipRegion;
67282ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight());
67382ec0b00f380906c1cdeb4b4cc4a355264ab3882scroggo@google.com    canvas->clipRegion(clipRegion);
674a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return canvas;
675a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
6760a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
6770a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString TiledPictureRenderer::getConfigNameInternal() {
6780a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    SkString name;
6790a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    if (fTileMinPowerOf2Width > 0) {
6800a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.append("pow2tile_");
6810a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%i", fTileMinPowerOf2Width);
6820a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    } else {
6830a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.append("tile_");
6840a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        if (fTileWidthPercentage > 0) {
6850a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com            name.appendf("%.f%%", fTileWidthPercentage);
6860a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        } else {
6870a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com            name.appendf("%i", fTileWidth);
6880a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        }
6890a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    }
6900a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    name.append("x");
6910a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    if (fTileHeightPercentage > 0) {
6920a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%.f%%", fTileHeightPercentage);
6930a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    } else {
6940a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com        name.appendf("%i", fTileHeight);
6950a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    }
6960a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return name;
6970a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
6980a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
69958b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
70058b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
701a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com// Holds all of the information needed to draw a set of tiles.
702a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comclass CloneData : public SkRunnable {
703a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
704a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.compublic:
705a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end,
706205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org              SkRunnable* done, ImageResultsAndExpectations* jsonSummaryPtr,
7078991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org              bool useChecksumBasedFilenames, bool enableWrites)
708a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        : fClone(clone)
709a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fCanvas(canvas)
7108991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org        , fEnableWrites(enableWrites)
711a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fRects(rects)
712a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fStart(start)
713a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fEnd(end)
714a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        , fSuccess(NULL)
715a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org        , fDone(done)
716f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        , fJsonSummaryPtr(jsonSummaryPtr)
717f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        , fUseChecksumBasedFilenames(useChecksumBasedFilenames) {
718a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkASSERT(fDone != NULL);
719a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
720a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
721a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    virtual void run() SK_OVERRIDE {
722a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkGraphics::SetTLSFontCacheLimit(1024 * 1024);
72384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
72484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        SkBitmap bitmap;
72584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        if (fBitmap != NULL) {
72684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            // All tiles are the same size.
7279c4e5ac5b7d32151d4d8ab1fb7ed443b35eb1254jvanverth@google.com            setup_bitmap(&bitmap, SkScalarFloorToInt(fRects[0].width()), SkScalarFloorToInt(fRects[0].height()));
72884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
729a7d8e3e990c43aedda6a66aa211f175213ac54c0skia.committer@gmail.com
730a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        for (int i = fStart; i < fEnd; i++) {
731145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            draw_tile_to_canvas(fCanvas, fRects[i], fClone);
7328991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org            if (fEnableWrites) {
7338991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                if (!write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr,
7348991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                           fUseChecksumBasedFilenames, &i)
7358991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                    && fSuccess != NULL) {
73684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                    *fSuccess = false;
7378991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                    // If one tile fails to write to a file, do not continue drawing the rest.
73884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                    break;
73984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com                }
7408991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                if (fBitmap != NULL) {
7418991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                    if (fCanvas->readPixels(&bitmap, 0, 0)) {
7428991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                        SkAutoLockPixels alp(*fBitmap);
7438991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                        bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(fRects[i].left()),
7448991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                                           SkScalarFloorToInt(fRects[i].top()));
7458991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                    } else {
7468991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                        *fSuccess = false;
7478991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                        // If one tile fails to read pixels, do not continue drawing the rest.
7488991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                        break;
7498991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                    }
7508991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                }
75184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            }
752a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        }
753a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fDone->run();
754a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
755bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
7563f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    void setPathsAndSuccess(const SkString& writePath, const SkString& mismatchPath,
7573f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                            const SkString& inputFilename, bool* success) {
7583f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        fWritePath.set(writePath);
7593f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        fMismatchPath.set(mismatchPath);
760f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org        fInputFilename.set(inputFilename);
761a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fSuccess = success;
762a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
763bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
76484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    void setBitmap(SkBitmap* bitmap) {
76584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        fBitmap = bitmap;
76684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
76784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
768a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comprivate:
769a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // All pointers unowned.
770a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkPicture*         fClone;      // Picture to draw from. Each CloneData has a unique one which
771a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                                    // is threadsafe.
772a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkCanvas*          fCanvas;     // Canvas to draw to. Reused for each tile.
7738991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org    bool               fEnableWrites; // TODO(epoger): Temporary hack; see declaration of
7748991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                                      // fEnableWrites in PictureRenderer.h.
7753f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    SkString           fWritePath;  // If not empty, write all results into this directory.
7763f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    SkString           fMismatchPath;  // If not empty, write all unexpected results into this dir.
777f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    SkString           fInputFilename; // Filename of input SkPicture file.
778a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkTDArray<SkRect>& fRects;      // All tiles of the picture.
779a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const int          fStart;      // Range of tiles drawn by this thread.
780a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const int          fEnd;
781a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool*              fSuccess;    // Only meaningful if path is non-null. Shared by all threads,
782a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com                                    // and only set to false upon failure to write to a PNG.
783a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkRunnable*        fDone;
78484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    SkBitmap*          fBitmap;
785205ce48c38c55ec7527d26042b5cea689369be8bcommit-bot@chromium.org    ImageResultsAndExpectations* fJsonSummaryPtr;
786f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.org    bool               fUseChecksumBasedFilenames;
78758b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com};
78858b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
789a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comMultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount)
790a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com: fNumThreads(threadCount)
791a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com, fThreadPool(threadCount)
792a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com, fCountdown(threadCount) {
793a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Only need to create fNumThreads - 1 clones, since one thread will use the base
794a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // picture.
795a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fPictureClones = SkNEW_ARRAY(SkPicture, fNumThreads - 1);
796a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCloneData = SkNEW_ARRAY(CloneData*, fNumThreads);
797a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
798a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
7993f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.orgvoid MultiCorePictureRenderer::init(SkPicture *pict, const SkString* writePath,
8003f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                    const SkString* mismatchPath, const SkString* inputFilename,
8013f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org                                    bool useChecksumBasedFilenames) {
802a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Set fPicture and the tiles.
8033f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    this->INHERITED::init(pict, writePath, mismatchPath, inputFilename, useChecksumBasedFilenames);
804a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads; ++i) {
805a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        *fCanvasPool.append() = this->setupCanvas(this->getTileWidth(), this->getTileHeight());
806a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    }
807a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Only need to create fNumThreads - 1 clones, since one thread will use the base picture.
808a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fPicture->clone(fPictureClones, fNumThreads - 1);
809a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Populate each thread with the appropriate data.
810a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Group the tiles into nearly equal size chunks, rounding up so we're sure to cover them all.
811a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    const int chunkSize = (fTileRects.count() + fNumThreads - 1) / fNumThreads;
812a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
813a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads; i++) {
814a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkPicture* pic;
815a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        if (i == fNumThreads-1) {
816a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            // The last set will use the original SkPicture.
817a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            pic = fPicture;
818a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        } else {
819a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com            pic = &fPictureClones[i];
820b6e806bf17ffcca0c147a7dab4fba104fe928a58scroggo@google.com        }
821a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        const int start = i * chunkSize;
822a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        const int end = SkMin32(start + chunkSize, fTileRects.count());
823a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fCloneData[i] = SkNEW_ARGS(CloneData,
824a3f882c4756bd8b9b6449dcc60b6d884ee0cc8edcommit-bot@chromium.org                                   (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown,
8258991c67f0c1b9364bb12dfb0f32a53bd5a3357f3commit-bot@chromium.org                                    fJsonSummaryPtr, useChecksumBasedFilenames, fEnableWrites));
826bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
827bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
82858b4ead36c62d8c0256ee4da554f3df2744d904cscroggo@google.com
829f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool MultiCorePictureRenderer::render(SkBitmap** out) {
830a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    bool success = true;
8313f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org    if (!fWritePath.isEmpty() || !fMismatchPath.isEmpty()) {
832a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        for (int i = 0; i < fNumThreads-1; i++) {
8333f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org            fCloneData[i]->setPathsAndSuccess(fWritePath, fMismatchPath, fInputFilename, &success);
834bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com        }
835bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com    }
836bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
83784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    if (NULL != out) {
83884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        *out = SkNEW(SkBitmap);
83984f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        setup_bitmap(*out, fPicture->width(), fPicture->height());
84084f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        for (int i = 0; i < fNumThreads; i++) {
84184f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            fCloneData[i]->setBitmap(*out);
84284f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
84384f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    } else {
84484f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        for (int i = 0; i < fNumThreads; i++) {
84584f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com            fCloneData[i]->setBitmap(NULL);
84684f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com        }
84784f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com    }
84884f548cc9daf77bb3ee7c59ad986eebe9ad1168eedisonn@google.com
849a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCountdown.reset(fNumThreads);
850a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads; i++) {
851a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fThreadPool.add(fCloneData[i]);
852acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com    }
853a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCountdown.wait();
854acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com
855a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    return success;
856a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com}
857a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
858a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comvoid MultiCorePictureRenderer::end() {
859a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    for (int i = 0; i < fNumThreads - 1; i++) {
860a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        SkDELETE(fCloneData[i]);
861a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com        fCloneData[i] = NULL;
862163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org    }
863a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
864a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    fCanvasPool.unrefAll();
865a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com
866a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    this->INHERITED::end();
867163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org}
868163b56734fe01c088581895a8e0b65ddf1cb4fa5keyar@chromium.org
869a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.comMultiCorePictureRenderer::~MultiCorePictureRenderer() {
870a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    // Each individual CloneData was deleted in end.
871a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkDELETE_ARRAY(fCloneData);
872a62da2fee72172a630c2d1dba0e529b357743662scroggo@google.com    SkDELETE_ARRAY(fPictureClones);
873bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com}
874bcdf2ec50dfd170959cc2db67c49f6dac084be03scroggo@google.com
8750a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString MultiCorePictureRenderer::getConfigNameInternal() {
8760a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    SkString name = this->INHERITED::getConfigNameInternal();
8770a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    name.appendf("_multi_%i_threads", fNumThreads);
8780a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return name;
8790a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
8800a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
881acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0scroggo@google.com///////////////////////////////////////////////////////////////////////////////////////////////
8829a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
8839a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.comvoid PlaybackCreationRenderer::setup() {
8845fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
8855fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    fRecorder.reset(SkNEW(SkPictureRecorder));
88684b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkCanvas* canvas = fRecorder->beginRecording(this->getViewWidth(), this->getViewHeight(),
8875fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org                                                 factory.get(),
88884b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com                                                 this->recordFlags());
88984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    this->scaleToScaleFactor(canvas);
8909b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas->drawPicture(fPicture);
8919a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com}
8929a4125283ad56cea3b986337cb669dde14bf0ed8scroggo@google.com
893f5e315ccf1ae2941f7cf53fa53e5c8c4bb665fe1commit-bot@chromium.orgbool PlaybackCreationRenderer::render(SkBitmap** out) {
89484b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    fPicture.reset(fRecorder->endRecording());
89581f9d2e05be4902993345dac93337158345c660bscroggo@google.com    // Since this class does not actually render, return false.
89681f9d2e05be4902993345dac93337158345c660bscroggo@google.com    return false;
897451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
898451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org
8990a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.comSkString PlaybackCreationRenderer::getConfigNameInternal() {
9000a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com    return SkString("playback_creation");
9010a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com}
9020a049b861e18c9c1ede865b8acbcbedc3dd10b43scroggo@google.com
9039313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org///////////////////////////////////////////////////////////////////////////////////////////////
9049313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org// SkPicture variants for each BBoxHierarchy type
9059313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
9065fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.orgSkBBHFactory* PictureRenderer::getFactory() {
9079313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    switch (fBBoxHierarchyType) {
9089313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        case kNone_BBoxHierarchyType:
90984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com            return NULL;
910c22d1398089fdb95480fb3459b23e4931e4f5280commit-bot@chromium.org        case kQuadTree_BBoxHierarchyType:
9115fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org            return SkNEW(SkQuadTreeFactory);
9129313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org        case kRTree_BBoxHierarchyType:
9135fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org            return SkNEW(SkRTreeFactory);
9147b53706a7d596a2d8dce6cfe5b543264e5a37239junov@chromium.org        case kTileGrid_BBoxHierarchyType:
9155fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org            return SkNEW_ARGS(SkTileGridFactory, (fGridInfo));
9169313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    }
9179313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    SkASSERT(0); // invalid bbhType
9189313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org    return NULL;
919451bb9f801d668275394ca5bd57f238e13cf3d17keyar@chromium.org}
9209313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org
921fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com///////////////////////////////////////////////////////////////////////////////
922fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
923fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comclass GatherRenderer : public PictureRenderer {
924fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.compublic:
9258ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE {
926fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
927fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                                       SkIntToScalar(fPicture->height()));
928fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
929fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        SkSafeUnref(data);
930c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
9313f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        return (fWritePath.isEmpty());    // we don't have anything to write
932fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
933c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
934fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comprivate:
935fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual SkString getConfigNameInternal() SK_OVERRIDE {
936fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        return SkString("gather_pixelrefs");
937fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
938fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com};
939fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
940fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comPictureRenderer* CreateGatherPixelRefsRenderer() {
941fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    return SkNEW(GatherRenderer);
942fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com}
943c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com
9445a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com///////////////////////////////////////////////////////////////////////////////
9455a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com
9465a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comclass PictureCloneRenderer : public PictureRenderer {
9475a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.compublic:
9488ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE {
9495a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        for (int i = 0; i < 100; ++i) {
9505a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com            SkPicture* clone = fPicture->clone();
9515a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com            SkSafeUnref(clone);
9525a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        }
953c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
9543f0451772109959fcb79bacf2c9a03e0eb39ff27commit-bot@chromium.org        return (fWritePath.isEmpty());    // we don't have anything to write
9555a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    }
956c7b4be7f110bc7b487c3c3f28d82877584e74c2fskia.committer@gmail.com
9575a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comprivate:
9585a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    virtual SkString getConfigNameInternal() SK_OVERRIDE {
9595a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com        return SkString("picture_clone");
9605a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    }
9615a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com};
9625a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com
9635a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.comPictureRenderer* CreatePictureCloneRenderer() {
9645a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com    return SkNEW(PictureCloneRenderer);
9655a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com}
9665a34fd3f9876174aea8b22e1b585b4244e71b0b1reed@google.com
9679313ca4bde606a18f29214eea8b8e47312b8fd9cjunov@chromium.org} // namespace sk_tools
968