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