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