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