| /* | |
| * Copyright 2025 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef PipelineCallbackHandler_DEFINED | |
| #define PipelineCallbackHandler_DEFINED | |
| #include "include/core/SkData.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/gpu/graphite/ContextOptions.h" | |
| #include "src/core/SkChecksum.h" | |
| #include "src/core/SkSpinlock.h" | |
| #include "src/core/SkTHash.h" | |
| #include <vector> | |
| class SkData; | |
| namespace skiatools::graphite { | |
| // This is intended to be an example of a Precompilation Callback handler. | |
| // For the gr*testprecompile configs it is used to: | |
| // collect all the Android-style keys that are used by a given source (e.g., gm, or skp) | |
| // recreate the Pipelines from the collected keys in `resetAndRecreatePipelines` | |
| // For the gr*testtracking configs it is used to: | |
| // collect all the Pipeline labels for a given source | |
| // print out a list of the labels at the end using `report` | |
| class PipelineCallBackHandler { | |
| public: | |
| static void CallBack(void* context, | |
| skgpu::graphite::ContextOptions::PipelineCacheOp op, | |
| const std::string& label, | |
| uint32_t uniqueKeyHash, | |
| bool fromPrecompile, | |
| sk_sp<SkData> androidStyleKey) { | |
| PipelineCallBackHandler* handler = reinterpret_cast<PipelineCallBackHandler*>(context); | |
| handler->add(op, label, uniqueKeyHash, fromPrecompile, std::move(androidStyleKey)); | |
| } | |
| void add(skgpu::graphite::ContextOptions::PipelineCacheOp op, | |
| const std::string& label, | |
| uint32_t uniqueKeyHash, | |
| bool fromPrecompile, | |
| sk_sp<SkData> androidStyleKey) SK_EXCLUDES(fSpinLock); | |
| void retrieveKeys(std::vector<sk_sp<SkData>>* result) SK_EXCLUDES(fSpinLock) { | |
| SkAutoSpinlock lock{ fSpinLock }; | |
| result->reserve(fMap.count()); | |
| fMap.foreach([result](std::unique_ptr<PipelineData>* data) { | |
| // Because not all Pipelines are serializable we need to check for nulls here | |
| if ((*data)->fAndroidStyleKey) { | |
| result->push_back((*data)->fAndroidStyleKey); | |
| } | |
| }); | |
| } | |
| void reset() SK_EXCLUDES(fSpinLock) { | |
| SkAutoSpinlock lock{ fSpinLock }; | |
| fMap.reset(); | |
| } | |
| void report() SK_EXCLUDES(fSpinLock); | |
| private: | |
| mutable SkSpinlock fSpinLock; | |
| struct PipelineData { | |
| PipelineData(const std::string& label, | |
| uint32_t uniqueKeyHash, | |
| bool fromPrecompile, | |
| sk_sp<SkData> androidStyleKey) : | |
| fLabel(label), | |
| fAndroidStyleKey(std::move(androidStyleKey)), | |
| fUniqueKeyHash(uniqueKeyHash), | |
| fUses(fromPrecompile ? 0 : 1), | |
| fFromPrecompile(fromPrecompile) { | |
| } | |
| std::string fLabel; | |
| sk_sp<SkData> fAndroidStyleKey; | |
| uint32_t fUniqueKeyHash; | |
| uint32_t fUses; | |
| bool fFromPrecompile; | |
| }; | |
| struct PipelineKey { | |
| const std::string* fLabel; | |
| uint32_t fUniqueKeyHash; | |
| static PipelineKey GetKey(const std::unique_ptr<PipelineData>& v) { | |
| return { &v->fLabel, v->fUniqueKeyHash }; | |
| } | |
| static uint32_t Hash(const PipelineKey& k) { return k.fUniqueKeyHash; } | |
| bool operator==(const PipelineKey& other) const { | |
| return fUniqueKeyHash == other.fUniqueKeyHash && *fLabel == *other.fLabel; | |
| } | |
| }; | |
| using Map = skia_private::THashTable<std::unique_ptr<PipelineData>, PipelineKey, PipelineKey>; | |
| Map fMap SK_GUARDED_BY(fSpinLock); | |
| }; | |
| } // namespace skiatools::graphite | |
| #endif // PipelineCallbackHandler_DEFINED |