📄 khronos_egl.c
字号:
/**************************************************************************
Name : khronos_egl.c
Title : Khronos EGL
Author : PowerVR
Created : December 2003
Copyright : 2003-2004 by Imagination Technologies Limited.
: All rights reserved.
: No part of this software, either material or conceptual
: may be copied or distributed, transmitted, transcribed,
: stored in a retrieval system or translated into any
: human or computer language in any form by any means,
: electronic, mechanical, manual or other-wise, or
: disclosed to third parties without the express written
: permission of Imagination Technologies Limited, Unit 8, HomePark
: Industrial Estate, King's Langley, Hertfordshire,
: WD4 8LZ, U.K.
Description : Khronos EGL
Platform : All
*******************************************************************************/
/* @todo this implementation of kegl is not thread safe.
*/
#define MODULE_ID MODID_KHRONOSEGL
#include <assert.h>
#include <string.h>
#include "drvegl.h"
#include "ogles_types.h"
#include "servicesglue.h"
#include "ws.h"
#include "wsglue.h"
#include "eglglue.h"
#include "osglue.h"
#include "egl_internal.h"
#include "cfg-core.h"
#include "cfg.h"
#include "tls.h"
#include "qsort.h"
#include "srv.h"
#include "generic-ws.h"
#include "services.h"
#include "debug.h"
#include "modid.h"
#include "misc.h"
#define ATTRIB_COUNT (_EGL_CONFIG_ATTR_LAST - _EGL_CONFIG_ATTR_FIRST + 1)
#define ATTRIB(config,n) (config)->attributes[(n)-_EGL_CONFIG_ATTR_FIRST]
void (* __GetProcAddress (const char *procname))(IMG_VOID);
/** @todo this currently will have everything on the same thread.... */
#define ENV_CurrentThread() 1
/** @todo GLES_ASSERT is not defined. */
#define GLES_ASSERT(a)
/* This function allows our assert to be embedded in an expression */
static INLINE int _exp_assert(int a)
{
assert(a);
return a;
}
#define ASSERT_EXP(a) (_exp_assert(a))
/* Bias upwards because EGL_NO_DISPLAY is zero */
#define SLOT_INDEX_TO_EGLDISPLAY(index) ((signed int)ASSERT_EXP(EGL_NO_DISPLAY == 0),(index+1))
#define EGLDISPLAY_TO_SLOT_INDEX(egldisplay) \
( \
(signed int)ASSERT_EXP(EGL_NO_DISPLAY == 0), \
(signed int)ASSERT_EXP(egldisplay > 0), \
((signed int)egldisplay-1) \
)
/*
<function>
FUNCTION : _TlsInit ()
PURPOSE : Initialise our thread local storage.
PARAMETERS : In: tls - Pointer to state structure.
RETURNS : None
</function>
*/
static EGLint
_TlsInit (TLS pTls)
{
EGLint i;
assert (pTls!=IMG_NULL);
pTls->lastError = EGL_NOT_INITIALIZED;
pTls->currentReadSurface = EGL_NO_SURFACE;
pTls->currentDrawSurface = EGL_NO_SURFACE;
pTls->currentContext = EGL_NO_CONTEXT;
pTls->count=1;
pTls->dpyCount = WS_GetDisplayCount ();
pTls->dpys = GLESMalloc (0, pTls->dpyCount * sizeof (*pTls->dpys));
if (pTls->dpys==IMG_NULL)
return EGL_FALSE;
for (i=0; i<pTls->dpyCount; i++)
{
pTls->dpys[i].isInitialised = EGL_FALSE;
pTls->dpys[i].nativeDisplay = (NativeDisplayType) EGL_NO_DISPLAY;
}
return EGL_TRUE;
}
/*
<function>
FUNCTION : _FindWindowSurface ()
PURPOSE : Search the surfaces associated with a specified display for
the surface which represents a specified native window.
PARAMETERS : In: pDpy - Display.
In: window - Native window.
RETURNS : Surface or IMG_NULL.
</function>
*/
KEGL_SURFACE *
_FindWindowSurface (KEGL_DISPLAY *pDpy, NativeWindowType window)
{
EGLSurface pSurface;
assert (pDpy!=IMG_NULL);
for (pSurface = pDpy->pHeadSurface; pSurface!=IMG_NULL;
pSurface = pSurface->pNextSurface)
{
if (pSurface->type == EGL_SURFACE_WINDOW
&& pSurface->u.window.native == window)
return pSurface;
}
return IMG_NULL;
}
/*
<function>
FUNCTION : _FindPixmapSurface ()
PURPOSE : Search the surfaces associated with a specified display for
the surface which represents a specified native pixmap.
PARAMETERS : In: pDpy - Display.
RETURNS : In: pixmap = Native pixmap.
</function>
*/
static KEGL_SURFACE *
_FindPixmapSurface (KEGL_DISPLAY *pDpy, NativePixmapType pixmap)
{
EGLSurface pSurface;
assert (pDpy!=IMG_NULL);
for (pSurface = pDpy->pHeadSurface; pSurface!=IMG_NULL;
pSurface = pSurface->pNextSurface)
{
if (pSurface->type == EGL_SURFACE_PIXMAP
&& pSurface->u.pixmap.native == pixmap)
return pSurface;
}
return IMG_NULL;
}
/*
<function>
FUNCTION : _InitialiseContextMode ()
PURPOSE : Initialise a GLEScontextMode from an EGLConfig.
PARAMETERS : Out: pCtx - Context mode to initialise.
: In: pCfg - Configuration.
RETURNS : None
</function>
*/
static void
_InitialiseContextMode (GLEScontextMode *pCtx,
KEGL_CONFIG *pCfg)
{
assert (pCtx!=IMG_NULL);
pCtx->bHaveDepthBuffer = IMG_FALSE;
if (CFGC_GetAttrib (pCfg, EGL_DEPTH_SIZE))
pCtx->bHaveDepthBuffer = IMG_TRUE;
pCtx->ui32RedBits = CFGC_GetAttrib (pCfg, EGL_RED_SIZE);
pCtx->ui32GreenBits = CFGC_GetAttrib (pCfg, EGL_GREEN_SIZE);
pCtx->ui32BlueBits = CFGC_GetAttrib (pCfg, EGL_BLUE_SIZE);
pCtx->ui32AlphaBits = CFGC_GetAttrib (pCfg, EGL_ALPHA_SIZE);
pCtx->ui32BlueShift = 0;
pCtx->ui32GreenShift = pCtx->ui32BlueShift + pCtx->ui32BlueBits;
pCtx->ui32RedShift = pCtx->ui32GreenShift + pCtx->ui32GreenBits;
pCtx->ui32AlphaShift = pCtx->ui32RedShift + pCtx->ui32RedBits;
pCtx->ui32ColorBits = CFGC_GetAttrib (pCfg, EGL_BUFFER_SIZE);
pCtx->ui32DepthBits = CFGC_GetAttrib (pCfg, EGL_DEPTH_SIZE);
SRV_FindPVRPixelFormat ( pCtx->ui32AlphaBits,
pCtx->ui32RedBits,
pCtx->ui32GreenBits,
pCtx->ui32BlueBits,
&(pCtx->ePixelFormat),
NULL);
switch (CFGC_GetAttrib (pCfg, EGL_SAMPLE_BUFFERS))
{
case 0:
/* No anti-aliasing */
pCtx->ui32AntiAliasMode=0;
break;
case 1:
switch (CFGC_GetAttrib (pCfg, EGL_SAMPLES))
{
case 0:
pCtx->ui32AntiAliasMode=0;
break;
case 2:
pCtx->ui32AntiAliasMode=GLES_ANTIALIAS_2x1;
break;
case 4:
pCtx->ui32AntiAliasMode=GLES_ANTIALIAS_2x2;
break;
}
break;
}
}
/*
<function>
FUNCTION : _DpySurfaceUnlink ()
PURPOSE : Unlink a surface from a display.
PARAMETERS : In: pDpy -
In: pSurface -
RETURNS : None
</function>
*/
static void
_DpySurfaceUnlink (KEGL_DISPLAY *pDpy, EGLSurface pSurface)
{
EGLSurface *p;
assert (pDpy!=IMG_NULL);
assert (pSurface!=IMG_NULL);
for (p = &pDpy->pHeadSurface; *p!=IMG_NULL; p = &((*p)->pNextSurface))
{
if (*p == pSurface)
{
*p = pSurface->pNextSurface;
return;
}
}
}
/*
<function>
FUNCTION : _ContextDelete
PURPOSE : Delete a context which is unbound.
PARAMETERS : In: pCtx - context to delete
RETURNS : None
</function>
*/
static EGLint
_ContextDelete (EGLContext pCtx)
{
IMG_BOOL imgResult;
imgResult = GLESDestroyGC (pCtx->hOGL);
CFGC_Unlink (pCtx->pCfg);
GLESFree (0, pCtx);
/* can this actually happen? If so ww don;t really have an appropriate
error code to return, EGL_BAD_ALLOC may need to be reconsidered */
if (!imgResult)
return EGL_BAD_ALLOC;
return EGL_SUCCESS;
}
/*
<function>
FUNCTION : _SurfaceDelete
PURPOSE : Delete a surface which is unbound.
PARAMETERS : In: pSurface - surface to delete.
RETURNS : None.
</function>
*/
static void
_SurfaceDelete (GLESSysContext *pvrsrv, EGLSurface pSurface)
{
_DpySurfaceUnlink (pSurface->pDpy, pSurface);
WS_DeleteDrawable (pSurface, pvrsrv);
CFGC_Unlink (pSurface->pCfg);
GLESFree (0, pSurface);
}
/*
<function>
FUNCTION : _CompatibleContextAndSurface
PURPOSE :
From k-egl specification section 2.2. A context and a surface are
considered compatible if they:
- have colour and ancillary buffers of the same depth
- were created with respect to the same display.
PARAMETERS : In: pCtx -
In: pSurface -
RETURNS : EGL_TRUE - Compatible.
EGL_FALSE - Not compatible.
</function>
*/
static EGLBoolean
_CompatibleContextAndSurface (EGLContext pCtx, EGLSurface pSurface)
{
assert (pCtx!=IMG_NULL);
assert (pSurface!=IMG_NULL);
if (pCtx->pDpy != pSurface->pDpy)
return EGL_FALSE;
return CFG_CompatibleConfigs (pCtx->pCfg, pSurface->pCfg);
}
/*
<function>
FUNCTION : _SurfaceUnbind
PURPOSE : Unbind a surface. A surface which is marked as 'isDeleting'
which becomes completely unbound is deleted.
PARAMETERS : In: pvrsrv - system context
In: pSurface - Surface to delete.
RETURNS : None
</function>
*/
static void
_SurfaceUnbind (GLESSysContext *pvrsrv, EGLSurface pSurface)
{
pSurface->currentCount--;
if (pSurface->currentCount==0)
if (pSurface->isDeleting)
_SurfaceDelete (pvrsrv, pSurface);
}
/*
<function>
FUNCTION : _ContextBoundToOtherThread
PURPOSE : Test is a context is currently bound to another thread.
PARAMETERS : In: pCtx - Context to test.
RETURNS : EGL_TRUE - Context is bound to another thread.
EGL_FALSE - Context is not bound to another thread.
</function>
*/
static EGLBoolean
_ContextBoundToOtherThread (EGLContext pCtx)
{
if (pCtx != EGL_NO_CONTEXT
&& pCtx->isCurrent
&& pCtx->boundThread != ENV_CurrentThread ())
return EGL_TRUE;
return EGL_FALSE;
}
/*
<function>
FUNCTION : _SurfaceBoundToOtherThread
PURPOSE : Test if a surface is currently bound to another thread.
PARAMETERS : In: pSurface - Surface to test.
RETURNS : EGL_TRUE - Surface is bound to another thread.
EGL_FALSE - Surface is not bound to another thread.
</function>
*/
static EGLBoolean
_SurfaceBoundToOtherThread (EGLSurface pSurface)
{
if (pSurface != EGL_NO_SURFACE
&& pSurface->currentCount > 0
&& pSurface->boundThread != ENV_CurrentThread ())
return EGL_TRUE;
return EGL_FALSE;
}
/*
<function>
FUNCTION : _ValidateAttribList
PURPOSE : Ensure that an attribute list contains only recognised
attributes.
PARAMETERS : In: pAttribList - attribute list to validate.
RETURNS : EGL_SUCCESS or EGL_BAD_PARAMETER
</function>
*/
#define _EGL_CONFIG_ATTR_FIRST 0x3020
#define _EGL_CONFIG_ATTR_LAST 0x3037
static EGLint
_ValidateAttribList (const EGLint *pAttribList)
{
/* All attributes have consecutive numbers, therefore we only need to
range check for valid attribute identifiers. */
if (pAttribList!=IMG_NULL)
{
while (*pAttribList!=EGL_NONE)
{
if (*pAttribList<_EGL_CONFIG_ATTR_FIRST
|| *pAttribList > _EGL_CONFIG_ATTR_LAST)
return EGL_BAD_PARAMETER;
pAttribList += 2;
}
}
return EGL_SUCCESS;
}
/*
<function>
FUNCTION : eglGetError
PURPOSE : Khronos EGL API
Request the last error code.
PARAMETERS : None.
RETURNS : The last error code returned from a Khronos EGL API call made
by the current thread.
</function>
*/
IMG_EXPORT EGLint
eglGetError (void)
{
TLS pTls = EGLGetTLSValue ();
if (pTls==IMG_NULL)
{
return EGL_SUCCESS;
}
DPF((DBG_VERBOSE, "egl (app->egl): eglGetError()"));
return pTls->lastError;
}
/*
<function>
FUNCTION : eglGetDisplay
PURPOSE : Retrieve the EGLDisplay for the specified native display.
This API entry point operates outside of the eglInitialise,
eglTerminate region and therefore does not set any error
code for retrieval by eglGetError.
PARAMETERS : In: nativeDisplay
RETURNS : EGLDisplay or EGL_NO_DISPLAY
</function>
*/
IMG_EXPORT EGLDisplay
eglGetDisplay (NativeDisplayType nativeDisplay)
{
TLS pTls;
EGLDisplay eglDpy = EGL_NO_DISPLAY;
IMG_BOOL bValidDisplay = IMG_FALSE;
IMG_INT iSlot = 0;
IMG_INT iFirstFreeSlot = -1;
pTls = TLS_Open (_TlsInit);
if (pTls==IMG_NULL)
{
return EGL_FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -