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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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