aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkMultiPictureDraw.cpp
blob: 1df27ff4cca7c970fc3ce713991e49d92bebec5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCanvas.h"
#include "SkCanvasPriv.h"
#include "SkMultiPictureDraw.h"
#include "SkPicture.h"
#include "SkTaskGroup.h"

void SkMultiPictureDraw::DrawData::draw() {
    fCanvas->drawPicture(fPicture, &fMatrix, fPaint);
}

void SkMultiPictureDraw::DrawData::init(SkCanvas* canvas, const SkPicture* picture,
                                        const SkMatrix* matrix, const SkPaint* paint) {
    fPicture = SkRef(picture);
    fCanvas = canvas;
    if (matrix) {
        fMatrix = *matrix;
    } else {
        fMatrix.setIdentity();
    }
    if (paint) {
        fPaint = new SkPaint(*paint);
    } else {
        fPaint = nullptr;
    }
}

void SkMultiPictureDraw::DrawData::Reset(SkTDArray<DrawData>& data) {
    for (int i = 0; i < data.count(); ++i) {
        data[i].fPicture->unref();
        delete data[i].fPaint;
    }
    data.rewind();
}

//////////////////////////////////////////////////////////////////////////////////////

SkMultiPictureDraw::SkMultiPictureDraw(int reserve) {
    if (reserve > 0) {
        fGPUDrawData.setReserve(reserve);
        fThreadSafeDrawData.setReserve(reserve);
    }
}

void SkMultiPictureDraw::reset() {
    DrawData::Reset(fGPUDrawData);
    DrawData::Reset(fThreadSafeDrawData);
}

void SkMultiPictureDraw::add(SkCanvas* canvas,
                             const SkPicture* picture,
                             const SkMatrix* matrix,
                             const SkPaint* paint) {
    if (nullptr == canvas || nullptr == picture) {
        SkDEBUGFAIL("parameters to SkMultiPictureDraw::add should be non-nullptr");
        return;
    }

    SkTDArray<DrawData>& array = canvas->getGrContext() ? fGPUDrawData : fThreadSafeDrawData;
    array.append()->init(canvas, picture, matrix, paint);
}

class AutoMPDReset : SkNoncopyable {
    SkMultiPictureDraw* fMPD;
public:
    AutoMPDReset(SkMultiPictureDraw* mpd) : fMPD(mpd) {}
    ~AutoMPDReset() { fMPD->reset(); }
};

//#define FORCE_SINGLE_THREAD_DRAWING_FOR_TESTING

void SkMultiPictureDraw::draw(bool flush) {
    AutoMPDReset mpdreset(this);

#ifdef FORCE_SINGLE_THREAD_DRAWING_FOR_TESTING
    for (int i = 0; i < fThreadSafeDrawData.count(); ++i) {
        fThreadSafeDrawData[i].draw();
    }
#else
    SkTaskGroup().batch(fThreadSafeDrawData.count(), [&](int i) {
        fThreadSafeDrawData[i].draw();
    });
#endif

    // N.B. we could get going on any GPU work from this main thread while the CPU work runs.
    // But in practice, we've either got GPU work or CPU work, not both.

    const int count = fGPUDrawData.count();
    if (0 == count) {
        return;
    }

    for (int i = 0; i < count; ++i) {
        const DrawData& data = fGPUDrawData[i];
        SkCanvas* canvas = data.fCanvas;
        const SkPicture* picture = data.fPicture;

        canvas->drawPicture(picture, &data.fMatrix, data.fPaint);
        if (flush) {
            canvas->flush();
        }
    }
}