C++程序  |  345行  |  10.21 KB

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