aboutsummaryrefslogtreecommitdiff
path: root/src/deps/skia/include/private/SkPaintParamsKey.h
blob: 44a88f59feb92f9ac022b4b15a6e0f01149efe8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPaintParamsKey_DEFINED
#define SkPaintParamsKey_DEFINED

#include <array>
#include <limits>
#include "include/core/SkTypes.h"

enum class SkBackend : uint8_t {
    kGanesh,
    kGraphite,
    kSkVM
};

// TODO: this needs to be expanded into a more flexible dictionary (esp. for user-supplied SkSL)
// TODO: should this enum actually be in ShaderCodeDictionary.h?
enum class CodeSnippetID : uint8_t {
    // TODO: It seems like this requires some refinement. Fundamentally this doesn't seem like a
    // draw that originated from a PaintParams.
    kDepthStencilOnlyDraw,

    // SkShader code snippets
    kSolidColorShader,
    kLinearGradientShader,
    kRadialGradientShader,
    kSweepGradientShader,
    kConicalGradientShader,

    // BlendMode code snippets
    kSimpleBlendMode,

    kLast = kSimpleBlendMode
};
static constexpr int kCodeSnippetIDCount = static_cast<int>(CodeSnippetID::kLast) + 1;

// This class is a compact representation of the shader needed to implement a given
// PaintParams. Its structure is a series of blocks where each block has a
// header that consists of 2-bytes - a 1-byte code-snippet ID and a 1-byte number-of-bytes-in-the-
// block field. The rest of the data in the block is dependent on the individual code snippet.
class SkPaintParamsKey {
public:
    static const int kBlockHeaderSizeInBytes = 2;
    static const int kBlockSizeOffsetInBytes = 1; // offset to the block size w/in the header

    // Block headers have the following structure:
    //  1st byte: codeSnippetID
    //  2nd byte: total blockSize in bytes
    // Returns the header's offset in the key - to be passed back into endBlock
    int beginBlock(CodeSnippetID codeSnippetID) {
        SkASSERT(fNumBytes < kMaxKeySize);

        this->addByte((uint8_t) codeSnippetID);
        this->addByte(0); // this needs to be patched up with a call to endBlock
        return fNumBytes - kBlockHeaderSizeInBytes;
    }

    // Update the size byte of a block header
    void endBlock(int headerOffset, CodeSnippetID codeSnippetID) {
        SkASSERT(fData[headerOffset] == (uint32_t) codeSnippetID);
        int blockSize = fNumBytes - headerOffset;
        SkASSERT(blockSize <= kMaxBlockSize);
        fData[headerOffset+1] = blockSize;
    }

    std::pair<CodeSnippetID, uint8_t> readCodeSnippetID(int headerOffset) const {
        SkASSERT(headerOffset < kMaxKeySize - kBlockHeaderSizeInBytes);

        CodeSnippetID id = static_cast<CodeSnippetID>(fData[headerOffset]);
        uint8_t blockSize = fData[headerOffset+1];
        SkASSERT(headerOffset + blockSize <= this->sizeInBytes());

        return { id, blockSize };
    }

    void addByte(uint8_t byte) {
        SkASSERT(fNumBytes < kMaxKeySize);

        fData[fNumBytes++] = byte;
    }

#ifdef SK_DEBUG
    static int DumpBlock(const SkPaintParamsKey&, int headerOffset);
    void dump() const;
#endif

    uint8_t byte(int offset) const { SkASSERT(offset < fNumBytes); return fData[offset]; }
    const void* data() const { return fData.data(); }
    int sizeInBytes() const { return fNumBytes; }

    bool operator==(const SkPaintParamsKey& that) const;
    bool operator!=(const SkPaintParamsKey& that) const { return !(*this == that); }

private:
    // TODO: need to make it so the key can can dynamically grow
    static const int kMaxKeySize = 32;
    static const int kMaxBlockSize = std::numeric_limits<uint8_t>::max();

    // TODO: It is probably overkill but we could encode the SkBackend in the first byte of
    // the key.
    int fNumBytes = 0;
    std::array<uint8_t, kMaxKeySize> fData;
};

#endif // SkPaintParamsKey_DEFINED