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" 20 #include "android/base/synchronization/AndroidLock.h" 21 22 #include <GLES2/gl2.h> 23 24 template <class IndexType, bool initialIsTrue> 25 class PredicateMap { 26 public: 27 static const uint64_t kBitsPerEntry = 64; add(IndexType objId)28 void add(IndexType objId) { 29 static const uint64_t kNone = 0ULL; 30 static const uint64_t kAll = ~kNone; 31 IndexType index = objId / kBitsPerEntry; 32 if (!mStorage.get_const(index)) { 33 mStorage.add(index, initialIsTrue ? kAll : kNone); 34 } 35 } 36 remove(IndexType objId)37 void remove(IndexType objId) { 38 if (initialIsTrue) { 39 set(objId, true); 40 } else { 41 set(objId, false); 42 } 43 } 44 set(IndexType objId,bool predicate)45 void set(IndexType objId, bool predicate) { 46 IndexType index = objId / kBitsPerEntry; 47 48 if (!mStorage.get_const(index)) return; 49 50 uint64_t* current = mStorage.get(index); 51 52 uint64_t flag = 1ULL << (objId % kBitsPerEntry); 53 54 if (predicate) { 55 *current = *current | flag; 56 } else { 57 *current = *current & (~flag); 58 } 59 } 60 get(IndexType objId)61 bool get(IndexType objId) const { 62 IndexType index = objId / kBitsPerEntry; 63 64 const uint64_t* current = mStorage.get_const(index); 65 66 if (!current) return initialIsTrue; 67 68 uint64_t flag = 1ULL << (objId % kBitsPerEntry); 69 return (flag & (*current)) != 0; 70 } 71 72 private: 73 using Storage = android::base::HybridComponentManager<10000, IndexType, uint64_t>; 74 Storage mStorage; 75 }; 76 77 // Structures for fast validation of uniforms/attribs. 78 79 struct UniformLocationInfo { 80 bool valid = false; 81 uint32_t columns; 82 uint32_t rows; 83 bool isSampler; 84 bool isInt; 85 bool isArray; 86 bool isUnsigned; 87 bool isBool; 88 }; 89 90 struct AttribIndexInfo { 91 bool validInProgram = false; 92 }; 93 94 using UniformValidationInfo = android::base::HybridComponentManager<1000, uint32_t, UniformLocationInfo>; 95 using AttribValidationInfo = android::base::HybridComponentManager<16, uint32_t, AttribIndexInfo>; 96 97 using LastQueryTargetInfo = android::base::HybridComponentManager<1000, uint32_t, uint32_t>; 98 99 using ExistenceMap = PredicateMap<uint32_t, false>; 100 101 struct RboProps { 102 GLenum format; 103 GLsizei multisamples; 104 GLsizei width; 105 GLsizei height; 106 bool previouslyBound; 107 uint32_t refcount; 108 bool boundEGLImage; 109 }; 110 111 struct SamplerProps { 112 uint32_t refcount; 113 }; 114 115 template <class T> 116 class ScopedLockedView { 117 public: ScopedLockedView(T * info)118 ScopedLockedView(T* info) : mInfo(info) { 119 mInfo->lock(); 120 } ~ScopedLockedView()121 virtual ~ScopedLockedView() { 122 mInfo->unlock(); 123 } 124 protected: 125 T* mInfo; 126 internalInfo()127 T* internalInfo() { return mInfo; } internalInfo_const()128 const T* internalInfo_const() const { return mInfo; } 129 }; 130 131 struct RenderbufferInfo { 132 android::base::guest::Lock infoLock; 133 android::base::HybridComponentManager<1000, uint32_t, RboProps> component; 134 lockRenderbufferInfo135 void lock() { infoLock.lock(); } unlockRenderbufferInfo136 void unlock() { infoLock.unlock(); } 137 138 class ScopedView : public ScopedLockedView<RenderbufferInfo> { 139 public: ScopedViewRenderbufferInfo140 ScopedView(RenderbufferInfo* info) : ScopedLockedView<RenderbufferInfo>(info) { } hasRboRenderbufferInfo141 bool hasRbo(GLuint id) const { 142 const RboProps* info = internalInfo_const()->component.get_const(id); 143 if (!info) return false; 144 return 0 != info->refcount; 145 } 146 virtual ~ScopedView() = default; getRenderbufferInfo147 RboProps* get(GLuint id) { 148 return internalInfo()->component.get(id); 149 } get_constRenderbufferInfo150 const RboProps* get_const(GLuint id) { 151 return internalInfo_const()->component.get_const(id); 152 } addFreshRenderbufferInfo153 void addFresh(GLuint id) { 154 RboProps props; 155 props.format = GL_NONE; 156 props.multisamples = 0; 157 props.width = 0; 158 props.height = 0; 159 props.previouslyBound = false; 160 props.refcount = 1; 161 props.boundEGLImage = false; 162 internalInfo()->component.add(id, props); 163 } bindRenderbufferInfo164 RboProps* bind(GLuint id) { 165 if (!hasRbo(id)) addFresh(id); 166 ref(id); 167 RboProps* res = get(id); 168 res->previouslyBound = true; 169 return res; 170 } refRenderbufferInfo171 void ref(GLuint id) { 172 RboProps* props = get(id); 173 if (!props) return; 174 ++props->refcount; 175 } unrefRenderbufferInfo176 bool unref(GLuint id) { 177 RboProps* props = get(id); 178 if (!props) return false; 179 if (!props->refcount) return false; 180 --props->refcount; 181 bool gone = 0 == props->refcount; 182 if (gone) { 183 props->format = 0; 184 props->multisamples = 0; 185 props->width = 0; 186 props->height = 0; 187 props->previouslyBound = false; 188 props->boundEGLImage = false; 189 } 190 return gone; 191 } 192 }; 193 }; 194 195 struct SamplerInfo { 196 android::base::guest::Lock infoLock; 197 android::base::HybridComponentManager<1000, uint32_t, SamplerProps> component; 198 lockSamplerInfo199 void lock() { infoLock.lock(); } unlockSamplerInfo200 void unlock() { infoLock.unlock(); } 201 202 class ScopedView : public ScopedLockedView<SamplerInfo> { 203 public: ScopedViewSamplerInfo204 ScopedView(SamplerInfo* info) : ScopedLockedView<SamplerInfo>(info) { } samplerExistsSamplerInfo205 bool samplerExists(GLuint id) const { 206 const SamplerProps* info = internalInfo_const()->component.get_const(id); 207 if (!info) return false; 208 return 0 != info->refcount; 209 } 210 virtual ~ScopedView() = default; getSamplerInfo211 SamplerProps* get(GLuint id) { 212 return internalInfo()->component.get(id); 213 } get_constSamplerInfo214 const SamplerProps* get_const(GLuint id) { 215 return internalInfo_const()->component.get_const(id); 216 } addFreshSamplerInfo217 void addFresh(GLuint id) { 218 SamplerProps props; 219 props.refcount = 1; 220 internalInfo()->component.add(id, props); 221 } bindSamplerInfo222 SamplerProps* bind(GLuint id) { 223 if (!samplerExists(id)) return 0; 224 ref(id); 225 SamplerProps* res = get(id); 226 return res; 227 } refSamplerInfo228 void ref(GLuint id) { 229 SamplerProps* props = get(id); 230 if (!props) return; 231 ++props->refcount; 232 } unrefSamplerInfo233 bool unref(GLuint id) { 234 SamplerProps* props = get(id); 235 if (!props) return false; 236 if (!props->refcount) return false; 237 --props->refcount; 238 bool gone = 0 == props->refcount; 239 return gone; 240 } 241 }; 242 }; 243 244 245 #endif 246