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