/* * Copyright 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H #define SF_RENDER_ENGINE_PROGRAMCACHE_H #include #include #include #include #include #include #include namespace android { class String8; namespace renderengine { struct Description; namespace gl { class Formatter; class Program; /* * This class generates GLSL programs suitable to handle a given * Description. It's responsible for figuring out what to * generate from a Description. * It also maintains a cache of these Programs. */ class ProgramCache : public Singleton { public: /* * Key is used to retrieve a Program in the cache. * A Key is generated from a Description. */ class Key { friend class ProgramCache; typedef uint32_t key_t; key_t mKey; public: enum { BLEND_SHIFT = 0, BLEND_MASK = 1 << BLEND_SHIFT, BLEND_PREMULT = 1 << BLEND_SHIFT, BLEND_NORMAL = 0 << BLEND_SHIFT, OPACITY_SHIFT = 1, OPACITY_MASK = 1 << OPACITY_SHIFT, OPACITY_OPAQUE = 1 << OPACITY_SHIFT, OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT, ALPHA_SHIFT = 2, ALPHA_MASK = 1 << ALPHA_SHIFT, ALPHA_LT_ONE = 1 << ALPHA_SHIFT, ALPHA_EQ_ONE = 0 << ALPHA_SHIFT, TEXTURE_SHIFT = 3, TEXTURE_MASK = 3 << TEXTURE_SHIFT, TEXTURE_OFF = 0 << TEXTURE_SHIFT, TEXTURE_EXT = 1 << TEXTURE_SHIFT, TEXTURE_2D = 2 << TEXTURE_SHIFT, ROUNDED_CORNERS_SHIFT = 5, ROUNDED_CORNERS_MASK = 1 << ROUNDED_CORNERS_SHIFT, ROUNDED_CORNERS_OFF = 0 << ROUNDED_CORNERS_SHIFT, ROUNDED_CORNERS_ON = 1 << ROUNDED_CORNERS_SHIFT, INPUT_TRANSFORM_MATRIX_SHIFT = 6, INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT, INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT, OUTPUT_TRANSFORM_MATRIX_SHIFT = 7, OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT, OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT, INPUT_TF_SHIFT = 8, INPUT_TF_MASK = 3 << INPUT_TF_SHIFT, INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT, INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT, INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT, INPUT_TF_HLG = 3 << INPUT_TF_SHIFT, OUTPUT_TF_SHIFT = 10, OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT, OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT, OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT, OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, Y410_BT2020_SHIFT = 12, Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, SHADOW_SHIFT = 13, SHADOW_MASK = 1 << SHADOW_SHIFT, SHADOW_OFF = 0 << SHADOW_SHIFT, SHADOW_ON = 1 << SHADOW_SHIFT, }; inline Key() : mKey(0) {} inline Key(const Key& rhs) : mKey(rhs.mKey) {} inline Key& set(key_t mask, key_t value) { mKey = (mKey & ~mask) | value; return *this; } inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; } inline bool hasTextureCoords() const { return isTexturing() && !drawShadows(); } inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); } inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; } inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } inline bool hasRoundedCorners() const { return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON; } inline bool drawShadows() const { return (mKey & SHADOW_MASK) == SHADOW_ON; } inline bool hasInputTransformMatrix() const { return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON; } inline bool hasOutputTransformMatrix() const { return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON; } inline bool hasTransformMatrix() const { return hasInputTransformMatrix() || hasOutputTransformMatrix(); } inline int getInputTF() const { return (mKey & INPUT_TF_MASK); } inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); } // When HDR and non-HDR contents are mixed, or different types of HDR contents are // mixed, we will do a tone mapping process to tone map the input content to output // content. Currently, the following conversions handled, they are: // * SDR -> HLG // * SDR -> PQ // * HLG -> PQ inline bool needsToneMapping() const { int inputTF = getInputTF(); int outputTF = getOutputTF(); // Return false when converting from SDR to SDR. if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) { return false; } if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) { return false; } inputTF >>= Key::INPUT_TF_SHIFT; outputTF >>= Key::OUTPUT_TF_SHIFT; return inputTF != outputTF; } inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } // for use by std::unordered_map bool operator==(const Key& other) const { return mKey == other.mKey; } struct Hash { size_t operator()(const Key& key) const { return static_cast(key.mKey); } }; }; ProgramCache() = default; ~ProgramCache() = default; // Generate shaders to populate the cache void primeCache(const EGLContext context, bool useColorManagement, bool toneMapperShaderOnly); size_t getSize(const EGLContext context) { return mCaches[context].size(); } // useProgram lookup a suitable program in the cache or generates one // if none can be found. void useProgram(const EGLContext context, const Description& description); private: // compute a cache Key from a Description static Key computeKey(const Description& description); // Generate EOTF based from Key. static void generateEOTF(Formatter& fs, const Key& needs); // Generate necessary tone mapping methods for OOTF. static void generateToneMappingProcess(Formatter& fs, const Key& needs); // Generate OOTF based from Key. static void generateOOTF(Formatter& fs, const Key& needs); // Generate OETF based from Key. static void generateOETF(Formatter& fs, const Key& needs); // generates a program from the Key static std::unique_ptr generateProgram(const Key& needs); // generates the vertex shader from the Key static String8 generateVertexShader(const Key& needs); // generates the fragment shader from the Key static String8 generateFragmentShader(const Key& needs); // Key/Value map used for caching Programs. Currently the cache // is never shrunk (and the GL program objects are never deleted). std::unordered_map, Key::Hash>> mCaches; }; } // namespace gl } // namespace renderengine ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key) } // namespace android #endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */