xref: /aosp_15_r20/external/skia/src/gpu/RefCntedCallback.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
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 skgpu_RefCntedCallback_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_RefCntedCallback_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker 
14*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu {
15*c8dee2aaSAndroid Build Coastguard Worker /**
16*c8dee2aaSAndroid Build Coastguard Worker  * Move-only type that calls a callback from its destructor.
17*c8dee2aaSAndroid Build Coastguard Worker  */
18*c8dee2aaSAndroid Build Coastguard Worker class AutoCallback {
19*c8dee2aaSAndroid Build Coastguard Worker public:
20*c8dee2aaSAndroid Build Coastguard Worker     using Context                 = void*;
21*c8dee2aaSAndroid Build Coastguard Worker     using Callback                = void (*)(Context);
22*c8dee2aaSAndroid Build Coastguard Worker     using CallbackWithStats       = void (*)(Context, const GpuStats&);
23*c8dee2aaSAndroid Build Coastguard Worker     using ResultCallback          = void (*)(Context, CallbackResult);
24*c8dee2aaSAndroid Build Coastguard Worker     using ResultCallbackWithStats = void (*)(Context, CallbackResult, const GpuStats&);
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback() = default;
27*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback(const AutoCallback&) = delete;
AutoCallback(AutoCallback && that)28*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback(AutoCallback&& that) { *this = std::move(that); }
29*c8dee2aaSAndroid Build Coastguard Worker 
AutoCallback(Callback proc,Context ctx)30*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback(Callback proc, Context ctx) : fReleaseProc(proc), fReleaseCtx(ctx) {}
AutoCallback(CallbackWithStats proc,Context ctx)31*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback(CallbackWithStats proc, Context ctx)
32*c8dee2aaSAndroid Build Coastguard Worker             : fReleaseWithStatsProc(proc), fReleaseCtx(ctx) {}
AutoCallback(ResultCallback proc,Context ctx)33*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback(ResultCallback proc, Context ctx) : fResultReleaseProc(proc), fReleaseCtx(ctx) {}
AutoCallback(ResultCallbackWithStats proc,Context ctx)34*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback(ResultCallbackWithStats proc, Context ctx)
35*c8dee2aaSAndroid Build Coastguard Worker             : fResultReleaseWithStatsProc(proc), fReleaseCtx(ctx) {}
36*c8dee2aaSAndroid Build Coastguard Worker 
~AutoCallback()37*c8dee2aaSAndroid Build Coastguard Worker     ~AutoCallback() {
38*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->operator bool() || true);  // run assert in the operator
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker         if (fResultReleaseWithStatsProc) {
41*c8dee2aaSAndroid Build Coastguard Worker             fResultReleaseWithStatsProc(fReleaseCtx, fResult, fGpuStats);
42*c8dee2aaSAndroid Build Coastguard Worker         } else if (fReleaseWithStatsProc) {
43*c8dee2aaSAndroid Build Coastguard Worker             fReleaseWithStatsProc(fReleaseCtx, fGpuStats);
44*c8dee2aaSAndroid Build Coastguard Worker         } else if (fResultReleaseProc) {
45*c8dee2aaSAndroid Build Coastguard Worker             fResultReleaseProc(fReleaseCtx, fResult);
46*c8dee2aaSAndroid Build Coastguard Worker         } else if (fReleaseProc) {
47*c8dee2aaSAndroid Build Coastguard Worker             fReleaseProc(fReleaseCtx);
48*c8dee2aaSAndroid Build Coastguard Worker         }
49*c8dee2aaSAndroid Build Coastguard Worker     }
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback& operator=(const AutoCallback&) = delete;
52*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback& operator=(AutoCallback&& that) {
53*c8dee2aaSAndroid Build Coastguard Worker         fReleaseCtx                 = that.fReleaseCtx;
54*c8dee2aaSAndroid Build Coastguard Worker         fReleaseProc                = that.fReleaseProc;
55*c8dee2aaSAndroid Build Coastguard Worker         fReleaseWithStatsProc       = that.fReleaseWithStatsProc;
56*c8dee2aaSAndroid Build Coastguard Worker         fResultReleaseProc          = that.fResultReleaseProc;
57*c8dee2aaSAndroid Build Coastguard Worker         fResultReleaseWithStatsProc = that.fResultReleaseWithStatsProc;
58*c8dee2aaSAndroid Build Coastguard Worker         fResult                     = that.fResult;
59*c8dee2aaSAndroid Build Coastguard Worker         fGpuStats                   = that.fGpuStats;
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker         that.fReleaseProc                = nullptr;
62*c8dee2aaSAndroid Build Coastguard Worker         that.fReleaseWithStatsProc       = nullptr;
63*c8dee2aaSAndroid Build Coastguard Worker         that.fResultReleaseProc          = nullptr;
64*c8dee2aaSAndroid Build Coastguard Worker         that.fResultReleaseWithStatsProc = nullptr;
65*c8dee2aaSAndroid Build Coastguard Worker         return *this;
66*c8dee2aaSAndroid Build Coastguard Worker     }
67*c8dee2aaSAndroid Build Coastguard Worker 
context()68*c8dee2aaSAndroid Build Coastguard Worker     Context context() const { return fReleaseCtx; }
69*c8dee2aaSAndroid Build Coastguard Worker 
receivesGpuStats()70*c8dee2aaSAndroid Build Coastguard Worker     bool receivesGpuStats() const { return fReleaseWithStatsProc || fResultReleaseWithStatsProc; }
71*c8dee2aaSAndroid Build Coastguard Worker 
setFailureResult()72*c8dee2aaSAndroid Build Coastguard Worker     void setFailureResult() {
73*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fResultReleaseProc || fResultReleaseWithStatsProc);
74*c8dee2aaSAndroid Build Coastguard Worker         // Shouldn't really be calling this multiple times.
75*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fResult == CallbackResult::kSuccess);
76*c8dee2aaSAndroid Build Coastguard Worker         fResult = CallbackResult::kFailed;
77*c8dee2aaSAndroid Build Coastguard Worker     }
78*c8dee2aaSAndroid Build Coastguard Worker 
setStats(const GpuStats & stats)79*c8dee2aaSAndroid Build Coastguard Worker     void setStats(const GpuStats& stats) {
80*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->receivesGpuStats());
81*c8dee2aaSAndroid Build Coastguard Worker         fGpuStats = stats;
82*c8dee2aaSAndroid Build Coastguard Worker     }
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker     explicit operator bool() const {
85*c8dee2aaSAndroid Build Coastguard Worker         auto toInt = [](auto p) { return p ? 1U : 0U; };
86*c8dee2aaSAndroid Build Coastguard Worker         auto total = toInt(fReleaseProc) + toInt(fReleaseWithStatsProc) + toInt(fResultReleaseProc);
87*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(total <= 1);
88*c8dee2aaSAndroid Build Coastguard Worker         return total == 1;
89*c8dee2aaSAndroid Build Coastguard Worker     }
90*c8dee2aaSAndroid Build Coastguard Worker 
91*c8dee2aaSAndroid Build Coastguard Worker private:
92*c8dee2aaSAndroid Build Coastguard Worker     Callback                fReleaseProc                = nullptr;
93*c8dee2aaSAndroid Build Coastguard Worker     CallbackWithStats       fReleaseWithStatsProc       = nullptr;
94*c8dee2aaSAndroid Build Coastguard Worker     ResultCallback          fResultReleaseProc          = nullptr;
95*c8dee2aaSAndroid Build Coastguard Worker     ResultCallbackWithStats fResultReleaseWithStatsProc = nullptr;
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker     Context        fReleaseCtx = nullptr;
98*c8dee2aaSAndroid Build Coastguard Worker     CallbackResult fResult     = CallbackResult::kSuccess;
99*c8dee2aaSAndroid Build Coastguard Worker     GpuStats       fGpuStats   = {};
100*c8dee2aaSAndroid Build Coastguard Worker };
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker /**
103*c8dee2aaSAndroid Build Coastguard Worker  * Ref-counted object that calls a callback from its destructor.
104*c8dee2aaSAndroid Build Coastguard Worker  */
105*c8dee2aaSAndroid Build Coastguard Worker class RefCntedCallback : public SkNVRefCnt<RefCntedCallback> {
106*c8dee2aaSAndroid Build Coastguard Worker public:
107*c8dee2aaSAndroid Build Coastguard Worker     using Context                 = AutoCallback::Context;
108*c8dee2aaSAndroid Build Coastguard Worker     using Callback                = AutoCallback::Callback;
109*c8dee2aaSAndroid Build Coastguard Worker     using CallbackWithStats       = AutoCallback::CallbackWithStats;
110*c8dee2aaSAndroid Build Coastguard Worker     using ResultCallback          = AutoCallback::ResultCallback;
111*c8dee2aaSAndroid Build Coastguard Worker     using ResultCallbackWithStats = AutoCallback::ResultCallbackWithStats;
112*c8dee2aaSAndroid Build Coastguard Worker 
Make(Callback proc,Context ctx)113*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RefCntedCallback> Make(Callback proc, Context ctx) { return MakeImpl(proc, ctx); }
114*c8dee2aaSAndroid Build Coastguard Worker 
Make(CallbackWithStats proc,Context ctx)115*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RefCntedCallback> Make(CallbackWithStats proc, Context ctx) {
116*c8dee2aaSAndroid Build Coastguard Worker         return MakeImpl(proc, ctx);
117*c8dee2aaSAndroid Build Coastguard Worker     }
118*c8dee2aaSAndroid Build Coastguard Worker 
Make(ResultCallback proc,Context ctx)119*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RefCntedCallback> Make(ResultCallback proc, Context ctx) {
120*c8dee2aaSAndroid Build Coastguard Worker         return MakeImpl(proc, ctx);
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker 
Make(ResultCallbackWithStats proc,Context ctx)123*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RefCntedCallback> Make(ResultCallbackWithStats proc, Context ctx) {
124*c8dee2aaSAndroid Build Coastguard Worker         return MakeImpl(proc, ctx);
125*c8dee2aaSAndroid Build Coastguard Worker     }
126*c8dee2aaSAndroid Build Coastguard Worker 
Make(AutoCallback && callback)127*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RefCntedCallback> Make(AutoCallback&& callback) {
128*c8dee2aaSAndroid Build Coastguard Worker         if (!callback) {
129*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
130*c8dee2aaSAndroid Build Coastguard Worker         }
131*c8dee2aaSAndroid Build Coastguard Worker         return sk_sp<RefCntedCallback>(new RefCntedCallback(std::move(callback)));
132*c8dee2aaSAndroid Build Coastguard Worker     }
133*c8dee2aaSAndroid Build Coastguard Worker 
context()134*c8dee2aaSAndroid Build Coastguard Worker     Context context() const { return fCallback.context(); }
135*c8dee2aaSAndroid Build Coastguard Worker 
receivesGpuStats()136*c8dee2aaSAndroid Build Coastguard Worker     bool receivesGpuStats() const { return fCallback.receivesGpuStats(); }
137*c8dee2aaSAndroid Build Coastguard Worker 
setFailureResult()138*c8dee2aaSAndroid Build Coastguard Worker     void setFailureResult() { fCallback.setFailureResult(); }
139*c8dee2aaSAndroid Build Coastguard Worker 
setStats(const GpuStats & stats)140*c8dee2aaSAndroid Build Coastguard Worker     void setStats(const GpuStats& stats) { fCallback.setStats(stats); }
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker private:
143*c8dee2aaSAndroid Build Coastguard Worker     template <typename R, typename... Args>
MakeImpl(R proc (Args...),Context ctx)144*c8dee2aaSAndroid Build Coastguard Worker     static sk_sp<RefCntedCallback> MakeImpl(R proc(Args...), Context ctx) {
145*c8dee2aaSAndroid Build Coastguard Worker         if (!proc) {
146*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
147*c8dee2aaSAndroid Build Coastguard Worker         }
148*c8dee2aaSAndroid Build Coastguard Worker         return sk_sp<RefCntedCallback>(new RefCntedCallback({proc, ctx}));
149*c8dee2aaSAndroid Build Coastguard Worker     }
150*c8dee2aaSAndroid Build Coastguard Worker 
RefCntedCallback(AutoCallback callback)151*c8dee2aaSAndroid Build Coastguard Worker     RefCntedCallback(AutoCallback callback) : fCallback(std::move(callback)) {}
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     AutoCallback fCallback;
154*c8dee2aaSAndroid Build Coastguard Worker };
155*c8dee2aaSAndroid Build Coastguard Worker 
156*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker #endif // skgpu_RefCntedCallback_DEFINED
159*c8dee2aaSAndroid Build Coastguard Worker 
160