blob: 400ad74fca4c4710f046dfb0b389450bd1c6bb7c [file] [log] [blame]
Mathias Agopian3f844832013-08-07 21:24:32 -07001/*
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
Chia-I Wud3b13cb2018-09-13 13:31:26 -070020#include <memory>
Chia-I Wu56d7b0a2018-10-01 15:13:11 -070021#include <unordered_map>
22
Peiyong Linfb530cf2018-12-15 05:07:38 +000023#include <EGL/egl.h>
Mathias Agopian3f844832013-08-07 21:24:32 -070024#include <GLES2/gl2.h>
Peiyong Lin833074a2018-08-28 11:53:54 -070025#include <renderengine/private/Description.h>
Chia-I Wub027f802017-11-29 14:00:52 -080026#include <utils/Singleton.h>
Mathias Agopian3f844832013-08-07 21:24:32 -070027#include <utils/TypeHelpers.h>
28
Mathias Agopian3f844832013-08-07 21:24:32 -070029namespace android {
30
Peiyong Lin833074a2018-08-28 11:53:54 -070031class String8;
32
33namespace renderengine {
34
Peiyong Lin70b26ce2018-09-18 19:02:39 -070035struct Description;
Peiyong Lin833074a2018-08-28 11:53:54 -070036
37namespace gl {
38
Peiyong Lin2542cb02018-04-30 17:29:53 -070039class Formatter;
Mathias Agopian3f844832013-08-07 21:24:32 -070040class Program;
Mathias Agopian3f844832013-08-07 21:24:32 -070041
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 */
48class ProgramCache : public Singleton<ProgramCache> {
49public:
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;
Chia-I Wub027f802017-11-29 14:00:52 -080058
Mathias Agopian3f844832013-08-07 21:24:32 -070059 public:
60 enum {
Chia-I Wu7e65bc02018-01-11 14:31:38 -080061 BLEND_SHIFT = 0,
62 BLEND_MASK = 1 << BLEND_SHIFT,
63 BLEND_PREMULT = 1 << BLEND_SHIFT,
64 BLEND_NORMAL = 0 << BLEND_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070065
Chia-I Wu7e65bc02018-01-11 14:31:38 -080066 OPACITY_SHIFT = 1,
67 OPACITY_MASK = 1 << OPACITY_SHIFT,
68 OPACITY_OPAQUE = 1 << OPACITY_SHIFT,
69 OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070070
Chia-I Wu7e65bc02018-01-11 14:31:38 -080071 ALPHA_SHIFT = 2,
72 ALPHA_MASK = 1 << ALPHA_SHIFT,
73 ALPHA_LT_ONE = 1 << ALPHA_SHIFT,
74 ALPHA_EQ_ONE = 0 << ALPHA_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070075
Chia-I Wu7e65bc02018-01-11 14:31:38 -080076 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,
Mathias Agopianff2ed702013-09-01 21:36:12 -070081
Lucas Dupin1b6531c2018-07-05 17:18:21 -070082 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,
Peiyong Lina296b0c2018-04-30 16:55:29 -070088 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,
Romain Guy88d37dd2017-05-26 17:57:05 -070091
Lucas Dupin1b6531c2018-07-05 17:18:21 -070092 OUTPUT_TRANSFORM_MATRIX_SHIFT = 7,
Peiyong Lina296b0c2018-04-30 16:55:29 -070093 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
Lucas Dupin1b6531c2018-07-05 17:18:21 -070097 INPUT_TF_SHIFT = 8,
Chia-I Wu7e65bc02018-01-11 14:31:38 -080098 INPUT_TF_MASK = 3 << INPUT_TF_SHIFT,
99 INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
100 INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800101 INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
Peiyong Lina3fb7d62018-04-11 17:41:47 -0700102 INPUT_TF_HLG = 3 << INPUT_TF_SHIFT,
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800103
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700104 OUTPUT_TF_SHIFT = 10,
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800105 OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
106 OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
107 OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800108 OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
Peiyong Lina3fb7d62018-04-11 17:41:47 -0700109 OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800110
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700111 Y410_BT2020_SHIFT = 12,
Chia-I Wu131d3762018-01-11 14:35:27 -0800112 Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT,
113 Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT,
114 Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -0700115 };
116
Chia-I Wub027f802017-11-29 14:00:52 -0800117 inline Key() : mKey(0) {}
118 inline Key(const Key& rhs) : mKey(rhs.mKey) {}
Mathias Agopian3f844832013-08-07 21:24:32 -0700119
120 inline Key& set(key_t mask, key_t value) {
121 mKey = (mKey & ~mask) | value;
122 return *this;
123 }
124
Chia-I Wub027f802017-11-29 14:00:52 -0800125 inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
126 inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
127 inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
128 inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
129 inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700130 inline bool hasRoundedCorners() const {
131 return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON;
132 }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700133 inline bool hasInputTransformMatrix() const {
134 return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON;
135 }
136 inline bool hasOutputTransformMatrix() const {
137 return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
138 }
139 inline bool hasTransformMatrix() const {
140 return hasInputTransformMatrix() || hasOutputTransformMatrix();
141 }
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800142 inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
143 inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
Peiyong Lin53f320e2018-04-23 17:31:06 -0700144
145 // When HDR and non-HDR contents are mixed, or different types of HDR contents are
146 // mixed, we will do a tone mapping process to tone map the input content to output
147 // content. Currently, the following conversions handled, they are:
148 // * SDR -> HLG
149 // * SDR -> PQ
150 // * HLG -> PQ
151 inline bool needsToneMapping() const {
152 int inputTF = getInputTF();
153 int outputTF = getOutputTF();
154
155 // Return false when converting from SDR to SDR.
156 if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
157 return false;
158 }
159 if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
160 return false;
161 }
162
163 inputTF >>= Key::INPUT_TF_SHIFT;
164 outputTF >>= Key::OUTPUT_TF_SHIFT;
165 return inputTF != outputTF;
166 }
Chia-I Wu131d3762018-01-11 14:35:27 -0800167 inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
Mathias Agopian3f844832013-08-07 21:24:32 -0700168
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700169 // for use by std::unordered_map
170
Peiyong Lin46080ef2018-10-26 18:43:14 -0700171 bool operator==(const Key& other) const { return mKey == other.mKey; }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700172
173 struct Hash {
Peiyong Lin46080ef2018-10-26 18:43:14 -0700174 size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700175 };
Mathias Agopian3f844832013-08-07 21:24:32 -0700176 };
177
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700178 ProgramCache() = default;
179 ~ProgramCache() = default;
Mathias Agopian3f844832013-08-07 21:24:32 -0700180
Chia-I Wu93e14df2018-06-04 10:10:17 -0700181 // Generate shaders to populate the cache
Peiyong Linfb530cf2018-12-15 05:07:38 +0000182 void primeCache(const EGLContext context, bool useColorManagement);
Chia-I Wu93e14df2018-06-04 10:10:17 -0700183
Peiyong Linfb530cf2018-12-15 05:07:38 +0000184 size_t getSize(const EGLContext context) { return mCaches[context].size(); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700185
Mathias Agopian3f844832013-08-07 21:24:32 -0700186 // useProgram lookup a suitable program in the cache or generates one
187 // if none can be found.
Peiyong Linfb530cf2018-12-15 05:07:38 +0000188 void useProgram(const EGLContext context, const Description& description);
Mathias Agopian3f844832013-08-07 21:24:32 -0700189
190private:
Mathias Agopian3f844832013-08-07 21:24:32 -0700191 // compute a cache Key from a Description
192 static Key computeKey(const Description& description);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700193 // Generate EOTF based from Key.
194 static void generateEOTF(Formatter& fs, const Key& needs);
Peiyong Lin53f320e2018-04-23 17:31:06 -0700195 // Generate necessary tone mapping methods for OOTF.
196 static void generateToneMappingProcess(Formatter& fs, const Key& needs);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700197 // Generate OOTF based from Key.
198 static void generateOOTF(Formatter& fs, const Key& needs);
199 // Generate OETF based from Key.
200 static void generateOETF(Formatter& fs, const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700201 // generates a program from the Key
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700202 static std::unique_ptr<Program> generateProgram(const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700203 // generates the vertex shader from the Key
204 static String8 generateVertexShader(const Key& needs);
205 // generates the fragment shader from the Key
206 static String8 generateFragmentShader(const Key& needs);
207
208 // Key/Value map used for caching Programs. Currently the cache
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700209 // is never shrunk (and the GL program objects are never deleted).
Peiyong Linfb530cf2018-12-15 05:07:38 +0000210 std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>>
211 mCaches;
Mathias Agopian3f844832013-08-07 21:24:32 -0700212};
213
Peiyong Lin46080ef2018-10-26 18:43:14 -0700214} // namespace gl
215} // namespace renderengine
Mathias Agopian3f844832013-08-07 21:24:32 -0700216
Peiyong Lin833074a2018-08-28 11:53:54 -0700217ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key)
218
Peiyong Lin46080ef2018-10-26 18:43:14 -0700219} // namespace android
Mathias Agopian3f844832013-08-07 21:24:32 -0700220
221#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */