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 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 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 58 EGLNativeInternalDisplayType EglDisplay::nativeType(){return m_dpy;} 59 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 67 bool EglDisplay::isInitialize() { return m_initialized;} 68 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 76 static bool compareEglConfigsPtrs(EglConfig* first,EglConfig* second) { 77 return *first < *second ; 78 } 79 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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