1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H
18 #define SF_RENDER_ENGINE_PROGRAMCACHE_H
19 
20 #include <GLES2/gl2.h>
21 
22 #include <utils/KeyedVector.h>
23 #include <utils/Singleton.h>
24 #include <utils/TypeHelpers.h>
25 
26 #include "Description.h"
27 
28 namespace android {
29 
30 class Description;
31 class Formatter;
32 class Program;
33 class String8;
34 
35 /*
36  * This class generates GLSL programs suitable to handle a given
37  * Description. It's responsible for figuring out what to
38  * generate from a Description.
39  * It also maintains a cache of these Programs.
40  */
41 class ProgramCache : public Singleton<ProgramCache> {
42 public:
43     /*
44      * Key is used to retrieve a Program in the cache.
45      * A Key is generated from a Description.
46      */
47     class Key {
48         friend class ProgramCache;
49         typedef uint32_t key_t;
50         key_t mKey;
51 
52     public:
53         enum {
54             BLEND_SHIFT = 0,
55             BLEND_MASK = 1 << BLEND_SHIFT,
56             BLEND_PREMULT = 1 << BLEND_SHIFT,
57             BLEND_NORMAL = 0 << BLEND_SHIFT,
58 
59             OPACITY_SHIFT = 1,
60             OPACITY_MASK = 1 << OPACITY_SHIFT,
61             OPACITY_OPAQUE = 1 << OPACITY_SHIFT,
62             OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT,
63 
64             ALPHA_SHIFT = 2,
65             ALPHA_MASK = 1 << ALPHA_SHIFT,
66             ALPHA_LT_ONE = 1 << ALPHA_SHIFT,
67             ALPHA_EQ_ONE = 0 << ALPHA_SHIFT,
68 
69             TEXTURE_SHIFT = 3,
70             TEXTURE_MASK = 3 << TEXTURE_SHIFT,
71             TEXTURE_OFF = 0 << TEXTURE_SHIFT,
72             TEXTURE_EXT = 1 << TEXTURE_SHIFT,
73             TEXTURE_2D = 2 << TEXTURE_SHIFT,
74 
75             INPUT_TRANSFORM_MATRIX_SHIFT = 5,
76             INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
77             INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT,
78             INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
79 
80             OUTPUT_TRANSFORM_MATRIX_SHIFT = 6,
81             OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
82             OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
83             OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
84 
85             INPUT_TF_SHIFT = 7,
86             INPUT_TF_MASK = 3 << INPUT_TF_SHIFT,
87             INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
88             INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
89             INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
90             INPUT_TF_HLG = 3 << INPUT_TF_SHIFT,
91 
92             OUTPUT_TF_SHIFT = 9,
93             OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
94             OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
95             OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
96             OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
97             OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT,
98 
99             Y410_BT2020_SHIFT = 11,
100             Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT,
101             Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT,
102             Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT,
103         };
104 
Key()105         inline Key() : mKey(0) {}
Key(const Key & rhs)106         inline Key(const Key& rhs) : mKey(rhs.mKey) {}
107 
set(key_t mask,key_t value)108         inline Key& set(key_t mask, key_t value) {
109             mKey = (mKey & ~mask) | value;
110             return *this;
111         }
112 
isTexturing()113         inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
getTextureTarget()114         inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
isPremultiplied()115         inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
isOpaque()116         inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
hasAlpha()117         inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
hasInputTransformMatrix()118         inline bool hasInputTransformMatrix() const {
119             return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON;
120         }
hasOutputTransformMatrix()121         inline bool hasOutputTransformMatrix() const {
122             return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
123         }
hasTransformMatrix()124         inline bool hasTransformMatrix() const {
125             return hasInputTransformMatrix() || hasOutputTransformMatrix();
126         }
getInputTF()127         inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
getOutputTF()128         inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
129 
130         // When HDR and non-HDR contents are mixed, or different types of HDR contents are
131         // mixed, we will do a tone mapping process to tone map the input content to output
132         // content. Currently, the following conversions handled, they are:
133         // * SDR -> HLG
134         // * SDR -> PQ
135         // * HLG -> PQ
needsToneMapping()136         inline bool needsToneMapping() const {
137             int inputTF = getInputTF();
138             int outputTF = getOutputTF();
139 
140             // Return false when converting from SDR to SDR.
141             if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
142                 return false;
143             }
144             if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
145                 return false;
146             }
147 
148             inputTF >>= Key::INPUT_TF_SHIFT;
149             outputTF >>= Key::OUTPUT_TF_SHIFT;
150             return inputTF != outputTF;
151         }
isY410BT2020()152         inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
153 
154         // this is the definition of a friend function -- not a method of class Needs
strictly_order_type(const Key & lhs,const Key & rhs)155         friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
156             return (lhs.mKey < rhs.mKey) ? 1 : 0;
157         }
158     };
159 
160     ProgramCache();
161     ~ProgramCache();
162 
163     // Generate shaders to populate the cache
164     void primeCache(bool hasWideColor);
165 
166     // useProgram lookup a suitable program in the cache or generates one
167     // if none can be found.
168     void useProgram(const Description& description);
169 
170 private:
171     // compute a cache Key from a Description
172     static Key computeKey(const Description& description);
173     // Generate EOTF based from Key.
174     static void generateEOTF(Formatter& fs, const Key& needs);
175     // Generate necessary tone mapping methods for OOTF.
176     static void generateToneMappingProcess(Formatter& fs, const Key& needs);
177     // Generate OOTF based from Key.
178     static void generateOOTF(Formatter& fs, const Key& needs);
179     // Generate OETF based from Key.
180     static void generateOETF(Formatter& fs, const Key& needs);
181     // generates a program from the Key
182     static Program* generateProgram(const Key& needs);
183     // generates the vertex shader from the Key
184     static String8 generateVertexShader(const Key& needs);
185     // generates the fragment shader from the Key
186     static String8 generateFragmentShader(const Key& needs);
187 
188     // Key/Value map used for caching Programs. Currently the cache
189     // is never shrunk.
190     DefaultKeyedVector<Key, Program*> mCache;
191 };
192 
193 ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key)
194 
195 } /* namespace android */
196 
197 #endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */
198