--- a/holdingarea/libEGL/src/eglapi.cpp Thu Sep 16 12:43:44 2010 +0100
+++ b/holdingarea/libEGL/src/eglapi.cpp Mon Sep 20 14:29:05 2010 +0100
@@ -1,2660 +1,2660 @@
-/* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and /or associated documentation files
- * (the "Materials "), to deal in the Materials without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Materials,
- * and to permit persons to whom the Materials are furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Materials.
- *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
- * THE USE OR OTHER DEALINGS IN THE MATERIALS.
- *
- * Initial Contributors:
- * Nokia Corporation - initial contribution.
- *
- * Contributors:
- *
- * Description:
- *
- */
-
-#include <string.h>
-#include <algorithm>
-#include <EGL/egl.h>
-#include "eglDefinitions.h"
-#include "eglInternal.h"
-#include "EGLState.h"
-#include "EGLProcess.h"
-#include "EGLDisplay.h"
-#include "EGLThread.h"
-#include "EGLContext.h"
-#include "EGLConfig.h"
-#include "EGLWindowSurface.h"
-#include "EGLPbufferSurface.h"
-#include "ColorDescriptor.h"
-#include "SurfaceDescriptor.h"
-#include "EGLExtension.h"
-#include "EGLOs.h"
-
-#if defined(_WIN32)
-#include <windows.h>
-#else
- // \todo other platforms
-#endif
-
-#if defined(_WIN32) && !defined(EGLI_USE_PLATSIM_EXTENSIONS)
-static DWORD g_tlsIndex = TLS_OUT_OF_INDEXES;
-#endif
-
-static CEGLState* g_eglState = NULL;
-static bool g_lockInitialized = false;
-EGLI_LOCK g_eglLock;
-
-CEGLState* getState()
- {
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
- if( !g_eglState )
- {
- g_eglState = EGLI_NEW CEGLState();
- if( !g_eglState )
- {
- return NULL;
- }
- if( !(g_eglState->Initialize()) )
- {
- delete g_eglState;
- g_eglState = NULL;
- return NULL;
- }
- g_eglState->AddRef();
- }
- return g_eglState;
-#elif defined(_WIN32)
- CEGLOs::GetLock( &g_eglLock );
- if( !g_eglState )
- {
- g_eglState = EGLI_NEW CEGLState();
- if( !g_eglState )
- {
- CEGLOs::ReleaseLock( &g_eglLock );
- return NULL;
- }
- if( !(g_eglState->Initialize()) )
- {
- delete g_eglState;
- g_eglState = NULL;
- CEGLOs::ReleaseLock( &g_eglLock );
- return NULL;
- }
- }
- EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
- if( g_tlsIndex == TLS_OUT_OF_INDEXES )
- {
- CEGLOs::ReleaseLock( &g_eglLock );
- return NULL;
- }
- CEGLThread* thread = (CEGLThread*)TlsGetValue( g_tlsIndex );
- if( g_eglState && !thread )
- {
- // \todo Remove CEGLProcess when platsim extensions are not needed any more
- thread = g_eglState->GetCurrentProcess()->AddThread( GetCurrentThreadId(), true, g_eglState->SupportedApis() );
- if( !thread )
- {
- CEGLOs::ReleaseLock( &g_eglLock );
- return NULL;
- }
- if( !(TlsSetValue( g_tlsIndex, (void *)thread )) )
- {
- CEGLOs::ReleaseLock( &g_eglLock );
- return NULL;
- }
- g_eglState->AddRef();
- }
- CEGLOs::ReleaseLock( &g_eglLock );
- return g_eglState;
-#else // Linux
- // \todo
- return NULL;
-#endif
- }
-
-static void releaseState()
- {
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
- if( g_eglState )
- {
- if( g_eglState->RemoveRef() )
- {
- delete g_eglState;
- g_eglState = NULL;
- }
- }
-#elif defined(_WIN32)
- CEGLOs::GetLock( &g_eglLock );
- if( g_eglState )
- {
- g_eglState->GetCurrentProcess()->RemoveThread( GetCurrentThreadId() );
- EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
- if( g_tlsIndex != TLS_OUT_OF_INDEXES )
- {
- TlsSetValue( g_tlsIndex, 0 );
- }
- }
- if( g_eglState && g_eglState->RemoveRef() )
- {
- delete g_eglState;
- g_eglState = NULL;
- }
- CEGLOs::ReleaseLock( &g_eglLock );
-#else // Linux
- // \todo
- EGLI_ASSERT( false );
-#endif
- }
-
-/*static*/ CEGLThread* getThread()
- {
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
- CEGLState* state = getState();
- CEGLProcess* process = state->GetCurrentProcess();
- if( process )
- {
- return process->CurrentThread();
- }
- return NULL;
-#elif defined(_WIN32)
- EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
- if( g_tlsIndex == TLS_OUT_OF_INDEXES )
- return NULL;
- CEGLThread* thread = (CEGLThread*)TlsGetValue( g_tlsIndex );
- if( !thread && GetLastError() == ERROR_SUCCESS )
- {
- // TlsGetValue() succeeded but didn't have thread => create one now
- CEGLState* state = getState();
- if( state )
- {
- thread = (CEGLThread*)TlsGetValue( g_tlsIndex );
- }
- }
- return thread;
-#else // Linux
- // \todo
- EGLI_ASSERT( false );
-#endif
- }
-
-void setEGLError( EGLint error )
- {
- CEGLThread* thread = getThread();
- if( thread )
- {
- thread->SetError( error );
- }
- }
-
-#define EGLI_GET_DISPLAY_RET(id,ret)\
- CEGLDisplay* display = state->GetDisplay( id );\
- if( !display )\
- {\
- EGLI_LEAVE_RET( ret, EGL_BAD_DISPLAY );\
- }\
- EGLI_ASSERT( display->ProcessId() == process->Id() );\
- if( !(display->IsInitialized()) )\
- {\
- EGLI_LEAVE_RET( ret, EGL_NOT_INITIALIZED );\
- }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*When there is no status to return (in other words, when eglGetError is called
-as the first EGL call in a thread, or immediately after calling eglReleaseThread),
-EGL_SUCCESS will be returned.*/
-EGLAPI EGLint EGLAPIENTRY eglGetError(void)
- {
- EGLint err = EGL_SUCCESS;
- CEGLThread* thread = getThread();
- if( thread )
- {
- err = thread->Error();
- thread->SetError( EGL_SUCCESS );
- }
- else
- {
- err = EGL_BAD_ALLOC;
- }
- return err;
- }
-
-EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
- {
- EGLI_ENTER_RET( EGL_NO_DISPLAY );
-
- if( display_id == EGL_DEFAULT_DISPLAY )
- {
- display_id = (EGLNativeDisplayType)state->DefaultDisplay();
- }
-
- CEGLDisplay* display = state->GetDisplayByNativeType( (EGLINativeDisplayType)display_id, process->Id() );
- if( !display )
- {
- if( !(CEGLOs::IsValidNativeDisplay( (EGLINativeDisplayType)display_id )) )
- {
- EGLI_LEAVE_RET( EGL_NO_DISPLAY, EGL_BAD_PARAMETER );
- }
- display = state->AddDisplay( (EGLINativeDisplayType)display_id, process->Id() );
- if( !display )
- {
- EGLI_LEAVE_RET( EGL_NO_DISPLAY, EGL_BAD_ALLOC );
- }
- display->AddRef();
- }
- EGLI_LEAVE_RET( (EGLDisplay)display, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
- {
- EGLI_ENTER_RET( EGL_FALSE );
-
- CEGLDisplay* display = state->GetDisplay( dpy );
- if( !display )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
- }
-
- if( !(display->IsInitialized()) && !(display->Initialize()) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_NOT_INITIALIZED );
- }
-
- if( major ) *major = 1;
- if( minor ) *minor = 4;
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- CEGLDisplay* display = state->GetDisplay( dpy );
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
- if( display && display->ProcessId() != process->Id() )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
- }
-#endif
- if( !display )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
- }
-
- if( !(display->IsInitialized()) )
- {
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
- display->RemoveRef();
- if( display->TerminateDisplay() )
- {
- state->RemoveDisplay( display );
- }
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-/*
- eglQueryString returns a pointer to a static, zero-terminated string describing
- some aspect of the EGL implementation running on the specified display. name
- may be one of EGL_CLIENT_APIS, EGL_EXTENSIONS, EGL_VENDOR, or EGL_-
- VERSION.
- The EGL_CLIENT_APIS string describes which client rendering APIs are
- supported. It is zero-terminated and contains a space-separated list of API
- names, which must include at least one of ‘‘OpenGL’’, ‘‘OpenGL_ES’’ or
- ‘‘OpenVG’’.
- The EGL_EXTENSIONS string describes which EGL extensions are supported
- by the EGL implementation running on the specified display. The string is zeroterminated
- and contains a space-separated list of extension names; extension names
- themselves do not contain spaces. If there are no extensions to EGL, then the empty
- string is returned.
- The format and contents of the EGL_VENDOR string is implementation dependent.
- The format of the EGL_VERSION string is:
- <major version.minor version><space><vendor specific info>
-*/
-
-EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
- {
- EGLI_ENTER_RET( NULL );
- EGLI_GET_DISPLAY_RET( dpy, NULL );
-
- const char* ret = NULL;
- switch(name)
- {
- case EGL_CLIENT_APIS:
- {
- switch( state->SupportedApis() )
- {
- case EGL_OPENVG_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT:
- {
- ret = "OpenVG OpenGL_ES OpenGL_ES2";
- break;
- }
-
- case EGL_OPENVG_BIT | EGL_OPENGL_ES_BIT:
- {
- ret = "OpenVG OpenGL_ES";
- break;
- }
-
- case EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT:
- {
- ret = "OpenVG OpenGL_ES2";
- break;
- }
-
- case EGL_OPENVG_BIT:
- {
- ret = "OpenVG";
- break;
- }
-
- case EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT:
- {
- ret = "OpenGL_ES OpenGL_ES2";
- break;
- }
-
- case EGL_OPENGL_ES_BIT:
- {
- ret = "OpenGL_ES";
- break;
- }
-
- case EGL_OPENGL_ES2_BIT:
- {
- ret = "OpenGL_ES2";
- break;
- }
-
- default:
- {
- ret = "";
- break;
- }
- }
- break;
- }
- case EGL_EXTENSIONS:
- {
- // TODO
- ret = "EGL_KHR_image_base";
- break;
- }
- case EGL_VENDOR:
- {
- ret = "Nokia";
- break;
- }
- case EGL_VERSION:
- {
- ret ="1.4 PlatSim";
- break;
- }
-
- default:
- {
- EGLI_LEAVE_RET( NULL, EGL_BAD_PARAMETER );
- break;
- }
- }
- EGLI_LEAVE_RET( ret, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
- EGLint config_size, EGLint *num_config)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- if( !num_config )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- EGLint configCount = state->ConfigCount();
- if( !configs )
- {
- *num_config = configCount;
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
- *num_config = EGLI_MIN( configCount, config_size );
-
- state->FillConfigs( configs, *num_config );
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
- EGLConfig *configs, EGLint config_size,
- EGLint *num_config)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- CColorDescriptor* colorDesc = EGLI_NEW CColorDescriptor( 0, 0, 0, 0, true, 0, false, 0, 0 );
- if( !colorDesc )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
- colorDesc->SetAttribute( EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER );
- CEGLConfig* filter = EGLI_NEW CEGLConfig(
- *colorDesc,
- EGL_DONT_CARE,
- EGL_DONT_CARE,
- EGL_DONT_CARE,
- EGL_DONT_CARE,
- 0, 0, 0,
- EGL_DONT_CARE,
- EGL_DONT_CARE,
- EGL_DONT_CARE,
- EGL_DONT_CARE,
- EGL_OPENGL_ES_BIT,
- 0, 0, 0,
- EGL_WINDOW_BIT,
- NULL ); // transparent color
- delete colorDesc;
- colorDesc = NULL;
- if( !filter )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
-
- EGLint configId = 0;
- EGLint matchPixmap = EGL_NONE;
-
- if( attrib_list && attrib_list[0] != EGL_NONE )
- {
- for( EGLint i=0; attrib_list[i] != EGL_NONE && configId == 0; i+=2 )
- {
- switch( attrib_list[i] )
- {
- case EGL_NATIVE_VISUAL_ID:
- case EGL_MAX_PBUFFER_HEIGHT:
- case EGL_MAX_PBUFFER_PIXELS:
- case EGL_MAX_PBUFFER_WIDTH:
- {
- // IGNORED
- break;
- }
-
- case EGL_CONFIG_ID:
- {
- configId = attrib_list[i+1];
- break;
- }
-
- case EGL_MATCH_NATIVE_PIXMAP:
- {
- matchPixmap = attrib_list[i+1];
- break;
- }
- default:
- {
- if( !(filter->SetAttribute(attrib_list[i], attrib_list[i+1])) )
- {
- delete filter;
- filter = NULL;
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
- }
- }
- }
- }
- }
-
- if( configId > 0 )
- {
- CEGLConfig* config = state->FindConfigById( configId );
- if( !config )
- {
- delete filter;
- filter = NULL;
- // TODO: is this correct error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
- *num_config = 1;
- configs[0] = (EGLConfig)config;
- delete filter;
- filter = NULL;
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
- if( matchPixmap != EGL_NONE )
- {
- // eglChooseConfig – only pbuffer supported, so no need for EGL_MATCH_NATIVE_PIXMAP
- }
-
- *num_config = state->MatchConfigs( filter, configs, config_size );
- delete filter;
- filter = NULL;
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig configId,
- EGLint attribute, EGLint *value)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
- if( !value )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
- CEGLConfig* config = state->GetConfig( configId );
- if( !config )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONFIG );
- }
- EGLint val = config->GetAttribute( attribute );
- if( val == EGL_BAD_ATTRIBUTE )
- {
- EGLI_LEAVE_RET( EGL_FALSE, val );
- }
- *value = val;
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig configId,
- EGLNativeWindowType win,
- const EGLint *attrib_list)
- {
- EGLI_ENTER_RET( EGL_NO_SURFACE );
- EGLI_GET_DISPLAY_RET ( dpy, EGL_NO_SURFACE );
- // \todo eglCreateWindowSurface – EGL_BAD_MATCH raised (as no window-supporting configs)
- CEGLConfig* config = state->GetConfig( configId );
- if( !config )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_CONFIG );
- }
- EGLint surfaceType = config->GetAttribute( EGL_SURFACE_TYPE );
- if( !(surfaceType & EGL_WINDOW_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
- CEGLSurface* surface = display->GetSurfaceByNativeType( (EGLINativeWindowType)win );
- if( surface && surface->Config() == config )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
-
- EGLint renderBuffer = EGL_BACK_BUFFER;
- EGLint colorSpace = EGL_VG_COLORSPACE_sRGB;
- EGLint alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
- EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
- if( attrib_list && attrib_list[0] != EGL_NONE )
- {
- for( int i=0; attrib_list[i] != EGL_NONE; i+=2 )
- {
- switch( attrib_list[i] )
- {
- case EGL_RENDER_BUFFER:
- renderBuffer = attrib_list[i+1];
- break;
-
- case EGL_VG_COLORSPACE:
- if( !(renderableType & EGL_OPENVG_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- colorSpace = attrib_list[i+1];
- break;
-
- case EGL_VG_ALPHA_FORMAT:
- if( !(renderableType & EGL_OPENVG_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- alphaFormat = attrib_list[i+1];
- break;
-
- default:
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- }
- }
-
- if( !(surfaceType & colorSpace) || !(surfaceType & alphaFormat) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
-
- if( !CEGLOs::IsValidNativeWindow( win ) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_NATIVE_WINDOW );
- }
-
- EGLIOsWindowContext* osContext = CEGLOs::CreateOSWindowContext( win, *config );
- if( !osContext )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
-
- surface = EGLI_NEW CEGLWindowSurface( config, colorSpace, alphaFormat, renderBuffer, osContext );
- if( !surface )
- {
- CEGLOs::DestroyOSWindowContext( osContext );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- // \note AddSurface() will destroy the object if it fails to take ownership
- surface = display->AddSurface( surface );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
-#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
- int width = 0;
- int height = 0;
- if( !CEGLOs::GetNativeWindowSize( win, width, height ) ||
- !(surface->Resize( width, height )) )
- {
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- // \todo Is this correct error?
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- if( (state->SupportedApis() & EGL_OPENVG_BIT) && (renderableType & EGL_OPENVG_BIT) )
- {
- SurfaceDescriptor* surfaceDesc = surface->Descriptor();
- if( !(state->VGInterface()->CreateSurface( surfaceDesc, surface->VGBuffers(), NULL )) )
- {
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- }
-#endif // EGLI_USE_PLATSIM_EXTENSIONS
-
- surface->AddRef();
-
- EGLI_LEAVE_RET( (EGLSurface)surface, EGL_SUCCESS );
- }
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig configId,
- const EGLint *attrib_list)
- {
- // \todo combine with eglCreatePbufferFromClientBuffer()
- EGLI_ENTER_RET( EGL_NO_SURFACE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_NO_SURFACE );
- CEGLConfig* config = state->GetConfig( configId );
- if( !config )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_CONFIG );
- }
-
- if( !(config->GetAttribute( EGL_SURFACE_TYPE ) & EGL_PBUFFER_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
-
- EGLint width = 0;
- EGLint height = 0;
- EGLint textureFormat = EGL_NO_TEXTURE;
- EGLint textureTarget = EGL_NO_TEXTURE;
- EGLint mipmapTexture = EGL_FALSE;
- EGLint largestPbuffer = EGL_FALSE;
- EGLint colorSpace = EGL_VG_COLORSPACE_sRGB;
- EGLint alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
-
- EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
- if( attrib_list && attrib_list[0] != EGL_NONE )
- {
- for( int i=0; attrib_list[i] != EGL_NONE; i+=2 )
- {
- EGLint value = attrib_list[i+1];
- switch( attrib_list[i] )
- {
- case EGL_WIDTH:
- {
- if( value < 0 )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
- }
- width = value;
- break;
- }
-
- case EGL_HEIGHT:
- {
- if( value < 0 )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
- }
- height = value;
- break;
- }
-
- case EGL_LARGEST_PBUFFER:
- {
- largestPbuffer = value;
- break;
- }
-
- case EGL_TEXTURE_FORMAT:
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) &&
- !(renderableType & EGL_OPENGL_ES2_BIT) ||
- (value != EGL_TEXTURE_RGB &&
- value != EGL_TEXTURE_RGBA &&
- value != EGL_NO_TEXTURE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- textureFormat = value;
- break;
- }
-
- case EGL_TEXTURE_TARGET:
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) &&
- !(renderableType & EGL_OPENGL_ES2_BIT) ||
- (value != EGL_TEXTURE_2D &&
- value != EGL_NO_TEXTURE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- textureTarget = value;
- break;
- }
-
- case EGL_MIPMAP_TEXTURE:
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) ||
- !(renderableType & EGL_OPENGL_ES2_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- mipmapTexture = value;
- break;
- }
-
- case EGL_VG_COLORSPACE:
- {
- if( !(renderableType & EGL_OPENVG_BIT) ||
- (value != EGL_VG_COLORSPACE_sRGB &&
- value != EGL_VG_COLORSPACE_LINEAR) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- colorSpace = value;
- break;
- }
-
- case EGL_VG_ALPHA_FORMAT:
- {
- if( !(renderableType & EGL_OPENVG_BIT) ||
- (value != EGL_VG_ALPHA_FORMAT_PRE &&
- value != EGL_VG_ALPHA_FORMAT_NONPRE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- alphaFormat = value;
- break;
- }
-
- default:
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- }
- }
-
- if( (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE) ||
- (textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
-
- CEGLPbufferSurface* surface = EGLI_NEW CEGLPbufferSurface( colorSpace, alphaFormat,
- EGL_BACK_BUFFER, config, largestPbuffer, textureFormat, textureTarget, mipmapTexture );
- // \note AddSurface() will destroy the object if it fails to take ownership
- surface = (CEGLPbufferSurface*)display->AddSurface( surface );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- if( !(surface->Resize(width, height)) )
- {
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- // \todo refactor all this surface creation stuff
- if( (renderableType & EGL_OPENVG_BIT) && (state->SupportedApis() & EGL_OPENVG_BIT) )
- {
- // \todo Delay surface creation until needed.
- // \todo largest Pbuffer
- if( !(state->VGInterface()->CreateSurface( surface->Descriptor(), surface->VGBuffers(), NULL )) )
- {
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- }
-
- if( renderableType & EGL_OPENGL_ES_BIT && (state->SupportedApis() & EGL_OPENGL_ES_BIT) )
- {
- struct EGLINativePbufferContainer* nativePbuffer = CEGLOs::CreateNativePbuffer( display->NativeType(),
- *config, width, height, largestPbuffer, textureFormat, textureTarget );
- if( !nativePbuffer )
- {
- if( surface->VGClientSurface() )
- {
- state->VGInterface()->ReleaseSurface( surface->VGClientSurface() );
- }
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- surface->SetNativePbufferContainer( nativePbuffer );
- }
-
- if( renderableType & EGL_OPENGL_ES2_BIT && (state->SupportedApis() & EGL_OPENGL_ES2_BIT) )
- {
- struct EGLINativePbufferContainer* nativePbuffer = CEGLOs::CreateNativePbuffer( display->NativeType(),
- *config, width, height, largestPbuffer, textureFormat, textureTarget );
- if( !nativePbuffer )
- {
- if( surface->VGClientSurface() )
- {
- state->VGInterface()->ReleaseSurface( surface->VGClientSurface() );
- }
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- surface->SetNativePbufferContainer( nativePbuffer );
- }
-
- surface->AddRef();
-
- EGLI_LEAVE_RET( (EGLSurface)surface, EGL_SUCCESS );
- }
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
- EGLNativePixmapType pixmap,
- const EGLint *attrib_list)
- {
- EGLI_ENTER_RET( EGL_NO_SURFACE );
- // eglCreatePixmapSurface – EGL_BAD_MATCH raised (as no pixmap-supporting configs)
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surfaceId)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
- CEGLSurface* surface = display->GetSurface( surfaceId );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
-
- // \note EGLI_ENTER_RET macro will fail if thread allocation didn't succeed
- CEGLThread* thread = getThread();
-
- surface->Lock();
- //TODO: client apis
- if( surface->RemoveRef() )
- {
- if( surface->VGClientSurface() )
- {
- if( !(state->VGInterface()->ReleaseSurface(surface->VGClientSurface())) )
- {
- // need to add reference because surface is still alive
- surface->AddRef();
- surface->Unlock();
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- }
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- surface = NULL;
- }
- else
- {
- surface->Terminate();
- }
- if( surface ) surface->Unlock();
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surfaceId,
- EGLint attribute, EGLint *value)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- if( !value )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- CEGLSurface* surface = display->GetSurface( surfaceId );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- surface->Lock();
- EGLint ret = EGL_BAD_ATTRIBUTE;
- switch( attribute )
- {
- case EGL_VG_ALPHA_FORMAT:
- {
- ret = surface->AlphaFormat();
- break;
- }
- case EGL_VG_COLORSPACE:
- {
- ret = surface->ColorSpace();
- break;
- }
- case EGL_CONFIG_ID:
- {
- ret = surface->Config()->Id();
- break;
- }
- case EGL_HEIGHT:
- {
- ret = surface->Height();
- break;
- }
- case EGL_WIDTH:
- {
- ret = surface->Width();
- break;
- }
- case EGL_HORIZONTAL_RESOLUTION:
- {
- if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
- {
- //TODO
- EGLI_ASSERT( false );
- }
- else
- {
- ret = EGL_UNKNOWN;
- }
- break;
- }
- case EGL_VERTICAL_RESOLUTION:
- {
- if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
- {
- //TODO
- EGLI_ASSERT( false );
- }
- else
- {
- ret = EGL_UNKNOWN;
- }
- break;
- }
- case EGL_PIXEL_ASPECT_RATIO:
- {
- if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
- {
- //TODO
- EGLI_ASSERT( false );
- }
- else
- {
- ret = EGL_UNKNOWN;
- }
- break;
- }
- case EGL_LARGEST_PBUFFER:
- {
- if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- ret = ((CEGLPbufferSurface*)surface)->IsLargestPbuffer();
- }
- break;
- }
- case EGL_MIPMAP_TEXTURE:
- {
- if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- ret = ((CEGLPbufferSurface*)surface)->MipmapTexture();
- }
- break;
- }
- case EGL_MIPMAP_LEVEL:
- {
- if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- ret = surface->MipmapLevel();
- }
- break;
- }
- case EGL_MULTISAMPLE_RESOLVE:
- {
- ret = surface->MultisampleResolve();
- break;
- }
- case EGL_RENDER_BUFFER:
- {
- ret = surface->RenderBuffer();
- break;
- }
- case EGL_SWAP_BEHAVIOR:
- {
- ret = surface->SwapBehavior();
- break;
- }
- case EGL_TEXTURE_FORMAT:
- {
- if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- ret = ((CEGLPbufferSurface*)surface)->TextureFormat();
- }
- break;
- }
- case EGL_TEXTURE_TARGET:
- {
- if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- ret = ((CEGLPbufferSurface*)surface)->TextureTarget();
- }
- break;
- }
- default:
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
- }
- }
- *value = ret;
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-
-EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
- {
- CEGLThread* thread = getThread();
- EGLI_ASSERT( thread != NULL );
-
- if( thread && thread->IsSupportedApi( api ) )
- {
- thread->SetApi( api );
- thread->SetError( EGL_SUCCESS );
- return EGL_TRUE;
- }
- else if( thread )
- {
- thread->SetError( EGL_BAD_PARAMETER );
- }
- return EGL_FALSE;
- }
-
-EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void)
- {
- CEGLThread* thread = getThread();
- EGLI_ASSERT( thread != NULL );
-
- EGLenum api = EGL_NONE;
- if( thread )
- {
- api = thread->CurrentApi();
- thread->SetError( EGL_SUCCESS );
- }
- return api;
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- // Macro above fails if thread is not available.
- CEGLThread* thread = getThread();
-
- switch( thread->CurrentApi() )
- {
- case EGL_OPENVG_API:
- {
- if( !(thread->CurrentVGSurface()) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CURRENT_SURFACE );
- }
- if( !(thread->CurrentVGContext()) )
- {
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
- if( !(state->VGInterface()) )
- {
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- state->VGInterface()->Finish();
- break;
- }
- case EGL_OPENGL_ES_API:
- {
- CEGLSurface* read = NULL;
- CEGLSurface* draw = NULL;
- thread->CurrentGLESSurfaces( &read, &draw );
- if( !read || !draw )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CURRENT_SURFACE );
- }
- if( !(thread->CurrentGLESContext()) )
- {
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
- state->GLESInterface( thread->CurrentGLESContext()->ClientVersion() )->Finish();
- break;
- }
- }
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void)
- {
-#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
-#if defined(_WIN32)
- EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
- if( TlsGetValue( g_tlsIndex ) == NULL )
- {
- // Already released or first call => success
- return EGL_TRUE;
- }
-#else // Linux
- // \todo
- EGLI_ASSERT( false );
-#endif
-#else
- EGLI_ENTER_RET( EGL_FALSE );
-#endif //EGLI_USE_PLATSIM_EXTENSIONS
-
- CEGLThread* thread = getThread();
- EGLenum api = thread->CurrentApi();
- if( thread->CurrentVGContext() )
- {
- const CEGLDisplay* display = thread->CurrentVGContext()->Display();
- EGLI_ASSERT( display );
- thread->SetApi( EGL_OPENVG_API );
- eglMakeCurrent( (EGLDisplay)display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
- }
- if( thread->CurrentGLESContext() )
- {
- const CEGLDisplay* display = thread->CurrentGLESContext()->Display();
- EGLI_ASSERT( display );
- thread->SetApi( EGL_OPENGL_ES_API );
- eglMakeCurrent( (EGLDisplay)display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
- }
- thread->SetApi( api );
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
- process->RemoveThread( thread->Id() );
- if( process->ThreadCount() == 0 )
- {
- // All threads destroyed from process => it's not a process any more
- state->RemoveProcess( process->Id() );
- process = NULL;
- }
-#else
- releaseState();
-#endif
- return EGL_TRUE;
- }
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
- EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
- EGLConfig configId, const EGLint *attrib_list)
- {
- // \todo combine with eglCreatePbufferSurface()
- EGLI_ENTER_RET( EGL_NO_SURFACE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_NO_SURFACE );
-
- // EGLI_ENTER_RET macro above will fail if thread is not available
- CEGLThread* thread = getThread();
- switch( buftype )
- {
- case EGL_OPENVG_IMAGE:
- {
- if( !(thread->CurrentVGContext()) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ACCESS );
- }
- break;
- }
-
- default:
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
- }
-
- CEGLConfig* config = state->GetConfig( configId );
- if( !config )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_CONFIG );
- }
-
- if( !(state->VGInterface()) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
-
- CColorDescriptor colorDescriptor;
- int width = 0;
- int height = 0;
- if( !(state->VGInterface()->IsValidImage(buffer, &colorDescriptor, &width, &height)) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
- }
- if( display->FindSurfaceByClientBuffer( buffer ) != NULL ||
- state->VGInterface()->IsImageInUse( buffer ) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ACCESS );
- }
- if( !(colorDescriptor.MatchBitDepth(*(config->GetDescriptor()))) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
-
- EGLint textureFormat = EGL_NO_TEXTURE;
- EGLint textureTarget = EGL_NO_TEXTURE;
- EGLint mipmapTexture = EGL_FALSE;
- EGLint largestPbuffer = EGL_FALSE;
- EGLint colorSpace = colorDescriptor.isNonlinear() ? EGL_VG_COLORSPACE_sRGB : EGL_VG_COLORSPACE_LINEAR;
- EGLint alphaFormat = colorDescriptor.isPremultiplied() ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE;
-
- EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
- if( attrib_list && attrib_list[0] != EGL_NONE )
- {
- for( int i=0; attrib_list[i] != EGL_NONE; i+=2 )
- {
- EGLint value = attrib_list[i+1];
- switch( attrib_list[i] )
- {
- case EGL_TEXTURE_FORMAT:
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) &&
- !(renderableType & EGL_OPENGL_ES2_BIT) ||
- (value != EGL_TEXTURE_RGB &&
- value != EGL_TEXTURE_RGBA &&
- value != EGL_NO_TEXTURE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- textureFormat = value;
- break;
- }
-
- case EGL_TEXTURE_TARGET:
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) &&
- !(renderableType & EGL_OPENGL_ES2_BIT) ||
- (value != EGL_TEXTURE_2D &&
- value != EGL_NO_TEXTURE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- textureTarget = value;
- break;
- }
-
- case EGL_MIPMAP_TEXTURE:
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) ||
- !(renderableType & EGL_OPENGL_ES2_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- mipmapTexture = value;
- break;
- }
-
- default:
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
- }
- }
- }
-
- if( (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE) ||
- (textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
- }
-
- CEGLPbufferSurface* surface = EGLI_NEW CEGLPbufferSurface( colorSpace, alphaFormat,
- EGL_BACK_BUFFER, config, largestPbuffer, textureFormat, textureTarget, mipmapTexture, buffer );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- // \note AddSurface() will destroy the object if it fails to take ownership
- surface = (CEGLPbufferSurface*)display->AddSurface( surface );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- if( !(surface->Resize(width, height)) )
- {
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
-
- if( !(state->VGInterface()->CreateSurface(surface->Descriptor(), surface->VGBuffers(), buffer)) )
- {
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( surface );
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
- }
- surface->AddRef();
-
- EGLI_LEAVE_RET( surface, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surfaceId,
- EGLint attribute, EGLint value)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
- CEGLSurface* surface = display->GetSurface( surfaceId );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- surface->Lock();
- switch( attribute )
- {
- case EGL_MIPMAP_LEVEL:
- {
- if( !(surface->Config()->GetAttribute( EGL_RENDERABLE_TYPE ) & EGL_OPENGL_ES_BIT ))
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
- break;
- }
- case EGL_MULTISAMPLE_RESOLVE:
- {
- bool hasBoxBit = !!(surface->Config()->GetAttribute( EGL_SURFACE_TYPE ) & EGL_MULTISAMPLE_RESOLVE_BOX_BIT );
- if( value != EGL_MULTISAMPLE_RESOLVE_BOX ||
- value != EGL_MULTISAMPLE_RESOLVE_DEFAULT )
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
- }
- else if( value == EGL_MULTISAMPLE_RESOLVE_BOX && !hasBoxBit )
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
- break;
- }
- case EGL_SWAP_BEHAVIOR:
- {
- bool hasPreservedBit = !!(surface->Config()->GetAttribute( EGL_SURFACE_TYPE ) & EGL_SWAP_BEHAVIOR_PRESERVED_BIT );
- if( value != EGL_BUFFER_PRESERVED ||
- value != EGL_BUFFER_DESTROYED )
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
- }
- else if( value == EGL_BUFFER_PRESERVED && !hasPreservedBit )
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
- break;
- }
- default:
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
- }
-
- }
- surface->SetAttribute( attribute, value );
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surfaceId, EGLint buffer)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- // EGLI_ENTER_RET macro above will fail if thread is not available
- CEGLThread* thread = getThread();
-
- CEGLSurface* surface = display->GetSurface( surfaceId );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
-
- if( buffer != EGL_BACK_BUFFER )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
-
- if( thread->CurrentGLESContext() == NULL)
- {
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
- if( surface->IsLocked() )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- surface->Lock();
-
- CEGLSurface* glesReadSurface;
- thread->CurrentGLESSurfaces( &glesReadSurface, NULL );
- state->SyncSurface( EGL_OPENVG_API, 0, surface, glesReadSurface );
-
- EGLint renderableType = surface->Config()->GetAttribute( EGL_RENDERABLE_TYPE );
-
- if( (!(renderableType & EGL_OPENGL_ES_BIT) && !(renderableType & EGL_OPENGL_ES2_BIT)) ||
- surface->Type() != CEGLSurface::PBUFFER_SURFACE ||
- (surface->Config()->GetAttribute( EGL_BIND_TO_TEXTURE_RGB ) == EGL_FALSE &&
- surface->Config()->GetAttribute( EGL_BIND_TO_TEXTURE_RGBA ) == EGL_FALSE ) )
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- if( ((CEGLPbufferSurface*)surface)->TextureFormat() == EGL_NO_TEXTURE )
- {
- surface->Unlock();
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
- bool mipmapTexture = !!((CEGLPbufferSurface*)surface)->MipmapTexture();
- IEGLtoGLESInterface* iFace = state->GLESInterface( thread->CurrentGLESContext()->ClientVersion() );
- if( surface->BoundContext() == thread->CurrentGLESContext() )
- {
- iFace->Flush();
- }
- else
- {
- // \todo Wait for all issued client API commands drawing to the surface to complete.
- }
- int level = surface->Attribute( EGL_MIPMAP_LEVEL );
- int textureName = iFace->BindTexImage( surface, level, mipmapTexture, surface->Descriptor(), surface->VGColorBuffer());
- EGLITextureBinding& binding = surface->TextureBinding();
- binding.name = textureName;
- binding.level = level;
- binding.clientVersion = thread->CurrentGLESContext()->ClientVersion();
- binding.context = eglGetCurrentContext();
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surfaceId, EGLint buffer)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- // EGLI_ENTER_RET macro above will fail if thread is not available
- CEGLThread* thread = getThread();
-
- if( buffer != EGL_BACK_BUFFER )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
- CEGLSurface* surface = display->GetSurface( surfaceId );
- // \todo errors etc.
- if( !surface || (surface && surface->Type() != CEGLSurface::PBUFFER_SURFACE) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- if( ((CEGLPbufferSurface*)surface)->TextureFormat() == EGL_NO_TEXTURE )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
-
- EGLITextureBinding& binding = surface->TextureBinding();
-
- if( display->GetContext( binding.context ))
- {
- EGLenum origAPI = eglQueryAPI();
- EGLSurface origReadSurface, origDrawSurface;
- EGLContext origContext;
- bool switchAPI = origAPI == EGL_OPENGL_ES_API;
- bool switchContext = binding.context != thread->CurrentGLESContext();
- if( switchAPI )
- {
- eglBindAPI( EGL_OPENGL_ES_API );
- }
- if( switchContext )
- {
- // Switch to the context where the texture lives.
- origReadSurface = eglGetCurrentSurface(EGL_READ);
- origDrawSurface = eglGetCurrentSurface(EGL_DRAW);
- origContext = eglGetCurrentContext();
- eglMakeCurrent( display, surfaceId, surfaceId, binding.context );
- }
- state->GLESInterface(binding.clientVersion)->ReleaseTexImage( binding.name, binding.level );
- if( switchContext )
- {
- // Switch back to the original context.
- eglMakeCurrent( display, origDrawSurface, origReadSurface, origContext );
- }
- if( switchAPI )
- {
- eglBindAPI( origAPI );
- }
- }
- else
- {
- // The context has been destroyed. Ignore the call.
- }
- binding.name = 0;
- surface->Unlock();
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
-
- if( !(thread->CurrentVGContext()) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
- }
- if( !(thread->CurrentVGSurface()) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- // eglSwapInterval – hardcode EGL_MAX_SWAP_INTERVAL and EGL_MIN_SWAP_INTERVAL to 1, so nothing here
- if( thread->CurrentVGSurface()->Type() == CEGLSurface::WINDOW_SURFACE )
- {
- ((CEGLWindowSurface*)thread->CurrentVGSurface())->SetSwapInterval( /*interval*/ 1 );
- }
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig configId,
- EGLContext share_context,
- const EGLint *attrib_list)
- {
- EGLI_ENTER_RET( EGL_NO_CONTEXT );
- EGLI_GET_DISPLAY_RET( dpy, EGL_NO_CONTEXT );
-
- CEGLConfig* config = state->GetConfig( configId );
- if( !config )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONFIG );
- }
-
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
-
- EGLenum currentApi = thread->CurrentApi();
- if( currentApi == EGL_NONE )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_MATCH );
- }
-
- CEGLContext* shareContext = NULL;
- if( share_context != EGL_NO_CONTEXT )
- {
- shareContext = display->GetContext( share_context );
- if( !shareContext || (shareContext && process->Id() != shareContext->ProcessId()) )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_MATCH );
- }
- if( currentApi != shareContext->ClientApi() )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONTEXT );
- }
- }
-
- EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
- EGLint clientVersion = 1;
- if( attrib_list && attrib_list[0] != EGL_NONE )
- {
- switch( attrib_list[0] )
- {
- case EGL_CONTEXT_CLIENT_VERSION:
- {
- if( currentApi != EGL_OPENGL_ES_API )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE );
- }
- if( attrib_list[1] == 1 ) //GLES 1.1
- {
- if( !(renderableType & EGL_OPENGL_ES_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONFIG );
- }
- clientVersion = 1;
- }
- else if( attrib_list[1] == 2 ) //GLES 2.0
- {
- if( !(renderableType & EGL_OPENGL_ES2_BIT) )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONFIG );
- }
- clientVersion = 2;
- }
- else
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE );
- }
- break;
- }
-
- default:
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE );
- break;
- }
- }
- }
-
- void* clientContext = NULL;
- CEGLContext* context = NULL;
- switch( currentApi )
- {
- case EGL_OPENVG_API:
- {
- EGLI_ASSERT( state->VGInterface() != NULL );
- clientContext = state->VGInterface()->CreateContext(
- shareContext != NULL ? shareContext->ClientContext() : shareContext );
- if( clientContext )
- {
- context = EGLI_NEW CEGLContext( process->Id(), display, config, currentApi, clientVersion, clientContext );
- // \note AddContext() will destroy the object if it fails to take ownership
- context = display->AddContext( context );
- if( !context )
- {
- state->VGInterface()->ReleaseContext( clientContext );
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
- }
- }
- break;
- }
-
- case EGL_OPENGL_ES_API:
- {
- EGLINativeContextType nativeShareContext = shareContext != NULL ? shareContext->NativeContext() : NULL;
- EGLINativeContextType nativeContext = CEGLOs::CreateNativeContext( *config, display->NativeType(), nativeShareContext );
- if( !nativeContext )
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
- }
-
- IEGLtoGLESInterface* iFace = state->GLESInterface( clientVersion );
- EGLI_ASSERT( iFace != NULL );
- clientContext = state->GLESInterface( clientVersion )->CreateContext( nativeContext );
- if( clientContext )
- {
- context = EGLI_NEW CEGLContext( process->Id(), display, config, currentApi, clientVersion, clientContext );
- if( context )
- // \note AddContext() will destroy the object if it fails to take ownership
- context = display->AddContext( context );
- if( !context )
- {
- iFace->ReleaseContext( clientContext );
- CEGLOs::DestroyNativeContext( nativeContext );
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
- }
- context->SetNativeContext( nativeContext );
- }
- else
- {
- CEGLOs::DestroyNativeContext( nativeContext );
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
- }
- break;
- }
-
- case EGL_NONE:
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_MATCH );
- break;
- }
- }
-
- if( context )
- {
- context->AddRef();
- }
- else
- {
- EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
- }
-
- EGLI_LEAVE_RET( (EGLContext)context, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
-
- CEGLContext* context = display->GetContext( ctx );
- if( !context )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
- }
-
- EGLenum clientApi = context->ClientApi();
- switch( clientApi )
- {
- case EGL_OPENVG_API:
- {
- if( context->RemoveRef() )
- {
- state->VGInterface()->ReleaseContext(context->ClientContext());
- // \note RemoveContext() will destroy the object
- display->RemoveContext( context );
- }
- else
- {
- context->Terminate();
- }
- break;
- }
-
- case EGL_OPENGL_ES_API:
- {
- if( context->RemoveRef() )
- {
- if( !(state->GLESInterface( context->ClientVersion() )->ReleaseContext( context->ClientContext() )) )
- {
- // \todo Handle errors!
- EGLI_ASSERT( false );
- }
- if( context->NativeContext() && !(CEGLOs::DestroyNativeContext(context->NativeContext())) )
- {
- // \todo Handle errors!
- EGLI_ASSERT( false );
- }
- // \note RemoveContext() will destroy the object
- display->RemoveContext( context );
- }
- else
- {
- context->Terminate();
- }
- break;
- }
- }
-
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
- EGLSurface read, EGLContext ctx)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread );
-
- bool releaseCurrent = ( draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT );
-
- if( (ctx == EGL_NO_CONTEXT && draw != EGL_NO_SURFACE && read != EGL_NO_SURFACE) ||
- ((draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE) && ctx != EGL_NO_CONTEXT) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
-
- CEGLContext* context = display->GetContext( ctx );
- if( (!releaseCurrent && !context ) || (context && context->ProcessId() != process->Id()) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
- }
-
- EGLenum currentApi = thread->CurrentApi();
- CEGLContext* currentContext = NULL;
- CEGLSurface* currentDrawSurface = NULL;
- CEGLSurface* currentReadSurface = NULL;
- CEGLSurface* drawSurface = NULL;
- CEGLSurface* readSurface = NULL;
-
- if( !releaseCurrent )
- {
- if( context && context->ClientApi() == EGL_OPENVG_API && ( draw != read ) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
- drawSurface = display->GetSurface( draw );
- readSurface = display->GetSurface( read );
- if( !drawSurface || !readSurface )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
-
- if( !(context->Config()->IsCompatible( *(drawSurface->Config()), context->ClientApi())) ||
- !(context->Config()->IsCompatible( *(readSurface->Config()), context->ClientApi())) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
- }
-
- if( (context->Thread() && context->Thread() != thread) ||
- (drawSurface->BoundContext() && drawSurface->BoundContext()->Thread() != thread) ||
- (readSurface->BoundContext() && readSurface->BoundContext()->Thread() != thread) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
-
- if( drawSurface->Type() == CEGLSurface::WINDOW_SURFACE &&
- !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)drawSurface)->NativeType())) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_WINDOW );
- }
- if( readSurface != drawSurface && readSurface->Type() == CEGLSurface::WINDOW_SURFACE &&
- !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)readSurface)->NativeType())) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_WINDOW );
- }
-
- // TODO: If binding ctx would exceed the number of current contexts of that client
- // API type supported by the implementation, an EGL_BAD_ACCESS error is
- // generated.
-
- // TODO: If either draw or read are pbuffers created with eglCreatePbufferFromClientBuffer,
- // and the underlying bound client API buffers are in use by the
- // client API that created them, an EGL_BAD_ACCESS error is generated
-
- // TODO: If draw and read cannot fit into graphics memory simultaneously, an EGL_BAD_MATCH error is generated.
-
- // TODO: If the previous context of the calling thread has unflushed commands, and
- // the previous surface is no longer valid, an EGL_BAD_CURRENT_SURFACE
- // error is generated.
-
- // TODO: If the ancillary buffers for draw and read cannot be allocated, an EGL_BAD_ALLOC error is generated.
-
- // TODO: If a power management event has occurred, an EGL_CONTEXT_LOST error is generated.
-
- // TODO: flush context
- switch( context->ClientApi() )
- {
- case EGL_OPENVG_API:
- {
- state->VGInterface()->Flush();
- currentContext = thread->SwitchVGContext( context );
- currentDrawSurface = thread->SwitchVGSurface( drawSurface );
- drawSurface->BindToContext( context );
- if( !(state->VGInterface()->SetCurrentSurface(context->ClientContext(), drawSurface->VGClientSurface())) )
- {
- // Restore previous context/surface
- thread->SwitchVGContext( currentContext );
- thread->SwitchVGSurface( currentDrawSurface );
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- // \todo track changes through locking
- drawSurface->SetVGDirty( true );
- break;
- }
-
- case EGL_OPENGL_ES_API:
- {
- if( thread->CurrentGLESContext() )
- {
- state->GLESInterface(context->ClientVersion())->Flush();
- }
- currentContext = thread->SwitchGLESContext( context );
- thread->SwitchGLESSurfaces( drawSurface, readSurface, currentReadSurface, currentDrawSurface );
- drawSurface->BindToContext( context );
- if( drawSurface != readSurface )
- {
- readSurface->BindToContext( context );
- }
- EGLINativeContextType nativeContext = (EGLINativeContextType)state->GLESInterface(context->ClientVersion())->GetNativeContext( context->ClientContext() );
- if( !(context->NativeGLFunctions()) )
- {
- EGLINativeGLFunctions* nativeFuncs = EGLI_NEW EGLINativeGLFunctions;
- if( !nativeFuncs )
- {
- // Restore previous context/surface
- thread->SwitchGLESContext( currentContext );
- thread->SwitchGLESSurfaces( currentReadSurface, currentDrawSurface, readSurface, drawSurface );
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
- memset( nativeFuncs, 0, sizeof(EGLINativeGLFunctions) );
- if( !(CEGLOs::InitializeNativeGLFunctions(nativeFuncs, display->NativeType(), nativeContext)) )
- {
- // Restore previous context/surface
- thread->SwitchGLESContext( currentContext );
- thread->SwitchGLESSurfaces( currentReadSurface, currentDrawSurface, readSurface, drawSurface );
- delete nativeFuncs;
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
- context->SetNativeGLFucntions( nativeFuncs );
- }
- EGLINativeDisplayType drawDC = NULL;
- EGLINativeDisplayType readDC = NULL;
- if( drawSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- drawDC = ((CEGLPbufferSurface*)drawSurface)->NativeDisplay();
- }
- else if( drawSurface->Type() == CEGLSurface::WINDOW_SURFACE )
- {
- drawDC = ((CEGLWindowSurface*)drawSurface)->OsContext()->glesDisplay;
- }
-
- if( readSurface == drawSurface )
- {
- readDC = drawDC;
- }
- else if( readSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- readDC = ((CEGLPbufferSurface*)readSurface)->NativeDisplay();
- }
- else if( readSurface->Type() == CEGLSurface::WINDOW_SURFACE )
- {
- readDC = ((CEGLWindowSurface*)readSurface)->OsContext()->glesDisplay;
- }
-
- if( !(CEGLOs::MakeNativeContextCurrent(context->NativeGLFunctions(), drawDC, readDC, context->NativeContext())) )
- {
- // Restore previous context/surface. CEGLOs::MakeNativeContextCurrent() will restore previous
- // native context/surface on failure
- thread->SwitchGLESContext( currentContext );
- thread->SwitchGLESSurfaces( currentReadSurface, currentDrawSurface, readSurface, drawSurface );
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- break;
- }
-
- default:
- {
- EGLI_ASSERT( false );
- break;
- }
- }
- }
- else
- {
- switch( currentApi )
- {
- case EGL_OPENVG_API:
- {
- state->VGInterface()->Flush();
- if( thread->CurrentGLESContext() )
- {
- // Sync surface before releasing the VG context because there
- // might not be a VG context if GLES locks the surface later.
- CEGLSurface* glesReadSurface;
- thread->CurrentGLESSurfaces( &glesReadSurface, NULL );
- state->SyncSurface( EGL_OPENGL_API, thread->CurrentGLESContext()->ClientVersion(), thread->CurrentVGSurface(), glesReadSurface );
- }
- currentContext = thread->SwitchVGContext( NULL );
- currentDrawSurface = thread->SwitchVGSurface( NULL );
- break;
- }
-
- case EGL_OPENGL_ES_API:
- {
- if( thread->CurrentGLESContext() )
- {
- state->GLESInterface(thread->CurrentGLESContext()->ClientVersion())->Flush();
- }
- if( thread->CurrentVGContext() )
- {
- // Sync surface before releasing the GLES context because there
- // might not be a GLES context if VG locks the surface later.
- CEGLSurface* glesReadSurface;
- CEGLSurface* glesDrawSurface;
- thread->CurrentGLESSurfaces( &glesReadSurface, &glesDrawSurface );
- state->SyncSurface( EGL_OPENVG_API, 0, glesReadSurface, glesReadSurface );
- if( glesDrawSurface != glesReadSurface )
- {
- state->SyncSurface( EGL_OPENVG_API, 0, glesDrawSurface, NULL );
- }
- }
- currentContext = thread->SwitchGLESContext( NULL );
- thread->SwitchGLESSurfaces( NULL, NULL, currentReadSurface, currentDrawSurface );
- break;
- }
- }
- }
-
- if( currentDrawSurface && currentDrawSurface != drawSurface )
- {
- currentDrawSurface->BindToContext( NULL );
- if( currentDrawSurface->RemoveRef() )
- {
- if( currentDrawSurface->VGClientSurface() )
- {
- if( !(state->VGInterface()->ReleaseSurface(currentDrawSurface->VGClientSurface())) )
- {
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- }
- if( currentDrawSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- //((CEGLPbufferSurface*)currentDrawSurface)->SetNativePbufferContainer( NULL );
- //EGLI_ASSERT( false );
- }
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( currentDrawSurface );
- }
- if( currentReadSurface == currentDrawSurface )
- {
- currentReadSurface = NULL;
- }
- currentDrawSurface = NULL;
- }
-
- if( currentReadSurface && currentReadSurface != readSurface )
- {
- currentReadSurface->BindToContext( NULL );
- if( currentReadSurface->RemoveRef() )
- {
- if( currentReadSurface->VGClientSurface() )
- {
- if( !(state->VGInterface()->ReleaseSurface(currentReadSurface->VGClientSurface())) )
- {
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- }
- if( currentReadSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
- {
- // \todo
- ((CEGLPbufferSurface*)currentReadSurface)->SetNativePbufferContainer( NULL );
- }
- // \note RemoveSurface() will destroy the object
- display->RemoveSurface( currentReadSurface );
- }
- }
-
- if( currentContext && currentContext != context )
- {
- currentContext->SetThread( NULL );
- if( currentContext->RemoveRef() )
- {
- if( currentContext->ClientContext() )
- {
- if( currentContext->ClientApi() == EGL_OPENVG_API )
- {
- bool success = state->VGInterface()->ReleaseContext( currentContext->ClientContext() );
- EGLI_ASSERT( success );
- }
- if( currentContext->ClientApi() == EGL_OPENGL_ES_API )
- {
- bool success = state->GLESInterface(currentContext->ClientVersion())->ReleaseContext(currentContext->ClientContext());
- EGLI_ASSERT( success );
- }
- }
- if( currentContext->NativeContext() )
- {
- if( !(CEGLOs::DestroyNativeContext(currentContext->NativeContext())) )
- {
- // \todo Handle errors!
- EGLI_ASSERT( false );
- }
- }
- // \note RemoveContext() will destroy the object
- display->RemoveContext( currentContext );
- currentContext = NULL;
- }
- }
- if( context && currentContext != context )
- {
- context->AddRef();
- }
- if( drawSurface && currentDrawSurface != drawSurface )
- {
- drawSurface->AddRef();
- }
- if( readSurface && readSurface != drawSurface && readSurface != currentReadSurface )
- {
- readSurface->AddRef();
- }
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-
-EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void)
- {
- EGLI_ENTER_RET( EGL_NO_CONTEXT );
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
- EGLContext ret = EGL_NO_CONTEXT;
- switch( thread->CurrentApi() )
- {
- case EGL_OPENVG_API:
- {
- if( thread->CurrentVGContext() )
- {
- ret = thread->CurrentVGContext();
- }
- break;
- }
- case EGL_OPENGL_ES_API:
- {
- if( thread->CurrentGLESContext() )
- {
- ret = thread->CurrentGLESContext();
- }
- break;
- }
- }
- EGLI_LEAVE_RET( ret, EGL_SUCCESS );
- }
-
-EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)
- {
- EGLI_ENTER_RET( EGL_NO_SURFACE );
- if( readdraw != EGL_READ && readdraw != EGL_DRAW )
- {
- EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
- }
-
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
-
- EGLSurface ret = EGL_NO_SURFACE;
- EGLenum currentApi = thread->CurrentApi();
- switch( currentApi )
- {
- case EGL_OPENVG_API:
- {
- CEGLContext* context = thread->CurrentVGContext();
- if( context )
- {
- ret = thread->CurrentVGSurface();
- }
- break;
- }
-
- case EGL_OPENGL_ES_API:
- {
- CEGLSurface* read = NULL;
- CEGLSurface* draw = NULL;
- thread->CurrentGLESSurfaces( &read, &draw );
- switch( readdraw )
- {
- case EGL_READ:
- {
- ret = (EGLSurface)read;
- break;
- }
-
- case EGL_DRAW:
- {
- ret = (EGLSurface)draw;
- break;
- }
- }
- break;
- }
-
- default:
- {
- EGLI_ASSERT( false );
- }
- }
- EGLI_LEAVE_RET( ret, EGL_SUCCESS );
- }
-
-EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)
- {
- EGLI_ENTER_RET( EGL_NO_DISPLAY );
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread );
- EGLenum currentApi = thread->CurrentApi();
- EGLDisplay ret = EGL_NO_DISPLAY;
- switch( currentApi )
- {
- case EGL_OPENVG_API:
- {
- if( thread->CurrentVGContext() )
- {
- ret = (EGLDisplay)thread->CurrentVGContext()->Display();
- }
- break;
- }
- case EGL_OPENGL_ES_API:
- {
- if( thread->CurrentGLESContext() )
- {
- ret = (EGLDisplay)thread->CurrentGLESContext()->Display();
- }
- break;
- }
-
- default:
- EGLI_ASSERT( false );
- }
- EGLI_LEAVE_RET( ret, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
- EGLint attribute, EGLint *value)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE )
- if( !value )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
- }
- CEGLContext* context = display->GetContext( ctx );
- if( !context )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
- }
- switch( attribute )
- {
- case EGL_CONFIG_ID:
- {
- *value = ((CEGLConfig*)context->Config())->GetAttribute( EGL_CONFIG_ID );
- break;
- }
-
- case EGL_CONTEXT_CLIENT_TYPE:
- {
- *value = context->ClientApi();
- break;
- }
-
- case EGL_CONTEXT_CLIENT_VERSION:
- {
- *value = context->ClientVersion();
- break;
- }
-
- case EGL_RENDER_BUFFER:
- {
- CEGLSurface* surface = NULL;
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
- if( thread->CurrentVGContext() == context )
- {
- surface = thread->CurrentVGSurface();
- }
- else if( thread->CurrentGLESContext() == context )
- {
- thread->CurrentGLESSurfaces( NULL, &surface );
- }
- else
- {
- surface = process->FindBoundSurface( context, false );
- }
- if( surface )
- {
- *value = surface->RenderBuffer();
- }
- else
- {
- *value = EGL_NONE;
- }
- break;
- }
-
- default:
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
- }
- }
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- // EGLI_ENTER_RET macro above will fail if thread is not available
- CEGLThread* thread = getThread();
- EGLBoolean ret = EGL_TRUE;
- EGLenum api = eglQueryAPI();
- if( eglBindAPI( EGL_OPENGL_ES_API ) )
- {
- ret = eglWaitClient();
- if( thread->IsSupportedApi(api) )
- {
- eglBindAPI( api );
- }
- }
- EGLI_LEAVE_RET( ret, thread->Error() );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- // eglWaitNative – no-op, as no such thing as native rendering to pbuffers
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surfaceId)
- {
- // \todo eglSwapBuffers – all surfaces are single-buffered pbuffers, so this just needs to do a flush in the current client API
- EGLI_ENTER_RET( EGL_FALSE );
- EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
-
- // EGLI_ENTER_RET macro above will fail if thread is not available
- CEGLThread* thread = getThread();
-
- CEGLSurface* surface = display->GetSurface( surfaceId );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- EGLenum currentApi = thread->CurrentApi();
- switch( currentApi )
- {
- case EGL_OPENVG_API:
- {
- if( thread->CurrentVGContext() != surface->BoundContext() )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- break;
- }
- case EGL_OPENGL_ES_API:
- {
- if( thread->CurrentGLESContext() != surface->BoundContext() )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
- // \todo other GLES stuff?
- }
- }
- if( surface->Type() != CEGLSurface::WINDOW_SURFACE || surface->RenderBuffer() == EGL_SINGLE_BUFFER )
- {
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
- if( !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)surface)->NativeType())) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_WINDOW );
- }
-#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
- int w, h;
- if( !(CEGLOs::GetNativeWindowSize(((CEGLWindowSurface*)surface)->NativeType(), w, h)) )
- {
- // \todo Error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
- }
-#else
- int w = surface->Width();
- int h = surface->Height();
-#endif
- if( surface->Width() != w || surface->Height() != h )
- {
- if( !(surface->Resize(w, h)) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
- if( w <= 0 || h <= 0 )
- {
- // invisible window => do nothing
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
- if( surface->VGClientSurface() && state->VGInterface() )
- {
- if( !(state->VGInterface()->ResizeSurface(thread->CurrentVGContext()->ClientContext(),
- surface->VGClientSurface(), w, h, surface->VGBuffers())) )
- {
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
- }
- }
- }
-
- EGLint stride = surface->Stride();
- void* buf = ((CEGLWindowSurface*)surface)->CurrentBuffer();
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
- buf = (void*)((char*)buf + ((surface->Height() - 1) * stride));
-#else
- switch( currentApi )
- {
- case EGL_OPENVG_API:
- {
- state->VGInterface()->CopyBuffers( buf, surface->Stride(), surface->VGClientSurface() );
- break;
- }
- case EGL_OPENGL_ES_API:
- {
- if( surface->BoundContext() && !(state->GLESInterface(surface->BoundContext()->ClientVersion())) )
- {
- // \todo error code?
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
- }
- }
- }
-#endif
- CEGLOs::BlitToOSWindow( currentApi, display, ((CEGLWindowSurface*)surface)->OsContext(), buf, surface->Width(), surface->Height(), stride );
- EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
- }
-
-EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
- EGLNativePixmapType target)
- {
- EGLI_ENTER_RET( EGL_FALSE );
- // eglCopyBuffers always raises EGL_BAD_NATIVE_PIXMAP error (as no native pixmaps supported)
- EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_PIXMAP );
- }
-
-/* Now, define eglGetProcAddress using the generic function ptr. type */
-EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
- eglGetProcAddress(const char *procname)
- {
- EGLI_ENTER_RET( NULL );
- // \todo EGL
- __eglMustCastToProperFunctionPointerType ret = NULL;
- if( strncmp( procname, "vg", 2 ) == 0 )
- {
- ret = state->VGInterface()->GetVGProcAddress( procname );
- }
- else if( strncmp( procname, "egl", 3 ) == 0 )
- {
- ret = (__eglMustCastToProperFunctionPointerType)CEGLExtension::eglGetProcAddress( procname );
- }
- else if( strncmp( procname, "gl", 2 ) == 0 )
- {
- ret = state->GLESInterface(2)->GetGLProcAddress( procname );
- if( ret == NULL )
- {
- // Not found in GLES2, try GLES1.
- ret = state->GLESInterface(1)->GetGLProcAddress( procname );
- }
- }
- else
- {
- // return just NULL pointer...
- }
- EGLI_LEAVE_RET( ret, EGL_SUCCESS );
- }
-
-#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
-// non-standard platsim functions
-EGLAPI void EGLAPIENTRY eglPlatsimSetProcessInformation( EGLint processId, EGLint threadId )
- {
- EGLI_ENTER_RET(EGLI_NO_RET);
- if( process && process->Id() != processId )
- {
- process = state->GetProcess( processId );
- }
- if( !process )
- {
- process = state->AddProcess( processId, true );
- EGLI_ASSERT( process != NULL );
- CEGLThread* thread = process->AddThread( threadId, true, state->SupportedApis() );
- EGLI_ASSERT( thread != NULL );
- }
- else if( !(process->HasThread( threadId )) )
- {
- CEGLThread* thread = process->AddThread( threadId, true, state->SupportedApis() );
- EGLI_ASSERT( thread != NULL );
- }
- else
- {
- state->SetCurrentProcessThread( processId, threadId );
- }
- EGLI_LEAVE_RET( EGLI_NO_RET, EGL_SUCCESS );
- }
-
-EGLAPI EGLint EGLAPIENTRY eglPlatsimGetError()
- {
- //TODO
- EGLI_ENTER_RET( EGL_SUCCESS );
- EGLI_ASSERT( process != NULL );
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
- EGLint err = thread->Error();
- EGLI_LEAVE_RET( err, err );
- }
-
-// This is called after eglCreateWindowSurface()
-EGLAPI void EGLAPIENTRY eglPlatsimSetSurfaceParams(
- EGLDisplay displayId, EGLSurface surfaceId, EGLint width, EGLint height,
- EGLint stride, void* buffer0, void *buffer1)
- {
- EGLI_ENTER_RET( EGLI_NO_RET );
- CEGLDisplay* display = state->GetDisplay( displayId );
- if( !display || (display && !(display->IsInitialized())) )
- {
- EGLI_LEAVE_RET( EGLI_NO_RET, EGL_NOT_INITIALIZED );
- }
- EGLI_ASSERT( display->ProcessId() == process->Id() );
-
- CEGLSurface* surface = display->GetSurface( surfaceId );
- if( !surface )
- {
- EGLI_LEAVE_RET( EGLI_NO_RET, EGL_BAD_SURFACE );
- }
-
- EGLI_ASSERT( surface->Type() == CEGLSurface::WINDOW_SURFACE );
- if( !(surface->Resize(width, height)) )
- {
- EGLI_LEAVE_RET( EGLI_NO_RET, EGL_BAD_ALLOC );
- }
- ((CEGLWindowSurface*)surface)->SetStride( stride );
- ((CEGLWindowSurface*)surface)->SetWindowBuffers( buffer0, buffer1 );
-
- CEGLThread* thread = process->CurrentThread();
- EGLI_ASSERT( thread != NULL );
- //TODO: resizing
- switch( thread->CurrentApi() )
- {
- case EGL_OPENVG_API:
- {
- if( !(surface->VGColorBuffer()) )
- {
- EGLI_ASSERT( state->VGInterface() != NULL );
- SurfaceDescriptor* surfaceDesc = surface->Descriptor();
- bool success = state->VGInterface()->CreateSurface( surfaceDesc, surface->VGBuffers(), NULL );
- EGLI_ASSERT( success );
- }
- break;
- }
- case EGL_OPENGL_ES_API:
- {
- //TODO: GLES not implemented
- //EGLI_ASSERT( false );
- break;
- }
- default:
- {
- EGLI_ASSERT( false );
- }
- }
-
- //TODO: what else?
- EGLI_LEAVE_RET( EGLI_NO_RET, EGL_SUCCESS );
- }
-
-EGLAPI EGLNativePixmapType EGLAPIENTRY eglPlatsimGetPixmapSurfaceBitmap( EGLDisplay display, EGLSurface surface)
- {
- //TODO
- return NULL;
- }
-#endif
-
-#if defined(_WIN32)
-
-BOOL WINAPI DllMain( HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved )
- {
-#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
- switch( fdwReason )
- {
- case DLL_PROCESS_ATTACH:
- {
- g_tlsIndex = TlsAlloc();
- if( g_tlsIndex == TLS_OUT_OF_INDEXES )
- return FALSE;
- if( !g_lockInitialized )
- {
- CEGLOs::InitializeLock( &g_eglLock );
- g_lockInitialized = true;
- }
- break;
- }
- case DLL_THREAD_ATTACH:
- {
- break;
- }
-
- case DLL_THREAD_DETACH:
- {
- break;
- }
- case DLL_PROCESS_DETACH:
- {
- if( g_eglState )
- {
- EGLI_ASSERT( g_eglState->RefCount() == 0 );
- delete g_eglState;
- g_eglState = NULL;
- }
- if( g_lockInitialized )
- {
- CEGLOs::DestroyLock( &g_eglLock );
- g_lockInitialized = false;
- }
- if( g_tlsIndex != TLS_OUT_OF_INDEXES )
- {
- TlsFree( g_tlsIndex );
- }
- break;
- }
- }
-#else
-switch( fdwReason )
- {
- case DLL_PROCESS_ATTACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- {
- break;
- }
- case DLL_PROCESS_DETACH:
- {
- EGLI_ASSERT( g_eglState == NULL );
- break;
- }
- }
-#endif // EGLI_USE_PLATSIM_EXTENSIONS
-
- return TRUE;
- }
-
-#endif // _WIN32
-
-#ifdef __cplusplus
-}
-#endif
+/* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and /or associated documentation files
+ * (the "Materials "), to deal in the Materials without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Materials,
+ * and to permit persons to whom the Materials are furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
+ * THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:
+ *
+ */
+
+#include <string.h>
+#include <algorithm>
+#include <EGL/egl.h>
+#include "eglDefinitions.h"
+#include "eglInternal.h"
+#include "EGLState.h"
+#include "EGLProcess.h"
+#include "EGLDisplay.h"
+#include "EGLThread.h"
+#include "EGLContext.h"
+#include "EGLConfig.h"
+#include "EGLWindowSurface.h"
+#include "EGLPbufferSurface.h"
+#include "ColorDescriptor.h"
+#include "SurfaceDescriptor.h"
+#include "EGLExtension.h"
+#include "EGLOs.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+#else
+ // \todo other platforms
+#endif
+
+#if defined(_WIN32) && !defined(EGLI_USE_PLATSIM_EXTENSIONS)
+static DWORD g_tlsIndex = TLS_OUT_OF_INDEXES;
+#endif
+
+static CEGLState* g_eglState = NULL;
+static bool g_lockInitialized = false;
+EGLI_LOCK g_eglLock;
+
+CEGLState* getState()
+ {
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ if( !g_eglState )
+ {
+ g_eglState = EGLI_NEW CEGLState();
+ if( !g_eglState )
+ {
+ return NULL;
+ }
+ if( !(g_eglState->Initialize()) )
+ {
+ delete g_eglState;
+ g_eglState = NULL;
+ return NULL;
+ }
+ g_eglState->AddRef();
+ }
+ return g_eglState;
+#elif defined(_WIN32)
+ CEGLOs::GetLock( &g_eglLock );
+ if( !g_eglState )
+ {
+ g_eglState = EGLI_NEW CEGLState();
+ if( !g_eglState )
+ {
+ CEGLOs::ReleaseLock( &g_eglLock );
+ return NULL;
+ }
+ if( !(g_eglState->Initialize()) )
+ {
+ delete g_eglState;
+ g_eglState = NULL;
+ CEGLOs::ReleaseLock( &g_eglLock );
+ return NULL;
+ }
+ }
+ EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
+ if( g_tlsIndex == TLS_OUT_OF_INDEXES )
+ {
+ CEGLOs::ReleaseLock( &g_eglLock );
+ return NULL;
+ }
+ CEGLThread* thread = (CEGLThread*)TlsGetValue( g_tlsIndex );
+ if( g_eglState && !thread )
+ {
+ // \todo Remove CEGLProcess when platsim extensions are not needed any more
+ thread = g_eglState->GetCurrentProcess()->AddThread( GetCurrentThreadId(), true, g_eglState->SupportedApis() );
+ if( !thread )
+ {
+ CEGLOs::ReleaseLock( &g_eglLock );
+ return NULL;
+ }
+ if( !(TlsSetValue( g_tlsIndex, (void *)thread )) )
+ {
+ CEGLOs::ReleaseLock( &g_eglLock );
+ return NULL;
+ }
+ g_eglState->AddRef();
+ }
+ CEGLOs::ReleaseLock( &g_eglLock );
+ return g_eglState;
+#else // Linux
+ // \todo
+ return NULL;
+#endif
+ }
+
+static void releaseState()
+ {
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ if( g_eglState )
+ {
+ if( g_eglState->RemoveRef() )
+ {
+ delete g_eglState;
+ g_eglState = NULL;
+ }
+ }
+#elif defined(_WIN32)
+ CEGLOs::GetLock( &g_eglLock );
+ if( g_eglState )
+ {
+ g_eglState->GetCurrentProcess()->RemoveThread( GetCurrentThreadId() );
+ EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
+ if( g_tlsIndex != TLS_OUT_OF_INDEXES )
+ {
+ TlsSetValue( g_tlsIndex, 0 );
+ }
+ }
+ if( g_eglState && g_eglState->RemoveRef() )
+ {
+ delete g_eglState;
+ g_eglState = NULL;
+ }
+ CEGLOs::ReleaseLock( &g_eglLock );
+#else // Linux
+ // \todo
+ EGLI_ASSERT( false );
+#endif
+ }
+
+/*static*/ CEGLThread* getThread()
+ {
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ CEGLState* state = getState();
+ CEGLProcess* process = state->GetCurrentProcess();
+ if( process )
+ {
+ return process->CurrentThread();
+ }
+ return NULL;
+#elif defined(_WIN32)
+ EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
+ if( g_tlsIndex == TLS_OUT_OF_INDEXES )
+ return NULL;
+ CEGLThread* thread = (CEGLThread*)TlsGetValue( g_tlsIndex );
+ if( !thread && GetLastError() == ERROR_SUCCESS )
+ {
+ // TlsGetValue() succeeded but didn't have thread => create one now
+ CEGLState* state = getState();
+ if( state )
+ {
+ thread = (CEGLThread*)TlsGetValue( g_tlsIndex );
+ }
+ }
+ return thread;
+#else // Linux
+ // \todo
+ EGLI_ASSERT( false );
+#endif
+ }
+
+void setEGLError( EGLint error )
+ {
+ CEGLThread* thread = getThread();
+ if( thread )
+ {
+ thread->SetError( error );
+ }
+ }
+
+#define EGLI_GET_DISPLAY_RET(id,ret)\
+ CEGLDisplay* display = state->GetDisplay( id );\
+ if( !display )\
+ {\
+ EGLI_LEAVE_RET( ret, EGL_BAD_DISPLAY );\
+ }\
+ EGLI_ASSERT( display->ProcessId() == process->Id() );\
+ if( !(display->IsInitialized()) )\
+ {\
+ EGLI_LEAVE_RET( ret, EGL_NOT_INITIALIZED );\
+ }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*When there is no status to return (in other words, when eglGetError is called
+as the first EGL call in a thread, or immediately after calling eglReleaseThread),
+EGL_SUCCESS will be returned.*/
+EGLAPI EGLint EGLAPIENTRY eglGetError(void)
+ {
+ EGLint err = EGL_SUCCESS;
+ CEGLThread* thread = getThread();
+ if( thread )
+ {
+ err = thread->Error();
+ thread->SetError( EGL_SUCCESS );
+ }
+ else
+ {
+ err = EGL_BAD_ALLOC;
+ }
+ return err;
+ }
+
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
+ {
+ EGLI_ENTER_RET( EGL_NO_DISPLAY );
+
+ if( display_id == EGL_DEFAULT_DISPLAY )
+ {
+ display_id = (EGLNativeDisplayType)state->DefaultDisplay();
+ }
+
+ CEGLDisplay* display = state->GetDisplayByNativeType( (EGLINativeDisplayType)display_id, process->Id() );
+ if( !display )
+ {
+ if( !(CEGLOs::IsValidNativeDisplay( (EGLINativeDisplayType)display_id )) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_DISPLAY, EGL_BAD_PARAMETER );
+ }
+ display = state->AddDisplay( (EGLINativeDisplayType)display_id, process->Id() );
+ if( !display )
+ {
+ EGLI_LEAVE_RET( EGL_NO_DISPLAY, EGL_BAD_ALLOC );
+ }
+ display->AddRef();
+ }
+ EGLI_LEAVE_RET( (EGLDisplay)display, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+
+ CEGLDisplay* display = state->GetDisplay( dpy );
+ if( !display )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
+ }
+
+ if( !(display->IsInitialized()) && !(display->Initialize()) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_NOT_INITIALIZED );
+ }
+
+ if( major ) *major = 1;
+ if( minor ) *minor = 4;
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ CEGLDisplay* display = state->GetDisplay( dpy );
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ if( display && display->ProcessId() != process->Id() )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
+ }
+#endif
+ if( !display )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_DISPLAY );
+ }
+
+ if( !(display->IsInitialized()) )
+ {
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+ display->RemoveRef();
+ if( display->TerminateDisplay() )
+ {
+ state->RemoveDisplay( display );
+ }
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+/*
+ eglQueryString returns a pointer to a static, zero-terminated string describing
+ some aspect of the EGL implementation running on the specified display. name
+ may be one of EGL_CLIENT_APIS, EGL_EXTENSIONS, EGL_VENDOR, or EGL_-
+ VERSION.
+ The EGL_CLIENT_APIS string describes which client rendering APIs are
+ supported. It is zero-terminated and contains a space-separated list of API
+ names, which must include at least one of ‘‘OpenGL’’, ‘‘OpenGL_ES’’ or
+ ‘‘OpenVG’’.
+ The EGL_EXTENSIONS string describes which EGL extensions are supported
+ by the EGL implementation running on the specified display. The string is zeroterminated
+ and contains a space-separated list of extension names; extension names
+ themselves do not contain spaces. If there are no extensions to EGL, then the empty
+ string is returned.
+ The format and contents of the EGL_VENDOR string is implementation dependent.
+ The format of the EGL_VERSION string is:
+ <major version.minor version><space><vendor specific info>
+*/
+
+EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
+ {
+ EGLI_ENTER_RET( NULL );
+ EGLI_GET_DISPLAY_RET( dpy, NULL );
+
+ const char* ret = NULL;
+ switch(name)
+ {
+ case EGL_CLIENT_APIS:
+ {
+ switch( state->SupportedApis() )
+ {
+ case EGL_OPENVG_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT:
+ {
+ ret = "OpenVG OpenGL_ES OpenGL_ES2";
+ break;
+ }
+
+ case EGL_OPENVG_BIT | EGL_OPENGL_ES_BIT:
+ {
+ ret = "OpenVG OpenGL_ES";
+ break;
+ }
+
+ case EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT:
+ {
+ ret = "OpenVG OpenGL_ES2";
+ break;
+ }
+
+ case EGL_OPENVG_BIT:
+ {
+ ret = "OpenVG";
+ break;
+ }
+
+ case EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT:
+ {
+ ret = "OpenGL_ES OpenGL_ES2";
+ break;
+ }
+
+ case EGL_OPENGL_ES_BIT:
+ {
+ ret = "OpenGL_ES";
+ break;
+ }
+
+ case EGL_OPENGL_ES2_BIT:
+ {
+ ret = "OpenGL_ES2";
+ break;
+ }
+
+ default:
+ {
+ ret = "";
+ break;
+ }
+ }
+ break;
+ }
+ case EGL_EXTENSIONS:
+ {
+ // TODO
+ ret = "EGL_KHR_image_base";
+ break;
+ }
+ case EGL_VENDOR:
+ {
+ ret = "Nokia";
+ break;
+ }
+ case EGL_VERSION:
+ {
+ ret ="1.4 PlatSim";
+ break;
+ }
+
+ default:
+ {
+ EGLI_LEAVE_RET( NULL, EGL_BAD_PARAMETER );
+ break;
+ }
+ }
+ EGLI_LEAVE_RET( ret, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
+ EGLint config_size, EGLint *num_config)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ if( !num_config )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ EGLint configCount = state->ConfigCount();
+ if( !configs )
+ {
+ *num_config = configCount;
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+ *num_config = EGLI_MIN( configCount, config_size );
+
+ state->FillConfigs( configs, *num_config );
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
+ EGLConfig *configs, EGLint config_size,
+ EGLint *num_config)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ CColorDescriptor* colorDesc = EGLI_NEW CColorDescriptor( 0, 0, 0, 0, true, 0, false, 0, 0 );
+ if( !colorDesc )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+ colorDesc->SetAttribute( EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER );
+ CEGLConfig* filter = EGLI_NEW CEGLConfig(
+ *colorDesc,
+ EGL_DONT_CARE,
+ EGL_DONT_CARE,
+ EGL_DONT_CARE,
+ EGL_DONT_CARE,
+ 0, 0, 0,
+ EGL_DONT_CARE,
+ EGL_DONT_CARE,
+ EGL_DONT_CARE,
+ EGL_DONT_CARE,
+ EGL_OPENGL_ES_BIT,
+ 0, 0, 0,
+ EGL_WINDOW_BIT,
+ NULL ); // transparent color
+ delete colorDesc;
+ colorDesc = NULL;
+ if( !filter )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+
+ EGLint configId = 0;
+ EGLint matchPixmap = EGL_NONE;
+
+ if( attrib_list && attrib_list[0] != EGL_NONE )
+ {
+ for( EGLint i=0; attrib_list[i] != EGL_NONE && configId == 0; i+=2 )
+ {
+ switch( attrib_list[i] )
+ {
+ case EGL_NATIVE_VISUAL_ID:
+ case EGL_MAX_PBUFFER_HEIGHT:
+ case EGL_MAX_PBUFFER_PIXELS:
+ case EGL_MAX_PBUFFER_WIDTH:
+ {
+ // IGNORED
+ break;
+ }
+
+ case EGL_CONFIG_ID:
+ {
+ configId = attrib_list[i+1];
+ break;
+ }
+
+ case EGL_MATCH_NATIVE_PIXMAP:
+ {
+ matchPixmap = attrib_list[i+1];
+ break;
+ }
+ default:
+ {
+ if( !(filter->SetAttribute(attrib_list[i], attrib_list[i+1])) )
+ {
+ delete filter;
+ filter = NULL;
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
+ }
+ }
+ }
+ }
+ }
+
+ if( configId > 0 )
+ {
+ CEGLConfig* config = state->FindConfigById( configId );
+ if( !config )
+ {
+ delete filter;
+ filter = NULL;
+ // TODO: is this correct error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+ *num_config = 1;
+ configs[0] = (EGLConfig)config;
+ delete filter;
+ filter = NULL;
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+ if( matchPixmap != EGL_NONE )
+ {
+ // eglChooseConfig – only pbuffer supported, so no need for EGL_MATCH_NATIVE_PIXMAP
+ }
+
+ *num_config = state->MatchConfigs( filter, configs, config_size );
+ delete filter;
+ filter = NULL;
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig configId,
+ EGLint attribute, EGLint *value)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+ if( !value )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+ CEGLConfig* config = state->GetConfig( configId );
+ if( !config )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONFIG );
+ }
+ EGLint val = config->GetAttribute( attribute );
+ if( val == EGL_BAD_ATTRIBUTE )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, val );
+ }
+ *value = val;
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig configId,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list)
+ {
+ EGLI_ENTER_RET( EGL_NO_SURFACE );
+ EGLI_GET_DISPLAY_RET ( dpy, EGL_NO_SURFACE );
+ // \todo eglCreateWindowSurface – EGL_BAD_MATCH raised (as no window-supporting configs)
+ CEGLConfig* config = state->GetConfig( configId );
+ if( !config )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_CONFIG );
+ }
+ EGLint surfaceType = config->GetAttribute( EGL_SURFACE_TYPE );
+ if( !(surfaceType & EGL_WINDOW_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+ CEGLSurface* surface = display->GetSurfaceByNativeType( (EGLINativeWindowType)win );
+ if( surface && surface->Config() == config )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+
+ EGLint renderBuffer = EGL_BACK_BUFFER;
+ EGLint colorSpace = EGL_VG_COLORSPACE_sRGB;
+ EGLint alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
+ EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
+ if( attrib_list && attrib_list[0] != EGL_NONE )
+ {
+ for( int i=0; attrib_list[i] != EGL_NONE; i+=2 )
+ {
+ switch( attrib_list[i] )
+ {
+ case EGL_RENDER_BUFFER:
+ renderBuffer = attrib_list[i+1];
+ break;
+
+ case EGL_VG_COLORSPACE:
+ if( !(renderableType & EGL_OPENVG_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ colorSpace = attrib_list[i+1];
+ break;
+
+ case EGL_VG_ALPHA_FORMAT:
+ if( !(renderableType & EGL_OPENVG_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ alphaFormat = attrib_list[i+1];
+ break;
+
+ default:
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ }
+ }
+
+ if( !(surfaceType & colorSpace) || !(surfaceType & alphaFormat) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+
+ if( !CEGLOs::IsValidNativeWindow( win ) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_NATIVE_WINDOW );
+ }
+
+ EGLIOsWindowContext* osContext = CEGLOs::CreateOSWindowContext( win, *config );
+ if( !osContext )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+
+ surface = EGLI_NEW CEGLWindowSurface( config, colorSpace, alphaFormat, renderBuffer, osContext );
+ if( !surface )
+ {
+ CEGLOs::DestroyOSWindowContext( osContext );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ // \note AddSurface() will destroy the object if it fails to take ownership
+ surface = display->AddSurface( surface );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ int width = 0;
+ int height = 0;
+ if( !CEGLOs::GetNativeWindowSize( win, width, height ) ||
+ !(surface->Resize( width, height )) )
+ {
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ // \todo Is this correct error?
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ if( (state->SupportedApis() & EGL_OPENVG_BIT) && (renderableType & EGL_OPENVG_BIT) )
+ {
+ SurfaceDescriptor* surfaceDesc = surface->Descriptor();
+ if( !(state->VGInterface()->CreateSurface( surfaceDesc, surface->VGBuffers(), NULL )) )
+ {
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ }
+#endif // EGLI_USE_PLATSIM_EXTENSIONS
+
+ surface->AddRef();
+
+ EGLI_LEAVE_RET( (EGLSurface)surface, EGL_SUCCESS );
+ }
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig configId,
+ const EGLint *attrib_list)
+ {
+ // \todo combine with eglCreatePbufferFromClientBuffer()
+ EGLI_ENTER_RET( EGL_NO_SURFACE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_NO_SURFACE );
+ CEGLConfig* config = state->GetConfig( configId );
+ if( !config )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_CONFIG );
+ }
+
+ if( !(config->GetAttribute( EGL_SURFACE_TYPE ) & EGL_PBUFFER_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+
+ EGLint width = 0;
+ EGLint height = 0;
+ EGLint textureFormat = EGL_NO_TEXTURE;
+ EGLint textureTarget = EGL_NO_TEXTURE;
+ EGLint mipmapTexture = EGL_FALSE;
+ EGLint largestPbuffer = EGL_FALSE;
+ EGLint colorSpace = EGL_VG_COLORSPACE_sRGB;
+ EGLint alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
+
+ EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
+ if( attrib_list && attrib_list[0] != EGL_NONE )
+ {
+ for( int i=0; attrib_list[i] != EGL_NONE; i+=2 )
+ {
+ EGLint value = attrib_list[i+1];
+ switch( attrib_list[i] )
+ {
+ case EGL_WIDTH:
+ {
+ if( value < 0 )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
+ }
+ width = value;
+ break;
+ }
+
+ case EGL_HEIGHT:
+ {
+ if( value < 0 )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
+ }
+ height = value;
+ break;
+ }
+
+ case EGL_LARGEST_PBUFFER:
+ {
+ largestPbuffer = value;
+ break;
+ }
+
+ case EGL_TEXTURE_FORMAT:
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) &&
+ !(renderableType & EGL_OPENGL_ES2_BIT) ||
+ (value != EGL_TEXTURE_RGB &&
+ value != EGL_TEXTURE_RGBA &&
+ value != EGL_NO_TEXTURE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ textureFormat = value;
+ break;
+ }
+
+ case EGL_TEXTURE_TARGET:
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) &&
+ !(renderableType & EGL_OPENGL_ES2_BIT) ||
+ (value != EGL_TEXTURE_2D &&
+ value != EGL_NO_TEXTURE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ textureTarget = value;
+ break;
+ }
+
+ case EGL_MIPMAP_TEXTURE:
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) ||
+ !(renderableType & EGL_OPENGL_ES2_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ mipmapTexture = value;
+ break;
+ }
+
+ case EGL_VG_COLORSPACE:
+ {
+ if( !(renderableType & EGL_OPENVG_BIT) ||
+ (value != EGL_VG_COLORSPACE_sRGB &&
+ value != EGL_VG_COLORSPACE_LINEAR) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ colorSpace = value;
+ break;
+ }
+
+ case EGL_VG_ALPHA_FORMAT:
+ {
+ if( !(renderableType & EGL_OPENVG_BIT) ||
+ (value != EGL_VG_ALPHA_FORMAT_PRE &&
+ value != EGL_VG_ALPHA_FORMAT_NONPRE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ alphaFormat = value;
+ break;
+ }
+
+ default:
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ }
+ }
+
+ if( (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE) ||
+ (textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+
+ CEGLPbufferSurface* surface = EGLI_NEW CEGLPbufferSurface( colorSpace, alphaFormat,
+ EGL_BACK_BUFFER, config, largestPbuffer, textureFormat, textureTarget, mipmapTexture );
+ // \note AddSurface() will destroy the object if it fails to take ownership
+ surface = (CEGLPbufferSurface*)display->AddSurface( surface );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ if( !(surface->Resize(width, height)) )
+ {
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ // \todo refactor all this surface creation stuff
+ if( (renderableType & EGL_OPENVG_BIT) && (state->SupportedApis() & EGL_OPENVG_BIT) )
+ {
+ // \todo Delay surface creation until needed.
+ // \todo largest Pbuffer
+ if( !(state->VGInterface()->CreateSurface( surface->Descriptor(), surface->VGBuffers(), NULL )) )
+ {
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ }
+
+ if( renderableType & EGL_OPENGL_ES_BIT && (state->SupportedApis() & EGL_OPENGL_ES_BIT) )
+ {
+ struct EGLINativePbufferContainer* nativePbuffer = CEGLOs::CreateNativePbuffer( display->NativeType(),
+ *config, width, height, largestPbuffer, textureFormat, textureTarget );
+ if( !nativePbuffer )
+ {
+ if( surface->VGClientSurface() )
+ {
+ state->VGInterface()->ReleaseSurface( surface->VGClientSurface() );
+ }
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ surface->SetNativePbufferContainer( nativePbuffer );
+ }
+
+ if( renderableType & EGL_OPENGL_ES2_BIT && (state->SupportedApis() & EGL_OPENGL_ES2_BIT) )
+ {
+ struct EGLINativePbufferContainer* nativePbuffer = CEGLOs::CreateNativePbuffer( display->NativeType(),
+ *config, width, height, largestPbuffer, textureFormat, textureTarget );
+ if( !nativePbuffer )
+ {
+ if( surface->VGClientSurface() )
+ {
+ state->VGInterface()->ReleaseSurface( surface->VGClientSurface() );
+ }
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ surface->SetNativePbufferContainer( nativePbuffer );
+ }
+
+ surface->AddRef();
+
+ EGLI_LEAVE_RET( (EGLSurface)surface, EGL_SUCCESS );
+ }
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint *attrib_list)
+ {
+ EGLI_ENTER_RET( EGL_NO_SURFACE );
+ // eglCreatePixmapSurface – EGL_BAD_MATCH raised (as no pixmap-supporting configs)
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surfaceId)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+
+ // \note EGLI_ENTER_RET macro will fail if thread allocation didn't succeed
+ CEGLThread* thread = getThread();
+
+ surface->Lock();
+ //TODO: client apis
+ if( surface->RemoveRef() )
+ {
+ if( surface->VGClientSurface() )
+ {
+ if( !(state->VGInterface()->ReleaseSurface(surface->VGClientSurface())) )
+ {
+ // need to add reference because surface is still alive
+ surface->AddRef();
+ surface->Unlock();
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ }
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ surface = NULL;
+ }
+ else
+ {
+ surface->Terminate();
+ }
+ if( surface ) surface->Unlock();
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surfaceId,
+ EGLint attribute, EGLint *value)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ if( !value )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ surface->Lock();
+ EGLint ret = EGL_BAD_ATTRIBUTE;
+ switch( attribute )
+ {
+ case EGL_VG_ALPHA_FORMAT:
+ {
+ ret = surface->AlphaFormat();
+ break;
+ }
+ case EGL_VG_COLORSPACE:
+ {
+ ret = surface->ColorSpace();
+ break;
+ }
+ case EGL_CONFIG_ID:
+ {
+ ret = surface->Config()->Id();
+ break;
+ }
+ case EGL_HEIGHT:
+ {
+ ret = surface->Height();
+ break;
+ }
+ case EGL_WIDTH:
+ {
+ ret = surface->Width();
+ break;
+ }
+ case EGL_HORIZONTAL_RESOLUTION:
+ {
+ if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
+ {
+ //TODO
+ EGLI_ASSERT( false );
+ }
+ else
+ {
+ ret = EGL_UNKNOWN;
+ }
+ break;
+ }
+ case EGL_VERTICAL_RESOLUTION:
+ {
+ if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
+ {
+ //TODO
+ EGLI_ASSERT( false );
+ }
+ else
+ {
+ ret = EGL_UNKNOWN;
+ }
+ break;
+ }
+ case EGL_PIXEL_ASPECT_RATIO:
+ {
+ if( surface->Type() == CEGLSurface::WINDOW_SURFACE )
+ {
+ //TODO
+ EGLI_ASSERT( false );
+ }
+ else
+ {
+ ret = EGL_UNKNOWN;
+ }
+ break;
+ }
+ case EGL_LARGEST_PBUFFER:
+ {
+ if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ ret = ((CEGLPbufferSurface*)surface)->IsLargestPbuffer();
+ }
+ break;
+ }
+ case EGL_MIPMAP_TEXTURE:
+ {
+ if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ ret = ((CEGLPbufferSurface*)surface)->MipmapTexture();
+ }
+ break;
+ }
+ case EGL_MIPMAP_LEVEL:
+ {
+ if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ ret = surface->MipmapLevel();
+ }
+ break;
+ }
+ case EGL_MULTISAMPLE_RESOLVE:
+ {
+ ret = surface->MultisampleResolve();
+ break;
+ }
+ case EGL_RENDER_BUFFER:
+ {
+ ret = surface->RenderBuffer();
+ break;
+ }
+ case EGL_SWAP_BEHAVIOR:
+ {
+ ret = surface->SwapBehavior();
+ break;
+ }
+ case EGL_TEXTURE_FORMAT:
+ {
+ if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ ret = ((CEGLPbufferSurface*)surface)->TextureFormat();
+ }
+ break;
+ }
+ case EGL_TEXTURE_TARGET:
+ {
+ if( surface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ ret = ((CEGLPbufferSurface*)surface)->TextureTarget();
+ }
+ break;
+ }
+ default:
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
+ }
+ }
+ *value = ret;
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
+ {
+ CEGLThread* thread = getThread();
+ EGLI_ASSERT( thread != NULL );
+
+ if( thread && thread->IsSupportedApi( api ) )
+ {
+ thread->SetApi( api );
+ thread->SetError( EGL_SUCCESS );
+ return EGL_TRUE;
+ }
+ else if( thread )
+ {
+ thread->SetError( EGL_BAD_PARAMETER );
+ }
+ return EGL_FALSE;
+ }
+
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void)
+ {
+ CEGLThread* thread = getThread();
+ EGLI_ASSERT( thread != NULL );
+
+ EGLenum api = EGL_NONE;
+ if( thread )
+ {
+ api = thread->CurrentApi();
+ thread->SetError( EGL_SUCCESS );
+ }
+ return api;
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ // Macro above fails if thread is not available.
+ CEGLThread* thread = getThread();
+
+ switch( thread->CurrentApi() )
+ {
+ case EGL_OPENVG_API:
+ {
+ if( !(thread->CurrentVGSurface()) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CURRENT_SURFACE );
+ }
+ if( !(thread->CurrentVGContext()) )
+ {
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+ if( !(state->VGInterface()) )
+ {
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ state->VGInterface()->Finish();
+ break;
+ }
+ case EGL_OPENGL_ES_API:
+ {
+ CEGLSurface* read = NULL;
+ CEGLSurface* draw = NULL;
+ thread->CurrentGLESSurfaces( &read, &draw );
+ if( !read || !draw )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CURRENT_SURFACE );
+ }
+ if( !(thread->CurrentGLESContext()) )
+ {
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+ state->GLESInterface( thread->CurrentGLESContext()->ClientVersion() )->Finish();
+ break;
+ }
+ }
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void)
+ {
+#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
+#if defined(_WIN32)
+ EGLI_ASSERT( g_tlsIndex != TLS_OUT_OF_INDEXES );
+ if( TlsGetValue( g_tlsIndex ) == NULL )
+ {
+ // Already released or first call => success
+ return EGL_TRUE;
+ }
+#else // Linux
+ // \todo
+ EGLI_ASSERT( false );
+#endif
+#else
+ EGLI_ENTER_RET( EGL_FALSE );
+#endif //EGLI_USE_PLATSIM_EXTENSIONS
+
+ CEGLThread* thread = getThread();
+ EGLenum api = thread->CurrentApi();
+ if( thread->CurrentVGContext() )
+ {
+ const CEGLDisplay* display = thread->CurrentVGContext()->Display();
+ EGLI_ASSERT( display );
+ thread->SetApi( EGL_OPENVG_API );
+ eglMakeCurrent( (EGLDisplay)display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
+ }
+ if( thread->CurrentGLESContext() )
+ {
+ const CEGLDisplay* display = thread->CurrentGLESContext()->Display();
+ EGLI_ASSERT( display );
+ thread->SetApi( EGL_OPENGL_ES_API );
+ eglMakeCurrent( (EGLDisplay)display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
+ }
+ thread->SetApi( api );
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ process->RemoveThread( thread->Id() );
+ if( process->ThreadCount() == 0 )
+ {
+ // All threads destroyed from process => it's not a process any more
+ state->RemoveProcess( process->Id() );
+ process = NULL;
+ }
+#else
+ releaseState();
+#endif
+ return EGL_TRUE;
+ }
+
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
+ EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+ EGLConfig configId, const EGLint *attrib_list)
+ {
+ // \todo combine with eglCreatePbufferSurface()
+ EGLI_ENTER_RET( EGL_NO_SURFACE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_NO_SURFACE );
+
+ // EGLI_ENTER_RET macro above will fail if thread is not available
+ CEGLThread* thread = getThread();
+ switch( buftype )
+ {
+ case EGL_OPENVG_IMAGE:
+ {
+ if( !(thread->CurrentVGContext()) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ACCESS );
+ }
+ break;
+ }
+
+ default:
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
+ }
+
+ CEGLConfig* config = state->GetConfig( configId );
+ if( !config )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_CONFIG );
+ }
+
+ if( !(state->VGInterface()) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+
+ CColorDescriptor colorDescriptor;
+ int width = 0;
+ int height = 0;
+ if( !(state->VGInterface()->IsValidImage(buffer, &colorDescriptor, &width, &height)) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
+ }
+ if( display->FindSurfaceByClientBuffer( buffer ) != NULL ||
+ state->VGInterface()->IsImageInUse( buffer ) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ACCESS );
+ }
+ if( !(colorDescriptor.MatchBitDepth(*(config->GetDescriptor()))) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+
+ EGLint textureFormat = EGL_NO_TEXTURE;
+ EGLint textureTarget = EGL_NO_TEXTURE;
+ EGLint mipmapTexture = EGL_FALSE;
+ EGLint largestPbuffer = EGL_FALSE;
+ EGLint colorSpace = colorDescriptor.isNonlinear() ? EGL_VG_COLORSPACE_sRGB : EGL_VG_COLORSPACE_LINEAR;
+ EGLint alphaFormat = colorDescriptor.isPremultiplied() ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE;
+
+ EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
+ if( attrib_list && attrib_list[0] != EGL_NONE )
+ {
+ for( int i=0; attrib_list[i] != EGL_NONE; i+=2 )
+ {
+ EGLint value = attrib_list[i+1];
+ switch( attrib_list[i] )
+ {
+ case EGL_TEXTURE_FORMAT:
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) &&
+ !(renderableType & EGL_OPENGL_ES2_BIT) ||
+ (value != EGL_TEXTURE_RGB &&
+ value != EGL_TEXTURE_RGBA &&
+ value != EGL_NO_TEXTURE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ textureFormat = value;
+ break;
+ }
+
+ case EGL_TEXTURE_TARGET:
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) &&
+ !(renderableType & EGL_OPENGL_ES2_BIT) ||
+ (value != EGL_TEXTURE_2D &&
+ value != EGL_NO_TEXTURE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ textureTarget = value;
+ break;
+ }
+
+ case EGL_MIPMAP_TEXTURE:
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) ||
+ !(renderableType & EGL_OPENGL_ES2_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ mipmapTexture = value;
+ break;
+ }
+
+ default:
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ATTRIBUTE );
+ }
+ }
+ }
+
+ if( (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE) ||
+ (textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_MATCH );
+ }
+
+ CEGLPbufferSurface* surface = EGLI_NEW CEGLPbufferSurface( colorSpace, alphaFormat,
+ EGL_BACK_BUFFER, config, largestPbuffer, textureFormat, textureTarget, mipmapTexture, buffer );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ // \note AddSurface() will destroy the object if it fails to take ownership
+ surface = (CEGLPbufferSurface*)display->AddSurface( surface );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ if( !(surface->Resize(width, height)) )
+ {
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+
+ if( !(state->VGInterface()->CreateSurface(surface->Descriptor(), surface->VGBuffers(), buffer)) )
+ {
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( surface );
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_ALLOC );
+ }
+ surface->AddRef();
+
+ EGLI_LEAVE_RET( surface, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surfaceId,
+ EGLint attribute, EGLint value)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ surface->Lock();
+ switch( attribute )
+ {
+ case EGL_MIPMAP_LEVEL:
+ {
+ if( !(surface->Config()->GetAttribute( EGL_RENDERABLE_TYPE ) & EGL_OPENGL_ES_BIT ))
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+ break;
+ }
+ case EGL_MULTISAMPLE_RESOLVE:
+ {
+ bool hasBoxBit = !!(surface->Config()->GetAttribute( EGL_SURFACE_TYPE ) & EGL_MULTISAMPLE_RESOLVE_BOX_BIT );
+ if( value != EGL_MULTISAMPLE_RESOLVE_BOX ||
+ value != EGL_MULTISAMPLE_RESOLVE_DEFAULT )
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
+ }
+ else if( value == EGL_MULTISAMPLE_RESOLVE_BOX && !hasBoxBit )
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+ break;
+ }
+ case EGL_SWAP_BEHAVIOR:
+ {
+ bool hasPreservedBit = !!(surface->Config()->GetAttribute( EGL_SURFACE_TYPE ) & EGL_SWAP_BEHAVIOR_PRESERVED_BIT );
+ if( value != EGL_BUFFER_PRESERVED ||
+ value != EGL_BUFFER_DESTROYED )
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
+ }
+ else if( value == EGL_BUFFER_PRESERVED && !hasPreservedBit )
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+ break;
+ }
+ default:
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
+ }
+
+ }
+ surface->SetAttribute( attribute, value );
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surfaceId, EGLint buffer)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ // EGLI_ENTER_RET macro above will fail if thread is not available
+ CEGLThread* thread = getThread();
+
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+
+ if( buffer != EGL_BACK_BUFFER )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+
+ if( thread->CurrentGLESContext() == NULL)
+ {
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+ if( surface->IsLocked() )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ surface->Lock();
+
+ CEGLSurface* glesReadSurface;
+ thread->CurrentGLESSurfaces( &glesReadSurface, NULL );
+ state->SyncSurface( EGL_OPENVG_API, 0, surface, glesReadSurface );
+
+ EGLint renderableType = surface->Config()->GetAttribute( EGL_RENDERABLE_TYPE );
+
+ if( (!(renderableType & EGL_OPENGL_ES_BIT) && !(renderableType & EGL_OPENGL_ES2_BIT)) ||
+ surface->Type() != CEGLSurface::PBUFFER_SURFACE ||
+ (surface->Config()->GetAttribute( EGL_BIND_TO_TEXTURE_RGB ) == EGL_FALSE &&
+ surface->Config()->GetAttribute( EGL_BIND_TO_TEXTURE_RGBA ) == EGL_FALSE ) )
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ if( ((CEGLPbufferSurface*)surface)->TextureFormat() == EGL_NO_TEXTURE )
+ {
+ surface->Unlock();
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+ bool mipmapTexture = !!((CEGLPbufferSurface*)surface)->MipmapTexture();
+ IEGLtoGLESInterface* iFace = state->GLESInterface( thread->CurrentGLESContext()->ClientVersion() );
+ if( surface->BoundContext() == thread->CurrentGLESContext() )
+ {
+ iFace->Flush();
+ }
+ else
+ {
+ // \todo Wait for all issued client API commands drawing to the surface to complete.
+ }
+ int level = surface->Attribute( EGL_MIPMAP_LEVEL );
+ int textureName = iFace->BindTexImage( surface, level, mipmapTexture, surface->Descriptor(), surface->VGColorBuffer());
+ EGLITextureBinding& binding = surface->TextureBinding();
+ binding.name = textureName;
+ binding.level = level;
+ binding.clientVersion = thread->CurrentGLESContext()->ClientVersion();
+ binding.context = eglGetCurrentContext();
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surfaceId, EGLint buffer)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ // EGLI_ENTER_RET macro above will fail if thread is not available
+ CEGLThread* thread = getThread();
+
+ if( buffer != EGL_BACK_BUFFER )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ // \todo errors etc.
+ if( !surface || (surface && surface->Type() != CEGLSurface::PBUFFER_SURFACE) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ if( ((CEGLPbufferSurface*)surface)->TextureFormat() == EGL_NO_TEXTURE )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+
+ EGLITextureBinding& binding = surface->TextureBinding();
+
+ if( display->GetContext( binding.context ))
+ {
+ EGLenum origAPI = eglQueryAPI();
+ EGLSurface origReadSurface, origDrawSurface;
+ EGLContext origContext;
+ bool switchAPI = origAPI == EGL_OPENGL_ES_API;
+ bool switchContext = binding.context != thread->CurrentGLESContext();
+ if( switchAPI )
+ {
+ eglBindAPI( EGL_OPENGL_ES_API );
+ }
+ if( switchContext )
+ {
+ // Switch to the context where the texture lives.
+ origReadSurface = eglGetCurrentSurface(EGL_READ);
+ origDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+ origContext = eglGetCurrentContext();
+ eglMakeCurrent( display, surfaceId, surfaceId, binding.context );
+ }
+ state->GLESInterface(binding.clientVersion)->ReleaseTexImage( binding.name, binding.level );
+ if( switchContext )
+ {
+ // Switch back to the original context.
+ eglMakeCurrent( display, origDrawSurface, origReadSurface, origContext );
+ }
+ if( switchAPI )
+ {
+ eglBindAPI( origAPI );
+ }
+ }
+ else
+ {
+ // The context has been destroyed. Ignore the call.
+ }
+ binding.name = 0;
+ surface->Unlock();
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+
+ if( !(thread->CurrentVGContext()) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
+ }
+ if( !(thread->CurrentVGSurface()) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ // eglSwapInterval – hardcode EGL_MAX_SWAP_INTERVAL and EGL_MIN_SWAP_INTERVAL to 1, so nothing here
+ if( thread->CurrentVGSurface()->Type() == CEGLSurface::WINDOW_SURFACE )
+ {
+ ((CEGLWindowSurface*)thread->CurrentVGSurface())->SetSwapInterval( /*interval*/ 1 );
+ }
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig configId,
+ EGLContext share_context,
+ const EGLint *attrib_list)
+ {
+ EGLI_ENTER_RET( EGL_NO_CONTEXT );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_NO_CONTEXT );
+
+ CEGLConfig* config = state->GetConfig( configId );
+ if( !config )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONFIG );
+ }
+
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+
+ EGLenum currentApi = thread->CurrentApi();
+ if( currentApi == EGL_NONE )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_MATCH );
+ }
+
+ CEGLContext* shareContext = NULL;
+ if( share_context != EGL_NO_CONTEXT )
+ {
+ shareContext = display->GetContext( share_context );
+ if( !shareContext || (shareContext && process->Id() != shareContext->ProcessId()) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_MATCH );
+ }
+ if( currentApi != shareContext->ClientApi() )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONTEXT );
+ }
+ }
+
+ EGLint renderableType = config->GetAttribute( EGL_RENDERABLE_TYPE );
+ EGLint clientVersion = 1;
+ if( attrib_list && attrib_list[0] != EGL_NONE )
+ {
+ switch( attrib_list[0] )
+ {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ {
+ if( currentApi != EGL_OPENGL_ES_API )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE );
+ }
+ if( attrib_list[1] == 1 ) //GLES 1.1
+ {
+ if( !(renderableType & EGL_OPENGL_ES_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONFIG );
+ }
+ clientVersion = 1;
+ }
+ else if( attrib_list[1] == 2 ) //GLES 2.0
+ {
+ if( !(renderableType & EGL_OPENGL_ES2_BIT) )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_CONFIG );
+ }
+ clientVersion = 2;
+ }
+ else
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE );
+ }
+ break;
+ }
+
+ default:
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE );
+ break;
+ }
+ }
+ }
+
+ void* clientContext = NULL;
+ CEGLContext* context = NULL;
+ switch( currentApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ EGLI_ASSERT( state->VGInterface() != NULL );
+ clientContext = state->VGInterface()->CreateContext(
+ shareContext != NULL ? shareContext->ClientContext() : shareContext );
+ if( clientContext )
+ {
+ context = EGLI_NEW CEGLContext( process->Id(), display, config, currentApi, clientVersion, clientContext );
+ // \note AddContext() will destroy the object if it fails to take ownership
+ context = display->AddContext( context );
+ if( !context )
+ {
+ state->VGInterface()->ReleaseContext( clientContext );
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
+ }
+ }
+ break;
+ }
+
+ case EGL_OPENGL_ES_API:
+ {
+ EGLINativeContextType nativeShareContext = shareContext != NULL ? shareContext->NativeContext() : NULL;
+ EGLINativeContextType nativeContext = CEGLOs::CreateNativeContext( *config, display->NativeType(), nativeShareContext );
+ if( !nativeContext )
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
+ }
+
+ IEGLtoGLESInterface* iFace = state->GLESInterface( clientVersion );
+ EGLI_ASSERT( iFace != NULL );
+ clientContext = state->GLESInterface( clientVersion )->CreateContext( nativeContext );
+ if( clientContext )
+ {
+ context = EGLI_NEW CEGLContext( process->Id(), display, config, currentApi, clientVersion, clientContext );
+ if( context )
+ // \note AddContext() will destroy the object if it fails to take ownership
+ context = display->AddContext( context );
+ if( !context )
+ {
+ iFace->ReleaseContext( clientContext );
+ CEGLOs::DestroyNativeContext( nativeContext );
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
+ }
+ context->SetNativeContext( nativeContext );
+ }
+ else
+ {
+ CEGLOs::DestroyNativeContext( nativeContext );
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
+ }
+ break;
+ }
+
+ case EGL_NONE:
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_MATCH );
+ break;
+ }
+ }
+
+ if( context )
+ {
+ context->AddRef();
+ }
+ else
+ {
+ EGLI_LEAVE_RET( EGL_NO_CONTEXT, EGL_BAD_ALLOC );
+ }
+
+ EGLI_LEAVE_RET( (EGLContext)context, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+
+ CEGLContext* context = display->GetContext( ctx );
+ if( !context )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
+ }
+
+ EGLenum clientApi = context->ClientApi();
+ switch( clientApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ if( context->RemoveRef() )
+ {
+ state->VGInterface()->ReleaseContext(context->ClientContext());
+ // \note RemoveContext() will destroy the object
+ display->RemoveContext( context );
+ }
+ else
+ {
+ context->Terminate();
+ }
+ break;
+ }
+
+ case EGL_OPENGL_ES_API:
+ {
+ if( context->RemoveRef() )
+ {
+ if( !(state->GLESInterface( context->ClientVersion() )->ReleaseContext( context->ClientContext() )) )
+ {
+ // \todo Handle errors!
+ EGLI_ASSERT( false );
+ }
+ if( context->NativeContext() && !(CEGLOs::DestroyNativeContext(context->NativeContext())) )
+ {
+ // \todo Handle errors!
+ EGLI_ASSERT( false );
+ }
+ // \note RemoveContext() will destroy the object
+ display->RemoveContext( context );
+ }
+ else
+ {
+ context->Terminate();
+ }
+ break;
+ }
+ }
+
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
+ EGLSurface read, EGLContext ctx)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread );
+
+ bool releaseCurrent = ( draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT );
+
+ if( (ctx == EGL_NO_CONTEXT && draw != EGL_NO_SURFACE && read != EGL_NO_SURFACE) ||
+ ((draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE) && ctx != EGL_NO_CONTEXT) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+
+ CEGLContext* context = display->GetContext( ctx );
+ if( (!releaseCurrent && !context ) || (context && context->ProcessId() != process->Id()) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
+ }
+
+ EGLenum currentApi = thread->CurrentApi();
+ CEGLContext* currentContext = NULL;
+ CEGLSurface* currentDrawSurface = NULL;
+ CEGLSurface* currentReadSurface = NULL;
+ CEGLSurface* drawSurface = NULL;
+ CEGLSurface* readSurface = NULL;
+
+ if( !releaseCurrent )
+ {
+ if( context && context->ClientApi() == EGL_OPENVG_API && ( draw != read ) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+ drawSurface = display->GetSurface( draw );
+ readSurface = display->GetSurface( read );
+ if( !drawSurface || !readSurface )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+
+ if( !(context->Config()->IsCompatible( *(drawSurface->Config()), context->ClientApi())) ||
+ !(context->Config()->IsCompatible( *(readSurface->Config()), context->ClientApi())) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_MATCH );
+ }
+
+ if( (context->Thread() && context->Thread() != thread) ||
+ (drawSurface->BoundContext() && drawSurface->BoundContext()->Thread() != thread) ||
+ (readSurface->BoundContext() && readSurface->BoundContext()->Thread() != thread) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+
+ if( drawSurface->Type() == CEGLSurface::WINDOW_SURFACE &&
+ !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)drawSurface)->NativeType())) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_WINDOW );
+ }
+ if( readSurface != drawSurface && readSurface->Type() == CEGLSurface::WINDOW_SURFACE &&
+ !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)readSurface)->NativeType())) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_WINDOW );
+ }
+
+ // TODO: If binding ctx would exceed the number of current contexts of that client
+ // API type supported by the implementation, an EGL_BAD_ACCESS error is
+ // generated.
+
+ // TODO: If either draw or read are pbuffers created with eglCreatePbufferFromClientBuffer,
+ // and the underlying bound client API buffers are in use by the
+ // client API that created them, an EGL_BAD_ACCESS error is generated
+
+ // TODO: If draw and read cannot fit into graphics memory simultaneously, an EGL_BAD_MATCH error is generated.
+
+ // TODO: If the previous context of the calling thread has unflushed commands, and
+ // the previous surface is no longer valid, an EGL_BAD_CURRENT_SURFACE
+ // error is generated.
+
+ // TODO: If the ancillary buffers for draw and read cannot be allocated, an EGL_BAD_ALLOC error is generated.
+
+ // TODO: If a power management event has occurred, an EGL_CONTEXT_LOST error is generated.
+
+ // TODO: flush context
+ switch( context->ClientApi() )
+ {
+ case EGL_OPENVG_API:
+ {
+ state->VGInterface()->Flush();
+ currentContext = thread->SwitchVGContext( context );
+ currentDrawSurface = thread->SwitchVGSurface( drawSurface );
+ drawSurface->BindToContext( context );
+ if( !(state->VGInterface()->SetCurrentSurface(context->ClientContext(), drawSurface->VGClientSurface())) )
+ {
+ // Restore previous context/surface
+ thread->SwitchVGContext( currentContext );
+ thread->SwitchVGSurface( currentDrawSurface );
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ // \todo track changes through locking
+ drawSurface->SetVGDirty( true );
+ break;
+ }
+
+ case EGL_OPENGL_ES_API:
+ {
+ if( thread->CurrentGLESContext() )
+ {
+ state->GLESInterface(context->ClientVersion())->Flush();
+ }
+ currentContext = thread->SwitchGLESContext( context );
+ thread->SwitchGLESSurfaces( drawSurface, readSurface, currentReadSurface, currentDrawSurface );
+ drawSurface->BindToContext( context );
+ if( drawSurface != readSurface )
+ {
+ readSurface->BindToContext( context );
+ }
+ EGLINativeContextType nativeContext = (EGLINativeContextType)state->GLESInterface(context->ClientVersion())->GetNativeContext( context->ClientContext() );
+ if( !(context->NativeGLFunctions()) )
+ {
+ EGLINativeGLFunctions* nativeFuncs = EGLI_NEW EGLINativeGLFunctions;
+ if( !nativeFuncs )
+ {
+ // Restore previous context/surface
+ thread->SwitchGLESContext( currentContext );
+ thread->SwitchGLESSurfaces( currentReadSurface, currentDrawSurface, readSurface, drawSurface );
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+ memset( nativeFuncs, 0, sizeof(EGLINativeGLFunctions) );
+ if( !(CEGLOs::InitializeNativeGLFunctions(nativeFuncs, display->NativeType(), nativeContext)) )
+ {
+ // Restore previous context/surface
+ thread->SwitchGLESContext( currentContext );
+ thread->SwitchGLESSurfaces( currentReadSurface, currentDrawSurface, readSurface, drawSurface );
+ delete nativeFuncs;
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+ context->SetNativeGLFucntions( nativeFuncs );
+ }
+ EGLINativeDisplayType drawDC = NULL;
+ EGLINativeDisplayType readDC = NULL;
+ if( drawSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ drawDC = ((CEGLPbufferSurface*)drawSurface)->NativeDisplay();
+ }
+ else if( drawSurface->Type() == CEGLSurface::WINDOW_SURFACE )
+ {
+ drawDC = ((CEGLWindowSurface*)drawSurface)->OsContext()->glesDisplay;
+ }
+
+ if( readSurface == drawSurface )
+ {
+ readDC = drawDC;
+ }
+ else if( readSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ readDC = ((CEGLPbufferSurface*)readSurface)->NativeDisplay();
+ }
+ else if( readSurface->Type() == CEGLSurface::WINDOW_SURFACE )
+ {
+ readDC = ((CEGLWindowSurface*)readSurface)->OsContext()->glesDisplay;
+ }
+
+ if( !(CEGLOs::MakeNativeContextCurrent(context->NativeGLFunctions(), drawDC, readDC, context->NativeContext())) )
+ {
+ // Restore previous context/surface. CEGLOs::MakeNativeContextCurrent() will restore previous
+ // native context/surface on failure
+ thread->SwitchGLESContext( currentContext );
+ thread->SwitchGLESSurfaces( currentReadSurface, currentDrawSurface, readSurface, drawSurface );
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ break;
+ }
+
+ default:
+ {
+ EGLI_ASSERT( false );
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch( currentApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ state->VGInterface()->Flush();
+ if( thread->CurrentGLESContext() )
+ {
+ // Sync surface before releasing the VG context because there
+ // might not be a VG context if GLES locks the surface later.
+ CEGLSurface* glesReadSurface;
+ thread->CurrentGLESSurfaces( &glesReadSurface, NULL );
+ state->SyncSurface( EGL_OPENGL_API, thread->CurrentGLESContext()->ClientVersion(), thread->CurrentVGSurface(), glesReadSurface );
+ }
+ currentContext = thread->SwitchVGContext( NULL );
+ currentDrawSurface = thread->SwitchVGSurface( NULL );
+ break;
+ }
+
+ case EGL_OPENGL_ES_API:
+ {
+ if( thread->CurrentGLESContext() )
+ {
+ state->GLESInterface(thread->CurrentGLESContext()->ClientVersion())->Flush();
+ }
+ if( thread->CurrentVGContext() )
+ {
+ // Sync surface before releasing the GLES context because there
+ // might not be a GLES context if VG locks the surface later.
+ CEGLSurface* glesReadSurface;
+ CEGLSurface* glesDrawSurface;
+ thread->CurrentGLESSurfaces( &glesReadSurface, &glesDrawSurface );
+ state->SyncSurface( EGL_OPENVG_API, 0, glesReadSurface, glesReadSurface );
+ if( glesDrawSurface != glesReadSurface )
+ {
+ state->SyncSurface( EGL_OPENVG_API, 0, glesDrawSurface, NULL );
+ }
+ }
+ currentContext = thread->SwitchGLESContext( NULL );
+ thread->SwitchGLESSurfaces( NULL, NULL, currentReadSurface, currentDrawSurface );
+ break;
+ }
+ }
+ }
+
+ if( currentDrawSurface && currentDrawSurface != drawSurface )
+ {
+ currentDrawSurface->BindToContext( NULL );
+ if( currentDrawSurface->RemoveRef() )
+ {
+ if( currentDrawSurface->VGClientSurface() )
+ {
+ if( !(state->VGInterface()->ReleaseSurface(currentDrawSurface->VGClientSurface())) )
+ {
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ }
+ if( currentDrawSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ //((CEGLPbufferSurface*)currentDrawSurface)->SetNativePbufferContainer( NULL );
+ //EGLI_ASSERT( false );
+ }
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( currentDrawSurface );
+ }
+ if( currentReadSurface == currentDrawSurface )
+ {
+ currentReadSurface = NULL;
+ }
+ currentDrawSurface = NULL;
+ }
+
+ if( currentReadSurface && currentReadSurface != readSurface )
+ {
+ currentReadSurface->BindToContext( NULL );
+ if( currentReadSurface->RemoveRef() )
+ {
+ if( currentReadSurface->VGClientSurface() )
+ {
+ if( !(state->VGInterface()->ReleaseSurface(currentReadSurface->VGClientSurface())) )
+ {
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ }
+ if( currentReadSurface->Type() == CEGLSurface::PBUFFER_SURFACE )
+ {
+ // \todo
+ ((CEGLPbufferSurface*)currentReadSurface)->SetNativePbufferContainer( NULL );
+ }
+ // \note RemoveSurface() will destroy the object
+ display->RemoveSurface( currentReadSurface );
+ }
+ }
+
+ if( currentContext && currentContext != context )
+ {
+ currentContext->SetThread( NULL );
+ if( currentContext->RemoveRef() )
+ {
+ if( currentContext->ClientContext() )
+ {
+ if( currentContext->ClientApi() == EGL_OPENVG_API )
+ {
+ bool success = state->VGInterface()->ReleaseContext( currentContext->ClientContext() );
+ EGLI_ASSERT( success );
+ }
+ if( currentContext->ClientApi() == EGL_OPENGL_ES_API )
+ {
+ bool success = state->GLESInterface(currentContext->ClientVersion())->ReleaseContext(currentContext->ClientContext());
+ EGLI_ASSERT( success );
+ }
+ }
+ if( currentContext->NativeContext() )
+ {
+ if( !(CEGLOs::DestroyNativeContext(currentContext->NativeContext())) )
+ {
+ // \todo Handle errors!
+ EGLI_ASSERT( false );
+ }
+ }
+ // \note RemoveContext() will destroy the object
+ display->RemoveContext( currentContext );
+ currentContext = NULL;
+ }
+ }
+ if( context && currentContext != context )
+ {
+ context->AddRef();
+ }
+ if( drawSurface && currentDrawSurface != drawSurface )
+ {
+ drawSurface->AddRef();
+ }
+ if( readSurface && readSurface != drawSurface && readSurface != currentReadSurface )
+ {
+ readSurface->AddRef();
+ }
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void)
+ {
+ EGLI_ENTER_RET( EGL_NO_CONTEXT );
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+ EGLContext ret = EGL_NO_CONTEXT;
+ switch( thread->CurrentApi() )
+ {
+ case EGL_OPENVG_API:
+ {
+ if( thread->CurrentVGContext() )
+ {
+ ret = thread->CurrentVGContext();
+ }
+ break;
+ }
+ case EGL_OPENGL_ES_API:
+ {
+ if( thread->CurrentGLESContext() )
+ {
+ ret = thread->CurrentGLESContext();
+ }
+ break;
+ }
+ }
+ EGLI_LEAVE_RET( ret, EGL_SUCCESS );
+ }
+
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)
+ {
+ EGLI_ENTER_RET( EGL_NO_SURFACE );
+ if( readdraw != EGL_READ && readdraw != EGL_DRAW )
+ {
+ EGLI_LEAVE_RET( EGL_NO_SURFACE, EGL_BAD_PARAMETER );
+ }
+
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+
+ EGLSurface ret = EGL_NO_SURFACE;
+ EGLenum currentApi = thread->CurrentApi();
+ switch( currentApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ CEGLContext* context = thread->CurrentVGContext();
+ if( context )
+ {
+ ret = thread->CurrentVGSurface();
+ }
+ break;
+ }
+
+ case EGL_OPENGL_ES_API:
+ {
+ CEGLSurface* read = NULL;
+ CEGLSurface* draw = NULL;
+ thread->CurrentGLESSurfaces( &read, &draw );
+ switch( readdraw )
+ {
+ case EGL_READ:
+ {
+ ret = (EGLSurface)read;
+ break;
+ }
+
+ case EGL_DRAW:
+ {
+ ret = (EGLSurface)draw;
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ EGLI_ASSERT( false );
+ }
+ }
+ EGLI_LEAVE_RET( ret, EGL_SUCCESS );
+ }
+
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)
+ {
+ EGLI_ENTER_RET( EGL_NO_DISPLAY );
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread );
+ EGLenum currentApi = thread->CurrentApi();
+ EGLDisplay ret = EGL_NO_DISPLAY;
+ switch( currentApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ if( thread->CurrentVGContext() )
+ {
+ ret = (EGLDisplay)thread->CurrentVGContext()->Display();
+ }
+ break;
+ }
+ case EGL_OPENGL_ES_API:
+ {
+ if( thread->CurrentGLESContext() )
+ {
+ ret = (EGLDisplay)thread->CurrentGLESContext()->Display();
+ }
+ break;
+ }
+
+ default:
+ EGLI_ASSERT( false );
+ }
+ EGLI_LEAVE_RET( ret, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
+ EGLint attribute, EGLint *value)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE )
+ if( !value )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_PARAMETER );
+ }
+ CEGLContext* context = display->GetContext( ctx );
+ if( !context )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_CONTEXT );
+ }
+ switch( attribute )
+ {
+ case EGL_CONFIG_ID:
+ {
+ *value = ((CEGLConfig*)context->Config())->GetAttribute( EGL_CONFIG_ID );
+ break;
+ }
+
+ case EGL_CONTEXT_CLIENT_TYPE:
+ {
+ *value = context->ClientApi();
+ break;
+ }
+
+ case EGL_CONTEXT_CLIENT_VERSION:
+ {
+ *value = context->ClientVersion();
+ break;
+ }
+
+ case EGL_RENDER_BUFFER:
+ {
+ CEGLSurface* surface = NULL;
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+ if( thread->CurrentVGContext() == context )
+ {
+ surface = thread->CurrentVGSurface();
+ }
+ else if( thread->CurrentGLESContext() == context )
+ {
+ thread->CurrentGLESSurfaces( NULL, &surface );
+ }
+ else
+ {
+ surface = process->FindBoundSurface( context, false );
+ }
+ if( surface )
+ {
+ *value = surface->RenderBuffer();
+ }
+ else
+ {
+ *value = EGL_NONE;
+ }
+ break;
+ }
+
+ default:
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ATTRIBUTE );
+ }
+ }
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ // EGLI_ENTER_RET macro above will fail if thread is not available
+ CEGLThread* thread = getThread();
+ EGLBoolean ret = EGL_TRUE;
+ EGLenum api = eglQueryAPI();
+ if( eglBindAPI( EGL_OPENGL_ES_API ) )
+ {
+ ret = eglWaitClient();
+ if( thread->IsSupportedApi(api) )
+ {
+ eglBindAPI( api );
+ }
+ }
+ EGLI_LEAVE_RET( ret, thread->Error() );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ // eglWaitNative – no-op, as no such thing as native rendering to pbuffers
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surfaceId)
+ {
+ // \todo eglSwapBuffers – all surfaces are single-buffered pbuffers, so this just needs to do a flush in the current client API
+ EGLI_ENTER_RET( EGL_FALSE );
+ EGLI_GET_DISPLAY_RET( dpy, EGL_FALSE );
+
+ // EGLI_ENTER_RET macro above will fail if thread is not available
+ CEGLThread* thread = getThread();
+
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ EGLenum currentApi = thread->CurrentApi();
+ switch( currentApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ if( thread->CurrentVGContext() != surface->BoundContext() )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ break;
+ }
+ case EGL_OPENGL_ES_API:
+ {
+ if( thread->CurrentGLESContext() != surface->BoundContext() )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+ // \todo other GLES stuff?
+ }
+ }
+ if( surface->Type() != CEGLSurface::WINDOW_SURFACE || surface->RenderBuffer() == EGL_SINGLE_BUFFER )
+ {
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+ if( !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)surface)->NativeType())) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_WINDOW );
+ }
+#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ int w, h;
+ if( !(CEGLOs::GetNativeWindowSize(((CEGLWindowSurface*)surface)->NativeType(), w, h)) )
+ {
+ // \todo Error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE );
+ }
+#else
+ int w = surface->Width();
+ int h = surface->Height();
+#endif
+ if( surface->Width() != w || surface->Height() != h )
+ {
+ if( !(surface->Resize(w, h)) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+ if( w <= 0 || h <= 0 )
+ {
+ // invisible window => do nothing
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+ if( surface->VGClientSurface() && state->VGInterface() )
+ {
+ if( !(state->VGInterface()->ResizeSurface(thread->CurrentVGContext()->ClientContext(),
+ surface->VGClientSurface(), w, h, surface->VGBuffers())) )
+ {
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC );
+ }
+ }
+ }
+
+ EGLint stride = surface->Stride();
+ void* buf = ((CEGLWindowSurface*)surface)->CurrentBuffer();
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ buf = (void*)((char*)buf + ((surface->Height() - 1) * stride));
+#else
+ switch( currentApi )
+ {
+ case EGL_OPENVG_API:
+ {
+ state->VGInterface()->CopyBuffers( buf, surface->Stride(), surface->VGClientSurface() );
+ break;
+ }
+ case EGL_OPENGL_ES_API:
+ {
+ if( surface->BoundContext() && !(state->GLESInterface(surface->BoundContext()->ClientVersion())) )
+ {
+ // \todo error code?
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS );
+ }
+ }
+ }
+#endif
+ CEGLOs::BlitToOSWindow( currentApi, display, ((CEGLWindowSurface*)surface)->OsContext(), buf, surface->Width(), surface->Height(), stride );
+ EGLI_LEAVE_RET( EGL_TRUE, EGL_SUCCESS );
+ }
+
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
+ EGLNativePixmapType target)
+ {
+ EGLI_ENTER_RET( EGL_FALSE );
+ // eglCopyBuffers always raises EGL_BAD_NATIVE_PIXMAP error (as no native pixmaps supported)
+ EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_NATIVE_PIXMAP );
+ }
+
+/* Now, define eglGetProcAddress using the generic function ptr. type */
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
+ eglGetProcAddress(const char *procname)
+ {
+ EGLI_ENTER_RET( NULL );
+ // \todo EGL
+ __eglMustCastToProperFunctionPointerType ret = NULL;
+ if( strncmp( procname, "vg", 2 ) == 0 )
+ {
+ ret = state->VGInterface()->GetVGProcAddress( procname );
+ }
+ else if( strncmp( procname, "egl", 3 ) == 0 )
+ {
+ ret = (__eglMustCastToProperFunctionPointerType)CEGLExtension::eglGetProcAddress( procname );
+ }
+ else if( strncmp( procname, "gl", 2 ) == 0 )
+ {
+ ret = state->GLESInterface(2)->GetGLProcAddress( procname );
+ if( ret == NULL )
+ {
+ // Not found in GLES2, try GLES1.
+ ret = state->GLESInterface(1)->GetGLProcAddress( procname );
+ }
+ }
+ else
+ {
+ // return just NULL pointer...
+ }
+ EGLI_LEAVE_RET( ret, EGL_SUCCESS );
+ }
+
+#if defined(EGLI_USE_PLATSIM_EXTENSIONS)
+// non-standard platsim functions
+EGLAPI void EGLAPIENTRY eglPlatsimSetProcessInformation( EGLint processId, EGLint threadId )
+ {
+ EGLI_ENTER_RET(EGLI_NO_RET);
+ if( process && process->Id() != processId )
+ {
+ process = state->GetProcess( processId );
+ }
+ if( !process )
+ {
+ process = state->AddProcess( processId, true );
+ EGLI_ASSERT( process != NULL );
+ CEGLThread* thread = process->AddThread( threadId, true, state->SupportedApis() );
+ EGLI_ASSERT( thread != NULL );
+ }
+ else if( !(process->HasThread( threadId )) )
+ {
+ CEGLThread* thread = process->AddThread( threadId, true, state->SupportedApis() );
+ EGLI_ASSERT( thread != NULL );
+ }
+ else
+ {
+ state->SetCurrentProcessThread( processId, threadId );
+ }
+ EGLI_LEAVE_RET( EGLI_NO_RET, EGL_SUCCESS );
+ }
+
+EGLAPI EGLint EGLAPIENTRY eglPlatsimGetError()
+ {
+ //TODO
+ EGLI_ENTER_RET( EGL_SUCCESS );
+ EGLI_ASSERT( process != NULL );
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+ EGLint err = thread->Error();
+ EGLI_LEAVE_RET( err, err );
+ }
+
+// This is called after eglCreateWindowSurface()
+EGLAPI void EGLAPIENTRY eglPlatsimSetSurfaceParams(
+ EGLDisplay displayId, EGLSurface surfaceId, EGLint width, EGLint height,
+ EGLint stride, void* buffer0, void *buffer1)
+ {
+ EGLI_ENTER_RET( EGLI_NO_RET );
+ CEGLDisplay* display = state->GetDisplay( displayId );
+ if( !display || (display && !(display->IsInitialized())) )
+ {
+ EGLI_LEAVE_RET( EGLI_NO_RET, EGL_NOT_INITIALIZED );
+ }
+ EGLI_ASSERT( display->ProcessId() == process->Id() );
+
+ CEGLSurface* surface = display->GetSurface( surfaceId );
+ if( !surface )
+ {
+ EGLI_LEAVE_RET( EGLI_NO_RET, EGL_BAD_SURFACE );
+ }
+
+ EGLI_ASSERT( surface->Type() == CEGLSurface::WINDOW_SURFACE );
+ if( !(surface->Resize(width, height)) )
+ {
+ EGLI_LEAVE_RET( EGLI_NO_RET, EGL_BAD_ALLOC );
+ }
+ ((CEGLWindowSurface*)surface)->SetStride( stride );
+ ((CEGLWindowSurface*)surface)->SetWindowBuffers( buffer0, buffer1 );
+
+ CEGLThread* thread = process->CurrentThread();
+ EGLI_ASSERT( thread != NULL );
+ //TODO: resizing
+ switch( thread->CurrentApi() )
+ {
+ case EGL_OPENVG_API:
+ {
+ if( !(surface->VGColorBuffer()) )
+ {
+ EGLI_ASSERT( state->VGInterface() != NULL );
+ SurfaceDescriptor* surfaceDesc = surface->Descriptor();
+ bool success = state->VGInterface()->CreateSurface( surfaceDesc, surface->VGBuffers(), NULL );
+ EGLI_ASSERT( success );
+ }
+ break;
+ }
+ case EGL_OPENGL_ES_API:
+ {
+ //TODO: GLES not implemented
+ //EGLI_ASSERT( false );
+ break;
+ }
+ default:
+ {
+ EGLI_ASSERT( false );
+ }
+ }
+
+ //TODO: what else?
+ EGLI_LEAVE_RET( EGLI_NO_RET, EGL_SUCCESS );
+ }
+
+EGLAPI EGLNativePixmapType EGLAPIENTRY eglPlatsimGetPixmapSurfaceBitmap( EGLDisplay display, EGLSurface surface)
+ {
+ //TODO
+ return NULL;
+ }
+#endif
+
+#if defined(_WIN32)
+
+BOOL WINAPI DllMain( HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved )
+ {
+#if !defined(EGLI_USE_PLATSIM_EXTENSIONS)
+ switch( fdwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ g_tlsIndex = TlsAlloc();
+ if( g_tlsIndex == TLS_OUT_OF_INDEXES )
+ return FALSE;
+ if( !g_lockInitialized )
+ {
+ CEGLOs::InitializeLock( &g_eglLock );
+ g_lockInitialized = true;
+ }
+ break;
+ }
+ case DLL_THREAD_ATTACH:
+ {
+ break;
+ }
+
+ case DLL_THREAD_DETACH:
+ {
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+ {
+ if( g_eglState )
+ {
+ EGLI_ASSERT( g_eglState->RefCount() == 0 );
+ delete g_eglState;
+ g_eglState = NULL;
+ }
+ if( g_lockInitialized )
+ {
+ CEGLOs::DestroyLock( &g_eglLock );
+ g_lockInitialized = false;
+ }
+ if( g_tlsIndex != TLS_OUT_OF_INDEXES )
+ {
+ TlsFree( g_tlsIndex );
+ }
+ break;
+ }
+ }
+#else
+switch( fdwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ {
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+ {
+ EGLI_ASSERT( g_eglState == NULL );
+ break;
+ }
+ }
+#endif // EGLI_USE_PLATSIM_EXTENSIONS
+
+ return TRUE;
+ }
+
+#endif // _WIN32
+
+#ifdef __cplusplus
+}
+#endif