1 /* 2 * Copyright (C) 2016 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 _OBJECT_NAME_MANAGER_H 17 #define _OBJECT_NAME_MANAGER_H 18 19 #include "aemu/base/synchronization/Lock.h" 20 #include "aemu/base/files/Stream.h" 21 #include "GLcommon/NamedObject.h" 22 #include "GLcommon/ObjectData.h" 23 24 #include <atomic> 25 #include <GLES/gl.h> 26 #include <unordered_map> 27 #include <unordered_set> 28 #include <memory> 29 30 enum LoadShaderOrProgram { 31 LOAD_SHADER, 32 LOAD_PROGRAM 33 }; 34 35 class GlobalNameSpace; 36 class NameSpace; 37 38 // 39 // class ShareGroup - 40 // That class manages objects of one "local" context share group, typically 41 // there will be one inctance of ShareGroup for each user OpenGL context 42 // unless the user context share with another user context. In that case they 43 // both will share the same ShareGroup instance. 44 // calls into that class gets serialized through a lock so it is thread safe. 45 // 46 class ShareGroup 47 { 48 friend class ObjectNameManager; 49 public: 50 ~ShareGroup(); 51 52 // 53 // genName - generates new object name and returns its name value. 54 // if genLocal is false, p_localName will be used as the name. 55 // This function also generates a "global" name for the object 56 // which can be queried using the getGlobalName function. 57 ObjectLocalName genName(GenNameInfo genNameInfo, ObjectLocalName p_localName = 0, bool genLocal= false); 58 // overload for generating non-shader object 59 ObjectLocalName genName(NamedObjectType namedObjectType, ObjectLocalName p_localName = 0, bool genLocal= false); 60 // overload for generating shader / program object 61 ObjectLocalName genName(ShaderProgramType shaderProgramType, ObjectLocalName p_localName = 0, bool genLocal= false, GLuint existingGlobal = 0); 62 63 // 64 // getGlobalName - retrieves the "global" name of an object or 0 if the 65 // object does not exist. 66 // 67 unsigned int getGlobalName(NamedObjectType p_type, ObjectLocalName p_localName); 68 69 // 70 // getLocalName - retrieves the "local" name of an object or 0 if the 71 // object does not exist. 72 // 73 ObjectLocalName getLocalName(NamedObjectType p_type, unsigned int p_globalName); 74 75 // 76 // getNamedObject - returns the smart pointer of an object or null if the 77 // object does not exist. 78 NamedObjectPtr getNamedObject(NamedObjectType p_type, ObjectLocalName p_localName); 79 80 // 81 // deleteName - deletes and object from the namespace as well as its 82 // global name from the global name space. 83 // 84 void deleteName(NamedObjectType p_type, ObjectLocalName p_localName); 85 86 // 87 // replaceGlobalName - replaces an object to map to an existing global 88 // named object. (used when creating EGLImage siblings) 89 // 90 void replaceGlobalObject(NamedObjectType p_type, ObjectLocalName p_localName, NamedObjectPtr p_globalObject); 91 92 // 93 // isObject - returns true if the named object exist. 94 // 95 bool isObject(NamedObjectType p_type, ObjectLocalName p_localName); 96 97 // 98 // Assign object global data to a names object 99 // 100 void setObjectData(NamedObjectType p_type, ObjectLocalName p_localName, 101 ObjectDataPtr data); 102 103 // 104 // If the object doesn't exist, create it with that name 105 // 106 unsigned int ensureObjectOnBind(NamedObjectType p_type, ObjectLocalName p_localName); 107 108 // 109 // Retrieve object global data 110 // 111 ObjectData* getObjectData(NamedObjectType p_type, ObjectLocalName p_localName); 112 ObjectDataPtr getObjectDataPtr(NamedObjectType p_type, ObjectLocalName p_localName); getId()113 uint64_t getId() const {return m_sharedGroupID;} 114 void preSave(GlobalNameSpace *globalNameSpace); 115 void onSave(android::base::Stream* stream); 116 void postSave(android::base::Stream* stream); 117 // postLoadRestore() restores resources on hardware GPU 118 void postLoadRestore(); 119 bool needRestore(); 120 private: 121 explicit ShareGroup(GlobalNameSpace *globalNameSpace, 122 uint64_t sharedGroupID, 123 android::base::Stream* stream, 124 const ObjectData::loadObject_t& loadObject); 125 126 void lockObjectData(); 127 void unlockObjectData(); 128 void setObjectDataLocked(NamedObjectType p_type, 129 ObjectLocalName p_localName, ObjectDataPtr&& data); 130 // 131 // sets an object to map to an existing global object. 132 // 133 void setGlobalObject(NamedObjectType p_type, ObjectLocalName p_localName, 134 NamedObjectPtr p_namedObject); 135 136 // A RAII autolock class for the objectData spinlock. 137 struct ObjectDataAutoLock; 138 139 private: 140 const ObjectDataPtr& getObjectDataPtrNoLock(NamedObjectType p_type, 141 ObjectLocalName p_localName); 142 143 android::base::Lock m_namespaceLock; 144 android::base::Lock m_restoreLock; 145 NameSpace* m_nameSpace[static_cast<int>(NamedObjectType::NUM_OBJECT_TYPES)]; 146 147 // |m_objectsData| has no measured data races, so replace heavyweight mutex 148 // with a simple spinlock - just in case if there's some missed 149 // multi-threaded access path. 150 // TODO(zyy@): Create a common spinlock class. 151 std::atomic_flag m_objectsDataLock = ATOMIC_FLAG_INIT; 152 // The ID of this shared group 153 // It is unique within its ObjectNameManager 154 uint64_t m_sharedGroupID; 155 enum {PreSaved, Saved, Empty} m_saveStage = Empty; 156 bool m_needLoadRestore = false; 157 }; 158 159 typedef std::shared_ptr<ShareGroup> ShareGroupPtr; 160 // TODO: refactor ShareGroupsMap so that it is indexed by share group id 161 typedef std::unordered_map<void*, ShareGroupPtr> ShareGroupsMap; 162 163 // 164 // ObjectNameManager - 165 // This class manages the set of all ShareGroups instances, 166 // each ShareGroup instance can be accessed through one or more 'groupName' 167 // values. the type of 'groupName' is void *, the intent is that the EGL 168 // layer will use the user context handle as the name for its ShareGroup 169 // object. Multiple names can be attached to a ShareGroup object to support 170 // user context sharing. 171 // 172 class ObjectNameManager 173 { 174 public: 175 explicit ObjectNameManager(GlobalNameSpace *globalNameSpace); 176 177 // 178 // createShareGroup - create a new ShareGroup object and attach it with 179 // the "name" specified by p_groupName. 180 // sharedGroupID : the ID of the shared group. While loading from a 181 // snapshot, please use the ID from the snapshot file. 182 // In all other situations, use 0 to auto-generate a 183 // new ID. 184 185 ShareGroupPtr createShareGroup(void *p_groupName, uint64_t sharedGroupID, 186 android::base::Stream* stream, const ObjectData::loadObject_t& loadObject); 187 188 // 189 // attachShareGroup - find the ShareGroup object attached to the ID 190 // specified in p_existingGroupID and attach p_groupName to the same 191 // ShareGroup instance. 192 // 193 ShareGroupPtr attachShareGroup(void *p_groupName, void *p_existingGroupName); 194 ShareGroupPtr attachOrCreateShareGroup(void *p_groupName, 195 uint64_t p_existingGroupID, android::base::Stream* stream, 196 const ObjectData::loadObject_t& loadObject); 197 198 // 199 // getShareGroup - retreive a ShareGroup object based on its "name" 200 // 201 ShareGroupPtr getShareGroup(void *p_groupName); 202 203 // 204 // deleteShareGroup - deletes the attachment of the p_groupName to its 205 // attached ShareGroup. When the last name of ShareGroup is 206 // deleted the ShareGroup object is destroyed. 207 // 208 void deleteShareGroup(void *p_groupName); 209 210 // 211 // getGlobalContext() - this function returns a name of an existing 212 // ShareGroup. The intent is that the EGL layer will 213 // use that function to get the GL context which each 214 // new context needs to share with. 215 // 216 void *getGlobalContext(); 217 void preSave(); 218 private: 219 // TODO: refactor share group map so that it is indexed by share group ID 220 ShareGroupsMap m_groups; 221 android::base::Lock m_lock; 222 GlobalNameSpace *m_globalNameSpace = nullptr; 223 // m_usedSharedGroupIDs is used to assign new IDs to new shared groups 224 std::unordered_multiset<uint64_t> m_usedSharedGroupIDs; 225 uint64_t m_nextSharedGroupID = 1; 226 }; 227 228 #endif 229