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