Home | History | Annotate | Download | only in EGL
      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