1 /*
2 * Copyright (C) 2011 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 #include "EglDisplay.h"
17 #include "EglOsApi.h"
18 #include <GLcommon/GLutils.h>
19 
EglDisplay(EGLNativeInternalDisplayType dpy,bool isDefault)20 EglDisplay::EglDisplay(EGLNativeInternalDisplayType dpy,bool isDefault) :
21     m_dpy(dpy),
22     m_initialized(false),
23     m_configInitialized(false),
24     m_isDefault(isDefault),
25     m_nextEglImageId(0),
26     m_globalSharedContext(NULL)
27 {
28     m_manager[GLES_1_1] = new ObjectNameManager(&m_globalNameSpace);
29     m_manager[GLES_2_0] = new ObjectNameManager(&m_globalNameSpace);
30 };
31 
~EglDisplay()32 EglDisplay::~EglDisplay() {
33     emugl::Mutex::AutoLock mutex(m_lock);
34 
35     //
36     // Destroy the global context if one was created.
37     // (should be true for windows platform only)
38     //
39     if (m_globalSharedContext != NULL) {
40         EglOS::destroyContext( m_dpy, m_globalSharedContext);
41     }
42 
43     if(m_isDefault) {
44         EglOS::releaseDisplay(m_dpy);
45     }
46 
47 
48     for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end(); it++) {
49         EglConfig* pConfig = *it;
50         if(pConfig) delete pConfig;
51     }
52 
53     delete m_manager[GLES_1_1];
54     delete m_manager[GLES_2_0];
55     EglOS::deleteDisplay(m_dpy);
56 }
57 
nativeType()58 EGLNativeInternalDisplayType EglDisplay::nativeType(){return m_dpy;}
59 
initialize(int renderableType)60 void EglDisplay::initialize(int renderableType) {
61     emugl::Mutex::AutoLock mutex(m_lock);
62     m_initialized = true;
63     initConfigurations(renderableType);
64     m_configInitialized = true;
65 }
66 
isInitialize()67 bool EglDisplay::isInitialize() { return m_initialized;}
68 
terminate()69 void EglDisplay::terminate(){
70     emugl::Mutex::AutoLock mutex(m_lock);
71      m_contexts.clear();
72      m_surfaces.clear();
73      m_initialized = false;
74 }
75 
compareEglConfigsPtrs(EglConfig * first,EglConfig * second)76 static bool compareEglConfigsPtrs(EglConfig* first,EglConfig* second) {
77     return *first < *second ;
78 }
79 
addMissingConfigs(void)80 void EglDisplay::addMissingConfigs(void)
81 {
82     m_configs.sort(compareEglConfigsPtrs);
83 
84     EGLConfig match;
85     EGLNativePixelFormatType tmpfrmt = PIXEL_FORMAT_INITIALIZER;
86     EglConfig dummy(5, 6, 5, 0,  // RGB_565
87                     EGL_DONT_CARE,EGL_DONT_CARE,
88                     16, // Depth
89                     EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,
90                     EGL_DONT_CARE, EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,tmpfrmt);
91 
92     if(!doChooseConfigs(dummy, &match, 1))
93     {
94         return;
95     }
96 
97     const EglConfig* config = (EglConfig*)match;
98 
99     int bSize;
100     config->getConfAttrib(EGL_BUFFER_SIZE,&bSize);
101 
102     if(bSize == 16)
103     {
104         return;
105     }
106 
107     int max_config_id = 0;
108 
109     for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) {
110         EGLint id;
111         (*it)->getConfAttrib(EGL_CONFIG_ID, &id);
112         if(id > max_config_id)
113             max_config_id = id;
114     }
115 
116     EglConfig* newConfig = new EglConfig(*config,max_config_id+1,5,6,5,0);
117 
118     m_configs.push_back(newConfig);
119 }
120 
initConfigurations(int renderableType)121 void EglDisplay::initConfigurations(int renderableType) {
122     if(m_configInitialized) return;
123     EglOS::queryConfigs(m_dpy,renderableType,m_configs);
124 
125     addMissingConfigs();
126     m_configs.sort(compareEglConfigsPtrs);
127 }
128 
getConfig(EGLConfig conf)129 EglConfig* EglDisplay::getConfig(EGLConfig conf) {
130     emugl::Mutex::AutoLock mutex(m_lock);
131 
132     for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) {
133         if(static_cast<EGLConfig>(*it) == conf) {
134             return (*it);
135 
136         }
137     }
138     return NULL;
139 }
140 
getSurface(EGLSurface surface)141 SurfacePtr EglDisplay::getSurface(EGLSurface surface) {
142     emugl::Mutex::AutoLock mutex(m_lock);
143     /* surface is "key" in map<unsigned int, SurfacePtr>. */
144     unsigned int hndl = SafeUIntFromPointer(surface);
145     SurfacesHndlMap::iterator it = m_surfaces.find(hndl);
146     return it != m_surfaces.end() ?
147                                   (*it).second :
148                                    SurfacePtr(NULL);
149 }
150 
getContext(EGLContext ctx)151 ContextPtr EglDisplay::getContext(EGLContext ctx) {
152     emugl::Mutex::AutoLock mutex(m_lock);
153     /* ctx is "key" in map<unsigned int, ContextPtr>. */
154     unsigned int hndl = SafeUIntFromPointer(ctx);
155     ContextsHndlMap::iterator it = m_contexts.find(hndl);
156     return it != m_contexts.end() ?
157                                   (*it).second :
158                                    ContextPtr(NULL);
159 }
160 
removeSurface(EGLSurface s)161 bool EglDisplay::removeSurface(EGLSurface s) {
162     emugl::Mutex::AutoLock mutex(m_lock);
163     /* s is "key" in map<unsigned int, SurfacePtr>. */
164     unsigned int hndl = SafeUIntFromPointer(s);
165     SurfacesHndlMap::iterator it = m_surfaces.find(hndl);
166     if(it != m_surfaces.end()) {
167         m_surfaces.erase(it);
168         return true;
169     }
170     return false;
171 }
172 
removeSurface(SurfacePtr s)173 bool EglDisplay::removeSurface(SurfacePtr s) {
174     emugl::Mutex::AutoLock mutex(m_lock);
175 
176     SurfacesHndlMap::iterator it;
177     for(it = m_surfaces.begin(); it!= m_surfaces.end();it++)
178     {
179         if((*it).second.Ptr() == s.Ptr()) {
180             break;
181         }
182     }
183     if(it != m_surfaces.end()) {
184         m_surfaces.erase(it);
185         return true;
186     }
187     return false;
188 }
189 
removeContext(EGLContext ctx)190 bool EglDisplay::removeContext(EGLContext ctx) {
191     emugl::Mutex::AutoLock mutex(m_lock);
192     /* ctx is "key" in map<unsigned int, ContextPtr>. */
193     unsigned int hndl = SafeUIntFromPointer(ctx);
194     ContextsHndlMap::iterator it = m_contexts.find(hndl);
195     if(it != m_contexts.end()) {
196         m_contexts.erase(it);
197         return true;
198     }
199     return false;
200 }
201 
removeContext(ContextPtr ctx)202 bool EglDisplay::removeContext(ContextPtr ctx) {
203     emugl::Mutex::AutoLock mutex(m_lock);
204 
205     ContextsHndlMap::iterator it;
206     for(it = m_contexts.begin(); it != m_contexts.end();it++) {
207         if((*it).second.Ptr() == ctx.Ptr()){
208             break;
209         }
210     }
211     if(it != m_contexts.end()) {
212         m_contexts.erase(it);
213         return true;
214     }
215     return false;
216 }
217 
getConfig(EGLint id)218 EglConfig* EglDisplay::getConfig(EGLint id) {
219     emugl::Mutex::AutoLock mutex(m_lock);
220 
221     for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) {
222         if((*it)->id() == id) {
223             return (*it);
224 
225         }
226     }
227     return NULL;
228 }
229 
getConfigs(EGLConfig * configs,int config_size)230 int EglDisplay::getConfigs(EGLConfig* configs,int config_size) {
231     emugl::Mutex::AutoLock mutex(m_lock);
232     int i = 0;
233     for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && i < config_size ;i++,it++) {
234         configs[i] = static_cast<EGLConfig>(*it);
235     }
236     return i;
237 }
238 
chooseConfigs(const EglConfig & dummy,EGLConfig * configs,int config_size)239 int EglDisplay::chooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) {
240     emugl::Mutex::AutoLock mutex(m_lock);
241     return doChooseConfigs(dummy, configs, config_size);
242 }
243 
doChooseConfigs(const EglConfig & dummy,EGLConfig * configs,int config_size)244 int EglDisplay::doChooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) {
245     int added = 0;
246     for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && (added < config_size || !configs);it++) {
247 
248        if( (*it)->choosen(dummy)){
249             if(configs) {
250                 configs[added] = static_cast<EGLConfig>(*it);
251             }
252             added++;
253        }
254     }
255     //no need to sort since the configurations are saved already in sorted maner
256     return added;
257 }
258 
addSurface(SurfacePtr s)259 EGLSurface EglDisplay::addSurface(SurfacePtr s ) {
260    emugl::Mutex::AutoLock mutex(m_lock);
261    unsigned int hndl = s.Ptr()->getHndl();
262    EGLSurface ret =reinterpret_cast<EGLSurface> (hndl);
263 
264    if(m_surfaces.find(hndl) != m_surfaces.end()) {
265        return ret;
266    }
267 
268    m_surfaces[hndl] = s;
269    return ret;
270 }
271 
addContext(ContextPtr ctx)272 EGLContext EglDisplay::addContext(ContextPtr ctx ) {
273     emugl::Mutex::AutoLock mutex(m_lock);
274 
275    unsigned int hndl = ctx.Ptr()->getHndl();
276    EGLContext ret    = reinterpret_cast<EGLContext> (hndl);
277 
278    if(m_contexts.find(hndl) != m_contexts.end()) {
279        return ret;
280    }
281    m_contexts[hndl] = ctx;
282    return ret;
283 }
284 
285 
addImageKHR(ImagePtr img)286 EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) {
287     emugl::Mutex::AutoLock mutex(m_lock);
288     do { ++m_nextEglImageId; } while(m_nextEglImageId == 0);
289     img->imageId = m_nextEglImageId;
290     m_eglImages[m_nextEglImageId] = img;
291     return reinterpret_cast<EGLImageKHR>(m_nextEglImageId);
292 }
293 
getImage(EGLImageKHR img)294 ImagePtr EglDisplay::getImage(EGLImageKHR img) {
295     emugl::Mutex::AutoLock mutex(m_lock);
296     /* img is "key" in map<unsigned int, ImagePtr>. */
297     unsigned int hndl = SafeUIntFromPointer(img);
298     ImagesHndlMap::iterator i( m_eglImages.find(hndl) );
299     return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL);
300 }
301 
destroyImageKHR(EGLImageKHR img)302 bool EglDisplay:: destroyImageKHR(EGLImageKHR img) {
303     emugl::Mutex::AutoLock mutex(m_lock);
304     /* img is "key" in map<unsigned int, ImagePtr>. */
305     unsigned int hndl = SafeUIntFromPointer(img);
306     ImagesHndlMap::iterator i( m_eglImages.find(hndl) );
307     if (i != m_eglImages.end())
308     {
309         m_eglImages.erase(i);
310         return true;
311     }
312     return false;
313 }
314 
getGlobalSharedContext()315 EGLNativeContextType EglDisplay::getGlobalSharedContext(){
316     emugl::Mutex::AutoLock mutex(m_lock);
317 #ifndef _WIN32
318     // find an existing OpenGL context to share with, if exist
319     EGLNativeContextType ret =
320         (EGLNativeContextType)m_manager[GLES_1_1]->getGlobalContext();
321     if (!ret)
322         ret = (EGLNativeContextType)m_manager[GLES_2_0]->getGlobalContext();
323     return ret;
324 #else
325     if (!m_globalSharedContext) {
326         //
327         // On windows we create a dummy context to serve as the
328         // "global context" which all contexts share with.
329         // This is because on windows it is not possible to share
330         // with a context which is already current. This dummy context
331         // will never be current to any thread so it is safe to share with.
332         // Create that context using the first config
333         if (m_configs.size() < 1) {
334             // Should not happen! config list should be initialized at this point
335             return NULL;
336         }
337         EglConfig *cfg = (*m_configs.begin());
338         m_globalSharedContext = EglOS::createContext(m_dpy,cfg,NULL);
339     }
340 
341     return m_globalSharedContext;
342 #endif
343 }
344