diff options
Diffstat (limited to 'distrib/android-emugl/host/libs/Translator/EGL/EglImp.cpp')
-rw-r--r-- | distrib/android-emugl/host/libs/Translator/EGL/EglImp.cpp | 1068 |
1 files changed, 1068 insertions, 0 deletions
diff --git a/distrib/android-emugl/host/libs/Translator/EGL/EglImp.cpp b/distrib/android-emugl/host/libs/Translator/EGL/EglImp.cpp new file mode 100644 index 000000000..30d358f59 --- /dev/null +++ b/distrib/android-emugl/host/libs/Translator/EGL/EglImp.cpp @@ -0,0 +1,1068 @@ +/* +* 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. +*/ +#ifdef _WIN32 +#undef EGLAPI +#define EGLAPI __declspec(dllexport) +#endif + +#include <EGL/egl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include "ThreadInfo.h" +#include <GLcommon/TranslatorIfaces.h> +#include "emugl/common/shared_library.h" + +#include "EglWindowSurface.h" +#include "EglPbufferSurface.h" +#include "EglPixmapSurface.h" +#include "EglGlobalInfo.h" +#include "EglThreadInfo.h" +#include "EglValidate.h" +#include "EglDisplay.h" +#include "EglContext.h" +#include "EglConfig.h" +#include "EglOsApi.h" +#include "ClientAPIExts.h" + +#define MAJOR 1 +#define MINOR 4 + +//declarations + +EglImage *attachEGLImage(unsigned int imageId); +void detachEGLImage(unsigned int imageId); +GLEScontext* getGLESContext(); + +#define tls_thread EglThreadInfo::get() + +EglGlobalInfo* g_eglInfo = NULL; +emugl::Mutex s_eglLock; + +void initGlobalInfo() +{ + emugl::Mutex::AutoLock mutex(s_eglLock); + if (!g_eglInfo) { + g_eglInfo = EglGlobalInfo::getInstance(); + } +} + +static EGLiface s_eglIface = { + getGLESContext : getGLESContext, + eglAttachEGLImage:attachEGLImage, + eglDetachEGLImage:detachEGLImage +}; + +/***************************************** supported extentions ***********************************************************************/ + +//extentions +#define EGL_EXTENTIONS 2 + +//decleration +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image); + +// extentions descriptors +static ExtentionDescriptor s_eglExtentions[] = { + {"eglCreateImageKHR" ,(__eglMustCastToProperFunctionPointerType)eglCreateImageKHR}, + {"eglDestroyImageKHR",(__eglMustCastToProperFunctionPointerType)eglDestroyImageKHR} + }; +static int s_eglExtentionsSize = sizeof(s_eglExtentions) / + sizeof(ExtentionDescriptor); + +/****************************************************************************************************************************************/ +//macros for accessing global egl info & tls objects + +#define CURRENT_THREAD() do {} while (0); + +#define RETURN_ERROR(ret,err) \ + CURRENT_THREAD() \ + if(tls_thread->getError() == EGL_SUCCESS) { \ + tls_thread->setError(err); \ + } \ + return ret; + +#define VALIDATE_DISPLAY_RETURN(EGLDisplay,ret) \ + EglDisplay* dpy = g_eglInfo->getDisplay(EGLDisplay); \ + if(!dpy){ \ + RETURN_ERROR(ret,EGL_BAD_DISPLAY); \ + } \ + if(!dpy->isInitialize()) { \ + RETURN_ERROR(ret,EGL_NOT_INITIALIZED); \ + } + +#define VALIDATE_CONFIG_RETURN(EGLConfig,ret) \ + EglConfig* cfg = dpy->getConfig(EGLConfig); \ + if(!cfg) { \ + RETURN_ERROR(ret,EGL_BAD_CONFIG); \ + } + +#define VALIDATE_SURFACE_RETURN(EGLSurface,ret,varName) \ + SurfacePtr varName = dpy->getSurface(EGLSurface); \ + if(!varName.Ptr()) { \ + RETURN_ERROR(ret,EGL_BAD_SURFACE); \ + } + +#define VALIDATE_CONTEXT_RETURN(EGLContext,ret) \ + ContextPtr ctx = dpy->getContext(EGLContext); \ + if(!ctx.Ptr()) { \ + RETURN_ERROR(ret,EGL_BAD_CONTEXT); \ + } + + +#define VALIDATE_DISPLAY(EGLDisplay) \ + VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE) + +#define VALIDATE_CONFIG(EGLConfig) \ + VALIDATE_CONFIG_RETURN(EGLConfig,EGL_FALSE) + +#define VALIDATE_SURFACE(EGLSurface,varName) \ + VALIDATE_SURFACE_RETURN(EGLSurface,EGL_FALSE,varName) + +#define VALIDATE_CONTEXT(EGLContext) \ + VALIDATE_CONTEXT_RETURN(EGLContext,EGL_FALSE) + + +GLEScontext* getGLESContext() +{ + ThreadInfo* thread = getThreadInfo(); + return thread->glesContext; +} + +EGLAPI EGLint EGLAPIENTRY eglGetError(void) { + CURRENT_THREAD(); + EGLint err = tls_thread->getError(); + tls_thread->setError(EGL_SUCCESS); + return err; +} + +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { + EglDisplay* dpy = NULL; + EGLNativeInternalDisplayType internalDisplay = NULL; + + initGlobalInfo(); + + if ((dpy = g_eglInfo->getDisplay(display_id))) { + return dpy; + } else { + + if( display_id == EGL_DEFAULT_DISPLAY) { + internalDisplay = g_eglInfo->getDefaultNativeDisplay(); + } else { + internalDisplay = g_eglInfo->generateInternalDisplay(display_id); + } + + dpy = g_eglInfo->addDisplay(display_id,internalDisplay); + if(dpy) return dpy; + return EGL_NO_DISPLAY; + } +} + + +#define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces" + +static __translator_getGLESIfaceFunc loadIfaces(const char* libName){ + emugl::SharedLibrary* libGLES = emugl::SharedLibrary::open(libName); + + if(!libGLES) return NULL; + __translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc)libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME); + if(!func) return NULL; + return func; +} + +#define LIB_GLES_CM_NAME EMUGL_LIBNAME("GLES_CM_translator") +#define LIB_GLES_V2_NAME EMUGL_LIBNAME("GLES_V2_translator") + +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) { + + initGlobalInfo(); + + EglDisplay* dpy = g_eglInfo->getDisplay(display); + if(!dpy) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_DISPLAY); + } + + if(major) *major = MAJOR; + if(minor) *minor = MINOR; + + __translator_getGLESIfaceFunc func = NULL; + int renderableType = EGL_OPENGL_ES_BIT; + + if(!g_eglInfo->getIface(GLES_1_1)) { + func = loadIfaces(LIB_GLES_CM_NAME); + if(func){ + g_eglInfo->setIface(func(&s_eglIface),GLES_1_1); + } else { + fprintf(stderr,"could not find ifaces for GLES CM 1.1\n"); + return EGL_FALSE; + } + } + if(!g_eglInfo->getIface(GLES_2_0)) { + func = loadIfaces(LIB_GLES_V2_NAME); + if(func){ + renderableType |= EGL_OPENGL_ES2_BIT; + g_eglInfo->setIface(func(&s_eglIface),GLES_2_0); + } else { + fprintf(stderr,"could not find ifaces for GLES 2.0\n"); + } + } + dpy->initialize(renderableType); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay display) { + VALIDATE_DISPLAY(display); + dpy->terminate(); + return EGL_TRUE; +} + +EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay display, EGLint name) { + VALIDATE_DISPLAY(display); + static const char* vendor = "Google"; + static const char* version = "1.4"; + static const char* extensions = "EGL_KHR_image_base EGL_KHR_gl_texture_2D_image"; + if(!EglValidate::stringName(name)) { + RETURN_ERROR(NULL,EGL_BAD_PARAMETER); + } + switch(name) { + case EGL_VENDOR: + return vendor; + case EGL_VERSION: + return version; + case EGL_EXTENSIONS: + return extensions; + } + return NULL; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay display, EGLConfig *configs, + EGLint config_size, EGLint *num_config) { + VALIDATE_DISPLAY(display); + if(!num_config) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + + if(configs == NULL) { + *num_config = dpy->nConfigs(); + } else { + *num_config = dpy->getConfigs(configs,config_size); + } + + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, + EGLint *num_config) { + VALIDATE_DISPLAY(display); + if(!num_config) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + + //selection defaults + // NOTE: Some variables below are commented out to reduce compiler warnings. + // TODO(digit): Look if these variables are really needed or not, and if so + // fix the code to do it properly. + EGLint surface_type = EGL_WINDOW_BIT; + EGLint renderable_type = EGL_OPENGL_ES_BIT; + //EGLBoolean bind_to_tex_rgb = EGL_DONT_CARE; + //EGLBoolean bind_to_tex_rgba = EGL_DONT_CARE; + EGLenum caveat = EGL_DONT_CARE; + EGLint config_id = EGL_DONT_CARE; + EGLBoolean native_renderable = EGL_DONT_CARE; + EGLint native_visual_type = EGL_DONT_CARE; + //EGLint max_swap_interval = EGL_DONT_CARE; + //EGLint min_swap_interval = EGL_DONT_CARE; + EGLint trans_red_val = EGL_DONT_CARE; + EGLint trans_green_val = EGL_DONT_CARE; + EGLint trans_blue_val = EGL_DONT_CARE; + EGLenum transparent_type = EGL_NONE; + //EGLint buffer_size = 0; + EGLint red_size = 0; + EGLint green_size = 0; + EGLint blue_size = 0; + EGLint alpha_size = 0; + EGLint depth_size = 0; + EGLint frame_buffer_level = 0; + //EGLint sample_buffers_num = 0; + EGLint samples_per_pixel = 0; + EGLint stencil_size = 0; + + if(!EglValidate::noAttribs(attrib_list)) { //there are attribs + int i = 0 ; + bool hasConfigId = false; + while(attrib_list[i] != EGL_NONE && !hasConfigId) { + switch(attrib_list[i]) { + case EGL_MAX_PBUFFER_WIDTH: + case EGL_MAX_PBUFFER_HEIGHT: + case EGL_MAX_PBUFFER_PIXELS: + case EGL_NATIVE_VISUAL_ID: + break; //we dont care from those selection crateria + case EGL_LEVEL: + if(attrib_list[i+1] == EGL_DONT_CARE) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + frame_buffer_level = attrib_list[i+1]; + break; + case EGL_BUFFER_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + //buffer_size = attrib_list[i+1]; + break; + case EGL_RED_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + red_size = attrib_list[i+1]; + break; + case EGL_GREEN_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + green_size = attrib_list[i+1]; + break; + case EGL_BLUE_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + blue_size = attrib_list[i+1]; + break; + case EGL_ALPHA_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + alpha_size = attrib_list[i+1]; + break; + case EGL_BIND_TO_TEXTURE_RGB: + //bind_to_tex_rgb = attrib_list[i+1]; + break; + case EGL_BIND_TO_TEXTURE_RGBA: + //bind_to_tex_rgba = attrib_list[i+1]; + break; + case EGL_CONFIG_CAVEAT: + if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_SLOW_CONFIG && attrib_list[i+1] != EGL_NON_CONFORMANT_CONFIG) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + caveat = attrib_list[i+1]; + break; + case EGL_CONFIG_ID: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + config_id = attrib_list[i+1]; + hasConfigId = true; + break; + case EGL_DEPTH_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + depth_size = attrib_list[i+1]; + break; + case EGL_MAX_SWAP_INTERVAL: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + //max_swap_interval = attrib_list[i+1]; + break; + case EGL_MIN_SWAP_INTERVAL: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + //min_swap_interval = attrib_list[i+1]; + break; + case EGL_NATIVE_RENDERABLE: + native_renderable = attrib_list[i+1]; + break; + case EGL_RENDERABLE_TYPE: + renderable_type = attrib_list[i+1]; + break; + case EGL_NATIVE_VISUAL_TYPE: + native_visual_type = attrib_list[i+1]; + break; + if(attrib_list[i+1] < 0 || attrib_list[i+1] > 1 ) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + case EGL_SAMPLE_BUFFERS: + //sample_buffers_num = attrib_list[i+1]; + break; + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + case EGL_SAMPLES: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + samples_per_pixel = attrib_list[i+1]; + break; + case EGL_STENCIL_SIZE: + if(attrib_list[i+1] < 0) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + stencil_size = attrib_list[i+1]; + break; + case EGL_SURFACE_TYPE: + surface_type = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_TYPE: + if(attrib_list[i+1] != EGL_NONE && attrib_list[i+1] != EGL_TRANSPARENT_RGB ) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + transparent_type = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_RED_VALUE: + trans_red_val = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_GREEN_VALUE: + trans_green_val = attrib_list[i+1]; + break; + case EGL_TRANSPARENT_BLUE_VALUE: + trans_blue_val = attrib_list[i+1]; + break; + default: + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + i+=2; + } + if(hasConfigId) { + EglConfig* pConfig = dpy->getConfig(config_id); + if(pConfig) { + if(configs) { + configs[0] = static_cast<EGLConfig>(pConfig); + } + *num_config = 1; + return EGL_TRUE; + } else { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + } + } + EGLNativePixelFormatType tmpfrmt = PIXEL_FORMAT_INITIALIZER; + EglConfig dummy(red_size,green_size,blue_size,alpha_size,caveat,config_id,depth_size, + frame_buffer_level,0,0,0,native_renderable,renderable_type,0,native_visual_type, + samples_per_pixel,stencil_size,surface_type,transparent_type, + trans_red_val,trans_green_val,trans_blue_val,tmpfrmt); + + *num_config = dpy->chooseConfigs(dummy,configs,config_size); + + + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay display, EGLConfig config, + EGLint attribute, EGLint *value) { + VALIDATE_DISPLAY(display); + VALIDATE_CONFIG(config); + if(!EglValidate::confAttrib(attribute)){ + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return cfg->getConfAttrib(attribute,value)? EGL_TRUE:EGL_FALSE; +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay display, EGLConfig config, + EGLNativeWindowType win, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); + VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); + + if(!(cfg->surfaceType() & EGL_WINDOW_BIT)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); + } + if(!EglOS::validNativeWin(dpy->nativeType(),win)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_NATIVE_WINDOW); + } + if(!EglValidate::noAttribs(attrib_list)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + if(EglWindowSurface::alreadyAssociatedWithConfig(win)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + + unsigned int width,height; + if(!EglOS::checkWindowPixelFormatMatch(dpy->nativeType(),win,cfg,&width,&height)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + SurfacePtr wSurface(new EglWindowSurface(dpy, win,cfg,width,height)); + if(!wSurface.Ptr()) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + return dpy->addSurface(wSurface); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); + VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); + if(!(cfg->surfaceType() & EGL_PBUFFER_BIT)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); + } + + + SurfacePtr pbSurface(new EglPbufferSurface(dpy,cfg)); + if(!pbSurface.Ptr()) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + + if(!EglValidate::noAttribs(attrib_list)) { //there are attribs + int i = 0 ; + while(attrib_list[i] != EGL_NONE) { + if(!pbSurface->setAttrib(attrib_list[i],attrib_list[i+1])) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + i+=2; + } + } + + EGLint width,height,largest,texTarget,texFormat; + EglPbufferSurface* tmpPbSurfacePtr = static_cast<EglPbufferSurface*>(pbSurface.Ptr()); + tmpPbSurfacePtr->getDim(&width,&height,&largest); + tmpPbSurfacePtr->getTexInfo(&texTarget,&texFormat); + + if(!EglValidate::pbufferAttribs(width,height,texFormat == EGL_NO_TEXTURE,texTarget == EGL_NO_TEXTURE)) { + //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad_value + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + + EGLNativeSurfaceType pb = EglOS::createPbufferSurface(dpy->nativeType(),cfg,tmpPbSurfacePtr); + if(!pb) { + //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad value + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + + tmpPbSurfacePtr->setNativePbuffer(pb); + return dpy->addSurface(pbSurface); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay display, EGLConfig config, + EGLNativePixmapType pixmap, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE); + VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE); + if(!(cfg->surfaceType() & EGL_PIXMAP_BIT)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH); + } + if(!EglValidate::noAttribs(attrib_list)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE); + } + if(EglPixmapSurface::alreadyAssociatedWithConfig(pixmap)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + + unsigned int width,height; + if(!EglOS::checkPixmapPixelFormatMatch(dpy->nativeType(),pixmap,cfg,&width,&height)) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + SurfacePtr pixSurface(new EglPixmapSurface(dpy, pixmap,cfg)); + if(!pixSurface.Ptr()) { + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC); + } + + return dpy->addSurface(pixSurface); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface) { + VALIDATE_DISPLAY(display); + SurfacePtr srfc = dpy->getSurface(surface); + if(!srfc.Ptr()) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + + dpy->removeSurface(surface); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay display, EGLSurface surface, + EGLint attribute, EGLint *value) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,srfc); + + if(!srfc->getAttrib(attribute,value)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay display, EGLSurface surface, + EGLint attribute, EGLint value) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,srfc); + if(!srfc->setAttrib(attribute,value)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return EGL_TRUE; +} + +EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config, + EGLContext share_context, + const EGLint *attrib_list) { + VALIDATE_DISPLAY_RETURN(display,EGL_NO_CONTEXT); + VALIDATE_CONFIG_RETURN(config,EGL_NO_CONTEXT); + + GLESVersion version = GLES_1_1; + if(!EglValidate::noAttribs(attrib_list)) { + int i = 0; + while(attrib_list[i] != EGL_NONE) { + switch(attrib_list[i]) { + case EGL_CONTEXT_CLIENT_VERSION: + if(attrib_list[i+1] == 2) { + version = GLES_2_0; + } else { + version = GLES_1_1; + } + break; + default: + RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); + } + i+=2; + } + } + GLESiface* iface = g_eglInfo->getIface(version); + GLEScontext* glesCtx = NULL; + if(iface) { + glesCtx = iface->createGLESContext(); + } else { // there is no interface for this gles version + RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE); + } + + ContextPtr sharedCtxPtr; + if(share_context != EGL_NO_CONTEXT) { + sharedCtxPtr = dpy->getContext(share_context); + if(!sharedCtxPtr.Ptr()) { + RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT); + } + } + + EGLNativeContextType globalSharedContext = dpy->getGlobalSharedContext(); + EGLNativeContextType nativeContext = EglOS::createContext(dpy->nativeType(),cfg,globalSharedContext); + + if(nativeContext) { + ContextPtr ctx(new EglContext(dpy, nativeContext,sharedCtxPtr,cfg,glesCtx,version,dpy->getManager(version))); + return dpy->addContext(ctx); + } else { + iface->deleteGLESContext(glesCtx); + } + +return EGL_NO_CONTEXT; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context) { + VALIDATE_DISPLAY(display); + VALIDATE_CONTEXT(context); + + dpy->removeContext(context); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface draw, + EGLSurface read, EGLContext context) { + VALIDATE_DISPLAY(display); + + + bool releaseContext = EglValidate::releaseContext(context,read,draw); + if(!releaseContext && EglValidate::badContextMatch(context,read,draw)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH); + } + + ThreadInfo* thread = getThreadInfo(); + ContextPtr prevCtx = thread->eglContext; + + if(releaseContext) { //releasing current context + if(prevCtx.Ptr()) { + g_eglInfo->getIface(prevCtx->version())->flush(); + if(!EglOS::makeCurrent(dpy->nativeType(),NULL,NULL,NULL)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); + } + thread->updateInfo(ContextPtr(NULL),dpy,NULL,ShareGroupPtr(NULL),dpy->getManager(prevCtx->version())); + } + } else { //assining new context + VALIDATE_CONTEXT(context); + VALIDATE_SURFACE(draw,newDrawSrfc); + VALIDATE_SURFACE(read,newReadSrfc); + + EglSurface* newDrawPtr = newDrawSrfc.Ptr(); + EglSurface* newReadPtr = newReadSrfc.Ptr(); + ContextPtr newCtx = ctx; + + if (newCtx.Ptr() && prevCtx.Ptr()) { + if (newCtx.Ptr() == prevCtx.Ptr()) { + if (newDrawPtr == prevCtx->draw().Ptr() && + newReadPtr == prevCtx->read().Ptr()) { + // nothing to do + return EGL_TRUE; + } + } + else { + // Make sure previous context is detached from surfaces + releaseContext = true; + } + } + + //surfaces compitability check + if(!((*ctx->getConfig()).compitableWith((*newDrawPtr->getConfig()))) || + !((*ctx->getConfig()).compitableWith((*newReadPtr->getConfig())))) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH); + } + + EGLNativeInternalDisplayType nativeDisplay = dpy->nativeType(); + EGLNativeSurfaceType nativeRead = newReadPtr->native(); + EGLNativeSurfaceType nativeDraw = newDrawPtr->native(); + //checking native window validity + if(newReadPtr->type() == EglSurface::WINDOW && !EglOS::validNativeWin(nativeDisplay,nativeRead)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); + } + if(newDrawPtr->type() == EglSurface::WINDOW && !EglOS::validNativeWin(nativeDisplay,nativeDraw)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW); + } + + //checking native pixmap validity + if(newReadPtr->type() == EglSurface::PIXMAP && !EglOS::validNativePixmap(nativeDisplay,nativeRead)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); + } + if(newDrawPtr->type() == EglSurface::PIXMAP && !EglOS::validNativePixmap(nativeDisplay,nativeDraw)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); + } + if(prevCtx.Ptr()) { + g_eglInfo->getIface(prevCtx->version())->flush(); + } + if(!EglOS::makeCurrent(dpy->nativeType(),newReadPtr,newDrawPtr,newCtx->nativeType())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS); + } + //TODO: handle the following errors + // EGL_BAD_CURRENT_SURFACE , EGL_CONTEXT_LOST , EGL_BAD_ACCESS + + thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version())); + newCtx->setSurfaces(newReadSrfc,newDrawSrfc); + g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(),newCtx->getShareGroup()); + + // Initialize the GLES extension function table used in + // eglGetProcAddress for the context's GLES version if not + // yet initialized. We initialize it here to make sure we call the + // GLES getProcAddress after when a context is bound. + g_eglInfo->initClientExtFuncTable(newCtx->version()); + } + + // release previous context surface binding + if(prevCtx.Ptr() && releaseContext) { + prevCtx->setSurfaces(SurfacePtr(NULL),SurfacePtr(NULL)); + } + + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay display, EGLContext context, + EGLint attribute, EGLint *value) { + VALIDATE_DISPLAY(display); + VALIDATE_CONTEXT(context); + + if(!ctx->getAttrib(attribute,value)){ + RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE); + } + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay display, EGLSurface surface) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,Srfc); + ThreadInfo* thread = getThreadInfo(); + ContextPtr currentCtx = thread->eglContext; + + + //if surface not window return + if(Srfc->type() != EglSurface::WINDOW){ + RETURN_ERROR(EGL_TRUE,EGL_SUCCESS); + } + + if(!currentCtx.Ptr() || !currentCtx->usingSurface(Srfc) || !EglOS::validNativeWin(dpy->nativeType(),Srfc.Ptr()->native())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + + EglOS::swapBuffers(dpy->nativeType(),Srfc->native()); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay display, EGLint interval) { + VALIDATE_DISPLAY(display); + ThreadInfo* thread = getThreadInfo(); + ContextPtr currCtx = thread->eglContext; + if(currCtx.Ptr()) { + if(!currCtx->read().Ptr() || !currCtx->draw().Ptr() || currCtx->draw()->type()!=EglSurface::WINDOW) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_CURRENT_SURFACE); + } + EglOS::swapInterval(dpy->nativeType(),currCtx->draw()->native(),interval); + } else { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + return EGL_TRUE; +} + + +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) { + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); + ContextPtr ctx = thread->eglContext; + if(dpy && ctx.Ptr()){ + // This double check is required because a context might still be current after it is destroyed - in which case + // its handle should be invalid, that is EGL_NO_CONTEXT should be returned even though the context is current + EGLContext c = (EGLContext)SafePointerFromUInt(ctx->getHndl()); + if(dpy->getContext(c).Ptr()) + { + return c; + } + } + return EGL_NO_CONTEXT; +} + +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { + if(!EglValidate::surfaceTarget(readdraw)) return EGL_NO_SURFACE; + + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); + ContextPtr ctx = thread->eglContext; + + if(dpy && ctx.Ptr()) { + SurfacePtr surface = readdraw == EGL_READ ? ctx->read() : ctx->draw(); + if(surface.Ptr()) + { + // This double check is required because a surface might still be + // current after it is destroyed - in which case its handle should + // be invalid, that is EGL_NO_SURFACE should be returned even + // though the surface is current. + EGLSurface s = (EGLSurface)SafePointerFromUInt(surface->getHndl()); + surface = dpy->getSurface(s); + if(surface.Ptr()) + { + return s; + } + } + } + return EGL_NO_SURFACE; +} + +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { + ThreadInfo* thread = getThreadInfo(); + return (thread->eglContext.Ptr()) ? thread->eglDisplay : EGL_NO_DISPLAY; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void) { + EGLenum api = eglQueryAPI(); + eglBindAPI(EGL_OPENGL_ES_API); + EGLBoolean ret = eglWaitClient(); + eglBindAPI(api); + return ret; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { + if(!EglValidate::engine(engine)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + ThreadInfo* thread = getThreadInfo(); + ContextPtr currCtx = thread->eglContext; + EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); + if(currCtx.Ptr()) { + SurfacePtr read = currCtx->read(); + SurfacePtr draw = currCtx->draw(); + + EGLNativeInternalDisplayType nativeDisplay = dpy->nativeType(); + if(read.Ptr()) { + if(read->type() == EglSurface::WINDOW && + !EglOS::validNativeWin(nativeDisplay,read->native())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + if(read->type() == EglSurface::PIXMAP && + !EglOS::validNativePixmap(nativeDisplay,read->native())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + } + if(draw.Ptr()) { + if(draw->type() == EglSurface::WINDOW && + !EglOS::validNativeWin(nativeDisplay,draw->native())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + if(draw->type() == EglSurface::PIXMAP && + !EglOS::validNativePixmap(nativeDisplay,draw->native())) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE); + } + } + } + EglOS::waitNative(); + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { + if(!EglValidate::supportedApi(api)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER); + } + CURRENT_THREAD(); + tls_thread->setApi(api); + return EGL_TRUE; +} + +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) { + CURRENT_THREAD(); + return tls_thread->getApi(); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void) { + ThreadInfo* thread = getThreadInfo(); + ContextPtr currCtx = thread->eglContext; + if(currCtx.Ptr()) { + if(!currCtx->read().Ptr() || !currCtx->draw().Ptr()) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_CURRENT_SURFACE); + } + g_eglInfo->getIface(currCtx->version())->finish(); + } + return EGL_TRUE; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) { + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); + return eglMakeCurrent(dpy,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); +} + +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY + eglGetProcAddress(const char *procname){ + __eglMustCastToProperFunctionPointerType retVal = NULL; + + initGlobalInfo(); + + if(!strncmp(procname,"egl",3)) { //EGL proc + for(int i=0;i < s_eglExtentionsSize;i++){ + if(strcmp(procname,s_eglExtentions[i].name) == 0){ + retVal = s_eglExtentions[i].address; + break; + } + } + } + else { + // Look at the clientAPI (GLES) supported extension + // function table. + retVal = ClientAPIExts::getProcAddress(procname); + } + return retVal; +} + +//not supported for now +/************************* NOT SUPPORTED FOR NOW ***********************/ +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer( + EGLDisplay display, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint *attrib_list) { + VALIDATE_DISPLAY(display); + VALIDATE_CONFIG(config); + //we do not support for now openVG, and the only client API resources which may be bound in this fashion are OpenVG + RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_PARAMETER); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay display, EGLSurface surface, + EGLNativePixmapType target) { + VALIDATE_DISPLAY(display); + VALIDATE_SURFACE(surface,srfc); + if(!EglOS::validNativePixmap(dpy->nativeType(),NULL)) { + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); + } + + //we do not need to support this for android , since we are not gonna use pixmaps + RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_PIXMAP); +} + +/***********************************************************************/ + + + +//do last ( only if needed) +/*********************************************************************************************************/ +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { +//TODO: +return 0; +} + +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { +//TODO: +return 0; +} +/*********************************************************************************************************/ + + +/************************** KHR IMAGE *************************************************************/ +EglImage *attachEGLImage(unsigned int imageId) +{ + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast<EglDisplay*>(thread->eglDisplay); + ContextPtr ctx = thread->eglContext; + if (ctx.Ptr()) { + ImagePtr img = dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId)); + if(img.Ptr()) { + ctx->attachImage(imageId,img); + return img.Ptr(); + } + } + return NULL; +} + +void detachEGLImage(unsigned int imageId) +{ + ThreadInfo* thread = getThreadInfo(); + ContextPtr ctx = thread->eglContext; + if (ctx.Ptr()) { + ctx->detachImage(imageId); + } +} + + +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) +{ + VALIDATE_DISPLAY(display); + VALIDATE_CONTEXT(context); + + // We only support EGL_GL_TEXTURE_2D images + if (target != EGL_GL_TEXTURE_2D_KHR) { + RETURN_ERROR(EGL_NO_IMAGE_KHR,EGL_BAD_PARAMETER); + } + + ThreadInfo* thread = getThreadInfo(); + ShareGroupPtr sg = thread->shareGroup; + if (sg.Ptr() != NULL) { + unsigned int globalTexName = sg->getGlobalName(TEXTURE, SafeUIntFromPointer(buffer)); + if (!globalTexName) return EGL_NO_IMAGE_KHR; + + ImagePtr img( new EglImage() ); + if (img.Ptr() != NULL) { + + ObjectDataPtr objData = sg->getObjectData(TEXTURE, SafeUIntFromPointer(buffer)); + if (!objData.Ptr()) return EGL_NO_IMAGE_KHR; + + TextureData *texData = (TextureData *)objData.Ptr(); + if(!texData->width || !texData->height) return EGL_NO_IMAGE_KHR; + img->width = texData->width; + img->height = texData->height; + img->border = texData->border; + img->internalFormat = texData->internalFormat; + img->globalTexName = globalTexName; + return dpy->addImageKHR(img); + } + } + + return EGL_NO_IMAGE_KHR; +} + + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image) +{ + VALIDATE_DISPLAY(display); + return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE; +} + +/*********************************************************************************/ |