blob: 653aaf0f6c86f6e74d5ac9903cff1b12e332fbb1 [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
Mathias Agopian3f844832013-08-07 21:24:32 -070023#include <GLES2/gl2.h>
Peiyong Lin833074a2018-08-28 11:53:54 -070024#include <renderengine/private/Description.h>
Chia-I Wub027f802017-11-29 14:00:52 -080025#include <utils/Singleton.h>
Mathias Agopian3f844832013-08-07 21:24:32 -070026#include <utils/TypeHelpers.h>
27
Mathias Agopian3f844832013-08-07 21:24:32 -070028namespace android {
29
Peiyong Lin833074a2018-08-28 11:53:54 -070030class String8;
31
32namespace renderengine {
33
Peiyong Lin70b26ce2018-09-18 19:02:39 -070034struct Description;
Peiyong Lin833074a2018-08-28 11:53:54 -070035
36namespace gl {
37
Peiyong Lin2542cb02018-04-30 17:29:53 -070038class Formatter;
Mathias Agopian3f844832013-08-07 21:24:32 -070039class Program;
Mathias Agopian3f844832013-08-07 21:24:32 -070040
41/*
42 * This class generates GLSL programs suitable to handle a given
43 * Description. It's responsible for figuring out what to
44 * generate from a Description.
45 * It also maintains a cache of these Programs.
46 */
47class ProgramCache : public Singleton<ProgramCache> {
48public:
49 /*
50 * Key is used to retrieve a Program in the cache.
51 * A Key is generated from a Description.
52 */
53 class Key {
54 friend class ProgramCache;
55 typedef uint32_t key_t;
56 key_t mKey;
Chia-I Wub027f802017-11-29 14:00:52 -080057
Mathias Agopian3f844832013-08-07 21:24:32 -070058 public:
59 enum {
Chia-I Wu7e65bc02018-01-11 14:31:38 -080060 BLEND_SHIFT = 0,
61 BLEND_MASK = 1 << BLEND_SHIFT,
62 BLEND_PREMULT = 1 << BLEND_SHIFT,
63 BLEND_NORMAL = 0 << BLEND_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070064
Chia-I Wu7e65bc02018-01-11 14:31:38 -080065 OPACITY_SHIFT = 1,
66 OPACITY_MASK = 1 << OPACITY_SHIFT,
67 OPACITY_OPAQUE = 1 << OPACITY_SHIFT,
68 OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070069
Chia-I Wu7e65bc02018-01-11 14:31:38 -080070 ALPHA_SHIFT = 2,
71 ALPHA_MASK = 1 << ALPHA_SHIFT,
72 ALPHA_LT_ONE = 1 << ALPHA_SHIFT,
73 ALPHA_EQ_ONE = 0 << ALPHA_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070074
Chia-I Wu7e65bc02018-01-11 14:31:38 -080075 TEXTURE_SHIFT = 3,
76 TEXTURE_MASK = 3 << TEXTURE_SHIFT,
77 TEXTURE_OFF = 0 << TEXTURE_SHIFT,
78 TEXTURE_EXT = 1 << TEXTURE_SHIFT,
79 TEXTURE_2D = 2 << TEXTURE_SHIFT,
Mathias Agopianff2ed702013-09-01 21:36:12 -070080
Lucas Dupin1b6531c2018-07-05 17:18:21 -070081 ROUNDED_CORNERS_SHIFT = 5,
82 ROUNDED_CORNERS_MASK = 1 << ROUNDED_CORNERS_SHIFT,
83 ROUNDED_CORNERS_OFF = 0 << ROUNDED_CORNERS_SHIFT,
84 ROUNDED_CORNERS_ON = 1 << ROUNDED_CORNERS_SHIFT,
85
86 INPUT_TRANSFORM_MATRIX_SHIFT = 6,
Peiyong Lina296b0c2018-04-30 16:55:29 -070087 INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
88 INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT,
89 INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
Romain Guy88d37dd2017-05-26 17:57:05 -070090
Lucas Dupin1b6531c2018-07-05 17:18:21 -070091 OUTPUT_TRANSFORM_MATRIX_SHIFT = 7,
Peiyong Lina296b0c2018-04-30 16:55:29 -070092 OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
93 OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
94 OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
95
Lucas Dupin1b6531c2018-07-05 17:18:21 -070096 INPUT_TF_SHIFT = 8,
Chia-I Wu7e65bc02018-01-11 14:31:38 -080097 INPUT_TF_MASK = 3 << INPUT_TF_SHIFT,
98 INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
99 INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800100 INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
Peiyong Lina3fb7d62018-04-11 17:41:47 -0700101 INPUT_TF_HLG = 3 << INPUT_TF_SHIFT,
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800102
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700103 OUTPUT_TF_SHIFT = 10,
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800104 OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
105 OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
106 OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800107 OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
Peiyong Lina3fb7d62018-04-11 17:41:47 -0700108 OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800109
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700110 Y410_BT2020_SHIFT = 12,
Chia-I Wu131d3762018-01-11 14:35:27 -0800111 Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT,
112 Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT,
113 Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -0700114 };
115
Chia-I Wub027f802017-11-29 14:00:52 -0800116 inline Key() : mKey(0) {}
117 inline Key(const Key& rhs) : mKey(rhs.mKey) {}
Mathias Agopian3f844832013-08-07 21:24:32 -0700118
119 inline Key& set(key_t mask, key_t value) {
120 mKey = (mKey & ~mask) | value;
121 return *this;
122 }
123
Chia-I Wub027f802017-11-29 14:00:52 -0800124 inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
125 inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
126 inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
127 inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
128 inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700129 inline bool hasRoundedCorners() const {
130 return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON;
131 }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700132 inline bool hasInputTransformMatrix() const {
133 return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON;
134 }
135 inline bool hasOutputTransformMatrix() const {
136 return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
137 }
138 inline bool hasTransformMatrix() const {
139 return hasInputTransformMatrix() || hasOutputTransformMatrix();
140 }
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800141 inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
142 inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
Peiyong Lin53f320e2018-04-23 17:31:06 -0700143
144 // When HDR and non-HDR contents are mixed, or different types of HDR contents are
145 // mixed, we will do a tone mapping process to tone map the input content to output
146 // content. Currently, the following conversions handled, they are:
147 // * SDR -> HLG
148 // * SDR -> PQ
149 // * HLG -> PQ
150 inline bool needsToneMapping() const {
151 int inputTF = getInputTF();
152 int outputTF = getOutputTF();
153
154 // Return false when converting from SDR to SDR.
155 if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
156 return false;
157 }
158 if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
159 return false;
160 }
161
162 inputTF >>= Key::INPUT_TF_SHIFT;
163 outputTF >>= Key::OUTPUT_TF_SHIFT;
164 return inputTF != outputTF;
165 }
Chia-I Wu131d3762018-01-11 14:35:27 -0800166 inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
Mathias Agopian3f844832013-08-07 21:24:32 -0700167
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700168 // for use by std::unordered_map
169
Peiyong Lin46080ef2018-10-26 18:43:14 -0700170 bool operator==(const Key& other) const { return mKey == other.mKey; }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700171
172 struct Hash {
Peiyong Lin46080ef2018-10-26 18:43:14 -0700173 size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700174 };
Mathias Agopian3f844832013-08-07 21:24:32 -0700175 };
176
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700177 ProgramCache() = default;
178 ~ProgramCache() = default;
Mathias Agopian3f844832013-08-07 21:24:32 -0700179
Chia-I Wu93e14df2018-06-04 10:10:17 -0700180 // Generate shaders to populate the cache
Peiyong Lin13effd12018-07-24 17:01:47 -0700181 void primeCache(bool useColorManagement);
Chia-I Wu93e14df2018-06-04 10:10:17 -0700182
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700183 size_t getSize() const { return mCache.size(); }
184
Mathias Agopian3f844832013-08-07 21:24:32 -0700185 // useProgram lookup a suitable program in the cache or generates one
186 // if none can be found.
187 void useProgram(const Description& description);
188
189private:
Mathias Agopian3f844832013-08-07 21:24:32 -0700190 // compute a cache Key from a Description
191 static Key computeKey(const Description& description);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700192 // Generate EOTF based from Key.
193 static void generateEOTF(Formatter& fs, const Key& needs);
Peiyong Lin53f320e2018-04-23 17:31:06 -0700194 // Generate necessary tone mapping methods for OOTF.
195 static void generateToneMappingProcess(Formatter& fs, const Key& needs);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700196 // Generate OOTF based from Key.
197 static void generateOOTF(Formatter& fs, const Key& needs);
198 // Generate OETF based from Key.
199 static void generateOETF(Formatter& fs, const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700200 // generates a program from the Key
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700201 static std::unique_ptr<Program> generateProgram(const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700202 // generates the vertex shader from the Key
203 static String8 generateVertexShader(const Key& needs);
204 // generates the fragment shader from the Key
205 static String8 generateFragmentShader(const Key& needs);
206
207 // Key/Value map used for caching Programs. Currently the cache
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700208 // is never shrunk (and the GL program objects are never deleted).
209 std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash> mCache;
Mathias Agopian3f844832013-08-07 21:24:32 -0700210};
211
Peiyong Lin46080ef2018-10-26 18:43:14 -0700212} // namespace gl
213} // namespace renderengine
Mathias Agopian3f844832013-08-07 21:24:32 -0700214
Peiyong Lin833074a2018-08-28 11:53:54 -0700215ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key)
216
Peiyong Lin46080ef2018-10-26 18:43:14 -0700217} // namespace android
Mathias Agopian3f844832013-08-07 21:24:32 -0700218
219#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */