/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "EglDisplay.h" #include "EglOsApi.h" #include <GLcommon/GLutils.h> #include <utils/threads.h> EglDisplay::EglDisplay(EGLNativeInternalDisplayType dpy,bool isDefault) : m_dpy(dpy), m_initialized(false), m_configInitialized(false), m_isDefault(isDefault), m_nextEglImageId(0), m_globalSharedContext(NULL) { m_manager[GLES_1_1] = new ObjectNameManager(&m_globalNameSpace); m_manager[GLES_2_0] = new ObjectNameManager(&m_globalNameSpace); }; EglDisplay::~EglDisplay() { android::Mutex::Autolock mutex(m_lock); // // Destroy the global context if one was created. // (should be true for windows platform only) // if (m_globalSharedContext != NULL) { EglOS::destroyContext( m_dpy, m_globalSharedContext); } if(m_isDefault) { EglOS::releaseDisplay(m_dpy); } for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end(); it++) { EglConfig* pConfig = *it; if(pConfig) delete pConfig; } delete m_manager[GLES_1_1]; delete m_manager[GLES_2_0]; EglOS::deleteDisplay(m_dpy); } EGLNativeInternalDisplayType EglDisplay::nativeType(){return m_dpy;} void EglDisplay::initialize(int renderableType) { android::Mutex::Autolock mutex(m_lock); m_initialized = true; initConfigurations(renderableType); m_configInitialized = true; } bool EglDisplay::isInitialize() { return m_initialized;} void EglDisplay::terminate(){ android::Mutex::Autolock mutex(m_lock); m_contexts.clear(); m_surfaces.clear(); m_initialized = false; } static bool compareEglConfigsPtrs(EglConfig* first,EglConfig* second) { return *first < *second ; } void EglDisplay::addMissingConfigs(void) { m_configs.sort(compareEglConfigsPtrs); EGLConfig match; EGLNativePixelFormatType tmpfrmt = PIXEL_FORMAT_INITIALIZER; EglConfig dummy(5, 6, 5, 0, // RGB_565 EGL_DONT_CARE,EGL_DONT_CARE, 16, // Depth 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, EGL_DONT_CARE, EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,EGL_DONT_CARE,tmpfrmt); if(!doChooseConfigs(dummy, &match, 1)) { return; } const EglConfig* config = (EglConfig*)match; int bSize; config->getConfAttrib(EGL_BUFFER_SIZE,&bSize); if(bSize == 16) { return; } int max_config_id = 0; for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { EGLint id; (*it)->getConfAttrib(EGL_CONFIG_ID, &id); if(id > max_config_id) max_config_id = id; } EglConfig* newConfig = new EglConfig(*config,max_config_id+1,5,6,5,0); m_configs.push_back(newConfig); } void EglDisplay::initConfigurations(int renderableType) { if(m_configInitialized) return; EglOS::queryConfigs(m_dpy,renderableType,m_configs); addMissingConfigs(); m_configs.sort(compareEglConfigsPtrs); } EglConfig* EglDisplay::getConfig(EGLConfig conf) { android::Mutex::Autolock mutex(m_lock); for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { if(static_cast<EGLConfig>(*it) == conf) { return (*it); } } return NULL; } SurfacePtr EglDisplay::getSurface(EGLSurface surface) { android::Mutex::Autolock mutex(m_lock); /* surface is "key" in map<unsigned int, SurfacePtr>. */ unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)surface); SurfacesHndlMap::iterator it = m_surfaces.find(hndl); return it != m_surfaces.end() ? (*it).second : SurfacePtr(NULL); } ContextPtr EglDisplay::getContext(EGLContext ctx) { android::Mutex::Autolock mutex(m_lock); /* ctx is "key" in map<unsigned int, ContextPtr>. */ unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)ctx); ContextsHndlMap::iterator it = m_contexts.find(hndl); return it != m_contexts.end() ? (*it).second : ContextPtr(NULL); } bool EglDisplay::removeSurface(EGLSurface s) { android::Mutex::Autolock mutex(m_lock); /* s is "key" in map<unsigned int, SurfacePtr>. */ unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)s); SurfacesHndlMap::iterator it = m_surfaces.find(hndl); if(it != m_surfaces.end()) { m_surfaces.erase(it); return true; } return false; } bool EglDisplay::removeSurface(SurfacePtr s) { android::Mutex::Autolock mutex(m_lock); SurfacesHndlMap::iterator it; for(it = m_surfaces.begin(); it!= m_surfaces.end();it++) { if((*it).second.Ptr() == s.Ptr()) { break; } } if(it != m_surfaces.end()) { m_surfaces.erase(it); return true; } return false; } bool EglDisplay::removeContext(EGLContext ctx) { android::Mutex::Autolock mutex(m_lock); /* ctx is "key" in map<unsigned int, ContextPtr>. */ unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)ctx); ContextsHndlMap::iterator it = m_contexts.find(hndl); if(it != m_contexts.end()) { m_contexts.erase(it); return true; } return false; } bool EglDisplay::removeContext(ContextPtr ctx) { android::Mutex::Autolock mutex(m_lock); ContextsHndlMap::iterator it; for(it = m_contexts.begin(); it != m_contexts.end();it++) { if((*it).second.Ptr() == ctx.Ptr()){ break; } } if(it != m_contexts.end()) { m_contexts.erase(it); return true; } return false; } EglConfig* EglDisplay::getConfig(EGLint id) { android::Mutex::Autolock mutex(m_lock); for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() ;it++) { if((*it)->id() == id) { return (*it); } } return NULL; } int EglDisplay::getConfigs(EGLConfig* configs,int config_size) { android::Mutex::Autolock mutex(m_lock); int i = 0; for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && i < config_size ;i++,it++) { configs[i] = static_cast<EGLConfig>(*it); } return i; } int EglDisplay::chooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) { android::Mutex::Autolock mutex(m_lock); return doChooseConfigs(dummy, configs, config_size); } int EglDisplay::doChooseConfigs(const EglConfig& dummy,EGLConfig* configs,int config_size) { int added = 0; for(ConfigsList::iterator it = m_configs.begin(); it != m_configs.end() && (added < config_size || !configs);it++) { if( (*it)->choosen(dummy)){ if(configs) { configs[added] = static_cast<EGLConfig>(*it); } added++; } } //no need to sort since the configurations are saved already in sorted maner return added; } EGLSurface EglDisplay::addSurface(SurfacePtr s ) { android::Mutex::Autolock mutex(m_lock); unsigned int hndl = s.Ptr()->getHndl(); EGLSurface ret =reinterpret_cast<EGLSurface> (hndl); if(m_surfaces.find(hndl) != m_surfaces.end()) { return ret; } m_surfaces[hndl] = s; return ret; } EGLContext EglDisplay::addContext(ContextPtr ctx ) { android::Mutex::Autolock mutex(m_lock); unsigned int hndl = ctx.Ptr()->getHndl(); EGLContext ret = reinterpret_cast<EGLContext> (hndl); if(m_contexts.find(hndl) != m_contexts.end()) { return ret; } m_contexts[hndl] = ctx; return ret; } EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) { android::Mutex::Autolock mutex(m_lock); do { ++m_nextEglImageId; } while(m_nextEglImageId == 0); img->imageId = m_nextEglImageId; m_eglImages[m_nextEglImageId] = img; return reinterpret_cast<EGLImageKHR>(m_nextEglImageId); } ImagePtr EglDisplay::getImage(EGLImageKHR img) { android::Mutex::Autolock mutex(m_lock); /* img is "key" in map<unsigned int, ImagePtr>. */ unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)img); ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL); } bool EglDisplay:: destroyImageKHR(EGLImageKHR img) { android::Mutex::Autolock mutex(m_lock); /* img is "key" in map<unsigned int, ImagePtr>. */ unsigned int hndl = ToTargetCompatibleHandle((uintptr_t)img); ImagesHndlMap::iterator i( m_eglImages.find(hndl) ); if (i != m_eglImages.end()) { m_eglImages.erase(i); return true; } return false; } EGLNativeContextType EglDisplay::getGlobalSharedContext(){ android::Mutex::Autolock mutex(m_lock); #ifndef _WIN32 // find an existing OpenGL context to share with, if exist EGLNativeContextType ret = (EGLNativeContextType)m_manager[GLES_1_1]->getGlobalContext(); if (!ret) ret = (EGLNativeContextType)m_manager[GLES_2_0]->getGlobalContext(); return ret; #else if (!m_globalSharedContext) { // // On windows we create a dummy context to serve as the // "global context" which all contexts share with. // This is because on windows it is not possible to share // with a context which is already current. This dummy context // will never be current to any thread so it is safe to share with. // Create that context using the first config if (m_configs.size() < 1) { // Should not happen! config list should be initialized at this point return NULL; } EglConfig *cfg = (*m_configs.begin()); m_globalSharedContext = EglOS::createContext(m_dpy,cfg,NULL); } return m_globalSharedContext; #endif }