Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2020 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 | #ifndef _STATE_TRACKING_SUPPORT_H_ |
| 17 | #define _STATE_TRACKING_SUPPORT_H_ |
| 18 | |
| 19 | #include "android/base/containers/HybridComponentManager.h" |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 20 | #include "android/base/synchronization/AndroidLock.h" |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 21 | |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 22 | #include <GLES2/gl2.h> |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 23 | #include <memory> |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 24 | |
| 25 | template <class IndexType, bool initialIsTrue> |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 26 | class PredicateMap { |
| 27 | public: |
| 28 | static const uint64_t kBitsPerEntry = 64; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 29 | void add(IndexType objId) { |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 30 | static const uint64_t kNone = 0ULL; |
| 31 | static const uint64_t kAll = ~kNone; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 32 | IndexType index = objId / kBitsPerEntry; |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 33 | if (!mStorage.get_const(index)) { |
| 34 | mStorage.add(index, initialIsTrue ? kAll : kNone); |
| 35 | } |
| 36 | } |
| 37 | |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 38 | void remove(IndexType objId) { |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 39 | if (initialIsTrue) { |
| 40 | set(objId, true); |
| 41 | } else { |
| 42 | set(objId, false); |
| 43 | } |
| 44 | } |
| 45 | |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 46 | void set(IndexType objId, bool predicate) { |
| 47 | IndexType index = objId / kBitsPerEntry; |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 48 | |
| 49 | if (!mStorage.get_const(index)) return; |
| 50 | |
| 51 | uint64_t* current = mStorage.get(index); |
| 52 | |
| 53 | uint64_t flag = 1ULL << (objId % kBitsPerEntry); |
| 54 | |
| 55 | if (predicate) { |
| 56 | *current = *current | flag; |
| 57 | } else { |
| 58 | *current = *current & (~flag); |
| 59 | } |
| 60 | } |
| 61 | |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 62 | bool get(IndexType objId) const { |
| 63 | IndexType index = objId / kBitsPerEntry; |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 64 | |
| 65 | const uint64_t* current = mStorage.get_const(index); |
| 66 | |
| 67 | if (!current) return initialIsTrue; |
| 68 | |
| 69 | uint64_t flag = 1ULL << (objId % kBitsPerEntry); |
| 70 | return (flag & (*current)) != 0; |
| 71 | } |
| 72 | |
| 73 | private: |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 74 | using Storage = android::base::HybridComponentManager<10000, IndexType, uint64_t>; |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 75 | Storage mStorage; |
| 76 | }; |
| 77 | |
Lingfeng Yang | 62054e9 | 2020-09-16 18:55:01 -0700 | [diff] [blame] | 78 | // Structures for fast validation of uniforms/attribs. |
| 79 | |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 80 | struct UniformLocationInfo { |
| 81 | bool valid = false; |
| 82 | uint32_t columns; |
| 83 | uint32_t rows; |
| 84 | bool isSampler; |
| 85 | bool isInt; |
| 86 | bool isArray; |
| 87 | bool isUnsigned; |
| 88 | bool isBool; |
| 89 | }; |
| 90 | |
Lingfeng Yang | 62054e9 | 2020-09-16 18:55:01 -0700 | [diff] [blame] | 91 | struct AttribIndexInfo { |
| 92 | bool validInProgram = false; |
| 93 | }; |
| 94 | |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 95 | using UniformValidationInfo = android::base::HybridComponentManager<1000, uint32_t, UniformLocationInfo>; |
Lingfeng Yang | 62054e9 | 2020-09-16 18:55:01 -0700 | [diff] [blame] | 96 | using AttribValidationInfo = android::base::HybridComponentManager<16, uint32_t, AttribIndexInfo>; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 97 | |
| 98 | using LastQueryTargetInfo = android::base::HybridComponentManager<1000, uint32_t, uint32_t>; |
| 99 | |
| 100 | using ExistenceMap = PredicateMap<uint32_t, false>; |
| 101 | |
| 102 | struct RboProps { |
| 103 | GLenum format; |
| 104 | GLsizei multisamples; |
| 105 | GLsizei width; |
| 106 | GLsizei height; |
| 107 | bool previouslyBound; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 108 | bool boundEGLImage; |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 109 | GLuint id; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 110 | }; |
| 111 | |
| 112 | struct SamplerProps { |
| 113 | uint32_t refcount; |
| 114 | }; |
| 115 | |
| 116 | template <class T> |
| 117 | class ScopedLockedView { |
| 118 | public: |
| 119 | ScopedLockedView(T* info) : mInfo(info) { |
| 120 | mInfo->lock(); |
| 121 | } |
| 122 | virtual ~ScopedLockedView() { |
| 123 | mInfo->unlock(); |
| 124 | } |
| 125 | protected: |
| 126 | T* mInfo; |
| 127 | |
| 128 | T* internalInfo() { return mInfo; } |
| 129 | const T* internalInfo_const() const { return mInfo; } |
| 130 | }; |
| 131 | |
| 132 | struct RenderbufferInfo { |
| 133 | android::base::guest::Lock infoLock; |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 134 | android::base::HybridComponentManager<1000, uint32_t, std::shared_ptr<RboProps>> component; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 135 | |
| 136 | void lock() { infoLock.lock(); } |
| 137 | void unlock() { infoLock.unlock(); } |
| 138 | |
| 139 | class ScopedView : public ScopedLockedView<RenderbufferInfo> { |
| 140 | public: |
| 141 | ScopedView(RenderbufferInfo* info) : ScopedLockedView<RenderbufferInfo>(info) { } |
| 142 | bool hasRbo(GLuint id) const { |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 143 | return nullptr != internalInfo_const()->component.get_const(id); |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 144 | } |
| 145 | virtual ~ScopedView() = default; |
| 146 | RboProps* get(GLuint id) { |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 147 | auto rboPropPtr = internalInfo()->component.get(id); |
| 148 | if (!rboPropPtr) { |
| 149 | return nullptr; |
| 150 | } |
| 151 | return rboPropPtr->get(); |
| 152 | } |
| 153 | std::shared_ptr<RboProps> get_or_add_shared_ptr(GLuint id) { |
| 154 | auto rboPropPtr = internalInfo()->component.get(id); |
| 155 | if (!rboPropPtr) { |
| 156 | addFresh(id); |
| 157 | rboPropPtr = internalInfo()->component.get(id); |
| 158 | } |
| 159 | return *rboPropPtr; |
| 160 | } |
| 161 | std::shared_ptr<RboProps> get_shared_ptr(GLuint id) { |
| 162 | auto rboPropPtr = internalInfo()->component.get(id); |
| 163 | if (!internalInfo()->component.get(id)) { |
| 164 | return nullptr; |
| 165 | } |
| 166 | return *rboPropPtr; |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 167 | } |
| 168 | const RboProps* get_const(GLuint id) { |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 169 | auto rboPropPtr = internalInfo()->component.get_const(id); |
| 170 | if (!rboPropPtr) { |
| 171 | return nullptr; |
| 172 | } |
| 173 | return rboPropPtr->get(); |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 174 | } |
| 175 | void addFresh(GLuint id) { |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 176 | std::shared_ptr<RboProps> props(new RboProps()); |
| 177 | props->format = GL_NONE; |
| 178 | props->multisamples = 0; |
| 179 | props->width = 0; |
| 180 | props->height = 0; |
| 181 | props->previouslyBound = false; |
| 182 | props->boundEGLImage = false; |
| 183 | props->id = id; |
| 184 | internalInfo()->component.add(id, std::move(props)); |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 185 | } |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 186 | std::shared_ptr<RboProps> bind(GLuint id) { |
| 187 | auto res = get_shared_ptr(id); |
| 188 | if (!res) { |
| 189 | addFresh(id); |
| 190 | res = get_shared_ptr(id); |
| 191 | } |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 192 | res->previouslyBound = true; |
| 193 | return res; |
| 194 | } |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 195 | void remove(GLuint id) { |
Yahan Zhou | 8764f2c | 2022-04-25 13:02:04 -0700 | [diff] [blame] | 196 | if (id == 0) { |
| 197 | return; |
| 198 | } |
Yahan Zhou | e9be354 | 2022-05-11 18:47:32 -0700 | [diff] [blame] | 199 | internalInfo()->component.remove(id); |
Lingfeng Yang | ed069c5 | 2020-09-03 19:11:02 -0700 | [diff] [blame] | 200 | } |
| 201 | }; |
| 202 | }; |
| 203 | |
| 204 | struct SamplerInfo { |
| 205 | android::base::guest::Lock infoLock; |
| 206 | android::base::HybridComponentManager<1000, uint32_t, SamplerProps> component; |
| 207 | |
| 208 | void lock() { infoLock.lock(); } |
| 209 | void unlock() { infoLock.unlock(); } |
| 210 | |
| 211 | class ScopedView : public ScopedLockedView<SamplerInfo> { |
| 212 | public: |
| 213 | ScopedView(SamplerInfo* info) : ScopedLockedView<SamplerInfo>(info) { } |
| 214 | bool samplerExists(GLuint id) const { |
| 215 | const SamplerProps* info = internalInfo_const()->component.get_const(id); |
| 216 | if (!info) return false; |
| 217 | return 0 != info->refcount; |
| 218 | } |
| 219 | virtual ~ScopedView() = default; |
| 220 | SamplerProps* get(GLuint id) { |
| 221 | return internalInfo()->component.get(id); |
| 222 | } |
| 223 | const SamplerProps* get_const(GLuint id) { |
| 224 | return internalInfo_const()->component.get_const(id); |
| 225 | } |
| 226 | void addFresh(GLuint id) { |
| 227 | SamplerProps props; |
| 228 | props.refcount = 1; |
| 229 | internalInfo()->component.add(id, props); |
| 230 | } |
| 231 | SamplerProps* bind(GLuint id) { |
| 232 | if (!samplerExists(id)) return 0; |
| 233 | ref(id); |
| 234 | SamplerProps* res = get(id); |
| 235 | return res; |
| 236 | } |
| 237 | void ref(GLuint id) { |
| 238 | SamplerProps* props = get(id); |
| 239 | if (!props) return; |
| 240 | ++props->refcount; |
| 241 | } |
| 242 | bool unref(GLuint id) { |
| 243 | SamplerProps* props = get(id); |
| 244 | if (!props) return false; |
| 245 | if (!props->refcount) return false; |
| 246 | --props->refcount; |
| 247 | bool gone = 0 == props->refcount; |
| 248 | return gone; |
| 249 | } |
| 250 | }; |
| 251 | }; |
| 252 | |
| 253 | |
Lingfeng Yang | 7d677c5 | 2020-08-19 09:06:15 -0700 | [diff] [blame] | 254 | #endif |