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 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 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 59 EGLNativeInternalDisplayType EglDisplay::nativeType(){return m_dpy;} 60 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 68 bool EglDisplay::isInitialize() { return m_initialized;} 69 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 77 static bool compareEglConfigsPtrs(EglConfig* first,EglConfig* second) { 78 return *first < *second ; 79 } 80 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 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 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 142 SurfacePtr EglDisplay::getSurface(EGLSurface surface) { 143 android::Mutex::Autolock mutex(m_lock); 144 /* surface is "key" in map<unsigned int, SurfacePtr>. */ 145 unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)surface); 146 SurfacesHndlMap::iterator it = m_surfaces.find(hndl); 147 return it != m_surfaces.end() ? 148 (*it).second : 149 SurfacePtr(NULL); 150 } 151 152 ContextPtr EglDisplay::getContext(EGLContext ctx) { 153 android::Mutex::Autolock mutex(m_lock); 154 /* ctx is "key" in map<unsigned int, ContextPtr>. */ 155 unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)ctx); 156 ContextsHndlMap::iterator it = m_contexts.find(hndl); 157 return it != m_contexts.end() ? 158 (*it).second : 159 ContextPtr(NULL); 160 } 161 162 bool EglDisplay::removeSurface(EGLSurface s) { 163 android::Mutex::Autolock mutex(m_lock); 164 /* s is "key" in map<unsigned int, SurfacePtr>. */ 165 unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)s); 166 SurfacesHndlMap::iterator it = m_surfaces.find(hndl); 167 if(it != m_surfaces.end()) { 168 m_surfaces.erase(it); 169 return true; 170 } 171 return false; 172 } 173 174 bool EglDisplay::removeSurface(SurfacePtr s) { 175 android::Mutex::Autolock mutex(m_lock); 176 177 SurfacesHndlMap::iterator it; 178 for(it = m_surfaces.begin(); it!= m_surfaces.end();it++) 179 { 180 if((*it).second.Ptr() == s.Ptr()) { 181 break; 182 } 183 } 184 if(it != m_surfaces.end()) { 185 m_surfaces.erase(it); 186 return true; 187 } 188 return false; 189 } 190 191 bool EglDisplay::removeContext(EGLContext ctx) { 192 android::Mutex::Autolock mutex(m_lock); 193 /* ctx is "key" in map<unsigned int, ContextPtr>. */ 194 unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)ctx); 195 ContextsHndlMap::iterator it = m_contexts.find(hndl); 196 if(it != m_contexts.end()) { 197 m_contexts.erase(it); 198 return true; 199 } 200 return false; 201 } 202 203 bool EglDisplay::removeContext(ContextPtr ctx) { 204 android::Mutex::Autolock mutex(m_lock); 205 206 ContextsHndlMap::iterator it; 207 for(it = m_contexts.begin(); it != m_contexts.end();it++) { 208 if((*it).second.Ptr() == ctx.Ptr()){ 209 break; 210 } 211 } 212 if(it != m_contexts.end()) { 213 m_contexts.erase(it); 214 return true; 215 } 216 return false; 217 } 218 219 EglConfig* EglDisplay::getConfig(EGLint id) { 220 android::Mutex::Autolock mutex(m_lock); 221 222 for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { 223 if((*it)->id() == id) { 224 return (*it); 225 226 } 227 } 228 return NULL; 229 } 230 231 int EglDisplay::getConfigs(EGLConfig* configs,int config_size) { 232 android::Mutex::Autolock mutex(m_lock); 233 int i = 0; 234 for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && i < config_size ;i++,it++) { 235 configs[i] = static_cast<EGLConfig>(*it); 236 } 237 return i; 238 } 239 240 int EglDisplay::chooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) { 241 android::Mutex::Autolock mutex(m_lock); 242 return doChooseConfigs(dummy, configs, config_size); 243 } 244 245 int EglDisplay::doChooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) { 246 int added = 0; 247 for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && (added < config_size || !configs);it++) { 248 249 if( (*it)->choosen(dummy)){ 250 if(configs) { 251 configs[added] = static_cast<EGLConfig>(*it); 252 } 253 added++; 254 } 255 } 256 //no need to sort since the configurations are saved already in sorted maner 257 return added; 258 } 259 260 EGLSurface EglDisplay::addSurface(SurfacePtr s ) { 261 android::Mutex::Autolock mutex(m_lock); 262 unsigned int hndl = s.Ptr()->getHndl(); 263 EGLSurface ret =reinterpret_cast<EGLSurface> (hndl); 264 265 if(m_surfaces.find(hndl) != m_surfaces.end()) { 266 return ret; 267 } 268 269 m_surfaces[hndl] = s; 270 return ret; 271 } 272 273 EGLContext EglDisplay::addContext(ContextPtr ctx ) { 274 android::Mutex::Autolock mutex(m_lock); 275 276 unsigned int hndl = ctx.Ptr()->getHndl(); 277 EGLContext ret = reinterpret_cast<EGLContext> (hndl); 278 279 if(m_contexts.find(hndl) != m_contexts.end()) { 280 return ret; 281 } 282 m_contexts[hndl] = ctx; 283 return ret; 284 } 285 286 287 EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) { 288 android::Mutex::Autolock mutex(m_lock); 289 do { ++m_nextEglImageId; } while(m_nextEglImageId == 0); 290 img->imageId = m_nextEglImageId; 291 m_eglImages[m_nextEglImageId] = img; 292 return reinterpret_cast<EGLImageKHR>(m_nextEglImageId); 293 } 294 295 ImagePtr EglDisplay::getImage(EGLImageKHR img) { 296 android::Mutex::Autolock mutex(m_lock); 297 /* img is "key" in map<unsigned int, ImagePtr>. */ 298 unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)img); 299 ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); 300 return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL); 301 } 302 303 bool EglDisplay:: destroyImageKHR(EGLImageKHR img) { 304 android::Mutex::Autolock mutex(m_lock); 305 /* img is "key" in map<unsigned int, ImagePtr>. */ 306 unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)img); 307 ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); 308 if (i != m_eglImages.end()) 309 { 310 m_eglImages.erase(i); 311 return true; 312 } 313 return false; 314 } 315 316 EGLNativeContextType EglDisplay::getGlobalSharedContext(){ 317 android::Mutex::Autolock mutex(m_lock); 318 #ifndef _WIN32 319 // find an existing OpenGL context to share with, if exist 320 EGLNativeContextType ret = 321 (EGLNativeContextType)m_manager[GLES_1_1]->getGlobalContext(); 322 if (!ret) 323 ret = (EGLNativeContextType)m_manager[GLES_2_0]->getGlobalContext(); 324 return ret; 325 #else 326 if (!m_globalSharedContext) { 327 // 328 // On windows we create a dummy context to serve as the 329 // "global context" which all contexts share with. 330 // This is because on windows it is not possible to share 331 // with a context which is already current. This dummy context 332 // will never be current to any thread so it is safe to share with. 333 // Create that context using the first config 334 if (m_configs.size() < 1) { 335 // Should not happen! config list should be initialized at this point 336 return NULL; 337 } 338 EglConfig *cfg = (*m_configs.begin()); 339 m_globalSharedContext = EglOS::createContext(m_dpy,cfg,NULL); 340 } 341 342 return m_globalSharedContext; 343 #endif 344 } 345