summaryrefslogtreecommitdiff
path: root/src/egl/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/main')
-rw-r--r--src/egl/main/Makefile19
-rw-r--r--src/egl/main/eglapi.c154
-rw-r--r--src/egl/main/eglapi.h24
-rw-r--r--src/egl/main/eglcompiler.h21
-rw-r--r--src/egl/main/eglconfig.c42
-rw-r--r--src/egl/main/eglconfig.h23
-rw-r--r--src/egl/main/eglconfigutil.c209
-rw-r--r--src/egl/main/eglconfigutil.h10
-rw-r--r--src/egl/main/eglcontext.c368
-rw-r--r--src/egl/main/eglcontext.h79
-rw-r--r--src/egl/main/eglcurrent.c47
-rw-r--r--src/egl/main/eglcurrent.h11
-rw-r--r--src/egl/main/egldisplay.c238
-rw-r--r--src/egl/main/egldisplay.h172
-rw-r--r--src/egl/main/egldriver.c517
-rw-r--r--src/egl/main/egldriver.h69
-rw-r--r--src/egl/main/eglglobals.c2
-rw-r--r--src/egl/main/eglglobals.h3
-rw-r--r--src/egl/main/eglimage.c90
-rw-r--r--src/egl/main/eglimage.h96
-rw-r--r--src/egl/main/egllog.h2
-rw-r--r--src/egl/main/eglmisc.c54
-rw-r--r--src/egl/main/eglmisc.h3
-rw-r--r--src/egl/main/eglmode.c60
-rw-r--r--src/egl/main/eglscreen.c18
-rw-r--r--src/egl/main/eglscreen.h3
-rw-r--r--src/egl/main/eglsurface.c484
-rw-r--r--src/egl/main/eglsurface.h122
-rw-r--r--src/egl/main/egltypedefs.h10
29 files changed, 1689 insertions, 1261 deletions
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index ec326a845d..31f214cf6f 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -19,6 +19,7 @@ HEADERS = \
egldisplay.h \
egldriver.h \
eglglobals.h \
+ eglimage.h \
egllog.h \
eglmisc.h \
eglmode.h \
@@ -36,6 +37,7 @@ SOURCES = \
egldisplay.c \
egldriver.c \
eglglobals.c \
+ eglimage.c \
egllog.c \
eglmisc.c \
eglmode.c \
@@ -47,8 +49,13 @@ OBJECTS = $(SOURCES:.c=.o)
# use dl*() to load drivers
-LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1
+LOCAL_CFLAGS = -D_EGL_PLATFORM_POSIX=1
+EGL_DEFAULT_DISPLAY = $(word 1, $(EGL_DISPLAYS))
+
+LOCAL_CFLAGS += \
+ -D_EGL_DEFAULT_DISPLAY=\"$(EGL_DEFAULT_DISPLAY)\" \
+ -D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\"
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
@@ -67,7 +74,15 @@ $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME): $(OBJECTS)
-install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
$(EGL_LIB_DEPS) $(OBJECTS)
-install: default
+install-headers:
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/KHR
+ $(INSTALL) -m 644 $(TOP)/include/KHR/*.h \
+ $(DESTDIR)$(INSTALL_INC_DIR)/KHR
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/EGL
+ $(INSTALL) -m 644 $(TOP)/include/EGL/*.h \
+ $(DESTDIR)$(INSTALL_INC_DIR)/EGL
+
+install: default install-headers
$(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
$(MINSTALL) $(TOP)/$(LIB_DIR)/$(EGL_LIB_GLOB) \
$(DESTDIR)$(INSTALL_LIB_DIR)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 14cc5fa613..364ad9c458 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -60,11 +60,13 @@
#include "egldisplay.h"
#include "egltypedefs.h"
#include "eglglobals.h"
+#include "eglcurrent.h"
#include "egldriver.h"
#include "eglsurface.h"
#include "eglconfig.h"
#include "eglscreen.h"
#include "eglmode.h"
+#include "eglimage.h"
/**
@@ -72,7 +74,7 @@
* We initialize our global vars and create a private _EGLDisplay object.
*/
EGLDisplay EGLAPIENTRY
-eglGetDisplay(NativeDisplayType nativeDisplay)
+eglGetDisplay(EGLNativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy;
dpy = _eglFindDisplay(nativeDisplay);
@@ -93,23 +95,24 @@ EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
- _EGLDriver *drv;
EGLint major_int, minor_int;
if (!disp)
return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
- drv = disp->Driver;
- if (!drv) {
- drv = _eglOpenDriver(disp);
- if (!drv)
- return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+ if (!disp->Initialized) {
+ _EGLDriver *drv = disp->Driver;
+
+ if (!drv) {
+ _eglPreloadDrivers();
+ drv = _eglMatchDriver(disp);
+ if (!drv)
+ return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+ }
/* Initialize the particular display now */
- if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) {
- _eglCloseDriver(drv, disp);
+ if (!drv->API.Initialize(drv, disp, &major_int, &minor_int))
return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
- }
disp->APImajor = major_int;
disp->APIminor = minor_int;
@@ -120,6 +123,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
disp->Driver = drv;
+ disp->Initialized = EGL_TRUE;
} else {
major_int = disp->APImajor;
minor_int = disp->APIminor;
@@ -139,16 +143,16 @@ EGLBoolean EGLAPIENTRY
eglTerminate(EGLDisplay dpy)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
- _EGLDriver *drv;
if (!disp)
return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
- drv = disp->Driver;
- if (drv) {
+ if (disp->Initialized) {
+ _EGLDriver *drv = disp->Driver;
+
drv->API.Terminate(drv, disp);
- _eglCloseDriver(drv, disp);
- disp->Driver = NULL;
+ /* do not reset disp->Driver */
+ disp->Initialized = EGL_FALSE;
}
return EGL_TRUE;
@@ -165,7 +169,7 @@ _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
_eglError(EGL_BAD_DISPLAY, msg);
return NULL;
}
- if (!disp->Driver) {
+ if (!disp->Initialized) {
_eglError(EGL_NOT_INITIALIZED, msg);
return NULL;
}
@@ -391,9 +395,19 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
_EGLSurface *read_surf = _eglLookupSurface(read, disp);
_EGLDriver *drv;
- drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!disp)
+ return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
+ drv = disp->Driver;
+
+ /* display is allowed to be uninitialized under certain condition */
+ if (!disp->Initialized) {
+ if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
+ ctx != EGL_NO_CONTEXT)
+ return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
+ }
if (!drv)
- return EGL_FALSE;
+ return EGL_TRUE;
+
if (!context && ctx != EGL_NO_CONTEXT)
return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
if ((!draw_surf && draw != EGL_NO_SURFACE) ||
@@ -415,7 +429,7 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx,
EGLSurface EGLAPIENTRY
eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
- NativeWindowType window, const EGLint *attrib_list)
+ EGLNativeWindowType window, const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
_EGLConfig *conf = _eglLookupConfig(config, disp);
@@ -436,7 +450,7 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLSurface EGLAPIENTRY
eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
- NativePixmapType pixmap, const EGLint *attrib_list)
+ EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
_EGLConfig *conf = _eglLookupConfig(config, disp);
@@ -524,7 +538,7 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval)
_EGLSurface *surf;
_EGL_DECLARE_DD(dpy);
- if (!ctx || !_eglIsContextLinked(ctx) || ctx->Display != disp)
+ if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
surf = ctx->DrawSurface;
@@ -550,7 +564,7 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
EGLBoolean EGLAPIENTRY
-eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
+eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
{
_EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
return drv->API.CopyBuffers(drv, disp, surf, target);
@@ -571,9 +585,9 @@ eglWaitClient(void)
return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
/* a valid current context implies an initialized current display */
- disp = ctx->Display;
+ disp = ctx->Resource.Display;
+ assert(disp->Initialized);
drv = disp->Driver;
- assert(drv);
return drv->API.WaitClient(drv, disp, ctx);
}
@@ -615,9 +629,9 @@ eglWaitNative(EGLint engine)
return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
/* a valid current context implies an initialized current display */
- disp = ctx->Display;
+ disp = ctx->Resource.Display;
+ assert(disp->Initialized);
drv = disp->Driver;
- assert(drv);
return drv->API.WaitNative(drv, disp, engine);
}
@@ -626,8 +640,8 @@ eglWaitNative(EGLint engine)
EGLDisplay EGLAPIENTRY
eglGetCurrentDisplay(void)
{
- _EGLDisplay *dpy = _eglGetCurrentDisplay();
- return _eglGetDisplayHandle(dpy);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ return (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
}
@@ -676,7 +690,8 @@ eglGetError(void)
}
-void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY
+eglGetProcAddress(const char *procname)
{
static const struct {
const char *name;
@@ -697,6 +712,10 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
{ "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
{ "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
#endif /* EGL_MESA_screen_surface */
+#ifdef EGL_KHR_image_base
+ { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
+ { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
+#endif /* EGL_KHR_image_base */
{ NULL, NULL }
};
EGLint i;
@@ -710,13 +729,12 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
}
}
- /* preload a driver if there isn't one */
- if (!_eglGlobal.NumDrivers)
- _eglPreloadDriver(NULL);
+ _eglPreloadDrivers();
/* now loop over drivers to query their procs */
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
- _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
+ _EGLDriver *drv = _eglGlobal.Drivers[i];
+ _EGLProc p = drv->API.GetProcAddress(drv, procname);
if (p)
return p;
}
@@ -977,14 +995,23 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLBoolean
eglReleaseThread(void)
{
- /* unbind current context */
+ /* unbind current contexts */
if (!_eglIsCurrentThreadDummy()) {
- _EGLDisplay *disp = _eglGetCurrentDisplay();
- _EGLDriver *drv;
- if (disp) {
- drv = disp->Driver;
- (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint api_index = t->CurrentAPIIndex;
+ EGLint i;
+
+ for (i = 0; i < _EGL_API_NUM_APIS; i++) {
+ _EGLContext *ctx = t->CurrentContexts[i];
+ if (ctx) {
+ _EGLDisplay *disp = ctx->Resource.Display;
+ _EGLDriver *drv = disp->Driver;
+ t->CurrentAPIIndex = i;
+ (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+ }
}
+
+ t->CurrentAPIIndex = api_index;
}
_eglDestroyCurrentThread();
@@ -993,3 +1020,52 @@ eglReleaseThread(void)
#endif /* EGL_VERSION_1_2 */
+
+
+#ifdef EGL_KHR_image_base
+
+
+EGLImageKHR
+eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLContext *context = _eglLookupContext(ctx, disp);
+ _EGLDriver *drv;
+ _EGLImage *img;
+
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
+ return EGL_NO_IMAGE_KHR;
+ if (!context && ctx != EGL_NO_CONTEXT) {
+ _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ img = drv->API.CreateImageKHR(drv,
+ disp, context, target, buffer, attr_list);
+ if (img)
+ return _eglLinkImage(img, disp);
+ else
+ return EGL_NO_IMAGE_KHR;
+}
+
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGLDriver *drv;
+
+ drv = _eglCheckDisplay(disp, __FUNCTION__);
+ if (!drv)
+ return EGL_FALSE;
+ if (!img)
+ return _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+
+ _eglUnlinkImage(img);
+ return drv->API.DestroyImageKHR(drv, disp, img);
+}
+
+
+#endif /* EGL_KHR_image_base */
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index aa0abe3eb6..c3676ec56a 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -4,7 +4,7 @@
/**
* A generic function ptr type
*/
-typedef void (*_EGLProc)();
+typedef void (*_EGLProc)(void);
/**
@@ -23,12 +23,13 @@ typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLC
/* context funcs */
typedef _EGLContext *(*CreateContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, _EGLContext *share_list, const EGLint *attrib_list);
typedef EGLBoolean (*DestroyContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
+/* this is the only function (other than Initialize) that may be called with an uninitialized display */
typedef EGLBoolean (*MakeCurrent_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx);
typedef EGLBoolean (*QueryContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint attribute, EGLint *value);
/* surface funcs */
-typedef _EGLSurface *(*CreateWindowSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, NativeWindowType window, const EGLint *attrib_list);
-typedef _EGLSurface *(*CreatePixmapSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, NativePixmapType pixmap, const EGLint *attrib_list);
+typedef _EGLSurface *(*CreateWindowSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, EGLNativeWindowType window, const EGLint *attrib_list);
+typedef _EGLSurface *(*CreatePixmapSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
typedef _EGLSurface *(*CreatePbufferSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, const EGLint *attrib_list);
typedef EGLBoolean (*DestroySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface);
typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint *value);
@@ -37,14 +38,14 @@ typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurf
typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw);
-typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, NativePixmapType target);
+typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLNativePixmapType target);
/* misc funcs */
typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine);
-typedef _EGLProc (*GetProcAddress_t)(const char *procname);
+typedef _EGLProc (*GetProcAddress_t)(_EGLDriver *drv, const char *procname);
@@ -69,6 +70,11 @@ typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDis
#endif /* EGL_VERSION_1_2 */
+#ifdef EGL_KHR_image_base
+typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list);
+typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
+#endif /* EGL_KHR_image_base */
+
/**
* The API dispatcher jumps through these functions
@@ -104,7 +110,7 @@ struct _egl_api
WaitNative_t WaitNative;
GetProcAddress_t GetProcAddress;
- /* EGL_MESA_screen extension */
+#ifdef EGL_MESA_screen_surface
ChooseModeMESA_t ChooseModeMESA;
GetModesMESA_t GetModesMESA;
GetModeAttribMESA_t GetModeAttribMESA;
@@ -117,10 +123,16 @@ struct _egl_api
QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA;
QueryScreenModeMESA_t QueryScreenModeMESA;
QueryModeStringMESA_t QueryModeStringMESA;
+#endif /* EGL_MESA_screen_surface */
#ifdef EGL_VERSION_1_2
CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
#endif
+
+#ifdef EGL_KHR_image_base
+ CreateImageKHR_t CreateImageKHR;
+ DestroyImageKHR_t DestroyImageKHR;
+#endif /* EGL_KHR_image_base */
};
#endif /* EGLAPI_INCLUDED */
diff --git a/src/egl/main/eglcompiler.h b/src/egl/main/eglcompiler.h
index f7c93f14ce..d844fbb0ef 100644
--- a/src/egl/main/eglcompiler.h
+++ b/src/egl/main/eglcompiler.h
@@ -64,11 +64,30 @@
/**
* Function visibility
*/
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
+#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303) \
+ || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
# define PUBLIC __attribute__((visibility("default")))
#else
# define PUBLIC
#endif
+/**
+ * The __FUNCTION__ gcc variable is generally only used for debugging.
+ * If we're not using gcc, define __FUNCTION__ as a cpp symbol here.
+ * Don't define it if using a newer Windows compiler.
+ */
+#ifndef __FUNCTION__
+# if defined(__VMS)
+# define __FUNCTION__ "VMS$NL:"
+# elif ((!defined __GNUC__) || (__GNUC__ < 2)) && (!defined __xlC__) && \
+ (!defined(_MSC_VER) || _MSC_VER < 1300)
+# if (__STDC_VERSION__ >= 199901L) /* C99 */ || \
+ (defined(__SUNPRO_C) && defined(__C99FEATURES__))
+# define __FUNCTION__ __func__
+# else
+# define __FUNCTION__ "<unknown>"
+# endif
+# endif
+#endif
#endif /* EGLCOMPILER_INCLUDED */
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index 31d69a7708..1190f8cdd5 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -4,13 +4,11 @@
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "eglconfig.h"
#include "egldisplay.h"
-#include "egldriver.h"
-#include "eglglobals.h"
+#include "eglcurrent.h"
#include "egllog.h"
@@ -27,10 +25,12 @@
* IDs are from 1 to N respectively.
*/
void
-_eglInitConfig(_EGLConfig *config, EGLint id)
+_eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id)
{
memset(config, 0, sizeof(*config));
+ config->Display = dpy;
+
/* some attributes take non-zero default values */
SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id);
SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_NONE);
@@ -224,7 +224,8 @@ static const struct {
{ EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO,
ATTRIB_CRITERION_SPECIAL,
EGL_NONE },
- { EGL_PRESERVED_RESOURCES, ATTRIB_TYPE_PSEUDO,
+ /* there is a gap before EGL_SAMPLES */
+ { 0x3030, ATTRIB_TYPE_PSEUDO,
ATTRIB_CRITERION_IGNORE,
0 },
{ EGL_NONE, ATTRIB_TYPE_PSEUDO,
@@ -328,6 +329,8 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
EGL_VG_ALPHA_FORMAT_PRE_BIT |
EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ if (conf->Display->Extensions.MESA_screen_surface)
+ mask |= EGL_SCREEN_BIT_MESA;
break;
case EGL_RENDERABLE_TYPE:
case EGL_CONFORMANT:
@@ -363,8 +366,11 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
valid = EGL_TRUE;
}
- if (!valid)
+ if (!valid) {
+ _eglLog(_EGL_DEBUG,
+ "attribute 0x%04x has an invalid value 0x%x", attr, val);
break;
+ }
}
/* any invalid attribute value should have been catched */
@@ -387,10 +393,18 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
valid = EGL_FALSE;
break;
}
+ if (!valid) {
+ _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
+ return EGL_FALSE;
+ }
val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS);
if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES))
valid = EGL_FALSE;
+ if (!valid) {
+ _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
+ return EGL_FALSE;
+ }
val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
if (!(val & EGL_WINDOW_BIT)) {
@@ -403,6 +417,10 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA))
valid = EGL_FALSE;
}
+ if (!valid) {
+ _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
+ return EGL_FALSE;
+ }
return valid;
}
@@ -454,8 +472,14 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
break;
}
- if (!matched)
+ if (!matched) {
+#ifdef DEBUG
+ _eglLog(_EGL_DEBUG,
+ "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
+ val, attr, cmp);
+#endif
break;
+ }
}
return matched;
@@ -730,7 +754,7 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
if (!num_configs)
return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
- _eglInitConfig(&criteria, 0);
+ _eglInitConfig(&criteria, disp, 0);
if (!_eglParseConfigAttribList(&criteria, attrib_list))
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
@@ -772,7 +796,7 @@ _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
/* there are some holes in the range */
switch (attr) {
- case EGL_PRESERVED_RESOURCES:
+ case 0x3030 /* a gap before EGL_SAMPLES */:
case EGL_NONE:
#ifdef EGL_VERSION_1_4
case EGL_MATCH_NATIVE_PIXMAP:
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
index 799bf4ee24..56ec95fe9a 100644
--- a/src/egl/main/eglconfig.h
+++ b/src/egl/main/eglconfig.h
@@ -21,6 +21,9 @@ struct _egl_config
};
+/**
+ * Macros for source level compatibility.
+ */
#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) _eglSetConfigKey(CONF, ATTR, VAL)
#define GET_CONFIG_ATTRIB(CONF, ATTR) _eglGetConfigKey(CONF, ATTR)
@@ -55,6 +58,10 @@ _eglResetConfigKeys(_EGLConfig *conf, EGLint val)
/**
* Update a config for a given key.
+ *
+ * Note that a valid key is not necessarily a valid attribute. There are gaps
+ * in the attribute enums. The separation is to catch application errors.
+ * Drivers should never set a key that is an invalid attribute.
*/
static INLINE void
_eglSetConfigKey(_EGLConfig *conf, EGLint key, EGLint val)
@@ -77,22 +84,8 @@ _eglGetConfigKey(const _EGLConfig *conf, EGLint key)
}
-/**
- * Set a given attribute.
- *
- * Because _eglGetConfigAttrib is already used as a fallback driver
- * function, this function is not considered to have a good name.
- * SET_CONFIG_ATTRIB is preferred over this function.
- */
-static INLINE void
-_eglSetConfigAttrib(_EGLConfig *conf, EGLint attr, EGLint val)
-{
- SET_CONFIG_ATTRIB(conf, attr, val);
-}
-
-
PUBLIC void
-_eglInitConfig(_EGLConfig *config, EGLint id);
+_eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id);
PUBLIC EGLConfig
diff --git a/src/egl/main/eglconfigutil.c b/src/egl/main/eglconfigutil.c
index 36e94f0d2d..e416b190f0 100644
--- a/src/egl/main/eglconfigutil.c
+++ b/src/egl/main/eglconfigutil.c
@@ -4,10 +4,8 @@
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include "eglconfigutil.h"
-#include "egllog.h"
/**
@@ -128,210 +126,3 @@ _eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m,
return EGL_TRUE;
}
-
-
-/**
- * Creates a set of \c _EGLConfigs that a driver will expose.
- *
- * A set of \c __GLcontextModes will be created based on the supplied
- * parameters. The number of modes processed will be 2 *
- * \c num_depth_stencil_bits * \c num_db_modes.
- *
- * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
- * \c db_modes, and \c visType into each \c __GLcontextModes element.
- * However, the meanings of \c fb_format and \c fb_type require further
- * explanation. The \c fb_format specifies which color components are in
- * each pixel and what the default order is. For example, \c GL_RGB specifies
- * that red, green, blue are available and red is in the "most significant"
- * position and blue is in the "least significant". The \c fb_type specifies
- * the bit sizes of each component and the actual ordering. For example, if
- * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
- * are the blue value, bits [10:5] are the green value, and bits [4:0] are
- * the red value.
- *
- * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
- * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
- * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
- * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
- * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
- * still uses 32-bits.
- *
- * If in doubt, look at the tables used in the function.
- *
- * \param configs the array of configs generated
- * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
- * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
- * \param fb_type Type of the pixels in the framebuffer. Currently only
- * \c GL_UNSIGNED_SHORT_5_6_5,
- * \c GL_UNSIGNED_SHORT_5_6_5_REV,
- * \c GL_UNSIGNED_INT_8_8_8_8, and
- * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
- * \param depth_bits Array of depth buffer sizes to be exposed.
- * \param stencil_bits Array of stencil buffer sizes to be exposed.
- * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
- * \c stencil_bits.
- * \param db_modes Array of buffer swap modes. If an element has a
- * value of \c GLX_NONE, then it represents a
- * single-buffered mode. Other valid values are
- * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
- * \c GLX_SWAP_UNDEFINED_OML. See the
- * GLX_OML_swap_method extension spec for more details.
- * \param num_db_modes Number of entries in \c db_modes.
- * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
- * \c GLX_DIRECT_COLOR.
- *
- * \returns
- * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
- * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
- * \c fb_type).
- *
- * \todo
- * There is currently no way to support packed RGB modes (i.e., modes with
- * exactly 3 bytes per pixel) or floating-point modes. This could probably
- * be done by creating some new, private enums with clever names likes
- * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
- * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
- */
-EGLBoolean
-_eglFillInConfigs(_EGLConfig * configs,
- GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- int visType)
-{
- static const uint8_t bits_table[3][4] = {
- /* R G B A */
- { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
- { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
- { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
- };
-
- /* The following arrays are all indexed by the fb_type masked with 0x07.
- * Given the four supported fb_type values, this results in valid array
- * indices of 3, 4, 5, and 7.
- */
- static const uint32_t masks_table_rgb[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
- {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_rgba[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
- {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
- };
-
-#if 0
- static const uint32_t masks_table_bgr[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
- {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgra[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
- {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
- };
-#endif
-
- static const uint8_t bytes_per_pixel[8] = {
- 0, 0, 0, 2, 2, 4, 0, 4
- };
-
- const uint8_t * bits;
- const uint32_t * masks;
- const int index = fb_type & 0x07;
- _EGLConfig *config;
- unsigned i;
- unsigned j;
- unsigned k;
-
- if ( bytes_per_pixel[index] == 0 ) {
- _eglLog(_EGL_INFO,
- "[_eglFillInConfigs:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
- __LINE__, fb_type);
- return GL_FALSE;
- }
-
- /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
- * the _REV versions.
- *
- * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
- */
- switch ( fb_format ) {
- case GL_RGB:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
- masks = masks_table_rgb[index];
- break;
-
- case GL_RGBA:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
- masks = masks_table_rgba[index];
- break;
-
-#if 0
- case GL_BGR:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
- masks = masks_table_bgr[index];
- break;
-
- case GL_BGRA:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
- masks = masks_table_bgra[index];
- break;
-#endif
-
- default:
- _eglLog(_EGL_WARNING,
- "[_eglFillInConfigs:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
- __LINE__, fb_format);
- return GL_FALSE;
- }
-
- config = configs;
- for (k = 0; k < num_depth_stencil_bits; k++) {
- for (i = 0; i < num_db_modes; i++) {
- for (j = 0; j < 2; j++) {
- _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
- _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
- _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
- _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
- _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
- bits[0] + bits[1] + bits[2] + bits[3]);
-
- _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
- _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
-
- _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
- EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
-
- config++;
- }
- }
- }
- return GL_TRUE;
-}
-
diff --git a/src/egl/main/eglconfigutil.h b/src/egl/main/eglconfigutil.h
index 9f8906dedb..c6f4819960 100644
--- a/src/egl/main/eglconfigutil.h
+++ b/src/egl/main/eglconfigutil.h
@@ -16,14 +16,4 @@ _eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m,
EGLint conformant, EGLint renderable_type);
-PUBLIC EGLBoolean
-_eglFillInConfigs( _EGLConfig *configs,
- EGLenum fb_format, EGLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const EGLenum * db_modes, unsigned num_db_modes,
- int visType );
-
-
-
#endif /* EGLCONFIGUTIL_INCLUDED */
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index ee4b1b59f5..012d8dfe1f 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -4,9 +4,96 @@
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldisplay.h"
-#include "egldriver.h"
-#include "eglglobals.h"
+#include "eglcurrent.h"
#include "eglsurface.h"
+#include "egllog.h"
+
+
+/**
+ * Return the API bit (one of EGL_xxx_BIT) of the context.
+ */
+static EGLint
+_eglGetContextAPIBit(_EGLContext *ctx)
+{
+ EGLint bit = 0;
+
+ switch (ctx->ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ switch (ctx->ClientVersion) {
+ case 1:
+ bit = EGL_OPENGL_ES_BIT;
+ break;
+ case 2:
+ bit = EGL_OPENGL_ES2_BIT;
+ break;
+ default:
+ break;
+ }
+ break;
+ case EGL_OPENVG_API:
+ bit = EGL_OPENVG_BIT;
+ break;
+ case EGL_OPENGL_API:
+ bit = EGL_OPENGL_BIT;
+ break;
+ default:
+ break;
+ }
+
+ return bit;
+}
+
+
+/**
+ * Parse the list of context attributes and return the proper error code.
+ */
+static EGLint
+_eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list)
+{
+ EGLenum api = ctx->ClientAPI;
+ EGLint i, err = EGL_SUCCESS;
+
+ if (!attrib_list)
+ return EGL_SUCCESS;
+
+ for (i = 0; attrib_list[i] != EGL_NONE; i++) {
+ EGLint attr = attrib_list[i++];
+ EGLint val = attrib_list[i];
+
+ switch (attr) {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ if (api != EGL_OPENGL_ES_API) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (val != 1 && val != 2) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ ctx->ClientVersion = val;
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+
+ if (err != EGL_SUCCESS) {
+ _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
+ break;
+ }
+ }
+
+ if (err == EGL_SUCCESS) {
+ EGLint renderable_type, api_bit;
+
+ renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
+ api_bit = _eglGetContextAPIBit(ctx);
+ if (!(renderable_type & api_bit))
+ err = EGL_BAD_CONFIG;
+ }
+
+ return err;
+}
/**
@@ -14,11 +101,11 @@
* in the attrib_list.
*/
EGLBoolean
-_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
- _EGLConfig *conf, const EGLint *attrib_list)
+_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
+ const EGLint *attrib_list)
{
- EGLint i;
const EGLenum api = eglQueryAPI();
+ EGLint err;
if (api == EGL_NONE) {
_eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
@@ -26,26 +113,16 @@ _eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
}
memset(ctx, 0, sizeof(_EGLContext));
+ ctx->Resource.Display = dpy;
+ ctx->ClientAPI = api;
+ ctx->Config = conf;
+ ctx->WindowRenderBuffer = EGL_NONE;
ctx->ClientVersion = 1; /* the default, per EGL spec */
- for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
- switch (attrib_list[i]) {
- case EGL_CONTEXT_CLIENT_VERSION:
- i++;
- ctx->ClientVersion = attrib_list[i];
- break;
- default:
- _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
- return EGL_FALSE;
- }
- }
-
- ctx->Config = conf;
- ctx->DrawSurface = EGL_NO_SURFACE;
- ctx->ReadSurface = EGL_NO_SURFACE;
- ctx->ClientAPI = api;
- ctx->WindowRenderBuffer = EGL_NONE;
+ err = _eglParseContextAttribList(ctx, attrib_list);
+ if (err != EGL_SUCCESS)
+ return _eglError(err, "eglCreateContext");
return EGL_TRUE;
}
@@ -58,20 +135,6 @@ _EGLContext *
_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
_EGLContext *share_list, const EGLint *attrib_list)
{
-#if 0 /* example code */
- _EGLContext *context;
-
- context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
- if (!context)
- return NULL;
-
- if (!_eglInitContext(drv, context, conf, attrib_list)) {
- free(context);
- return NULL;
- }
-
- return context;
-#endif
return NULL;
}
@@ -140,99 +203,169 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
/**
- * Drivers will typically call this to do the error checking and
- * update the various flags.
- * Then, the driver will do its device-dependent Make-Current stuff.
+ * Bind the context to the surfaces. Return the surfaces that are "orphaned".
+ * That is, when the context is not NULL, return the surfaces it previously
+ * bound to; when the context is NULL, the same surfaces are returned.
*/
-EGLBoolean
-_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
- _EGLSurface *read, _EGLContext *ctx)
+static void
+_eglBindContextToSurfaces(_EGLContext *ctx,
+ _EGLSurface **draw, _EGLSurface **read)
+{
+ _EGLSurface *newDraw = *draw, *newRead = *read;
+
+ if (newDraw->CurrentContext)
+ newDraw->CurrentContext->DrawSurface = NULL;
+ newDraw->CurrentContext = ctx;
+
+ if (newRead->CurrentContext)
+ newRead->CurrentContext->ReadSurface = NULL;
+ newRead->CurrentContext = ctx;
+
+ if (ctx) {
+ *draw = ctx->DrawSurface;
+ ctx->DrawSurface = newDraw;
+
+ *read = ctx->ReadSurface;
+ ctx->ReadSurface = newRead;
+ }
+}
+
+
+/**
+ * Bind the context to the thread and return the previous context.
+ *
+ * Note that the context may be NULL.
+ */
+static _EGLContext *
+_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- _EGLContext *oldContext = NULL;
- _EGLSurface *oldDrawSurface = NULL;
- _EGLSurface *oldReadSurface = NULL;
EGLint apiIndex;
+ _EGLContext *oldCtx;
+
+ apiIndex = (ctx) ?
+ _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
+
+ oldCtx = t->CurrentContexts[apiIndex];
+ if (ctx == oldCtx)
+ return NULL;
+
+ if (oldCtx)
+ oldCtx->Binding = NULL;
+ if (ctx)
+ ctx->Binding = t;
+
+ t->CurrentContexts[apiIndex] = ctx;
+
+ return oldCtx;
+}
+
+
+/**
+ * Return true if the given context and surfaces can be made current.
+ */
+static EGLBoolean
+_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint conflict_api;
if (_eglIsCurrentThreadDummy())
return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
- if (ctx) {
- /* error checking */
- if (ctx->Binding && ctx->Binding != t)
- return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
- if (draw == NULL || read == NULL)
+ /* this is easy */
+ if (!ctx) {
+ if (draw || read)
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- if (draw->Config != ctx->Config || read->Config != ctx->Config)
- return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- if ((draw->Binding && draw->Binding->Binding != t) ||
- (read->Binding && read->Binding->Binding != t))
- return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+ return EGL_TRUE;
+ }
+
+ /* ctx/draw/read must be all given */
+ if (draw == NULL || read == NULL)
+ return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+
+ /* context stealing from another thread is not allowed */
+ if (ctx->Binding && ctx->Binding != t)
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+
+ /*
+ * The spec says
+ *
+ * "If ctx is current to some other thread, or if either draw or read are
+ * bound to contexts in another thread, an EGL_BAD_ACCESS error is
+ * generated."
+ *
+ * But it also says
+ *
+ * "at most one context may be bound to a particular surface at a given
+ * time"
+ *
+ * The latter is more restrictive so we can check only the latter case.
+ */
+ if ((draw->CurrentContext && draw->CurrentContext != ctx) ||
+ (read->CurrentContext && read->CurrentContext != ctx))
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+ /* simply require the configs to be equal */
+ if (draw->Config != ctx->Config || read->Config != ctx->Config)
+ return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+
+ switch (ctx->ClientAPI) {
#ifdef EGL_VERSION_1_4
- /* OpenGL and OpenGL ES are conflicting */
- switch (ctx->ClientAPI) {
- case EGL_OPENGL_ES_API:
- if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)])
- return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
- break;
- case EGL_OPENGL_API:
- if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)])
- return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
- break;
- default:
- break;
- }
+ /* OpenGL and OpenGL ES are conflicting */
+ case EGL_OPENGL_ES_API:
+ conflict_api = EGL_OPENGL_API;
+ break;
+ case EGL_OPENGL_API:
+ conflict_api = EGL_OPENGL_ES_API;
+ break;
#endif
- apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
- }
- else {
- if (draw != NULL || read != NULL)
- return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
- apiIndex = t->CurrentAPIIndex;
+ default:
+ conflict_api = -1;
+ break;
}
- oldContext = t->CurrentContexts[apiIndex];
- if (oldContext) {
- oldDrawSurface = oldContext->DrawSurface;
- oldReadSurface = oldContext->ReadSurface;
- assert(oldDrawSurface);
- assert(oldReadSurface);
-
- /* break old bindings */
- t->CurrentContexts[apiIndex] = NULL;
- oldContext->Binding = NULL;
- oldContext->DrawSurface = NULL;
- oldContext->ReadSurface = NULL;
- oldDrawSurface->Binding = NULL;
- oldReadSurface->Binding = NULL;
+ if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
+ return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Bind the context to the current thread and given surfaces. Return the
+ * previously bound context and the surfaces it bound to. Each argument is
+ * both input and output.
+ */
+EGLBoolean
+_eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ _EGLContext *newCtx = *ctx, *oldCtx;
+
+ if (!_eglCheckMakeCurrent(newCtx, *draw, *read))
+ return EGL_FALSE;
+
+ /* bind the new context */
+ oldCtx = _eglBindContextToThread(newCtx, t);
+ *ctx = oldCtx;
+ if (newCtx)
+ _eglBindContextToSurfaces(newCtx, draw, read);
+ /* unbind the old context from its binding surfaces */
+ if (oldCtx) {
/*
- * check if the old context or surfaces need to be deleted
+ * If the new context replaces some old context, the new one should not
+ * be current before the replacement and it should not be bound to any
+ * surface.
*/
- if (!_eglIsSurfaceLinked(oldDrawSurface)) {
- assert(draw != oldDrawSurface && read != oldDrawSurface);
- drv->API.DestroySurface(drv, dpy, oldDrawSurface);
- }
- if (oldReadSurface != oldDrawSurface &&
- !_eglIsSurfaceLinked(oldReadSurface)) {
- assert(draw != oldReadSurface && read != oldReadSurface);
- drv->API.DestroySurface(drv, dpy, oldReadSurface);
- }
- if (!_eglIsContextLinked(oldContext)) {
- assert(ctx != oldContext);
- drv->API.DestroyContext(drv, dpy, oldContext);
- }
- }
+ if (newCtx)
+ assert(!*draw && !*read);
- /* build new bindings */
- if (ctx) {
- t->CurrentContexts[apiIndex] = ctx;
- ctx->Binding = t;
- ctx->DrawSurface = draw;
- ctx->ReadSurface = read;
- draw->Binding = ctx;
- read->Binding = ctx;
+ *draw = oldCtx->DrawSurface;
+ *read = oldCtx->ReadSurface;
+ assert(*draw && *read);
+
+ _eglBindContextToSurfaces(NULL, draw, read);
}
return EGL_TRUE;
@@ -240,6 +373,17 @@ _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
/**
+ * Just a placeholder/demo function. Drivers should override this.
+ */
+EGLBoolean
+_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
+ _EGLSurface *read, _EGLContext *ctx)
+{
+ return EGL_FALSE;
+}
+
+
+/**
* This is defined by the EGL_MESA_copy_context extension.
*/
EGLBoolean
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
index cb9e3f4a89..cfe92dd9f5 100644
--- a/src/egl/main/eglcontext.h
+++ b/src/egl/main/eglcontext.h
@@ -1,9 +1,9 @@
-
#ifndef EGLCONTEXT_INCLUDED
#define EGLCONTEXT_INCLUDED
#include "egltypedefs.h"
+#include "egldisplay.h"
/**
@@ -11,9 +11,8 @@
*/
struct _egl_context
{
- /* Managed by EGLDisplay for linking */
- _EGLDisplay *Display;
- _EGLContext *Next;
+ /* A context is a display resource */
+ _EGLResource Resource;
/* The bound status of the context */
_EGLThreadInfo *Binding;
@@ -31,7 +30,7 @@ struct _egl_context
PUBLIC EGLBoolean
-_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
+_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy,
_EGLConfig *config, const EGLint *attrib_list);
@@ -48,6 +47,10 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint att
PUBLIC EGLBoolean
+_eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read);
+
+
+extern EGLBoolean
_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx);
@@ -57,6 +60,9 @@ _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLConte
/**
* Return true if the context is bound to a thread.
+ *
+ * The binding is considered a reference to the context. Drivers should not
+ * destroy a context when it is bound.
*/
static INLINE EGLBoolean
_eglIsContextBound(_EGLContext *ctx)
@@ -65,4 +71,67 @@ _eglIsContextBound(_EGLContext *ctx)
}
+/**
+ * Link a context to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+static INLINE EGLContext
+_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
+{
+ _eglLinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT, dpy);
+ return (EGLContext) ctx;
+}
+
+
+/**
+ * Unlink a linked context from its display.
+ * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
+ */
+static INLINE void
+_eglUnlinkContext(_EGLContext *ctx)
+{
+ _eglUnlinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT);
+}
+
+
+/**
+ * Lookup a handle to find the linked context.
+ * Return NULL if the handle has no corresponding linked context.
+ */
+static INLINE _EGLContext *
+_eglLookupContext(EGLContext context, _EGLDisplay *dpy)
+{
+ _EGLContext *ctx = (_EGLContext *) context;
+ if (!dpy || !_eglCheckResource((void *) ctx, _EGL_RESOURCE_CONTEXT, dpy))
+ ctx = NULL;
+ return ctx;
+}
+
+
+/**
+ * Return the handle of a linked context, or EGL_NO_CONTEXT.
+ */
+static INLINE EGLContext
+_eglGetContextHandle(_EGLContext *ctx)
+{
+ _EGLResource *res = (_EGLResource *) ctx;
+ return (res && _eglIsResourceLinked(res)) ?
+ (EGLContext) ctx : EGL_NO_CONTEXT;
+}
+
+
+/**
+ * Return true if the context is linked to a display.
+ *
+ * The link is considered a reference to the context (the display is owning the
+ * context). Drivers should not destroy a context when it is linked.
+ */
+static INLINE EGLBoolean
+_eglIsContextLinked(_EGLContext *ctx)
+{
+ _EGLResource *res = (_EGLResource *) ctx;
+ return (res && _eglIsResourceLinked(res));
+}
+
+
#endif /* EGLCONTEXT_INCLUDED */
diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
index df506151b5..989c19a2fa 100644
--- a/src/egl/main/eglcurrent.c
+++ b/src/egl/main/eglcurrent.c
@@ -1,10 +1,9 @@
#include <stdlib.h>
#include <string.h>
-#include "eglcurrent.h"
-#include "eglcontext.h"
+#include "eglglobals.h"
#include "egllog.h"
#include "eglmutex.h"
-#include "eglglobals.h"
+#include "eglcurrent.h"
/* This should be kept in sync with _eglInitThreadInfo() */
@@ -227,50 +226,24 @@ _eglIsCurrentThreadDummy(void)
/**
- * Return the currently bound context, or NULL.
- */
-_EGLContext *
-_eglGetCurrentContext(void)
-{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- return t->CurrentContexts[t->CurrentAPIIndex];
-}
-
-
-/**
- * Return the display of the currently bound context, or NULL.
+ * Return the currently bound context of the given API, or NULL.
*/
-_EGLDisplay *
-_eglGetCurrentDisplay(void)
+PUBLIC _EGLContext *
+_eglGetAPIContext(EGLenum api)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
- _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex];
- if (ctx)
- return ctx->Display;
- else
- return NULL;
+ return t->CurrentContexts[_eglConvertApiToIndex(api)];
}
/**
- * Return the read or write surface of the currently bound context, or NULL.
+ * Return the currently bound context of the current API, or NULL.
*/
-_EGLSurface *
-_eglGetCurrentSurface(EGLint readdraw)
+_EGLContext *
+_eglGetCurrentContext(void)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
- _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex];
- if (ctx) {
- switch (readdraw) {
- case EGL_DRAW:
- return ctx->DrawSurface;
- case EGL_READ:
- return ctx->ReadSurface;
- default:
- return NULL;
- }
- }
- return NULL;
+ return t->CurrentContexts[t->CurrentAPIIndex];
}
diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h
index c4478b3891..e5c94ce60a 100644
--- a/src/egl/main/eglcurrent.h
+++ b/src/egl/main/eglcurrent.h
@@ -1,6 +1,7 @@
#ifndef EGLCURRENT_INCLUDED
#define EGLCURRENT_INCLUDED
+
#include "egltypedefs.h"
@@ -73,15 +74,11 @@ _eglIsCurrentThreadDummy(void);
PUBLIC _EGLContext *
-_eglGetCurrentContext(void);
-
+_eglGetAPIContext(EGLenum api);
-PUBLIC _EGLDisplay *
-_eglGetCurrentDisplay(void);
-
-PUBLIC _EGLSurface *
-_eglGetCurrentSurface(EGLint readdraw);
+PUBLIC _EGLContext *
+_eglGetCurrentContext(void);
PUBLIC EGLBoolean
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 896d60dbe1..d7a8d14292 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -10,7 +10,6 @@
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
-#include "eglstring.h"
#include "eglmutex.h"
#include "egllog.h"
@@ -26,12 +25,18 @@ _eglFiniDisplay(void)
/* atexit function is called with global mutex locked */
dpyList = _eglGlobal.DisplayList;
while (dpyList) {
+ EGLint i;
+
/* pop list head */
dpy = dpyList;
dpyList = dpyList->Next;
- if (dpy->ContextList || dpy->SurfaceList)
- _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
+ for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
+ if (dpy->ResourceLists[i]) {
+ _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
+ break;
+ }
+ }
free(dpy);
}
@@ -40,53 +45,17 @@ _eglFiniDisplay(void)
/**
- * If the first character is '!' we interpret it as specific driver name
- * (i.e. "!r200" or "!i830"). Whatever follows ':' is interpreted as
- * arguments.
- *
- * The caller may free() the returned driver name.
- */
-char *
-_eglSplitDisplayString(const char *dpyString, const char **args)
-{
- char *drv, *p;
-
- if (!dpyString || dpyString[0] != '!')
- return NULL;
- drv = _eglstrdup(dpyString + 1);
- if (!drv)
- return NULL;
-
- p = strchr(dpyString, ':');
- if (p) {
- drv[p - dpyString] = '\0';
- p++;
- }
- if (args)
- *args = p;
-
- return drv;
-}
-
-
-/**
* Allocate a new _EGLDisplay object for the given nativeDisplay handle.
* We'll also try to determine the device driver name at this time.
*
* Note that nativeDisplay may be an X Display ptr, or a string.
*/
_EGLDisplay *
-_eglNewDisplay(NativeDisplayType nativeDisplay)
+_eglNewDisplay(EGLNativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
if (dpy) {
dpy->NativeDisplay = nativeDisplay;
-
- dpy->DriverName = _eglPreloadDriver(dpy);
- if (!dpy->DriverName) {
- free(dpy);
- return NULL;
- }
}
return dpy;
}
@@ -144,7 +113,7 @@ _eglUnlinkDisplay(_EGLDisplay *dpy)
* linked displays.
*/
_EGLDisplay *
-_eglFindDisplay(NativeDisplayType nativeDisplay)
+_eglFindDisplay(EGLNativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy;
@@ -171,29 +140,27 @@ _eglFindDisplay(NativeDisplayType nativeDisplay)
void
_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
{
- _EGLContext *contexts;
- _EGLSurface *surfaces;
-
- contexts = display->ContextList;
- surfaces = display->SurfaceList;
+ _EGLResource *list;
- while (contexts) {
- _EGLContext *ctx = contexts;
- contexts = contexts->Next;
+ list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
+ while (list) {
+ _EGLContext *ctx = (_EGLContext *) list;
+ list = list->Next;
_eglUnlinkContext(ctx);
drv->API.DestroyContext(drv, display, ctx);
}
- assert(!display->ContextList);
+ assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
- while (surfaces) {
- _EGLSurface *surf = surfaces;
- surfaces = surfaces->Next;
+ list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
+ while (list) {
+ _EGLSurface *surf = (_EGLSurface *) list;
+ list = list->Next;
_eglUnlinkSurface(surf);
drv->API.DestroySurface(drv, display, surf);
}
- assert(!display->SurfaceList);
+ assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
}
@@ -212,97 +179,13 @@ _eglCleanupDisplay(_EGLDisplay *disp)
free(disp->Configs);
disp->Configs = NULL;
disp->NumConfigs = 0;
+ disp->MaxConfigs = 0;
}
/* XXX incomplete */
}
-/**
- * Link a context to a display and return the handle of the link.
- * The handle can be passed to client directly.
- */
-EGLContext
-_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
-{
- ctx->Display = dpy;
- ctx->Next = dpy->ContextList;
- dpy->ContextList = ctx;
- return (EGLContext) ctx;
-}
-
-
-/**
- * Unlink a linked context from its display.
- * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
- */
-void
-_eglUnlinkContext(_EGLContext *ctx)
-{
- _EGLContext *prev;
-
- prev = ctx->Display->ContextList;
- if (prev != ctx) {
- while (prev) {
- if (prev->Next == ctx)
- break;
- prev = prev->Next;
- }
- assert(prev);
- prev->Next = ctx->Next;
- }
- else {
- ctx->Display->ContextList = ctx->Next;
- }
-
- ctx->Next = NULL;
- ctx->Display = NULL;
-}
-
-
-/**
- * Link a surface to a display and return the handle of the link.
- * The handle can be passed to client directly.
- */
-EGLSurface
-_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
-{
- surf->Display = dpy;
- surf->Next = dpy->SurfaceList;
- dpy->SurfaceList = surf;
- return (EGLSurface) surf;
-}
-
-
-/**
- * Unlink a linked surface from its display.
- * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
- */
-void
-_eglUnlinkSurface(_EGLSurface *surf)
-{
- _EGLSurface *prev;
-
- prev = surf->Display->SurfaceList;
- if (prev != surf) {
- while (prev) {
- if (prev->Next == surf)
- break;
- prev = prev->Next;
- }
- assert(prev);
- prev->Next = surf->Next;
- }
- else {
- prev = NULL;
- surf->Display->SurfaceList = surf->Next;
- }
-
- surf->Next = NULL;
- surf->Display = NULL;
-}
-
-
#ifndef _EGL_SKIP_HANDLE_CHECK
@@ -327,45 +210,70 @@ _eglCheckDisplayHandle(EGLDisplay dpy)
/**
- * Return EGL_TRUE if the given handle is a valid handle to a context.
+ * Return EGL_TRUE if the given resource is valid. That is, the display does
+ * own the resource.
*/
EGLBoolean
-_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
+_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
{
- _EGLContext *cur = NULL;
-
- if (dpy)
- cur = dpy->ContextList;
- while (cur) {
- if (cur == (_EGLContext *) ctx) {
- assert(cur->Display == dpy);
+ _EGLResource *list = dpy->ResourceLists[type];
+
+ if (!res)
+ return EGL_FALSE;
+
+ while (list) {
+ if (res == (void *) list) {
+ assert(list->Display == dpy);
break;
}
- cur = cur->Next;
+ list = list->Next;
}
- return (cur != NULL);
+
+ return (list != NULL);
}
+#endif /* !_EGL_SKIP_HANDLE_CHECK */
+
+
/**
- * Return EGL_TRUE if the given handle is a valid handle to a surface.
+ * Link a resource to a display.
*/
-EGLBoolean
-_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
+void
+_eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy)
{
- _EGLSurface *cur = NULL;
+ assert(!res->Display || res->Display == dpy);
- if (dpy)
- cur = dpy->SurfaceList;
- while (cur) {
- if (cur == (_EGLSurface *) surf) {
- assert(cur->Display == dpy);
- break;
- }
- cur = cur->Next;
- }
- return (cur != NULL);
+ res->Display = dpy;
+ res->IsLinked = EGL_TRUE;
+ res->Next = dpy->ResourceLists[type];
+ dpy->ResourceLists[type] = res;
}
-#endif /* !_EGL_SKIP_HANDLE_CHECK */
+/**
+ * Unlink a linked resource from its display.
+ */
+void
+_eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
+{
+ _EGLResource *prev;
+
+ prev = res->Display->ResourceLists[type];
+ if (prev != res) {
+ while (prev) {
+ if (prev->Next == res)
+ break;
+ prev = prev->Next;
+ }
+ assert(prev);
+ prev->Next = res->Next;
+ }
+ else {
+ res->Display->ResourceLists[type] = res->Next;
+ }
+
+ res->Next = NULL;
+ /* do not reset res->Display */
+ res->IsLinked = EGL_FALSE;
+}
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 4f619e5371..03903290fd 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -1,10 +1,32 @@
#ifndef EGLDISPLAY_INCLUDED
#define EGLDISPLAY_INCLUDED
+
#include "egltypedefs.h"
#include "egldefines.h"
-#include "eglcontext.h"
-#include "eglsurface.h"
+
+
+enum _egl_resource_type {
+ _EGL_RESOURCE_CONTEXT,
+ _EGL_RESOURCE_SURFACE,
+ _EGL_RESOURCE_IMAGE,
+
+ _EGL_NUM_RESOURCES
+};
+
+
+/**
+ * A resource of a display.
+ */
+struct _egl_resource
+{
+ /* which display the resource belongs to */
+ _EGLDisplay *Display;
+ EGLBoolean IsLinked;
+
+ /* used to link resources of the same type */
+ _EGLResource *Next;
+};
/**
@@ -14,6 +36,13 @@ struct _egl_extensions
{
EGLBoolean MESA_screen_surface;
EGLBoolean MESA_copy_context;
+ EGLBoolean KHR_image_base;
+ EGLBoolean KHR_image_pixmap;
+ EGLBoolean KHR_vg_parent_image;
+ EGLBoolean KHR_gl_texture_2D_image;
+ EGLBoolean KHR_gl_texture_cubemap_image;
+ EGLBoolean KHR_gl_texture_3D_image;
+ EGLBoolean KHR_gl_renderbuffer_image;
char String[_EGL_MAX_EXTENSIONS_LEN];
};
@@ -26,7 +55,7 @@ struct _egl_display
EGLNativeDisplayType NativeDisplay;
- const char *DriverName;
+ EGLBoolean Initialized; /**< True if the display is initialized */
_EGLDriver *Driver;
void *DriverData; /* private to driver */
@@ -39,8 +68,6 @@ struct _egl_display
_EGLExtensions Extensions;
- int LargestPbuffer;
-
EGLint NumScreens;
_EGLScreen **Screens; /* array [NumScreens] */
@@ -48,9 +75,8 @@ struct _egl_display
EGLint NumConfigs;
_EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */
- /* lists of linked contexts and surface */
- _EGLContext *ContextList;
- _EGLSurface *SurfaceList;
+ /* lists of resources */
+ _EGLResource *ResourceLists[_EGL_NUM_RESOURCES];
};
@@ -58,12 +84,8 @@ extern void
_eglFiniDisplay(void);
-extern char *
-_eglSplitDisplayString(const char *dpyString, const char **args);
-
-
extern _EGLDisplay *
-_eglNewDisplay(NativeDisplayType displayName);
+_eglNewDisplay(EGLNativeDisplayType displayName);
extern EGLDisplay
@@ -75,7 +97,7 @@ _eglUnlinkDisplay(_EGLDisplay *dpy);
extern _EGLDisplay *
-_eglFindDisplay(NativeDisplayType nativeDisplay);
+_eglFindDisplay(EGLNativeDisplayType nativeDisplay);
PUBLIC void
@@ -86,22 +108,6 @@ PUBLIC void
_eglCleanupDisplay(_EGLDisplay *disp);
-extern EGLContext
-_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy);
-
-
-extern void
-_eglUnlinkContext(_EGLContext *ctx);
-
-
-extern EGLSurface
-_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy);
-
-
-extern void
-_eglUnlinkSurface(_EGLSurface *surf);
-
-
#ifndef _EGL_SKIP_HANDLE_CHECK
@@ -109,12 +115,8 @@ extern EGLBoolean
_eglCheckDisplayHandle(EGLDisplay dpy);
-extern EGLBoolean
-_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy);
-
-
-extern EGLBoolean
-_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy);
+PUBLIC EGLBoolean
+_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy);
#else /* !_EGL_SKIP_HANDLE_CHECK */
@@ -129,18 +131,9 @@ _eglCheckDisplayHandle(EGLDisplay dpy)
static INLINE EGLBoolean
-_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
+_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy);
{
- _EGLContext *c = (_EGLContext *) ctx;
- return (dpy && c && c->Display == dpy);
-}
-
-
-static INLINE EGLBoolean
-_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
-{
- _EGLSurface *s = (_EGLSurface *) surf;
- return (dpy && s && s->Display == dpy);
+ return (((_EGLResource *) res)->Display == dpy);
}
@@ -181,92 +174,21 @@ _eglIsDisplayLinked(_EGLDisplay *dpy)
}
-/**
- * Lookup a handle to find the linked context.
- * Return NULL if the handle has no corresponding linked context.
- */
-static INLINE _EGLContext *
-_eglLookupContext(EGLContext context, _EGLDisplay *dpy)
-{
- _EGLContext *ctx = (_EGLContext *) context;
- if (!_eglCheckContextHandle(context, dpy))
- ctx = NULL;
- return ctx;
-}
-
-
-/**
- * Return the handle of a linked context, or EGL_NO_CONTEXT.
- */
-static INLINE EGLContext
-_eglGetContextHandle(_EGLContext *ctx)
-{
- return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT);
-}
-
-
-/**
- * Return true if the context is linked to a display.
- */
-static INLINE EGLBoolean
-_eglIsContextLinked(_EGLContext *ctx)
-{
- return (EGLBoolean) (_eglGetContextHandle(ctx) != EGL_NO_CONTEXT);
-}
-
-
-/**
- * Lookup a handle to find the linked surface.
- * Return NULL if the handle has no corresponding linked surface.
- */
-static INLINE _EGLSurface *
-_eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy)
-{
- _EGLSurface *surf = (_EGLSurface *) surface;
- if (!_eglCheckSurfaceHandle(surf, dpy))
- surf = NULL;
- return surf;
-}
+extern void
+_eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy);
-/**
- * Return the handle of a linked surface, or EGL_NO_SURFACE.
- */
-static INLINE EGLSurface
-_eglGetSurfaceHandle(_EGLSurface *surf)
-{
- return (EGLSurface) ((surf && surf->Display) ? surf : EGL_NO_SURFACE);
-}
+extern void
+_eglUnlinkResource(_EGLResource *res, _EGLResourceType type);
/**
- * Return true if the surface is linked to a display.
+ * Return true if the resource is linked.
*/
static INLINE EGLBoolean
-_eglIsSurfaceLinked(_EGLSurface *surf)
-{
- return (EGLBoolean) (_eglGetSurfaceHandle(surf) != EGL_NO_SURFACE);
-}
-
-
-/**
- * Cast an unsigned int to a pointer.
- */
-static INLINE void *
-_eglUIntToPointer(unsigned int v)
-{
- return (void *) ((uintptr_t) v);
-}
-
-
-/**
- * Cast a pointer to an unsigned int. The pointer must be one that is
- * returned by _eglUIntToPointer.
- */
-static INLINE unsigned int
-_eglPointerToUInt(const void *p)
+_eglIsResourceLinked(_EGLResource *res)
{
- return (unsigned int) ((uintptr_t) p);
+ return res->IsLinked;
}
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index 018b06d3be..a87c697b11 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -19,9 +19,13 @@
#include "eglscreen.h"
#include "eglstring.h"
#include "eglsurface.h"
+#include "eglimage.h"
-#if defined(_EGL_PLATFORM_X)
+#if defined(_EGL_PLATFORM_POSIX)
#include <dlfcn.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
#endif
@@ -49,10 +53,17 @@ close_library(HMODULE lib)
}
-#elif defined(_EGL_PLATFORM_X)
+static const char *
+library_suffix(void)
+{
+ return ".dll";
+}
+
+
+#elif defined(_EGL_PLATFORM_POSIX)
-static const char DefaultDriverName[] = "egl_softpipe";
+static const char DefaultDriverName[] = "egl_glx";
typedef void * lib_handle;
@@ -68,8 +79,17 @@ close_library(void *lib)
dlclose(lib);
}
+
+static const char *
+library_suffix(void)
+{
+ return ".so";
+}
+
+
#else /* _EGL_PLATFORM_NO_OS */
+
static const char DefaultDriverName[] = "builtin";
typedef void *lib_handle;
@@ -86,67 +106,21 @@ close_library(void *lib)
}
-#endif
+static const char *
+library_suffix(void)
+{
+ return NULL;
+}
-/**
- * Choose a driver for a given display.
- * The caller may free() the returned strings.
- */
-static char *
-_eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
-{
- char *path = NULL;
- const char *args = NULL;
- const char *suffix = NULL;
- const char *p;
-
- path = getenv("EGL_DRIVER");
- if (path)
- path = _eglstrdup(path);
-
-#if defined(_EGL_PLATFORM_X)
- if (!path && dpy && dpy->NativeDisplay) {
- /* assume (wrongly!) that the native display is a display string */
- path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args);
- }
- suffix = "so";
-#elif defined(_EGL_PLATFORM_WINDOWS)
- suffix = "dll";
-#else /* _EGL_PLATFORM_NO_OS */
- if (path) {
- /* force the use of the default driver */
- _eglLog(_EGL_DEBUG, "ignore EGL_DRIVER");
- free(path);
- path = NULL;
- }
- suffix = NULL;
#endif
- if (!path)
- path = _eglstrdup(DefaultDriverName);
-
- /* append suffix if there isn't */
- p = strrchr(path, '.');
- if (!p && suffix) {
- size_t len = strlen(path);
- char *tmp = malloc(len + strlen(suffix) + 2);
- if (tmp) {
- memcpy(tmp, path, len);
- tmp[len++] = '.';
- tmp[len] = '\0';
- strcat(tmp + len, suffix);
-
- free(path);
- path = tmp;
- }
- }
-
- if (argsRet)
- *argsRet = (args) ? _eglstrdup(args) : NULL;
- return path;
-}
+#define NUM_PROBE_CACHE_SLOTS 8
+static struct {
+ EGLint keys[NUM_PROBE_CACHE_SLOTS];
+ const void *values[NUM_PROBE_CACHE_SLOTS];
+} _eglProbeCache;
/**
@@ -168,7 +142,7 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle)
/* XXX untested */
if (lib)
mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
-#elif defined(_EGL_PLATFORM_X)
+#elif defined(_EGL_PLATFORM_POSIX)
if (lib) {
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
if (!mainFunc)
@@ -208,11 +182,10 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle)
/**
- * Load the named driver. The path and args passed will be
- * owned by the driver and freed.
+ * Load the named driver.
*/
static _EGLDriver *
-_eglLoadDriver(char *path, char *args)
+_eglLoadDriver(const char *path, const char *args)
{
_EGLMain_t mainFunc;
lib_handle lib;
@@ -234,8 +207,19 @@ _eglLoadDriver(char *path, char *args)
drv->Name = "UNNAMED";
}
- drv->Path = path;
- drv->Args = args;
+ drv->Path = _eglstrdup(path);
+ drv->Args = (args) ? _eglstrdup(args) : NULL;
+ if (!drv->Path || (args && !drv->Args)) {
+ if (drv->Path)
+ free((char *) drv->Path);
+ if (drv->Args)
+ free((char *) drv->Args);
+ drv->Unload(drv);
+ if (lib)
+ close_library(lib);
+ return NULL;
+ }
+
drv->LibHandle = lib;
return drv;
@@ -244,89 +228,316 @@ _eglLoadDriver(char *path, char *args)
/**
* Match a display to a preloaded driver.
+ *
+ * The matching is done by finding the driver with the highest score.
*/
-static _EGLDriver *
+_EGLDriver *
_eglMatchDriver(_EGLDisplay *dpy)
{
- _EGLDriver *defaultDriver = NULL;
- EGLint i;
+ _EGLDriver *best_drv = NULL;
+ EGLint best_score = -1, i;
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
_EGLDriver *drv = _eglGlobal.Drivers[i];
+ EGLint score;
+
+ score = (drv->Probe) ? drv->Probe(drv, dpy) : 0;
+ if (score > best_score) {
+ if (best_drv) {
+ _eglLog(_EGL_DEBUG, "driver %s has higher score than %s",
+ drv->Name, best_drv->Name);
+ }
+
+ best_drv = drv;
+ best_score = score;
+ /* perfect match */
+ if (score >= 100)
+ break;
+ }
+ }
+
+ return best_drv;
+}
- /* display specifies a driver */
- if (dpy->DriverName) {
- if (strcmp(dpy->DriverName, drv->Name) == 0)
- return drv;
+
+/**
+ * A loader function for use with _eglPreloadForEach. The loader data is the
+ * filename of the driver. This function stops on the first valid driver.
+ */
+static EGLBoolean
+_eglLoaderFile(const char *dir, size_t len, void *loader_data)
+{
+ _EGLDriver *drv;
+ char path[1024];
+ const char *filename = (const char *) loader_data;
+ size_t flen = strlen(filename);
+
+ /* make a full path */
+ if (len + flen + 2 > sizeof(path))
+ return EGL_TRUE;
+ if (len) {
+ memcpy(path, dir, len);
+ path[len++] = '/';
+ }
+ memcpy(path + len, filename, flen);
+ len += flen;
+ path[len] = '\0';
+
+ drv = _eglLoadDriver(path, NULL);
+ /* fix the path and load again */
+ if (!drv && library_suffix()) {
+ const char *suffix = library_suffix();
+ size_t slen = strlen(suffix);
+ const char *p;
+ EGLBoolean need_suffix;
+
+ p = filename + flen - slen;
+ need_suffix = (p < filename || strcmp(p, suffix) != 0);
+ if (need_suffix && len + slen + 1 <= sizeof(path)) {
+ strcpy(path + len, suffix);
+ drv = _eglLoadDriver(path, NULL);
}
- else if (drv->Probe) {
- if (drv->Probe(drv, dpy))
- return drv;
+ }
+ if (!drv)
+ return EGL_TRUE;
+
+ /* remember the driver and stop */
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+ return EGL_FALSE;
+}
+
+
+/**
+ * A loader function for use with _eglPreloadForEach. The loader data is the
+ * pattern (prefix) of the files to look for.
+ */
+static EGLBoolean
+_eglLoaderPattern(const char *dir, size_t len, void *loader_data)
+{
+#if defined(_EGL_PLATFORM_POSIX)
+ const char *prefix, *suffix;
+ size_t prefix_len, suffix_len;
+ DIR *dirp;
+ struct dirent *dirent;
+ char path[1024];
+
+ if (len + 2 > sizeof(path))
+ return EGL_TRUE;
+ if (len) {
+ memcpy(path, dir, len);
+ path[len++] = '/';
+ }
+ path[len] = '\0';
+
+ dirp = opendir(path);
+ if (!dirp)
+ return EGL_TRUE;
+
+ prefix = (const char *) loader_data;
+ prefix_len = strlen(prefix);
+ suffix = library_suffix();
+ suffix_len = (suffix) ? strlen(suffix) : 0;
+
+ while ((dirent = readdir(dirp))) {
+ _EGLDriver *drv;
+ size_t dirent_len = strlen(dirent->d_name);
+ const char *p;
+
+ /* match the prefix */
+ if (strncmp(dirent->d_name, prefix, prefix_len) != 0)
+ continue;
+ /* match the suffix */
+ if (suffix) {
+ p = dirent->d_name + dirent_len - suffix_len;
+ if (p < dirent->d_name || strcmp(p, suffix) != 0)
+ continue;
}
- else {
- if (!defaultDriver)
- defaultDriver = drv;
+
+ /* make a full path and load the driver */
+ if (len + dirent_len + 1 <= sizeof(path)) {
+ strcpy(path + len, dirent->d_name);
+ drv = _eglLoadDriver(path, NULL);
+ if (drv)
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
}
}
- return defaultDriver;
+ closedir(dirp);
+
+ return EGL_TRUE;
+#else /* _EGL_PLATFORM_POSIX */
+ /* stop immediately */
+ return EGL_FALSE;
+#endif
}
/**
- * Load a driver and save it.
+ * Run the preload function on each driver directory and return the number of
+ * drivers loaded.
+ *
+ * The process may end prematurely if the callback function returns false.
*/
-const char *
-_eglPreloadDriver(_EGLDisplay *dpy)
+static EGLint
+_eglPreloadForEach(const char *search_path,
+ EGLBoolean (*loader)(const char *, size_t, void *),
+ void *loader_data)
{
- char *path, *args;
- _EGLDriver *drv;
- EGLint i;
+ const char *cur, *next;
+ size_t len;
+ EGLint num_drivers = _eglGlobal.NumDrivers;
- path = _eglChooseDriver(dpy, &args);
- if (!path)
- return NULL;
+ cur = search_path;
+ while (cur) {
+ next = strchr(cur, ':');
+ len = (next) ? next - cur : strlen(cur);
- for (i = 0; i < _eglGlobal.NumDrivers; i++) {
- drv = _eglGlobal.Drivers[i];
- if (strcmp(drv->Path, path) == 0) {
- _eglLog(_EGL_DEBUG, "Driver %s is already preloaded",
- drv->Name);
- free(path);
- if (args)
- free(args);
- return drv->Name;
+ if (!loader(cur, len, loader_data))
+ break;
+
+ cur = (next) ? next + 1 : NULL;
+ }
+
+ return (_eglGlobal.NumDrivers - num_drivers);
+}
+
+
+/**
+ * Return a list of colon-separated driver directories.
+ */
+static const char *
+_eglGetSearchPath(void)
+{
+ static const char *search_path;
+
+#if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS)
+ if (!search_path) {
+ static char buffer[1024];
+ const char *p;
+ int ret;
+
+ p = getenv("EGL_DRIVERS_PATH");
+#if defined(_EGL_PLATFORM_POSIX)
+ if (p && (geteuid() != getuid() || getegid() != getgid())) {
+ _eglLog(_EGL_DEBUG,
+ "ignore EGL_DRIVERS_PATH for setuid/setgid binaries");
+ p = NULL;
+ }
+#endif /* _EGL_PLATFORM_POSIX */
+
+ if (p) {
+ ret = snprintf(buffer, sizeof(buffer),
+ "%s:%s", p, _EGL_DRIVER_SEARCH_DIR);
+ if (ret > 0 && ret < sizeof(buffer))
+ search_path = buffer;
}
}
+ if (!search_path)
+ search_path = _EGL_DRIVER_SEARCH_DIR;
+#else
+ search_path = "";
+#endif
- drv = _eglLoadDriver(path, args);
- if (!drv)
- return NULL;
+ return search_path;
+}
- _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
- return drv->Name;
+/**
+ * Preload a user driver.
+ *
+ * A user driver can be specified by EGL_DRIVER.
+ */
+static EGLBoolean
+_eglPreloadUserDriver(void)
+{
+ const char *search_path = _eglGetSearchPath();
+ char *env;
+
+ env = getenv("EGL_DRIVER");
+#if defined(_EGL_PLATFORM_POSIX)
+ if (env && strchr(env, '/')) {
+ search_path = "";
+ if ((geteuid() != getuid() || getegid() != getgid())) {
+ _eglLog(_EGL_DEBUG,
+ "ignore EGL_DRIVER for setuid/setgid binaries");
+ env = NULL;
+ }
+ }
+#endif /* _EGL_PLATFORM_POSIX */
+ if (!env)
+ return EGL_FALSE;
+
+ if (!_eglPreloadForEach(search_path, _eglLoaderFile, (void *) env)) {
+ _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver");
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
}
/**
- * Open a preloaded driver.
+ * Preload display drivers.
+ *
+ * Display drivers are a set of drivers that support a certain display system.
+ * The display system may be specified by EGL_DISPLAY.
+ *
+ * FIXME This makes libEGL a memory hog if an user driver is not specified and
+ * there are many display drivers.
*/
-_EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy)
+static EGLBoolean
+_eglPreloadDisplayDrivers(void)
{
- _EGLDriver *drv = _eglMatchDriver(dpy);
- return drv;
+ const char *dpy;
+ char prefix[32];
+ int ret;
+
+ dpy = getenv("EGL_DISPLAY");
+ if (!dpy || !dpy[0])
+ dpy = _EGL_DEFAULT_DISPLAY;
+ if (!dpy || !dpy[0])
+ return EGL_FALSE;
+
+ ret = snprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
+ if (ret < 0 || ret >= sizeof(prefix))
+ return EGL_FALSE;
+
+ return (_eglPreloadForEach(_eglGetSearchPath(),
+ _eglLoaderPattern, (void *) prefix) > 0);
+}
+
+
+/**
+ * Preload the default driver.
+ */
+static EGLBoolean
+_eglPreloadDefaultDriver(void)
+{
+ return (_eglPreloadForEach(_eglGetSearchPath(),
+ _eglLoaderFile, (void *) DefaultDriverName) > 0);
}
/**
- * Close a preloaded driver.
+ * Preload drivers.
+ *
+ * This function loads the driver modules and creates the corresponding
+ * _EGLDriver objects.
*/
EGLBoolean
-_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy)
+_eglPreloadDrivers(void)
{
- return EGL_TRUE;
+ EGLBoolean loaded;
+
+ /* already preloaded */
+ if (_eglGlobal.NumDrivers)
+ return EGL_TRUE;
+
+ loaded = (_eglPreloadUserDriver() ||
+ _eglPreloadDisplayDrivers() ||
+ _eglPreloadDefaultDriver());
+
+ return loaded;
}
@@ -360,20 +571,6 @@ _eglUnloadDrivers(void)
/**
- * Given a display handle, return the _EGLDriver for that display.
- */
-_EGLDriver *
-_eglLookupDriver(EGLDisplay dpy)
-{
- _EGLDisplay *d = _eglLookupDisplay(dpy);
- if (d)
- return d->Driver;
- else
- return NULL;
-}
-
-
-/**
* Plug all the available fallback routines into the given driver's
* dispatch table.
*/
@@ -428,56 +625,50 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
#ifdef EGL_VERSION_1_2
drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
#endif /* EGL_VERSION_1_2 */
-}
+#ifdef EGL_KHR_image_base
+ drv->API.CreateImageKHR = _eglCreateImageKHR;
+ drv->API.DestroyImageKHR = _eglDestroyImageKHR;
+#endif /* EGL_KHR_image_base */
+}
/**
- * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
- * are supported on the system by looking for standard library names.
+ * Set the probe cache at the given key.
+ *
+ * A key, instead of a _EGLDriver, is used to allow the probe cache to be share
+ * by multiple drivers.
*/
-EGLint
-_eglFindAPIs(void)
+void
+_eglSetProbeCache(EGLint key, const void *val)
{
- EGLint mask = 0x0;
- lib_handle lib;
-#if defined(_EGL_PLATFORM_WINDOWS)
- /* XXX not sure about these names */
- const char *es1_libname = "libGLESv1_CM.dll";
- const char *es2_libname = "libGLESv2.dll";
- const char *gl_libname = "OpenGL32.dll";
- const char *vg_libname = "libOpenVG.dll";
-#elif defined(_EGL_PLATFORM_X)
- const char *es1_libname = "libGLESv1_CM.so";
- const char *es2_libname = "libGLESv2.so";
- const char *gl_libname = "libGL.so";
- const char *vg_libname = "libOpenVG.so";
-#else /* _EGL_PLATFORM_NO_OS */
- const char *es1_libname = NULL;
- const char *es2_libname = NULL;
- const char *gl_libname = NULL;
- const char *vg_libname = NULL;
-#endif
+ EGLint idx;
- if ((lib = open_library(es1_libname))) {
- close_library(lib);
- mask |= EGL_OPENGL_ES_BIT;
+ for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
+ if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
+ break;
}
+ assert(key > 0);
+ assert(idx < NUM_PROBE_CACHE_SLOTS);
- if ((lib = open_library(es2_libname))) {
- close_library(lib);
- mask |= EGL_OPENGL_ES2_BIT;
- }
+ _eglProbeCache.keys[idx] = key;
+ _eglProbeCache.values[idx] = val;
+}
- if ((lib = open_library(gl_libname))) {
- close_library(lib);
- mask |= EGL_OPENGL_BIT;
- }
- if ((lib = open_library(vg_libname))) {
- close_library(lib);
- mask |= EGL_OPENVG_BIT;
+/**
+ * Return the probe cache at the given key.
+ */
+const void *
+_eglGetProbeCache(EGLint key)
+{
+ EGLint idx;
+
+ for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
+ if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
+ break;
}
- return mask;
+ return (idx < NUM_PROBE_CACHE_SLOTS && _eglProbeCache.keys[idx] == key) ?
+ _eglProbeCache.values[idx] : NULL;
}
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
index 59bd1954aa..55686681dc 100644
--- a/src/egl/main/egldriver.h
+++ b/src/egl/main/egldriver.h
@@ -7,6 +7,36 @@
/**
+ * Define an inline driver typecast function.
+ *
+ * Note that this macro defines a function and should not be ended with a
+ * semicolon when used.
+ */
+#define _EGL_DRIVER_TYPECAST(drvtype, egltype, code) \
+ static INLINE struct drvtype *drvtype(const egltype *obj) \
+ { return (struct drvtype *) code; }
+
+
+/**
+ * Define the driver typecast functions for _EGLDriver, _EGLDisplay,
+ * _EGLContext, _EGLSurface, and _EGLConfig.
+ *
+ * Note that this macro defines several functions and should not be ended with
+ * a semicolon when used.
+ */
+#define _EGL_DRIVER_STANDARD_TYPECASTS(drvname) \
+ _EGL_DRIVER_TYPECAST(drvname ## _driver, _EGLDriver, obj) \
+ /* note that this is not a direct cast */ \
+ _EGL_DRIVER_TYPECAST(drvname ## _display, _EGLDisplay, obj->DriverData) \
+ _EGL_DRIVER_TYPECAST(drvname ## _context, _EGLContext, obj) \
+ _EGL_DRIVER_TYPECAST(drvname ## _surface, _EGLSurface, obj) \
+ _EGL_DRIVER_TYPECAST(drvname ## _config, _EGLConfig, obj)
+
+
+typedef _EGLDriver *(*_EGLMain_t)(const char *args);
+
+
+/**
* Base class for device drivers.
*/
struct _egl_driver
@@ -16,9 +46,22 @@ struct _egl_driver
const char *Args; /**< args to load this driver */
const char *Name; /**< name of this driver */
- /**< probe a display to see if it is supported */
- EGLBoolean (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy);
- /**< called before dlclose to release this driver */
+
+ /**
+ * Probe a display and return a score.
+ *
+ * Roughly,
+ * 50 means the driver supports the display;
+ * 90 means the driver can accelerate the display;
+ * 100 means a perfect match.
+ */
+ EGLint (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy);
+
+ /**
+ * Release the driver resource.
+ *
+ * It is called before dlclose().
+ */
void (*Unload)(_EGLDriver *drv);
_EGLAPI API; /**< EGL API dispatch table */
@@ -29,32 +72,28 @@ PUBLIC _EGLDriver *
_eglMain(const char *args);
-extern const char *
-_eglPreloadDriver(_EGLDisplay *dpy);
-
-
extern _EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy);
+_eglMatchDriver(_EGLDisplay *dpy);
extern EGLBoolean
-_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy);
+_eglPreloadDrivers(void);
-void
+extern void
_eglUnloadDrivers(void);
-extern _EGLDriver *
-_eglLookupDriver(EGLDisplay d);
+PUBLIC void
+_eglInitDriverFallbacks(_EGLDriver *drv);
PUBLIC void
-_eglInitDriverFallbacks(_EGLDriver *drv);
+_eglSetProbeCache(EGLint key, const void *val);
-PUBLIC EGLint
-_eglFindAPIs(void);
+PUBLIC const void *
+_eglGetProbeCache(EGLint key);
#endif /* EGLDRIVER_INCLUDED */
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
index 443d0f072c..5182b18e22 100644
--- a/src/egl/main/eglglobals.c
+++ b/src/egl/main/eglglobals.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
#include <assert.h>
#include "eglglobals.h"
+#include "egldisplay.h"
#include "egldriver.h"
-#include "egllog.h"
#include "eglmutex.h"
diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h
index 5ebb914ca7..cd1dd5851b 100644
--- a/src/egl/main/eglglobals.h
+++ b/src/egl/main/eglglobals.h
@@ -1,9 +1,8 @@
#ifndef EGLGLOBALS_INCLUDED
#define EGLGLOBALS_INCLUDED
+
#include "egltypedefs.h"
-#include "egldisplay.h"
-#include "eglcurrent.h"
#include "eglmutex.h"
diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c
new file mode 100644
index 0000000000..5732ef35ec
--- /dev/null
+++ b/src/egl/main/eglimage.c
@@ -0,0 +1,90 @@
+#include <assert.h>
+#include <string.h>
+
+#include "eglimage.h"
+#include "eglcurrent.h"
+#include "egllog.h"
+
+
+#ifdef EGL_KHR_image_base
+
+
+/**
+ * Parse the list of image attributes and return the proper error code.
+ */
+static EGLint
+_eglParseImageAttribList(_EGLImage *img, const EGLint *attrib_list)
+{
+ EGLint i, err = EGL_SUCCESS;
+
+ if (!attrib_list)
+ return EGL_SUCCESS;
+
+ for (i = 0; attrib_list[i] != EGL_NONE; i++) {
+ EGLint attr = attrib_list[i++];
+ EGLint val = attrib_list[i];
+
+ switch (attr) {
+ case EGL_IMAGE_PRESERVED_KHR:
+ img->Preserved = val;
+ break;
+ case EGL_GL_TEXTURE_LEVEL_KHR:
+ img->GLTextureLevel = val;
+ break;
+ case EGL_GL_TEXTURE_ZOFFSET_KHR:
+ img->GLTextureZOffset = val;
+ break;
+ default:
+ /* unknown attrs are ignored */
+ break;
+ }
+
+ if (err != EGL_SUCCESS) {
+ _eglLog(_EGL_DEBUG, "bad image attribute 0x%04x", attr);
+ break;
+ }
+ }
+
+ return err;
+}
+
+
+EGLBoolean
+_eglInitImage(_EGLImage *img, _EGLDisplay *dpy, const EGLint *attrib_list)
+{
+ EGLint err;
+
+ memset(img, 0, sizeof(_EGLImage));
+ img->Resource.Display = dpy;
+
+ img->Preserved = EGL_FALSE;
+ img->GLTextureLevel = 0;
+ img->GLTextureZOffset = 0;
+
+ err = _eglParseImageAttribList(img, attrib_list);
+ if (err != EGL_SUCCESS)
+ return _eglError(err, "eglCreateImageKHR");
+
+ return EGL_TRUE;
+}
+
+
+_EGLImage *
+_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer,
+ const EGLint *attr_list)
+{
+ /* driver should override this function */
+ return NULL;
+}
+
+
+EGLBoolean
+_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image)
+{
+ /* driver should override this function */
+ return EGL_FALSE;
+}
+
+
+#endif /* EGL_KHR_image_base */
diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h
new file mode 100644
index 0000000000..2c0fb16d1d
--- /dev/null
+++ b/src/egl/main/eglimage.h
@@ -0,0 +1,96 @@
+#ifndef EGLIMAGE_INCLUDED
+#define EGLIMAGE_INCLUDED
+
+
+#include "egltypedefs.h"
+#include "egldisplay.h"
+
+
+/**
+ * "Base" class for device driver images.
+ */
+struct _egl_image
+{
+ /* An image is a display resource */
+ _EGLResource Resource;
+
+ EGLBoolean Preserved;
+ EGLint GLTextureLevel;
+ EGLint GLTextureZOffset;
+};
+
+
+PUBLIC EGLBoolean
+_eglInitImage(_EGLImage *img, _EGLDisplay *dpy, const EGLint *attrib_list);
+
+
+extern _EGLImage *
+_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+ EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list);
+
+
+extern EGLBoolean
+_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
+
+
+/**
+ * Link an image to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+static INLINE EGLImageKHR
+_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy)
+{
+ _eglLinkResource(&img->Resource, _EGL_RESOURCE_IMAGE, dpy);
+ return (EGLImageKHR) img;
+}
+
+
+/**
+ * Unlink a linked image from its display.
+ * Accessing an unlinked image should generate EGL_BAD_PARAMETER error.
+ */
+static INLINE void
+_eglUnlinkImage(_EGLImage *img)
+{
+ _eglUnlinkResource(&img->Resource, _EGL_RESOURCE_IMAGE);
+}
+
+
+/**
+ * Lookup a handle to find the linked image.
+ * Return NULL if the handle has no corresponding linked image.
+ */
+static INLINE _EGLImage *
+_eglLookupImage(EGLImageKHR image, _EGLDisplay *dpy)
+{
+ _EGLImage *img = (_EGLImage *) image;
+ if (!dpy || !_eglCheckResource((void *) img, _EGL_RESOURCE_IMAGE, dpy))
+ img = NULL;
+ return img;
+}
+
+
+/**
+ * Return the handle of a linked image, or EGL_NO_IMAGE_KHR.
+ */
+static INLINE EGLImageKHR
+_eglGetImageHandle(_EGLImage *img)
+{
+ _EGLResource *res = (_EGLResource *) img;
+ return (res && _eglIsResourceLinked(res)) ?
+ (EGLImageKHR) img : EGL_NO_IMAGE_KHR;
+}
+
+
+/**
+ * Return true if the image is linked to a display.
+ */
+static INLINE EGLBoolean
+_eglIsImageLinked(_EGLImage *img)
+{
+ _EGLResource *res = (_EGLResource *) img;
+ return (res && _eglIsResourceLinked(res));
+}
+
+
+#endif /* EGLIMAGE_INCLUDED */
diff --git a/src/egl/main/egllog.h b/src/egl/main/egllog.h
index 3a99bfea4b..03bef2670f 100644
--- a/src/egl/main/egllog.h
+++ b/src/egl/main/egllog.h
@@ -1,8 +1,10 @@
#ifndef EGLLOG_INCLUDED
#define EGLLOG_INCLUDED
+
#include "egltypedefs.h"
+
#define _EGL_FATAL 0 /* unrecoverable error */
#define _EGL_WARNING 1 /* recoverable error/problem */
#define _EGL_INFO 2 /* just useful info */
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index e66913320b..984e426686 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -33,28 +33,70 @@
#include <assert.h>
#include <string.h>
-#include "eglglobals.h"
+#include "eglcurrent.h"
#include "eglmisc.h"
#include "egldisplay.h"
/**
+ * Copy the extension into the string and update the string pointer.
+ */
+static EGLint
+_eglAppendExtension(char **str, const char *ext)
+{
+ char *s = *str;
+ EGLint len = strlen(ext);
+
+ if (s) {
+ memcpy(s, ext, len);
+ s[len++] = ' ';
+ s[len] = '\0';
+
+ *str += len;
+ }
+ else {
+ len++;
+ }
+
+ return len;
+}
+
+
+/**
* Examine the individual extension enable/disable flags and recompute
* the driver's Extensions string.
*/
static void
_eglUpdateExtensionsString(_EGLDisplay *dpy)
{
+#define _EGL_CHECK_EXTENSION(ext) \
+ do { \
+ if (dpy->Extensions.ext) { \
+ _eglAppendExtension(&exts, "EGL_" #ext); \
+ assert(exts <= dpy->Extensions.String + _EGL_MAX_EXTENSIONS_LEN); \
+ } \
+ } while (0)
+
char *exts = dpy->Extensions.String;
if (exts[0])
return;
- if (dpy->Extensions.MESA_screen_surface)
- strcat(exts, "EGL_MESA_screen_surface ");
- if (dpy->Extensions.MESA_copy_context)
- strcat(exts, "EGL_MESA_copy_context ");
- assert(strlen(exts) < _EGL_MAX_EXTENSIONS_LEN);
+ _EGL_CHECK_EXTENSION(MESA_screen_surface);
+ _EGL_CHECK_EXTENSION(MESA_copy_context);
+
+ _EGL_CHECK_EXTENSION(KHR_image_base);
+ _EGL_CHECK_EXTENSION(KHR_image_pixmap);
+ if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
+ _eglAppendExtension(&exts, "EGL_KHR_image");
+
+ _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
+ _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
+ _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
+ _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
+ _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
+
+#undef _EGL_CHECK_EXTENSION
}
diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h
index 829d4cde79..5e6a2d41df 100644
--- a/src/egl/main/eglmisc.h
+++ b/src/egl/main/eglmisc.h
@@ -29,7 +29,8 @@
#ifndef EGLMISC_INCLUDED
#define EGLMISC_INCLUDED
-#include "egldriver.h"
+
+#include "egltypedefs.h"
extern const char *
diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c
index 0f3ba6e5c0..66446c0495 100644
--- a/src/egl/main/eglmode.c
+++ b/src/egl/main/eglmode.c
@@ -1,4 +1,3 @@
-#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -6,29 +5,14 @@
#include "egldisplay.h"
#include "egldriver.h"
#include "eglmode.h"
-#include "eglglobals.h"
+#include "eglcurrent.h"
#include "eglscreen.h"
+#include "eglstring.h"
#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
-static char *
-my_strdup(const char *s)
-{
- if (s) {
- int l = strlen(s);
- char *s2 = malloc(l + 1);
- if (s2)
- strcpy(s2, s);
- return s2;
- }
- else {
- return NULL;
- }
-}
-
-
/**
* Given an EGLModeMESA handle, return the corresponding _EGLMode object
* or null if non-existant.
@@ -82,7 +66,7 @@ _eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height,
screen->Modes[n].RefreshRate = refreshRate;
screen->Modes[n].Optimal = EGL_FALSE;
screen->Modes[n].Interlaced = EGL_FALSE;
- screen->Modes[n].Name = my_strdup(name);
+ screen->Modes[n].Name = _eglstrdup(name);
screen->NumModes++;
return screen->Modes + n;
}
@@ -366,41 +350,3 @@ _eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m)
{
return m->Name;
}
-
-
-#if 0
-static int
-_eglRand(int max)
-{
- return rand() % max;
-}
-
-void
-_eglTestModeModule(void)
-{
- EGLint count = 30;
- _EGLMode *modes = (_EGLMode *) malloc(count * sizeof(_EGLMode));
- _EGLMode **modeList = (_EGLMode **) malloc(count * sizeof(_EGLMode*));
- EGLint i;
-
- for (i = 0; i < count; i++) {
- modes[i].Handle = _eglRand(20);
- modes[i].Width = 512 + 256 * _eglRand(2);
- modes[i].Height = 512 + 256 * _eglRand(2);
- modes[i].RefreshRate = 50 + 5 * _eglRand(3);
- modes[i].Interlaced = _eglRand(2);
- modes[i].Optimal = _eglRand(4) == 0;
- modeList[i] = modes + i;
- }
-
- /* sort array of pointers */
- qsort(modeList, count, sizeof(_EGLMode *), compareModes);
-
- for (i = 0; i < count; i++) {
- _EGLMode *m = modeList[i];
- printf("%2d: %3d %4d x %4d @ %3d opt %d int %d\n", i,
- m->Handle, m->Width, m->Height, m->RefreshRate,
- m->Optimal, m->Interlaced);
- }
-}
-#endif
diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c
index 14a1e9f8fe..97a405a4b4 100644
--- a/src/egl/main/eglscreen.c
+++ b/src/egl/main/eglscreen.c
@@ -17,6 +17,7 @@
#include "egldisplay.h"
#include "eglglobals.h"
+#include "eglcurrent.h"
#include "eglmode.h"
#include "eglconfig.h"
#include "eglsurface.h"
@@ -110,27 +111,12 @@ _eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens
/**
- * Example function - drivers should do a proper implementation.
+ * Drivers should do a proper implementation.
*/
_EGLSurface *
_eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
const EGLint *attrib_list)
{
-#if 0 /* THIS IS JUST EXAMPLE CODE */
- _EGLSurface *surf;
-
- surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
- if (!surf)
- return NULL;
-
- if (!_eglInitSurface(drv, surf, EGL_SCREEN_BIT_MESA,
- conf, attrib_list)) {
- free(surf);
- return NULL;
- }
-
- return surf;
-#endif
return NULL;
}
diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h
index d52e5388c3..c400ac3d15 100644
--- a/src/egl/main/eglscreen.h
+++ b/src/egl/main/eglscreen.h
@@ -2,6 +2,9 @@
#define EGLSCREEN_INCLUDED
+#include "egltypedefs.h"
+
+
/**
* Per-screen information.
* Note that an EGL screen doesn't have a size. A screen may be set to
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 940a1b760c..8026a6314d 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -9,8 +9,7 @@
#include "egldisplay.h"
#include "eglcontext.h"
#include "eglconfig.h"
-#include "egldriver.h"
-#include "eglglobals.h"
+#include "eglcurrent.h"
#include "egllog.h"
#include "eglsurface.h"
@@ -32,23 +31,168 @@ _eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
/**
+ * Parse the list of surface attributes and return the proper error code.
+ */
+static EGLint
+_eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
+{
+ EGLint type = surf->Type;
+ EGLint i, err = EGL_SUCCESS;
+
+ if (!attrib_list)
+ return EGL_SUCCESS;
+
+ for (i = 0; attrib_list[i] != EGL_NONE; i++) {
+ EGLint attr = attrib_list[i++];
+ EGLint val = attrib_list[i];
+
+ switch (attr) {
+ /* common (except for screen surfaces) attributes */
+ case EGL_VG_COLORSPACE:
+ if (type == EGL_SCREEN_BIT_MESA) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ switch (val) {
+ case EGL_VG_COLORSPACE_sRGB:
+ case EGL_VG_COLORSPACE_LINEAR:
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surf->VGColorspace = val;
+ break;
+ case EGL_VG_ALPHA_FORMAT:
+ if (type == EGL_SCREEN_BIT_MESA) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ switch (val) {
+ case EGL_VG_ALPHA_FORMAT_NONPRE:
+ case EGL_VG_ALPHA_FORMAT_PRE:
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surf->VGAlphaFormat = val;
+ break;
+ /* window surface attributes */
+ case EGL_RENDER_BUFFER:
+ if (type != EGL_WINDOW_BIT) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ surf->RenderBuffer = val;
+ break;
+ /* pbuffer surface attributes */
+ case EGL_WIDTH:
+ if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (val < 0) {
+ err = EGL_BAD_PARAMETER;
+ break;
+ }
+ surf->Width = val;
+ break;
+ case EGL_HEIGHT:
+ if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (val < 0) {
+ err = EGL_BAD_PARAMETER;
+ break;
+ }
+ surf->Height = val;
+ break;
+ case EGL_LARGEST_PBUFFER:
+ if (type != EGL_PBUFFER_BIT) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ surf->LargestPbuffer = !!val;
+ break;
+ case EGL_TEXTURE_FORMAT:
+ if (type != EGL_PBUFFER_BIT) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ switch (val) {
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ case EGL_NO_TEXTURE:
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surf->TextureFormat = val;
+ break;
+ case EGL_TEXTURE_TARGET:
+ if (type != EGL_PBUFFER_BIT) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ switch (val) {
+ case EGL_TEXTURE_2D:
+ case EGL_NO_TEXTURE:
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surf->TextureTarget = val;
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ if (type != EGL_PBUFFER_BIT) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ surf->MipmapTexture = !!val;
+ break;
+ /* no pixmap surface specific attributes */
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+
+ if (err != EGL_SUCCESS) {
+ _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
+ break;
+ }
+ }
+
+ return err;
+}
+
+
+/**
* Do error check on parameters and initialize the given _EGLSurface object.
* \return EGL_TRUE if no errors, EGL_FALSE otherwise.
*/
EGLBoolean
-_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
+_eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
_EGLConfig *conf, const EGLint *attrib_list)
{
const char *func;
- EGLint width = 0, height = 0, largest = 0;
- EGLint texFormat = EGL_NO_TEXTURE, texTarget = EGL_NO_TEXTURE;
- EGLint mipmapTex = EGL_FALSE;
EGLint renderBuffer = EGL_BACK_BUFFER;
-#ifdef EGL_VERSION_1_2
- EGLint colorspace = EGL_COLORSPACE_sRGB;
- EGLint alphaFormat = EGL_ALPHA_FORMAT_NONPRE;
-#endif
- EGLint i;
+ EGLint err;
switch (type) {
case EGL_WINDOW_BIT:
@@ -70,158 +214,41 @@ _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
return EGL_FALSE;
}
- if (!conf) {
- _eglError(EGL_BAD_CONFIG, func);
- return EGL_FALSE;
- }
-
if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) {
/* The config can't be used to create a surface of this type */
_eglError(EGL_BAD_CONFIG, func);
return EGL_FALSE;
}
- /*
- * Parse attribute list. Different kinds of surfaces support different
- * attributes.
- */
- for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
- switch (attrib_list[i]) {
- case EGL_WIDTH:
- if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
- width = attrib_list[++i];
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_HEIGHT:
- if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
- height = attrib_list[++i];
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_LARGEST_PBUFFER:
- if (type == EGL_PBUFFER_BIT) {
- largest = attrib_list[++i];
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_TEXTURE_FORMAT:
- if (type == EGL_PBUFFER_BIT) {
- texFormat = attrib_list[++i];
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_TEXTURE_TARGET:
- if (type == EGL_PBUFFER_BIT) {
- texTarget = attrib_list[++i];
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_MIPMAP_TEXTURE:
- if (type == EGL_PBUFFER_BIT) {
- mipmapTex = attrib_list[++i];
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
-#ifdef EGL_VERSION_1_2
- case EGL_RENDER_BUFFER:
- if (type == EGL_WINDOW_BIT) {
- renderBuffer = attrib_list[++i];
- if (renderBuffer != EGL_BACK_BUFFER &&
- renderBuffer != EGL_SINGLE_BUFFER) {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_COLORSPACE:
- if (type == EGL_WINDOW_BIT ||
- type == EGL_PBUFFER_BIT ||
- type == EGL_PIXMAP_BIT) {
- colorspace = attrib_list[++i];
- if (colorspace != EGL_COLORSPACE_sRGB &&
- colorspace != EGL_COLORSPACE_LINEAR) {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
- case EGL_ALPHA_FORMAT:
- if (type == EGL_WINDOW_BIT ||
- type == EGL_PBUFFER_BIT ||
- type == EGL_PIXMAP_BIT) {
- alphaFormat = attrib_list[++i];
- if (alphaFormat != EGL_ALPHA_FORMAT_NONPRE &&
- alphaFormat != EGL_ALPHA_FORMAT_PRE) {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- break;
-
-#endif /* EGL_VERSION_1_2 */
- default:
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
- }
-
- if (width < 0 || height < 0) {
- _eglError(EGL_BAD_ATTRIBUTE, func);
- return EGL_FALSE;
- }
-
memset(surf, 0, sizeof(_EGLSurface));
- surf->Config = conf;
+ surf->Resource.Display = dpy;
surf->Type = type;
- surf->Width = width;
- surf->Height = height;
- surf->TextureFormat = texFormat;
- surf->TextureTarget = texTarget;
- surf->MipmapTexture = mipmapTex;
+ surf->Config = conf;
+
+ surf->Width = 0;
+ surf->Height = 0;
+ surf->TextureFormat = EGL_NO_TEXTURE;
+ surf->TextureTarget = EGL_NO_TEXTURE;
+ surf->MipmapTexture = EGL_FALSE;
+ surf->LargestPbuffer = EGL_FALSE;
+ surf->RenderBuffer = renderBuffer;
+ surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
+ surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
+
surf->MipmapLevel = 0;
+ surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
+ surf->SwapBehavior = EGL_BUFFER_DESTROYED;
+
+ surf->HorizontalResolution = EGL_UNKNOWN;
+ surf->VerticalResolution = EGL_UNKNOWN;
+ surf->AspectRatio = EGL_UNKNOWN;
+
/* the default swap interval is 1 */
_eglClampSwapInterval(surf, 1);
-#ifdef EGL_VERSION_1_2
- surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */
- surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */
- surf->VerticalResolution = EGL_UNKNOWN; /* set by caller */
- surf->AspectRatio = EGL_UNKNOWN; /* set by caller */
- surf->RenderBuffer = renderBuffer;
- surf->AlphaFormat = alphaFormat;
- surf->Colorspace = colorspace;
-#endif
+ err = _eglParseSurfaceAttribList(surf, attrib_list);
+ if (err != EGL_SUCCESS)
+ return _eglError(err, func);
return EGL_TRUE;
}
@@ -237,7 +264,7 @@ _eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
EGLBoolean
_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
- NativePixmapType target)
+ EGLNativePixmapType target)
{
/* copy surface to native pixmap */
/* All implementation burdon for this is in the device driver */
@@ -252,139 +279,95 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
switch (attribute) {
case EGL_WIDTH:
*value = surface->Width;
- return EGL_TRUE;
+ break;
case EGL_HEIGHT:
*value = surface->Height;
- return EGL_TRUE;
+ break;
case EGL_CONFIG_ID:
*value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
- return EGL_TRUE;
+ break;
case EGL_LARGEST_PBUFFER:
- *value = dpy->LargestPbuffer;
- return EGL_TRUE;
- case EGL_SURFACE_TYPE:
- *value = surface->Type;
- return EGL_TRUE;
-#ifdef EGL_VERSION_1_1
+ *value = surface->LargestPbuffer;
+ break;
case EGL_TEXTURE_FORMAT:
/* texture attributes: only for pbuffers, no error otherwise */
if (surface->Type == EGL_PBUFFER_BIT)
*value = surface->TextureFormat;
- return EGL_TRUE;
+ break;
case EGL_TEXTURE_TARGET:
if (surface->Type == EGL_PBUFFER_BIT)
*value = surface->TextureTarget;
- return EGL_TRUE;
+ break;
case EGL_MIPMAP_TEXTURE:
if (surface->Type == EGL_PBUFFER_BIT)
*value = surface->MipmapTexture;
- return EGL_TRUE;
+ break;
case EGL_MIPMAP_LEVEL:
if (surface->Type == EGL_PBUFFER_BIT)
*value = surface->MipmapLevel;
- return EGL_TRUE;
-#endif /* EGL_VERSION_1_1 */
-#ifdef EGL_VERSION_1_2
+ break;
case EGL_SWAP_BEHAVIOR:
*value = surface->SwapBehavior;
- return EGL_TRUE;
+ break;
case EGL_RENDER_BUFFER:
*value = surface->RenderBuffer;
- return EGL_TRUE;
+ break;
case EGL_PIXEL_ASPECT_RATIO:
*value = surface->AspectRatio;
- return EGL_TRUE;
+ break;
case EGL_HORIZONTAL_RESOLUTION:
*value = surface->HorizontalResolution;
- return EGL_TRUE;
+ break;
case EGL_VERTICAL_RESOLUTION:
*value = surface->VerticalResolution;
- return EGL_TRUE;
- case EGL_ALPHA_FORMAT:
- *value = surface->AlphaFormat;
- return EGL_TRUE;
- case EGL_COLORSPACE:
- *value = surface->Colorspace;
- return EGL_TRUE;
-#endif /* EGL_VERSION_1_2 */
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ *value = surface->MultisampleResolve;
+ break;
+ case EGL_VG_ALPHA_FORMAT:
+ *value = surface->VGAlphaFormat;
+ break;
+ case EGL_VG_COLORSPACE:
+ *value = surface->VGColorspace;
+ break;
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
return EGL_FALSE;
}
+
+ return EGL_TRUE;
}
/**
- * Example function - drivers should do a proper implementation.
+ * Drivers should do a proper implementation.
*/
_EGLSurface *
_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
- NativeWindowType window, const EGLint *attrib_list)
+ EGLNativeWindowType window, const EGLint *attrib_list)
{
-#if 0 /* THIS IS JUST EXAMPLE CODE */
- _EGLSurface *surf;
-
- surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
- if (!surf)
- return NULL;
-
- if (!_eglInitSurface(drv, surf, EGL_WINDOW_BIT, conf, attrib_list)) {
- free(surf);
- return NULL;
- }
-
- return surf;
-#endif
return NULL;
}
/**
- * Example function - drivers should do a proper implementation.
+ * Drivers should do a proper implementation.
*/
_EGLSurface *
_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
- NativePixmapType pixmap, const EGLint *attrib_list)
+ EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
-#if 0 /* THIS IS JUST EXAMPLE CODE */
- _EGLSurface *surf;
-
- surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
- if (!surf)
- return NULL;
-
- if (!_eglInitSurface(drv, surf, EGL_PIXMAP_BIT, conf, attrib_list)) {
- free(surf);
- return NULL;
- }
-
- return surf;
-#endif
return NULL;
}
/**
- * Example function - drivers should do a proper implementation.
+ * Drivers should do a proper implementation.
*/
_EGLSurface *
_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
const EGLint *attrib_list)
{
-#if 0 /* THIS IS JUST EXAMPLE CODE */
- _EGLSurface *surf;
-
- surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
- if (!surf)
- return NULL;
-
- if (!_eglInitSurface(drv, surf, EGL_PBUFFER_BIT, conf, attrib_list)) {
- free(surf);
- return NULL;
- }
-
- return NULL;
-#endif
return NULL;
}
@@ -408,14 +391,59 @@ EGLBoolean
_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
EGLint attribute, EGLint value)
{
+ EGLint confval;
+ EGLint err = EGL_SUCCESS;
+
switch (attribute) {
case EGL_MIPMAP_LEVEL:
+ confval = GET_CONFIG_ATTRIB(surface->Config, EGL_RENDERABLE_TYPE);
+ if (!(confval & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT))) {
+ err = EGL_BAD_PARAMETER;
+ break;
+ }
surface->MipmapLevel = value;
break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ switch (value) {
+ case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
+ break;
+ case EGL_MULTISAMPLE_RESOLVE_BOX:
+ confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE);
+ if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
+ err = EGL_BAD_MATCH;
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surface->MultisampleResolve = value;
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ switch (value) {
+ case EGL_BUFFER_DESTROYED:
+ break;
+ case EGL_BUFFER_PRESERVED:
+ confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE);
+ if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
+ err = EGL_BAD_MATCH;
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surface->SwapBehavior = value;
+ break;
default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib");
- return EGL_FALSE;
+ err = EGL_BAD_ATTRIBUTE;
+ break;
}
+
+ if (err != EGL_SUCCESS)
+ return _eglError(err, "eglSurfaceAttrib");
return EGL_TRUE;
}
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index dacdf7e63c..0a00035730 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -3,6 +3,7 @@
#include "egltypedefs.h"
+#include "egldisplay.h"
/**
@@ -10,38 +11,43 @@
*/
struct _egl_surface
{
- /* Managed by EGLDisplay for linking */
- _EGLDisplay *Display;
- _EGLSurface *Next;
+ /* A surface is a display resource */
+ _EGLResource Resource;
- /* The bound status of the surface */
- _EGLContext *Binding;
- EGLBoolean BoundToTexture;
+ /* The context that is currently bound to the surface */
+ _EGLContext *CurrentContext;
_EGLConfig *Config;
EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
- EGLint Width, Height;
- EGLint TextureFormat, TextureTarget;
- EGLint MipmapTexture, MipmapLevel;
- EGLint SwapInterval;
- /* If type == EGL_SCREEN_BIT: */
- EGLint VisibleRefCount; /* number of screens I'm displayed on */
+ /* attributes set by attribute list */
+ EGLint Width, Height;
+ EGLenum TextureFormat;
+ EGLenum TextureTarget;
+ EGLBoolean MipmapTexture;
+ EGLBoolean LargestPbuffer;
+ EGLenum RenderBuffer;
+ EGLenum VGAlphaFormat;
+ EGLenum VGColorspace;
+
+ /* attributes set by eglSurfaceAttrib */
+ EGLint MipmapLevel;
+ EGLenum MultisampleResolve;
+ EGLenum SwapBehavior;
-#ifdef EGL_VERSION_1_2
- EGLint SwapBehavior; /* one of EGL_BUFFER_PRESERVED/DESTROYED */
EGLint HorizontalResolution, VerticalResolution;
EGLint AspectRatio;
- EGLint RenderBuffer; /* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER */
- EGLint AlphaFormat; /* EGL_ALPHA_FORMAT_NONPRE or EGL_ALPHA_FORMAT_PRE */
- EGLint Colorspace; /* EGL_COLORSPACE_sRGB or EGL_COLORSPACE_LINEAR */
-#endif /* EGL_VERSION_1_2 */
+
+ EGLint SwapInterval;
+
+ /* True if the surface is bound to an OpenGL ES texture */
+ EGLBoolean BoundToTexture;
};
PUBLIC EGLBoolean
-_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
+_eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
_EGLConfig *config, const EGLint *attrib_list);
@@ -50,7 +56,7 @@ _eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf);
extern EGLBoolean
-_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, NativePixmapType target);
+_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLNativePixmapType target);
extern EGLBoolean
@@ -58,11 +64,11 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint at
extern _EGLSurface *
-_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list);
+_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLNativeWindowType window, const EGLint *attrib_list);
extern _EGLSurface *
-_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list);
+_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLNativePixmapType pixmap, const EGLint *attrib_list);
extern _EGLSurface *
@@ -100,14 +106,78 @@ _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy,
/**
- * Return true if the surface is bound to a thread.
- * A surface bound to a texutre is not considered bound by
- * this function.
+ * Return true if there is a context bound to the surface.
+ *
+ * The binding is considered a reference to the surface. Drivers should not
+ * destroy a surface when it is bound.
*/
static INLINE EGLBoolean
_eglIsSurfaceBound(_EGLSurface *surf)
{
- return (surf->Binding != NULL);
+ return (surf->CurrentContext != NULL);
+}
+
+
+/**
+ * Link a surface to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+static INLINE EGLSurface
+_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
+{
+ _eglLinkResource(&surf->Resource, _EGL_RESOURCE_SURFACE, dpy);
+ return (EGLSurface) surf;
+}
+
+
+/**
+ * Unlink a linked surface from its display.
+ * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
+ */
+static INLINE void
+_eglUnlinkSurface(_EGLSurface *surf)
+{
+ _eglUnlinkResource(&surf->Resource, _EGL_RESOURCE_SURFACE);
+}
+
+
+/**
+ * Lookup a handle to find the linked surface.
+ * Return NULL if the handle has no corresponding linked surface.
+ */
+static INLINE _EGLSurface *
+_eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy)
+{
+ _EGLSurface *surf = (_EGLSurface *) surface;
+ if (!dpy || !_eglCheckResource((void *) surf, _EGL_RESOURCE_SURFACE, dpy))
+ surf = NULL;
+ return surf;
+}
+
+
+/**
+ * Return the handle of a linked surface, or EGL_NO_SURFACE.
+ */
+static INLINE EGLSurface
+_eglGetSurfaceHandle(_EGLSurface *surf)
+{
+ _EGLResource *res = (_EGLResource *) surf;
+ return (res && _eglIsResourceLinked(res)) ?
+ (EGLSurface) surf : EGL_NO_SURFACE;
+}
+
+
+/**
+ * Return true if the surface is linked to a display.
+ *
+ * The link is considered a reference to the surface (the display is owning the
+ * surface). Drivers should not destroy a surface when it is linked.
+ */
+static INLINE EGLBoolean
+_eglIsSurfaceLinked(_EGLSurface *surf)
+{
+ _EGLResource *res = (_EGLResource *) surf;
+ return (res && _eglIsResourceLinked(res));
}
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
index 4461440b9b..e0c95762c6 100644
--- a/src/egl/main/egltypedefs.h
+++ b/src/egl/main/egltypedefs.h
@@ -8,6 +8,8 @@
#include "eglcompiler.h"
+typedef enum _egl_resource_type _EGLResourceType;
+
typedef struct _egl_api _EGLAPI;
typedef struct _egl_config _EGLConfig;
@@ -20,16 +22,16 @@ typedef struct _egl_driver _EGLDriver;
typedef struct _egl_extensions _EGLExtensions;
+typedef struct _egl_image _EGLImage;
+
typedef struct _egl_mode _EGLMode;
+typedef struct _egl_resource _EGLResource;
+
typedef struct _egl_screen _EGLScreen;
typedef struct _egl_surface _EGLSurface;
typedef struct _egl_thread_info _EGLThreadInfo;
-
-typedef _EGLDriver *(*_EGLMain_t)(const char *args);
-
-
#endif /* EGLTYPEDEFS_INCLUDED */