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