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 DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT = 14, 122 DISPLAY_COLOR_TRANSFORM_MATRIX_MASK = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT, 123 DISPLAY_COLOR_TRANSFORM_MATRIX_OFF = 0 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT, 124 DISPLAY_COLOR_TRANSFORM_MATRIX_ON = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT, 125 }; 126 Key()127 inline Key() : mKey(0) {} Key(const Key & rhs)128 inline Key(const Key& rhs) : mKey(rhs.mKey) {} 129 set(key_t mask,key_t value)130 inline Key& set(key_t mask, key_t value) { 131 mKey = (mKey & ~mask) | value; 132 return *this; 133 } 134 isTexturing()135 inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } hasTextureCoords()136 inline bool hasTextureCoords() const { return isTexturing() && !drawShadows(); } getTextureTarget()137 inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } isPremultiplied()138 inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } isOpaque()139 inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } hasAlpha()140 inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } hasRoundedCorners()141 inline bool hasRoundedCorners() const { 142 return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON; 143 } drawShadows()144 inline bool drawShadows() const { return (mKey & SHADOW_MASK) == SHADOW_ON; } hasInputTransformMatrix()145 inline bool hasInputTransformMatrix() const { 146 return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; 147 } hasOutputTransformMatrix()148 inline bool hasOutputTransformMatrix() const { 149 return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; 150 } hasDisplayColorMatrix()151 inline bool hasDisplayColorMatrix() const { 152 return (mKey & DISPLAY_COLOR_TRANSFORM_MATRIX_MASK) == 153 DISPLAY_COLOR_TRANSFORM_MATRIX_ON; 154 } hasTransformMatrix()155 inline bool hasTransformMatrix() const { 156 return hasInputTransformMatrix() || hasOutputTransformMatrix(); 157 } getInputTF()158 inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } getOutputTF()159 inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } 160 161 // When HDR and non-HDR contents are mixed, or different types of HDR contents are 162 // mixed, we will do a tone mapping process to tone map the input content to output 163 // content. Currently, the following conversions handled, they are: 164 // * SDR -> HLG 165 // * SDR -> PQ 166 // * HLG -> PQ needsToneMapping()167 inline bool needsToneMapping() const { 168 int inputTF = getInputTF(); 169 int outputTF = getOutputTF(); 170 171 // Return false when converting from SDR to SDR. 172 if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { 173 return false; 174 } 175 if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { 176 return false; 177 } 178 179 inputTF >>= Key::INPUT_TF_SHIFT; 180 outputTF >>= Key::OUTPUT_TF_SHIFT; 181 return inputTF != outputTF; 182 } isY410BT2020()183 inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } 184 185 // for use by std::unordered_map 186 187 bool operator==(const Key& other) const { return mKey == other.mKey; } 188 189 struct Hash { operatorHash190 size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); } 191 }; 192 }; 193 194 ProgramCache() = default; 195 ~ProgramCache() = default; 196 197 // Generate shaders to populate the cache 198 void primeCache(const EGLContext context, bool useColorManagement, bool toneMapperShaderOnly); 199 getSize(const EGLContext context)200 size_t getSize(const EGLContext context) { return mCaches[context].size(); } 201 202 // useProgram lookup a suitable program in the cache or generates one 203 // if none can be found. 204 void useProgram(const EGLContext context, const Description& description); 205 purgeCaches()206 void purgeCaches() { mCaches.clear(); } 207 208 private: 209 // compute a cache Key from a Description 210 static Key computeKey(const Description& description); 211 // Generate EOTF based from Key. 212 static void generateEOTF(Formatter& fs, const Key& needs); 213 // Generate necessary tone mapping methods for OOTF. 214 static void generateToneMappingProcess(Formatter& fs, const Key& needs); 215 // Generate OOTF based from Key. 216 static void generateOOTF(Formatter& fs, const Key& needs); 217 // Generate OETF based from Key. 218 static void generateOETF(Formatter& fs, const Key& needs); 219 // generates a program from the Key 220 static std::unique_ptr<Program> generateProgram(const Key& needs); 221 // generates the vertex shader from the Key 222 static String8 generateVertexShader(const Key& needs); 223 // generates the fragment shader from the Key 224 static String8 generateFragmentShader(const Key& needs); 225 226 // Key/Value map used for caching Programs. Currently the cache 227 // is never shrunk (and the GL program objects are never deleted). 228 std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>> 229 mCaches; 230 }; 231 232 } // namespace gl 233 } // namespace renderengine 234 235 ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key) 236 237 } // namespace android 238 239 #endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */ 240