• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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