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 "aemu/base/containers/HybridComponentManager.h" 20 #include "aemu/base/synchronization/AndroidLock.h" 21 22 #include <GLES2/gl2.h> 23 #include <memory> 24 25 template <class IndexType, bool initialIsTrue> 26 class PredicateMap { 27 public: 28 static const uint64_t kBitsPerEntry = 64; add(IndexType objId)29 void add(IndexType objId) { 30 static const uint64_t kNone = 0ULL; 31 static const uint64_t kAll = ~kNone; 32 IndexType index = objId / kBitsPerEntry; 33 if (!mStorage.get_const(index)) { 34 mStorage.add(index, initialIsTrue ? kAll : kNone); 35 } 36 } 37 remove(IndexType objId)38 void remove(IndexType objId) { 39 if (initialIsTrue) { 40 set(objId, true); 41 } else { 42 set(objId, false); 43 } 44 } 45 set(IndexType objId,bool predicate)46 void set(IndexType objId, bool predicate) { 47 IndexType index = objId / kBitsPerEntry; 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 get(IndexType objId)62 bool get(IndexType objId) const { 63 IndexType index = objId / kBitsPerEntry; 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: 74 using Storage = gfxstream::guest::HybridComponentManager<10000, IndexType, uint64_t>; 75 Storage mStorage; 76 }; 77 78 // Structures for fast validation of uniforms/attribs. 79 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 91 struct AttribIndexInfo { 92 bool validInProgram = false; 93 }; 94 95 using UniformValidationInfo = gfxstream::guest::HybridComponentManager<1000, uint32_t, UniformLocationInfo>; 96 using AttribValidationInfo = gfxstream::guest::HybridComponentManager<16, uint32_t, AttribIndexInfo>; 97 98 using LastQueryTargetInfo = gfxstream::guest::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; 108 bool boundEGLImage; 109 GLuint id; 110 }; 111 112 struct SamplerProps { 113 uint32_t refcount; 114 }; 115 116 template <class T> 117 class ScopedLockedView { 118 public: ScopedLockedView(T * info)119 ScopedLockedView(T* info) : mInfo(info) { 120 mInfo->lock(); 121 } ~ScopedLockedView()122 virtual ~ScopedLockedView() { 123 mInfo->unlock(); 124 } 125 protected: 126 T* mInfo; 127 internalInfo()128 T* internalInfo() { return mInfo; } internalInfo_const()129 const T* internalInfo_const() const { return mInfo; } 130 }; 131 132 struct RenderbufferInfo { 133 gfxstream::guest::Lock infoLock; 134 gfxstream::guest::HybridComponentManager<1000, uint32_t, std::shared_ptr<RboProps>> component; 135 lockRenderbufferInfo136 void lock() { infoLock.lock(); } unlockRenderbufferInfo137 void unlock() { infoLock.unlock(); } 138 139 class ScopedView : public ScopedLockedView<RenderbufferInfo> { 140 public: ScopedViewRenderbufferInfo141 ScopedView(RenderbufferInfo* info) : ScopedLockedView<RenderbufferInfo>(info) { } hasRboRenderbufferInfo142 bool hasRbo(GLuint id) const { 143 return nullptr != internalInfo_const()->component.get_const(id); 144 } 145 virtual ~ScopedView() = default; getRenderbufferInfo146 RboProps* get(GLuint id) { 147 auto rboPropPtr = internalInfo()->component.get(id); 148 if (!rboPropPtr) { 149 return nullptr; 150 } 151 return rboPropPtr->get(); 152 } get_or_add_shared_ptrRenderbufferInfo153 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 } get_shared_ptrRenderbufferInfo161 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; 167 } get_constRenderbufferInfo168 const RboProps* get_const(GLuint id) { 169 auto rboPropPtr = internalInfo()->component.get_const(id); 170 if (!rboPropPtr) { 171 return nullptr; 172 } 173 return rboPropPtr->get(); 174 } addFreshRenderbufferInfo175 void addFresh(GLuint id) { 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)); 185 } bindRenderbufferInfo186 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 } 192 res->previouslyBound = true; 193 return res; 194 } removeRenderbufferInfo195 void remove(GLuint id) { 196 if (id == 0) { 197 return; 198 } 199 internalInfo()->component.remove(id); 200 } 201 }; 202 }; 203 204 struct SamplerInfo { 205 gfxstream::guest::Lock infoLock; 206 gfxstream::guest::HybridComponentManager<1000, uint32_t, SamplerProps> component; 207 lockSamplerInfo208 void lock() { infoLock.lock(); } unlockSamplerInfo209 void unlock() { infoLock.unlock(); } 210 211 class ScopedView : public ScopedLockedView<SamplerInfo> { 212 public: ScopedViewSamplerInfo213 ScopedView(SamplerInfo* info) : ScopedLockedView<SamplerInfo>(info) { } samplerExistsSamplerInfo214 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; getSamplerInfo220 SamplerProps* get(GLuint id) { 221 return internalInfo()->component.get(id); 222 } get_constSamplerInfo223 const SamplerProps* get_const(GLuint id) { 224 return internalInfo_const()->component.get_const(id); 225 } addFreshSamplerInfo226 void addFresh(GLuint id) { 227 SamplerProps props; 228 props.refcount = 1; 229 internalInfo()->component.add(id, props); 230 } bindSamplerInfo231 SamplerProps* bind(GLuint id) { 232 if (!samplerExists(id)) return 0; 233 ref(id); 234 SamplerProps* res = get(id); 235 return res; 236 } refSamplerInfo237 void ref(GLuint id) { 238 SamplerProps* props = get(id); 239 if (!props) return; 240 ++props->refcount; 241 } unrefSamplerInfo242 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 254 #endif 255