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 <memory> 21 #include <unordered_map> 22 23 #include <EGL/egl.h> 24 #include <GLES2/gl2.h> 25 #include <renderengine/private/Description.h> 26 #include <utils/Singleton.h> 27 #include <utils/TypeHelpers.h> 28 29 namespace android { 30 31 class String8; 32 33 namespace renderengine { 34 35 struct Description; 36 37 namespace gl { 38 39 class Formatter; 40 class Program; 41 42 /* 43 * This class generates GLSL programs suitable to handle a given 44 * Description. It's responsible for figuring out what to 45 * generate from a Description. 46 * It also maintains a cache of these Programs. 47 */ 48 class ProgramCache : public Singleton<ProgramCache> { 49 public: 50 /* 51 * Key is used to retrieve a Program in the cache. 52 * A Key is generated from a Description. 53 */ 54 class Key { 55 friend class ProgramCache; 56 typedef uint32_t key_t; 57 key_t mKey; 58 59 public: 60 enum { 61 BLEND_SHIFT = 0, 62 BLEND_MASK = 1 << BLEND_SHIFT, 63 BLEND_PREMULT = 1 << BLEND_SHIFT, 64 BLEND_NORMAL = 0 << BLEND_SHIFT, 65 66 OPACITY_SHIFT = 1, 67 OPACITY_MASK = 1 << OPACITY_SHIFT, 68 OPACITY_OPAQUE = 1 << OPACITY_SHIFT, 69 OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT, 70 71 ALPHA_SHIFT = 2, 72 ALPHA_MASK = 1 << ALPHA_SHIFT, 73 ALPHA_LT_ONE = 1 << ALPHA_SHIFT, 74 ALPHA_EQ_ONE = 0 << ALPHA_SHIFT, 75 76 TEXTURE_SHIFT = 3, 77 TEXTURE_MASK = 3 << TEXTURE_SHIFT, 78 TEXTURE_OFF = 0 << TEXTURE_SHIFT, 79 TEXTURE_EXT = 1 << TEXTURE_SHIFT, 80 TEXTURE_2D = 2 << TEXTURE_SHIFT, 81 82 ROUNDED_CORNERS_SHIFT = 5, 83 ROUNDED_CORNERS_MASK = 1 << ROUNDED_CORNERS_SHIFT, 84 ROUNDED_CORNERS_OFF = 0 << ROUNDED_CORNERS_SHIFT, 85 ROUNDED_CORNERS_ON = 1 << ROUNDED_CORNERS_SHIFT, 86 87 INPUT_TRANSFORM_MATRIX_SHIFT = 6, 88 INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, 89 INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT, 90 INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, 91 92 OUTPUT_TRANSFORM_MATRIX_SHIFT = 7, 93 OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, 94 OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT, 95 OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, 96 97 INPUT_TF_SHIFT = 8, 98 INPUT_TF_MASK = 3 << INPUT_TF_SHIFT, 99 INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT, 100 INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT, 101 INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT, 102 INPUT_TF_HLG = 3 << INPUT_TF_SHIFT, 103 104 OUTPUT_TF_SHIFT = 10, 105 OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT, 106 OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT, 107 OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT, 108 OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, 109 OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, 110 111 Y410_BT2020_SHIFT = 12, 112 Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, 113 Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, 114 Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, 115 116 SHADOW_SHIFT = 13, 117 SHADOW_MASK = 1 << SHADOW_SHIFT, 118 SHADOW_OFF = 0 << SHADOW_SHIFT, 119 SHADOW_ON = 1 << SHADOW_SHIFT, 120 }; 121 Key()122 inline Key() : mKey(0) {} Key(const Key & rhs)123 inline Key(const Key& rhs) : mKey(rhs.mKey) {} 124 set(key_t mask,key_t value)125 inline Key& set(key_t mask, key_t value) { 126 mKey = (mKey & ~mask) | value; 127 return *this; 128 } 129 isTexturing()130 inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } hasTextureCoords()131 inline bool hasTextureCoords() const { return isTexturing() && !drawShadows(); } getTextureTarget()132 inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } isPremultiplied()133 inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } isOpaque()134 inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } hasAlpha()135 inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } hasRoundedCorners()136 inline bool hasRoundedCorners() const { 137 return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON; 138 } drawShadows()139 inline bool drawShadows() const { return (mKey & SHADOW_MASK) == SHADOW_ON; } hasInputTransformMatrix()140 inline bool hasInputTransformMatrix() const { 141 return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; 142 } hasOutputTransformMatrix()143 inline bool hasOutputTransformMatrix() const { 144 return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; 145 } hasTransformMatrix()146 inline bool hasTransformMatrix() const { 147 return hasInputTransformMatrix() || hasOutputTransformMatrix(); 148 } getInputTF()149 inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } getOutputTF()150 inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } 151 152 // When HDR and non-HDR contents are mixed, or different types of HDR contents are 153 // mixed, we will do a tone mapping process to tone map the input content to output 154 // content. Currently, the following conversions handled, they are: 155 // * SDR -> HLG 156 // * SDR -> PQ 157 // * HLG -> PQ needsToneMapping()158 inline bool needsToneMapping() const { 159 int inputTF = getInputTF(); 160 int outputTF = getOutputTF(); 161 162 // Return false when converting from SDR to SDR. 163 if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { 164 return false; 165 } 166 if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { 167 return false; 168 } 169 170 inputTF >>= Key::INPUT_TF_SHIFT; 171 outputTF >>= Key::OUTPUT_TF_SHIFT; 172 return inputTF != outputTF; 173 } isY410BT2020()174 inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } 175 176 // for use by std::unordered_map 177 178 bool operator==(const Key& other) const { return mKey == other.mKey; } 179 180 struct Hash { operatorHash181 size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); } 182 }; 183 }; 184 185 ProgramCache() = default; 186 ~ProgramCache() = default; 187 188 // Generate shaders to populate the cache 189 void primeCache(const EGLContext context, bool useColorManagement, bool toneMapperShaderOnly); 190 getSize(const EGLContext context)191 size_t getSize(const EGLContext context) { return mCaches[context].size(); } 192 193 // useProgram lookup a suitable program in the cache or generates one 194 // if none can be found. 195 void useProgram(const EGLContext context, const Description& description); 196 197 private: 198 // compute a cache Key from a Description 199 static Key computeKey(const Description& description); 200 // Generate EOTF based from Key. 201 static void generateEOTF(Formatter& fs, const Key& needs); 202 // Generate necessary tone mapping methods for OOTF. 203 static void generateToneMappingProcess(Formatter& fs, const Key& needs); 204 // Generate OOTF based from Key. 205 static void generateOOTF(Formatter& fs, const Key& needs); 206 // Generate OETF based from Key. 207 static void generateOETF(Formatter& fs, const Key& needs); 208 // generates a program from the Key 209 static std::unique_ptr<Program> generateProgram(const Key& needs); 210 // generates the vertex shader from the Key 211 static String8 generateVertexShader(const Key& needs); 212 // generates the fragment shader from the Key 213 static String8 generateFragmentShader(const Key& needs); 214 215 // Key/Value map used for caching Programs. Currently the cache 216 // is never shrunk (and the GL program objects are never deleted). 217 std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>> 218 mCaches; 219 }; 220 221 } // namespace gl 222 } // namespace renderengine 223 224 ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key) 225 226 } // namespace android 227 228 #endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */ 229