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