SkDeferredCanvas.cpp revision 7112173c3c4cd1b1e7da8cdf971d71f01dd91299
14370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
24370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com/*
310f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org * Copyright 2012 Google Inc.
44370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com *
54370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com * Use of this source code is governed by a BSD-style license that can be
64370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com * found in the LICENSE file.
74370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com */
84370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
94370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkDeferredCanvas.h"
104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org#include "SkChunkAlloc.h"
124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkColorFilter.h"
1388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org#include "SkDevice.h"
144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkDrawFilter.h"
1588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org#include "SkGPipe.h"
1688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org#include "SkPaint.h"
1788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org#include "SkShader.h"
184370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
19bfeddae9da240693441556b2f278827e213f75e8junov@chromium.orgenum {
20bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org    // Deferred canvas will auto-flush when recording reaches this limit
21bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org    kDefaultMaxRecordingStorageBytes = 64*1024*1024,
22bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org};
23bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org
244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comnamespace {
2510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.orgbool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint) {
2610f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    if (bitmap && bitmap->getTexture() && !bitmap->isImmutable()) {
2710f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        return true;
2810f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    }
2910f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    if (paint) {
3010f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        SkShader* shader = paint->getShader();
3110f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        // Here we detect the case where the shader is an SkBitmapProcShader
3210f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        // with a gpu texture attached.  Checking this without RTTI
3310f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        // requires making the assumption that only gradient shaders
3410f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        // and SkBitmapProcShader implement asABitmap().  The following
3510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        // code may need to be revised if that assumption is ever broken.
3610f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        if (shader && !shader->asAGradient(NULL)) {
3710f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org            SkBitmap bm;
38d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            if (shader->asABitmap(&bm, NULL, NULL) &&
3910f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org                NULL != bm.getTexture()) {
4010f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org                return true;
4110f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org            }
4210f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        }
4310f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    }
4410f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    return false;
45b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org}
46b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org}
47b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org
48b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.orgclass AutoImmediateDrawIfNeeded {
49b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.orgpublic:
50d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
5110f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org                              const SkPaint* paint) {
5210f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        this->init(canvas, bitmap, paint);
5310f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    }
5410f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org
5510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
5610f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        this->init(canvas, NULL, paint);
57b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org    }
58b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org
59b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org    ~AutoImmediateDrawIfNeeded() {
60b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org        if (fCanvas) {
61b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org            fCanvas->setDeferredDrawing(true);
62b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org        }
63b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org    }
64b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.orgprivate:
6510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint)
6610f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    {
6710f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        if (canvas.isDeferredDrawing() && shouldDrawImmediately(bitmap, paint)) {
6810f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org            canvas.setDeferredDrawing(false);
6910f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org            fCanvas = &canvas;
7010f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        } else {
7110f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org            fCanvas = NULL;
7210f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org        }
7310f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    }
7410f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org
75b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org    SkDeferredCanvas* fCanvas;
76b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org};
77b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org
78b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.orgnamespace {
794370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
80d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool isPaintOpaque(const SkPaint* paint,
81c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                   const SkBitmap* bmpReplacesShader = NULL) {
824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: SkXfermode should have a virtual isOpaque method, which would
834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // make it possible to test modes that do not have a Coeff representation.
8487f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org
8587f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org    if (!paint) {
8687f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        return bmpReplacesShader ? bmpReplacesShader->isOpaque() : true;
8787f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org    }
8887f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org
894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkXfermode::Coeff srcCoeff, dstCoeff;
9087f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org    if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){
914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        switch (dstCoeff) {
924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kZero_Coeff:
934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kISA_Coeff:
9587f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (paint->getAlpha() != 255) {
964370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
974370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
984370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            if (bmpReplacesShader) {
994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                if (!bmpReplacesShader->isOpaque()) {
1004370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    break;
1014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                }
10287f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            } else if (paint->getShader() && !paint->getShader()->isOpaque()) {
1034370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
105d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            if (paint->getColorFilter() &&
106c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                ((paint->getColorFilter()->getFlags() &
1074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
1084370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1094370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
1104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
1114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kSA_Coeff:
11287f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (paint->getAlpha() != 0) {
1134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
115d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            if (paint->getColorFilter() &&
116c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                ((paint->getColorFilter()->getFlags() &
1174370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
1184370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
1204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
1214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kSC_Coeff:
12287f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (paint->getColor() != 0) { // all components must be 0
1234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
12587f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (bmpReplacesShader || paint->getShader()) {
1264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1274370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
128c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org            if (paint->getColorFilter() && (
129c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                (paint->getColorFilter()->getFlags() &
1304370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
1314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
1324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
1334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
1344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        default:
1354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            break;
1364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
1374370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
1384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return false;
1394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1404370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1414370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com} // unnamed namespace
1424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
14388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org//-----------------------------------------------------------------------------
14488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org// DeferredPipeController
14588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org//-----------------------------------------------------------------------------
14688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
14788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgclass DeferredPipeController : public SkGPipeController {
14888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgpublic:
14988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    DeferredPipeController();
15088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void setPlaybackCanvas(SkCanvas*);
15188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual ~DeferredPipeController();
15288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
15388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
15488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void playback();
15588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void reset();
15688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    bool hasRecorded() const { return fAllocator.blockCount() != 0; }
15788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
15888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgprivate:
15988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    enum {
16088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        kMinBlockSize = 4096
16188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    };
16288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    struct PipeBlock {
16388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
16488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        void* fBlock;
16588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        size_t fSize;
16688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    };
16788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void* fBlock;
16888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    size_t fBytesWritten;
16988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkChunkAlloc fAllocator;
17088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkTDArray<PipeBlock> fBlockList;
17188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkGPipeReader fReader;
17288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org};
17388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
17488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgDeferredPipeController::DeferredPipeController() :
17588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fAllocator(kMinBlockSize) {
17688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBlock = NULL;
17788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBytesWritten = 0;
17888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
17988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
18088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgDeferredPipeController::~DeferredPipeController() {
18188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fAllocator.reset();
18288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
18388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
18488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) {
18588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fReader.setCanvas(canvas);
18688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
18788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
18888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid* DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) {
18988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (fBlock) {
19088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        // Save the previous block for later
19188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        PipeBlock previousBloc(fBlock, fBytesWritten);
19288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fBlockList.push(previousBloc);
19388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
19488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    int32_t blockSize = SkMax32(minRequest, kMinBlockSize);
19588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBlock = fAllocator.allocThrow(blockSize);
19688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBytesWritten = 0;
19788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    *actual = blockSize;
19888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fBlock;
19988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
20088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
20188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredPipeController::notifyWritten(size_t bytes) {
20288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBytesWritten += bytes;
20388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
20488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
20588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredPipeController::playback() {
206d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
20788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) {
20888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize);
20988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
21088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBlockList.reset();
21188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
21288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (fBlock) {
21388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fReader.playback(fBlock, fBytesWritten);
21488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fBlock = NULL;
21588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
21688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
21788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    // Release all allocated blocks
21888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fAllocator.reset();
21988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
22088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
22188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredPipeController::reset() {
22288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBlockList.reset();
22388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fBlock = NULL;
22488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fAllocator.reset();
22588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
22688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
22788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org//-----------------------------------------------------------------------------
22888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org// DeferredDevice
22988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org//-----------------------------------------------------------------------------
23088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
23188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgclass DeferredDevice : public SkDevice {
23288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgpublic:
23388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    DeferredDevice(SkDevice* immediateDevice,
2349ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        SkDeferredCanvas::NotificationClient* notificationClient = NULL);
23588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    ~DeferredDevice();
23688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
2379ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient);
23888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkCanvas* recordingCanvas();
23988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
24088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkDevice* immediateDevice() const {return fImmediateDevice;}
24188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    bool isFreshFrame();
24288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    size_t storageAllocatedForRecording() const;
24388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    size_t freeMemoryIfPossible(size_t bytesToFree);
24488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void flushPending();
24588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void contentsCleared();
24688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void setMaxRecordingStorage(size_t);
2479ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    void recordedDrawCommand();
24888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
24988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
25088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual int width() const SK_OVERRIDE;
25188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual int height() const SK_OVERRIDE;
25288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
25388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
25488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
25588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                               int width, int height,
25688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                               bool isOpaque,
25788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                               Usage usage) SK_OVERRIDE;
25888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
25988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void writePixels(const SkBitmap& bitmap, int x, int y,
26088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                SkCanvas::Config8888 config8888) SK_OVERRIDE;
26188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
26288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgprotected:
26388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
26488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual bool onReadPixels(const SkBitmap& bitmap,
26588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                int x, int y,
26688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                SkCanvas::Config8888 config8888) SK_OVERRIDE;
26788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
26888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    // The following methods are no-ops on a deferred device
26988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
27088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        SK_OVERRIDE
27188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {return false;}
27288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
27388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                const SkClipStack&) SK_OVERRIDE
27488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {}
27588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
27688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    // None of the following drawing methods should ever get called on the
27788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    // deferred device
27888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void clear(SkColor color)
27988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
28088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawPaint(const SkDraw&, const SkPaint& paint)
28188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
28288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
28388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            size_t count, const SkPoint[],
28488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkPaint& paint)
28588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
28688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawRect(const SkDraw&, const SkRect& r,
28788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkPaint& paint)
28888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
28988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawPath(const SkDraw&, const SkPath& path,
29088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkPaint& paint,
29188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkMatrix* prePathMatrix = NULL,
29288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            bool pathIsMutable = false)
29388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
29488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
29588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkIRect* srcRectOrNull,
29688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkMatrix& matrix, const SkPaint& paint)
29788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
29888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
29988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            int x, int y, const SkPaint& paint)
30088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
30188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawText(const SkDraw&, const void* text, size_t len,
30288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            SkScalar x, SkScalar y, const SkPaint& paint)
30388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
30488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
30588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                const SkScalar pos[], SkScalar constY,
30688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                int scalarsPerPos, const SkPaint& paint)
30788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
30888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawTextOnPath(const SkDraw&, const void* text,
30988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                size_t len, const SkPath& path,
31088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                const SkMatrix* matrix,
31188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                const SkPaint& paint)
31288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
31388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
31488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                    size_t len, const SkPoint pos[],
31588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                    const SkPaint& paint,
31688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                    const SkPath& path,
31788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                    const SkMatrix* matrix)
31888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
31988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
32088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                int vertexCount, const SkPoint verts[],
32188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                const SkPoint texs[], const SkColor colors[],
32288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                SkXfermode* xmode, const uint16_t indices[],
32388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                int indexCount, const SkPaint& paint)
32488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
32588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
32688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                            const SkPaint&)
32788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        {SkASSERT(0);}
32888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgprivate:
32988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    virtual void flush();
33088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
33188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void endRecording();
33288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    void beginRecording();
33388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
33488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    DeferredPipeController fPipeController;
33588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkGPipeWriter  fPipeWriter;
33688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkDevice* fImmediateDevice;
33788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkCanvas* fImmediateCanvas;
33888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkCanvas* fRecordingCanvas;
3399ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    SkDeferredCanvas::NotificationClient* fNotificationClient;
34088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    bool fFreshFrame;
34188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    size_t fMaxRecordingStorageBytes;
3429ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    size_t fPreviousStorageAllocated;
34388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org};
34488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
34588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgDeferredDevice::DeferredDevice(
3469ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    SkDevice* immediateDevice, SkDeferredCanvas::NotificationClient* notificationClient) :
34788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkDevice(SkBitmap::kNo_Config, immediateDevice->width(),
34888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org             immediateDevice->height(), immediateDevice->isOpaque())
349a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org    , fRecordingCanvas(NULL)
3509ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    , fFreshFrame(true)
3519ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    , fPreviousStorageAllocated(0){
35288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
35388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
3549ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    fNotificationClient = notificationClient;
35588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas
35688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice));
35788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fPipeController.setPlaybackCanvas(fImmediateCanvas);
35888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->beginRecording();
35988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
36088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
36188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgDeferredDevice::~DeferredDevice() {
36288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->flushPending();
36388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkSafeUnref(fImmediateCanvas);
36488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
36588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
36688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
36788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fMaxRecordingStorageBytes = maxStorage;
36888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->recordingCanvas(); // Accessing the recording canvas applies the new limit.
36988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
37088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
37188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::endRecording() {
37288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fPipeWriter.endRecording();
37388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fPipeController.reset();
37488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fRecordingCanvas = NULL;
37588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
37688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
37788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::beginRecording() {
378a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org    SkASSERT(NULL == fRecordingCanvas);
379d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0,
380a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        fImmediateDevice->width(), fImmediateDevice->height());
38188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
382d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3839ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.orgvoid DeferredDevice::setNotificationClient(
3849ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    SkDeferredCanvas::NotificationClient* notificationClient) {
38552805485581cff7e13134aa1465a2950f7bed007junov@chromium.org    fNotificationClient = notificationClient;
38688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
38788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
38888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::contentsCleared() {
38988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (!fRecordingCanvas->isDrawingToLayer()) {
39088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fFreshFrame = true;
39188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
39288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        // TODO: find a way to transfer the state stack and layers
39388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        // to the new recording canvas.  For now, purging only works
394a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        // with an empty stack.  A save count of 1 means an empty stack.
395a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        SkASSERT(fRecordingCanvas->getSaveCount() >= 1);
396a8db8fe39a640bda4b85b9342c3b6b2525142afajunov@chromium.org        if (fRecordingCanvas->getSaveCount() == 1) {
39788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
39888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // Save state that is trashed by the purge
39988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter();
40088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            SkSafeRef(drawFilter); // So that it survives the purge
40188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            SkMatrix matrix = fRecordingCanvas->getTotalMatrix();
40288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            SkRegion clipRegion = fRecordingCanvas->getTotalClip();
40388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
40488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // beginRecording creates a new recording canvas and discards the
40588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // old one, hence purging deferred draw ops.
40688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            this->endRecording();
40788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            this->beginRecording();
4089ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org            fPreviousStorageAllocated = storageAllocatedForRecording();
40988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
41088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // Restore pre-purge state
41188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            if (!clipRegion.isEmpty()) {
412d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                fRecordingCanvas->clipRegion(clipRegion,
41388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                    SkRegion::kReplace_Op);
41488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            }
41588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            if (!matrix.isIdentity()) {
41688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                fRecordingCanvas->setMatrix(matrix);
41788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            }
41888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            if (drawFilter) {
41988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                fRecordingCanvas->setDrawFilter(drawFilter)->unref();
42088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            }
42188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        }
42288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
42388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
42488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
42588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgbool DeferredDevice::isFreshFrame() {
42688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    bool ret = fFreshFrame;
42788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fFreshFrame = false;
42888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return ret;
42988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
43088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
43188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::flushPending() {
43288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (!fPipeController.hasRecorded()) {
43388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        return;
43488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
4359ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    if (fNotificationClient) {
4369ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        fNotificationClient->prepareForDraw();
43788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
43888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fPipeWriter.flushRecording(true);
43988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fPipeController.playback();
4409ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    if (fNotificationClient) {
4419ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        fNotificationClient->flushedDrawCommands();
4429ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    }
4439ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    fPreviousStorageAllocated = storageAllocatedForRecording();
44488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
44588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
44688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::flush() {
44788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->flushPending();
44888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    fImmediateCanvas->flush();
44988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
45088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
45188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgsize_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
4529ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree);
4539ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    fPreviousStorageAllocated = storageAllocatedForRecording();
4549ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
45588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
45688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
45788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgsize_t DeferredDevice::storageAllocatedForRecording() const {
45888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return (fPipeController.storageAllocatedForRecording()
45988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            + fPipeWriter.storageAllocatedForRecording());
46088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
46188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
4629ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.orgvoid DeferredDevice::recordedDrawCommand() {
46388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    size_t storageAllocated = this->storageAllocatedForRecording();
4649ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
46588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (storageAllocated > fMaxRecordingStorageBytes) {
46688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        // First, attempt to reduce cache without flushing
46788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        size_t tryFree = storageAllocated - fMaxRecordingStorageBytes;
46888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        if (this->freeMemoryIfPossible(tryFree) < tryFree) {
46988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // Flush is necessary to free more space.
47088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            this->flushPending();
47188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes
47288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            // which could cause a high flushing frequency.
473100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.com            this->freeMemoryIfPossible(~0U);
47488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        }
4759ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        storageAllocated = this->storageAllocatedForRecording();
47688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
4779ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
478d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    if (fNotificationClient &&
4799ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        storageAllocated != fPreviousStorageAllocated) {
4809ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        fPreviousStorageAllocated = storageAllocated;
4819ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        fNotificationClient->storageAllocatedForRecordingChanged(storageAllocated);
4829ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    }
4839ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org}
4849ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
4859ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.orgSkCanvas* DeferredDevice::recordingCanvas() {
48688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fRecordingCanvas;
48788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
48888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
489d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comuint32_t DeferredDevice::getDeviceCapabilities() {
49088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fImmediateDevice->getDeviceCapabilities();
49188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
49288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
493d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comint DeferredDevice::width() const {
49488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fImmediateDevice->width();
49588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
49688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
49788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgint DeferredDevice::height() const {
498d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    return fImmediateDevice->height();
49988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
50088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
50188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgSkGpuRenderTarget* DeferredDevice::accessRenderTarget() {
50288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->flushPending();
50388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fImmediateDevice->accessRenderTarget();
50488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
50588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
50688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgvoid DeferredDevice::writePixels(const SkBitmap& bitmap,
50788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    int x, int y, SkCanvas::Config8888 config8888) {
50888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
50988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
51088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        (y + bitmap.height()) >= height()) {
51188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        this->contentsCleared();
51288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
51388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
51488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
51588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        SkCanvas::kNative_Premul_Config8888 != config8888 &&
51688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        kPMColorAlias != config8888) {
51788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        //Special case config: no deferral
51888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        this->flushPending();
51988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fImmediateDevice->writePixels(bitmap, x, y, config8888);
52088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        return;
52188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
52288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
52388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkPaint paint;
52488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
52588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    if (shouldDrawImmediately(&bitmap, NULL)) {
52688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        this->flushPending();
52788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        fImmediateCanvas->drawSprite(bitmap, x, y, &paint);
52888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    } else {
52988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        this->recordingCanvas()->drawSprite(bitmap, x, y, &paint);
5309ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        this->recordedDrawCommand();
5319ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
53288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    }
53388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
53488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
53588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgconst SkBitmap& DeferredDevice::onAccessBitmap(SkBitmap*) {
53688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->flushPending();
53788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fImmediateDevice->accessBitmap(false);
53888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
53988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
54088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgSkDevice* DeferredDevice::onCreateCompatibleDevice(
54188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkBitmap::Config config, int width, int height, bool isOpaque,
54288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    Usage usage) {
54388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
54488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    // Save layer usage not supported, and not required by SkDeferredCanvas.
54588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkASSERT(usage != kSaveLayer_Usage);
54688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    // Create a compatible non-deferred device.
54788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    SkAutoTUnref<SkDevice> compatibleDevice
54888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org        (fImmediateDevice->createCompatibleDevice(config, width, height,
54988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org            isOpaque));
5509ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return SkNEW_ARGS(DeferredDevice, (compatibleDevice, fNotificationClient));
55188e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
55288e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
55388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgbool DeferredDevice::onReadPixels(
55488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
55588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->flushPending();
55688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
55788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org                                                   x, y, config8888);
55888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
55988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
56088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
561c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::SkDeferredCanvas() {
5629060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->init();
5634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
565c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::SkDeferredCanvas(SkDevice* device) {
5669060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->init();
5679060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->setDevice(device);
5684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5694370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
570c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::init() {
5715e5a095a94281167056da707b03930f135748d71junov@chromium.org    fDeferredDrawing = true; // On by default
5724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
574bfeddae9da240693441556b2f278827e213f75e8junov@chromium.orgvoid SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
5759060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->validate();
576bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org    this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
577bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org}
578bfeddae9da240693441556b2f278827e213f75e8junov@chromium.org
5792e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.orgsize_t SkDeferredCanvas::storageAllocatedForRecording() const {
5802e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org    return this->getDeferredDevice()->storageAllocatedForRecording();
5812e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org}
5822e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org
5832e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.orgsize_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
5842e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org    return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
5852e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org}
5862e14ba8ceb41c68042ff133fecf0561a2c22efcajunov@chromium.org
5879ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.orgvoid SkDeferredCanvas::recordedDrawCommand() {
5889ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    if (fDeferredDrawing) {
5899ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        this->getDeferredDevice()->recordedDrawCommand();
5909ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    }
5919ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org}
5929ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
593c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::validate() const {
5949060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    SkASSERT(this->getDevice());
5954370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5964370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5975e5a095a94281167056da707b03930f135748d71junov@chromium.orgSkCanvas* SkDeferredCanvas::drawingCanvas() const {
5989060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->validate();
5999060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() :
6009060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->immediateCanvas();
6015e5a095a94281167056da707b03930f135748d71junov@chromium.org}
6025e5a095a94281167056da707b03930f135748d71junov@chromium.org
60388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgSkCanvas* SkDeferredCanvas::immediateCanvas() const {
60488e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    this->validate();
60588e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return this->getDeferredDevice()->immediateCanvas();
60688e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
60788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
60888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgDeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
60988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return static_cast<DeferredDevice*>(this->getDevice());
6104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
6114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
612c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::setDeferredDrawing(bool val) {
6139060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->validate(); // Must set device before calling this method
6144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (val != fDeferredDrawing) {
6154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        if (fDeferredDrawing) {
6165e5a095a94281167056da707b03930f135748d71junov@chromium.org            // Going live.
6179060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org            this->getDeferredDevice()->flushPending();
6184370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
6194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        fDeferredDrawing = val;
6204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
6214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
6224370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
62388e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgbool SkDeferredCanvas::isDeferredDrawing() const {
624b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org    return fDeferredDrawing;
625b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org}
626b10a6bd0a7df0ceeea0d53585c049450ec58b4b9junov@chromium.org
62788e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.orgbool SkDeferredCanvas::isFreshFrame() const {
62888e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org    return this->getDeferredDevice()->isFreshFrame();
62988e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org}
63088e29146c1efc5ff8eec06076c9dce12684f2c11junov@chromium.org
631c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::~SkDeferredCanvas() {
6324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
6334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
634c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDevice* SkDeferredCanvas::setDevice(SkDevice* device) {
6359060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (device)))->unref();
6364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return device;
6374370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
6384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
6399ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.orgSkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
6409ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    NotificationClient* notificationClient) {
641c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org
6429060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    DeferredDevice* deferredDevice = this->getDeferredDevice();
6434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkASSERT(deferredDevice);
6444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (deferredDevice) {
6459ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org        deferredDevice->setNotificationClient(notificationClient);
6464370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
6479ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return notificationClient;
6484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
6494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
6504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::isFullFrame(const SkRect* rect,
651c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                   const SkPaint* paint) const {
6529060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    SkCanvas* canvas = this->drawingCanvas();
6539060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    SkISize canvasSize = this->getDeviceSize();
6544370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (rect) {
6554370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        if (!canvas->getTotalMatrix().rectStaysRect()) {
6564370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return false; // conservative
6574370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
6584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
6594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        SkRect transformedRect;
6604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
6614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
6624370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        if (paint) {
6634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            SkPaint::Style paintStyle = paint->getStyle();
664d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            if (!(paintStyle == SkPaint::kFill_Style ||
6654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                paintStyle == SkPaint::kStrokeAndFill_Style)) {
6664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                return false;
6674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
6684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            if (paint->getMaskFilter() || paint->getLooper()
6694370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                || paint->getPathEffect() || paint->getImageFilter()) {
6704370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                return false; // conservative
6714370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
6724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
6734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
6744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        // The following test holds with AA enabled, and is conservative
6754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        // by a 0.5 pixel margin with AA disabled
676d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        if (transformedRect.fLeft > SkIntToScalar(0) ||
677d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com            transformedRect.fTop > SkIntToScalar(0) ||
678b1e218e782261304440199642f1b98e7ba96b525junov@chromium.org            transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) ||
679b1e218e782261304440199642f1b98e7ba96b525junov@chromium.org            transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) {
6804370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return false;
6814370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
6824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
6834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
6844370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    switch (canvas->getClipType()) {
6854370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkCanvas::kRect_ClipType :
6864370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            {
6874370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkIRect bounds;
6884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                canvas->getClipDeviceBounds(&bounds);
689d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                if (bounds.fLeft > 0 || bounds.fTop > 0 ||
690d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                    bounds.fRight < canvasSize.fWidth ||
6914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    bounds.fBottom < canvasSize.fHeight)
6924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    return false;
6934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
6944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            break;
6954370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkCanvas::kComplex_ClipType :
6964370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return false; // conservative
6974370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkCanvas::kEmpty_ClipType:
6984370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        default:
6994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            break;
7004370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    };
7014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return true;
7034370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
705c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgint SkDeferredCanvas::save(SaveFlags flags) {
7069060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->save(flags);
7079ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    int val = this->INHERITED::save(flags);
7089ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7099ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
7109ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comint SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
714c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                SaveFlags flags) {
7159060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->saveLayer(bounds, paint, flags);
716a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    int count = this->INHERITED::save(flags);
717a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    this->clipRectBounds(bounds, flags, NULL);
7189ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7199ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org
720a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return count;
7214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7224370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
723c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::restore() {
7249060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->restore();
725a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    this->INHERITED::restore();
7269ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7274370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
729c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::isDrawingToLayer() const {
7309060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    return this->drawingCanvas()->isDrawingToLayer();
7314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
733c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) {
7349060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->translate(dx, dy);
7359ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::translate(dx, dy);
7369ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7379ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
740c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) {
7419060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->scale(sx, sy);
7429ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::scale(sx, sy);
7439ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7449ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7454370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7464370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
747c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::rotate(SkScalar degrees) {
7489060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->rotate(degrees);
7499ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::rotate(degrees);
7509ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7519ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
754c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) {
7559060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->skew(sx, sy);
7569ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::skew(sx, sy);
7579ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7589ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
761c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::concat(const SkMatrix& matrix) {
7629060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->concat(matrix);
7639ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::concat(matrix);
7649ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7659ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
768c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
7699060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->setMatrix(matrix);
770a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    this->INHERITED::setMatrix(matrix);
7719ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::clipRect(const SkRect& rect,
7754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                SkRegion::Op op,
776c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                bool doAntiAlias) {
7779060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->clipRect(rect, op, doAntiAlias);
7789ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::clipRect(rect, op, doAntiAlias);
7799ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7809ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7814370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::clipPath(const SkPath& path,
7844370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                SkRegion::Op op,
785c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                bool doAntiAlias) {
7869060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->clipPath(path, op, doAntiAlias);
7879ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::clipPath(path, op, doAntiAlias);
7889ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7899ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7904370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
793c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  SkRegion::Op op) {
7949060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->clipRegion(deviceRgn, op);
7959ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    bool val = this->INHERITED::clipRegion(deviceRgn, op);
7969ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
7979ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return val;
7984370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
800c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::clear(SkColor color) {
8014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // purge pending commands
8024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeferredDrawing) {
8039060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->contentsCleared();
8044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
8054370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8069060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->clear(color);
8079ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8084370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8094370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
810c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawPaint(const SkPaint& paint) {
811d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    if (fDeferredDrawing && this->isFullFrame(NULL, &paint) &&
812c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org        isPaintOpaque(&paint)) {
8139060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->contentsCleared();
8144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
81510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
8169060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawPaint(paint);
8179ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8184370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawPoints(PointMode mode, size_t count,
821c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  const SkPoint pts[], const SkPaint& paint) {
82210f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
8239060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawPoints(mode, count, pts, paint);
8249ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
827c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
828d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    if (fDeferredDrawing && this->isFullFrame(&rect, &paint) &&
829c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org        isPaintOpaque(&paint)) {
8309060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->contentsCleared();
8314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
8324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
83310f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
8349060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawRect(rect, paint);
8359ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8374370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
838c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
83910f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
8409060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawPath(path, paint);
8419ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
845c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  SkScalar top, const SkPaint* paint) {
8468f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    SkRect bitmapRect = SkRect::MakeXYWH(left, top,
8478f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
848d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    if (fDeferredDrawing &&
8499060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->isFullFrame(&bitmapRect, paint) &&
85087f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        isPaintOpaque(paint, &bitmap)) {
8519060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->contentsCleared();
8524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
8534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
85410f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
8559060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawBitmap(bitmap, left, top, paint);
8569ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8574370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8597112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkDeferredCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
8607112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com                                            const SkRect* src,
8617112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com                                            const SkRect& dst,
8627112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com                                            const SkPaint* paint) {
863d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    if (fDeferredDrawing &&
8649060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->isFullFrame(&dst, paint) &&
86587f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        isPaintOpaque(paint, &bitmap)) {
8669060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->contentsCleared();
8674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
8684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
86910f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
8707112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    this->drawingCanvas()->drawBitmapRectToRect(bitmap, src, dst, paint);
8719ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
8764370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                        const SkMatrix& m,
877c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                        const SkPaint* paint) {
8784370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
8794370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // covers canvas entirely and transformed bitmap covers canvas entirely
88010f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
8819060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawBitmapMatrix(bitmap, m, paint);
8829ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8844370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8854370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap,
8864370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkIRect& center, const SkRect& dst,
887c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                      const SkPaint* paint) {
8884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
8894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // covers canvas entirely and dst covers canvas entirely
89010f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
8919060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawBitmapNine(bitmap, center, dst, paint);
8929ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
8934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8954370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
896c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  const SkPaint* paint) {
8978f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    SkRect bitmapRect = SkRect::MakeXYWH(
8988f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(left),
899d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        SkIntToScalar(top),
9008f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(bitmap.width()),
9018f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(bitmap.height()));
902d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    if (fDeferredDrawing &&
9039060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->isFullFrame(&bitmapRect, paint) &&
90487f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        isPaintOpaque(paint, &bitmap)) {
9059060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org        this->getDeferredDevice()->contentsCleared();
9064370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
9074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
90810f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
9099060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawSprite(bitmap, left, top, paint);
9109ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawText(const void* text, size_t byteLength,
914c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                SkScalar x, SkScalar y, const SkPaint& paint) {
91510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
9169060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawText(text, byteLength, x, y, paint);
9179ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9184370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawPosText(const void* text, size_t byteLength,
921c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                   const SkPoint pos[], const SkPaint& paint) {
92210f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
9239060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawPosText(text, byteLength, pos, paint);
9249ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9274370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength,
9284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkScalar xpos[], SkScalar constY,
929c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                    const SkPaint& paint) {
93010f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
9319060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
9329ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
9364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkPath& path,
9374370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkMatrix* matrix,
938c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                      const SkPaint& paint) {
93910f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
9409060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawTextOnPath(text, byteLength, path, matrix, paint);
9419ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
944c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawPicture(SkPicture& picture) {
9459060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawPicture(picture);
9469ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9474370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
9504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkPoint vertices[],
9514370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkPoint texs[],
9524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkColor colors[], SkXfermode* xmode,
9534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const uint16_t indices[], int indexCount,
954c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                    const SkPaint& paint) {
95510f7f97d4213a251d63fcfcfd6e55b7b528d949ajunov@chromium.org    AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
9569060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
9579060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org                                        indices, indexCount, paint);
9589ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
961c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
9629060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    this->drawingCanvas()->setBounder(bounder);
9639ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->INHERITED::setBounder(bounder);
9649ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
9659ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    return bounder;
9664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
968c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
969d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    this->drawingCanvas()->setDrawFilter(filter);
9709ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->INHERITED::setDrawFilter(filter);
9719ed02b9da25a76ee4c73c1ab19c18b899a223a17junov@chromium.org    this->recordedDrawCommand();
972d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    return filter;
9734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkDeferredCanvas::canvasForDrawIter() {
9769060c9bae9dc895ffe73adefccbc896d2973882djunov@chromium.org    return this->drawingCanvas();
9774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
978