Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/gpu/GrDeferredProxyUploader.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2017 Google Inc.
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
#ifndef GrDeferredProxyUploader_DEFINED
9
#define GrDeferredProxyUploader_DEFINED
10
11
#include "include/core/SkRefCnt.h"
12
#include "include/private/SkSemaphore.h"
13
#include "src/core/SkAutoPixmapStorage.h"
14
15
#include "src/gpu/GrOpFlushState.h"
16
#include "src/gpu/GrTextureProxyPriv.h"
17
18
/**
19
 * GrDeferredProxyUploader assists with threaded generation of textures. Currently used by both
20
 * software clip masks, and the software path renderer. The calling code typically needs to store
21
 * some additional data (T) for use on the worker thread. GrTDeferredProxyUploader allows storing
22
 * such data. The common flow is:
23
 *
24
 * 1) A GrTDeferredProxyUploader is created, with some payload (eg an SkPath to draw).
25
 *    The uploader is owned by the proxy that it's going to populate.
26
 * 2) A task is created with a pointer to the uploader. A worker thread executes that task, using
27
 *    the payload data to allocate and fill in the fPixels pixmap.
28
 * 3) The worker thread calls signalAndFreeData(), which notifies the main thread that the pixmap
29
 *    is ready, and then deletes the payload data (which is no longer needed).
30
 * 4) In parallel to 2-3, on the main thread... Some op is created that refers to the proxy. When
31
 *    that op is added to an op list, the op list retains a pointer to the "deferred" proxies.
32
 * 5) At flush time, the op list ensures that the deferred proxies are instantiated, then calls
33
 *    scheduleUpload on those proxies, which calls scheduleUpload on the uploader (below).
34
 * 6) scheduleUpload defers the upload even further, by adding an ASAPUpload to the flush.
35
 * 7) When the ASAP upload happens, we wait to make sure that the pixels are marked ready
36
 *    (from step #3 on the worker thread). Then we perform the actual upload to the texture.
37
 *    Finally, we call resetDeferredUploader, which deletes the uploader object, causing fPixels
38
 *    to be freed.
39
 */
40
class GrDeferredProxyUploader : public SkNoncopyable {
41
public:
42
0
    GrDeferredProxyUploader() : fScheduledUpload(false), fWaited(false) {}
43
44
0
    virtual ~GrDeferredProxyUploader() {
45
        // In normal usage (i.e., through GrTDeferredProxyUploader) this will be redundant
46
0
        this->wait();
47
0
    }
48
49
0
    void scheduleUpload(GrOpFlushState* flushState, GrTextureProxy* proxy) {
50
0
        if (fScheduledUpload) {
51
            // Multiple references to the owning proxy may have caused us to already execute
52
0
            return;
53
0
        }
54
55
0
        auto uploadMask = [this, proxy](GrDeferredTextureUploadWritePixelsFn& writePixelsFn) {
56
0
            this->wait();
57
0
            GrColorType pixelColorType = SkColorTypeToGrColorType(this->fPixels.info().colorType());
58
            // If the worker thread was unable to allocate pixels, this check will fail, and we'll
59
            // end up drawing with an uninitialized mask texture, but at least we won't crash.
60
0
            if (this->fPixels.addr()) {
61
0
                writePixelsFn(proxy,
62
0
                              SkIRect::MakeSize(fPixels.dimensions()),
63
0
                              pixelColorType,
64
0
                              this->fPixels.addr(),
65
0
                              this->fPixels.rowBytes());
66
0
            }
67
            // Upload has finished, so tell the proxy to release this GrDeferredProxyUploader
68
0
            proxy->texPriv().resetDeferredUploader();
69
0
        };
70
0
        flushState->addASAPUpload(std::move(uploadMask));
71
0
        fScheduledUpload = true;
72
0
    }
73
74
0
    void signalAndFreeData() {
75
0
        this->freeData();
76
0
        fPixelsReady.signal();
77
0
    }
78
79
0
    SkAutoPixmapStorage* getPixels() { return &fPixels; }
80
81
protected:
82
0
    void wait() {
83
0
        if (!fWaited) {
84
0
            fPixelsReady.wait();
85
0
            fWaited = true;
86
0
        }
87
0
    }
88
89
private:
90
0
    virtual void freeData() {}
91
92
    SkAutoPixmapStorage fPixels;
93
    SkSemaphore fPixelsReady;
94
    bool fScheduledUpload;
95
    bool fWaited;
96
};
97
98
template <typename T>
99
class GrTDeferredProxyUploader : public GrDeferredProxyUploader {
100
public:
101
    template <typename... Args>
102
    GrTDeferredProxyUploader(Args&&... args)
103
0
        : fData(std::make_unique<T>(std::forward<Args>(args)...)) {
104
0
    }
Unexecuted instantiation: SoftwarePathRenderer.cpp:GrTDeferredProxyUploader<(anonymous namespace)::SoftwarePathData>::GrTDeferredProxyUploader<SkIRect const&, SkMatrix const&, GrStyledShape const&, GrAA&>(SkIRect const&, SkMatrix const&, GrStyledShape const&, GrAA&)
Unexecuted instantiation: GrTDeferredProxyUploader<SkTArray<skgpu::v1::ClipStack::Element, false> >::GrTDeferredProxyUploader<int&>(int&)
105
106
0
    ~GrTDeferredProxyUploader() override {
107
        // We need to wait here, so that we don't free fData before the worker thread is done
108
        // with it. (This happens if the proxy is deleted early due to a full clear or failure
109
        // of an op list to instantiate).
110
0
        this->wait();
111
0
    }
Unexecuted instantiation: SoftwarePathRenderer.cpp:GrTDeferredProxyUploader<(anonymous namespace)::SoftwarePathData>::~GrTDeferredProxyUploader()
Unexecuted instantiation: GrTDeferredProxyUploader<SkTArray<skgpu::v1::ClipStack::Element, false> >::~GrTDeferredProxyUploader()
112
113
0
    T& data() { return *fData; }
Unexecuted instantiation: SoftwarePathRenderer.cpp:GrTDeferredProxyUploader<(anonymous namespace)::SoftwarePathData>::data()
Unexecuted instantiation: GrTDeferredProxyUploader<SkTArray<skgpu::v1::ClipStack::Element, false> >::data()
114
115
private:
116
0
    void freeData() override {
117
0
        fData.reset();
118
0
    }
Unexecuted instantiation: SoftwarePathRenderer.cpp:GrTDeferredProxyUploader<(anonymous namespace)::SoftwarePathData>::freeData()
Unexecuted instantiation: GrTDeferredProxyUploader<SkTArray<skgpu::v1::ClipStack::Element, false> >::freeData()
119
120
    std::unique_ptr<T> fData;
121
};
122
123
#endif