1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 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_KeyBuilder_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_KeyBuilder_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h" 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 16*c8dee2aaSAndroid Build Coastguard Worker #include <string_view> 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu { 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker class KeyBuilder { 21*c8dee2aaSAndroid Build Coastguard Worker public: KeyBuilder(skia_private::TArray<uint32_t,true> * data)22*c8dee2aaSAndroid Build Coastguard Worker KeyBuilder(skia_private::TArray<uint32_t, true>* data) : fData(data) {} 23*c8dee2aaSAndroid Build Coastguard Worker ~KeyBuilder()24*c8dee2aaSAndroid Build Coastguard Worker virtual ~KeyBuilder() { 25*c8dee2aaSAndroid Build Coastguard Worker // Ensure that flush was called before we went out of scope 26*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fBitsUsed == 0); 27*c8dee2aaSAndroid Build Coastguard Worker } 28*c8dee2aaSAndroid Build Coastguard Worker addBits(uint32_t numBits,uint32_t val,std::string_view label)29*c8dee2aaSAndroid Build Coastguard Worker virtual void addBits(uint32_t numBits, uint32_t val, std::string_view label) { 30*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(numBits > 0 && numBits <= 32); 31*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(numBits == 32 || (val < (1u << numBits))); 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker fCurValue |= (val << fBitsUsed); 34*c8dee2aaSAndroid Build Coastguard Worker fBitsUsed += numBits; 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker if (fBitsUsed >= 32) { 37*c8dee2aaSAndroid Build Coastguard Worker // Overflow, start a new working value 38*c8dee2aaSAndroid Build Coastguard Worker fData->push_back(fCurValue); 39*c8dee2aaSAndroid Build Coastguard Worker uint32_t excess = fBitsUsed - 32; 40*c8dee2aaSAndroid Build Coastguard Worker fCurValue = excess ? (val >> (numBits - excess)) : 0; 41*c8dee2aaSAndroid Build Coastguard Worker fBitsUsed = excess; 42*c8dee2aaSAndroid Build Coastguard Worker } 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCurValue < (1u << fBitsUsed)); 45*c8dee2aaSAndroid Build Coastguard Worker } 46*c8dee2aaSAndroid Build Coastguard Worker addBytes(uint32_t numBytes,const void * data,std::string_view label)47*c8dee2aaSAndroid Build Coastguard Worker void addBytes(uint32_t numBytes, const void* data, std::string_view label) { 48*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data); 49*c8dee2aaSAndroid Build Coastguard Worker for (; numBytes --> 0; bytes++) { 50*c8dee2aaSAndroid Build Coastguard Worker this->addBits(8, *bytes, label); 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker } 53*c8dee2aaSAndroid Build Coastguard Worker addBool(bool b,std::string_view label)54*c8dee2aaSAndroid Build Coastguard Worker void addBool(bool b, std::string_view label) { 55*c8dee2aaSAndroid Build Coastguard Worker this->addBits(1, b, label); 56*c8dee2aaSAndroid Build Coastguard Worker } 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker void add32(uint32_t v, std::string_view label = "unknown") { 59*c8dee2aaSAndroid Build Coastguard Worker this->addBits(32, v, label); 60*c8dee2aaSAndroid Build Coastguard Worker } 61*c8dee2aaSAndroid Build Coastguard Worker appendComment(const char * comment)62*c8dee2aaSAndroid Build Coastguard Worker virtual void appendComment(const char* comment) {} 63*c8dee2aaSAndroid Build Coastguard Worker 64*c8dee2aaSAndroid Build Coastguard Worker // Introduces a word-boundary in the key. Must be called before using the key with any cache, 65*c8dee2aaSAndroid Build Coastguard Worker // but can also be called to create a break between generic data and backend-specific data. flush()66*c8dee2aaSAndroid Build Coastguard Worker void flush() { 67*c8dee2aaSAndroid Build Coastguard Worker if (fBitsUsed) { 68*c8dee2aaSAndroid Build Coastguard Worker fData->push_back(fCurValue); 69*c8dee2aaSAndroid Build Coastguard Worker fCurValue = 0; 70*c8dee2aaSAndroid Build Coastguard Worker fBitsUsed = 0; 71*c8dee2aaSAndroid Build Coastguard Worker } 72*c8dee2aaSAndroid Build Coastguard Worker } 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker private: 75*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<uint32_t, true>* fData; 76*c8dee2aaSAndroid Build Coastguard Worker uint32_t fCurValue = 0; 77*c8dee2aaSAndroid Build Coastguard Worker uint32_t fBitsUsed = 0; // ... in current value 78*c8dee2aaSAndroid Build Coastguard Worker }; 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker class StringKeyBuilder : public KeyBuilder { 81*c8dee2aaSAndroid Build Coastguard Worker public: StringKeyBuilder(skia_private::TArray<uint32_t,true> * data)82*c8dee2aaSAndroid Build Coastguard Worker StringKeyBuilder(skia_private::TArray<uint32_t, true>* data) : KeyBuilder(data) {} 83*c8dee2aaSAndroid Build Coastguard Worker addBits(uint32_t numBits,uint32_t val,std::string_view label)84*c8dee2aaSAndroid Build Coastguard Worker void addBits(uint32_t numBits, uint32_t val, std::string_view label) override { 85*c8dee2aaSAndroid Build Coastguard Worker KeyBuilder::addBits(numBits, val, label); 86*c8dee2aaSAndroid Build Coastguard Worker fDescription.appendf("%.*s: %u\n", (int)label.size(), label.data(), val); 87*c8dee2aaSAndroid Build Coastguard Worker } 88*c8dee2aaSAndroid Build Coastguard Worker appendComment(const char * comment)89*c8dee2aaSAndroid Build Coastguard Worker void appendComment(const char* comment) override { 90*c8dee2aaSAndroid Build Coastguard Worker fDescription.appendf("%s\n", comment); 91*c8dee2aaSAndroid Build Coastguard Worker } 92*c8dee2aaSAndroid Build Coastguard Worker description()93*c8dee2aaSAndroid Build Coastguard Worker SkString description() const { return fDescription; } 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker private: 96*c8dee2aaSAndroid Build Coastguard Worker SkString fDescription; 97*c8dee2aaSAndroid Build Coastguard Worker }; 98*c8dee2aaSAndroid Build Coastguard Worker 99*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu 100*c8dee2aaSAndroid Build Coastguard Worker 101*c8dee2aaSAndroid Build Coastguard Worker #endif // skgpu_KeyBuilder_DEFINED 102