diff options
Diffstat (limited to 'src/egl')
38 files changed, 1380 insertions, 1604 deletions
diff --git a/src/egl/drivers/Makefile.template b/src/egl/drivers/Makefile.template new file mode 100644 index 0000000000..e9a614ce62 --- /dev/null +++ b/src/egl/drivers/Makefile.template @@ -0,0 +1,51 @@ +# src/egl/drivers/Makefile.template +# +# Drivers should define +# +# EGL_DRIVER, the driver name +# EGL_SOURCES, the driver sources +# EGL_INCLUDES, the include pathes +# EGL_CFLAGS, additional CFLAGS +# EGL_LIBS, additional LIBS +# +# before including this template. +# + + +EGL_DRIVER_PATH = $(TOP)/$(LIB_DIR)/$(EGL_DRIVER) +EGL_OBJECTS = $(EGL_SOURCES:.c=.o) + + +default: depend $(EGL_DRIVER_PATH) + +$(EGL_DRIVER_PATH): $(EGL_DRIVER) + $(INSTALL) $< $(TOP)/$(LIB_DIR) + +$(EGL_DRIVER): $(EGL_OBJECTS) Makefile $(TOP)/src/egl/drivers/Makefile.template + @$(MKLIB) -o $(EGL_DRIVER) -noprefix \ + -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -L$(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ + $(EGL_OBJECTS) $(EGL_LIBS) + +.c.o: + $(CC) -c $(EGL_INCLUDES) $(CFLAGS) $(EGL_CFLAGS) $< -o $@ + + +install: $(EGL_DRIVER_PATH) + $(INSTALL) -d $(DESTDIR)$(EGL_DRIVER_INSTALL_DIR) + $(MINSTALL) $(EGL_DRIVER_PATH) $(DESTDIR)$(EGL_DRIVER_INSTALL_DIR) + +clean: + rm -f $(EGL_DRIVER) + rm -f $(EGL_OBJECTS) + rm -f depend depend.bak + +depend: $(EGL_SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(EGL_INCLUDES) $(EGL_SOURCES) \ + >/dev/null 2>/dev/null + +sinclude depend +# DO NOT DELETE diff --git a/src/egl/drivers/demo/Makefile b/src/egl/drivers/demo/Makefile deleted file mode 100644 index 444dfb35bd..0000000000 --- a/src/egl/drivers/demo/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# src/egl/drivers/demo/Makefile - -TOP = ../../../.. -include $(TOP)/configs/current - - -INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main $(X11_INCLUDES) - - -SOURCES = demo.c - -OBJECTS = $(SOURCES:.c=.o) - - -.c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ - - - -default: $(TOP)/$(LIB_DIR)/demodriver.so - - -$(TOP)/$(LIB_DIR)/demodriver.so: $(OBJECTS) - $(MKLIB) -o demodriver.so -noprefix -linker '$(CC)' \ - -ldflags '$(LDFLAGS)' -install $(TOP)/$(LIB_DIR) \ - $(OBJECTS) - -install: - -clean: - -rm -f *.o - -rm -f *.so diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c deleted file mode 100644 index 0933c0bdaa..0000000000 --- a/src/egl/drivers/demo/demo.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Sample driver: Demo - */ - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include "eglconfig.h" -#include "eglcontext.h" -#include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" -#include "eglmode.h" -#include "eglscreen.h" -#include "eglsurface.h" - - -/** - * Demo driver-specific driver class derived from _EGLDriver - */ -typedef struct demo_driver -{ - _EGLDriver Base; /* base class/object */ - unsigned DemoStuff; -} DemoDriver; - -#define DEMO_DRIVER(D) ((DemoDriver *) (D)) - - -/** - * Demo driver-specific surface class derived from _EGLSurface - */ -typedef struct demo_surface -{ - _EGLSurface Base; /* base class/object */ - unsigned DemoStuff; -} DemoSurface; - - -/** - * Demo driver-specific context class derived from _EGLContext - */ -typedef struct demo_context -{ - _EGLContext Base; /* base class/object */ - unsigned DemoStuff; -} DemoContext; - - - -static EGLBoolean -demoInitialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor) -{ - _EGLScreen *scrn; - EGLint i; - - /* Create a screen */ - scrn = calloc(1, sizeof(*scrn)); - _eglAddScreen(disp, scrn); - - /* Create the screen's modes - silly example */ - _eglAddNewMode(scrn, 1600, 1200, 72 * 1000, "1600x1200-72"); - _eglAddNewMode(scrn, 1280, 1024, 72 * 1000, "1280x1024-70"); - _eglAddNewMode(scrn, 1280, 1024, 70 * 1000, "1280x1024-70"); - _eglAddNewMode(scrn, 1024, 768, 72 * 1000, "1024x768-72"); - - /* Create the display's visual configs - silly example */ - for (i = 0; i < 4; i++) { - _EGLConfig *config = calloc(1, sizeof(_EGLConfig)); - _eglInitConfig(config, i + 1); - _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); - _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); - _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); - _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); - _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); - if (i & 1) { - _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 32); - } - if (i & 2) { - _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); - } - _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, - (EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)); - _eglAddConfig(disp, config); - } - - /* enable supported extensions */ - disp->Extensions.MESA_screen_surface = EGL_TRUE; - disp->Extensions.MESA_copy_context = EGL_TRUE; - - *major = 1; - *minor = 0; - - return EGL_TRUE; -} - - -static EGLBoolean -demoTerminate(_EGLDriver *drv, _EGLDisplay *dpy) -{ - /*DemoDriver *demo = DEMO_DRIVER(dpy);*/ - return EGL_TRUE; -} - - -static DemoContext * -LookupDemoContext(_EGLContext *c) -{ - return (DemoContext *) c; -} - - -static DemoSurface * -LookupDemoSurface(_EGLSurface *s) -{ - return (DemoSurface *) s; -} - - -static _EGLContext * -demoCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list) -{ - DemoContext *c; - int i; - - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - /* no attribs defined for now */ - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); - return NULL; - } - } - - c = (DemoContext *) calloc(1, sizeof(DemoContext)); - if (!c) - return NULL; - - _eglInitContext(drv, &c->Base, conf, attrib_list); - c->DemoStuff = 1; - printf("demoCreateContext\n"); - - return &c->Base; -} - - -static _EGLSurface * -demoCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) -{ - int i; - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - /* no attribs at this time */ - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface"); - return NULL; - } - } - printf("eglCreateWindowSurface()\n"); - /* XXX unfinished */ - - return NULL; -} - - -static _EGLSurface * -demoCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list) -{ - EGLint i; - - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - /* no attribs at this time */ - default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface"); - return NULL; - } - } - - if (GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) == 0) { - _eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface"); - return NULL; - } - - printf("eglCreatePixmapSurface()\n"); - return NULL; -} - - -static _EGLSurface * -demoCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - const EGLint *attrib_list) -{ - DemoSurface *surf = (DemoSurface *) calloc(1, sizeof(DemoSurface)); - - if (!surf) - return NULL; - - if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, - conf, attrib_list)) { - free(surf); - return NULL; - } - - /* a real driver would allocate the pbuffer memory here */ - - return &surf->Base; -} - - -static EGLBoolean -demoDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) -{ - DemoSurface *fs = LookupDemoSurface(surface); - if (!_eglIsSurfaceBound(&fs->Base)) - free(fs); - return EGL_TRUE; -} - - -static EGLBoolean -demoDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context) -{ - DemoContext *fc = LookupDemoContext(context); - if (!_eglIsContextBound(&fc->Base)) - free(fc); - return EGL_TRUE; -} - - -static EGLBoolean -demoMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *drawSurf, _EGLSurface *readSurf, _EGLContext *ctx) -{ - /*DemoDriver *demo = DEMO_DRIVER(dpy);*/ - EGLBoolean b; - - b = _eglMakeCurrent(drv, dpy, drawSurf, readSurf, ctx); - if (!b) - return EGL_FALSE; - - /* XXX this is where we'd do the hardware context switch */ - (void) drawSurf; - (void) readSurf; - (void) ctx; - - printf("eglMakeCurrent()\n"); - return EGL_TRUE; -} - - -static void -demoUnload(_EGLDriver *drv) -{ - free(drv); -} - - -/** - * The bootstrap function. Return a new DemoDriver object and - * plug in API functions. - */ -_EGLDriver * -_eglMain(const char *args) -{ - DemoDriver *demo; - - demo = (DemoDriver *) calloc(1, sizeof(DemoDriver)); - if (!demo) { - return NULL; - } - - /* First fill in the dispatch table with defaults */ - _eglInitDriverFallbacks(&demo->Base); - /* then plug in our Demo-specific functions */ - demo->Base.API.Initialize = demoInitialize; - demo->Base.API.Terminate = demoTerminate; - demo->Base.API.CreateContext = demoCreateContext; - demo->Base.API.MakeCurrent = demoMakeCurrent; - demo->Base.API.CreateWindowSurface = demoCreateWindowSurface; - demo->Base.API.CreatePixmapSurface = demoCreatePixmapSurface; - demo->Base.API.CreatePbufferSurface = demoCreatePbufferSurface; - demo->Base.API.DestroySurface = demoDestroySurface; - demo->Base.API.DestroyContext = demoDestroyContext; - - demo->Base.Name = "egl/demo"; - demo->Base.Unload = demoUnload; - - return &demo->Base; -} diff --git a/src/egl/drivers/glx/Makefile b/src/egl/drivers/glx/Makefile index 20ef0352ad..634638f538 100644 --- a/src/egl/drivers/glx/Makefile +++ b/src/egl/drivers/glx/Makefile @@ -1,77 +1,16 @@ # src/egl/drivers/glx/Makefile -# Build XEGL DRI driver loader library: egl_glx.so - - TOP = ../../../.. include $(TOP)/configs/current +EGL_DRIVER = egl_glx.so +EGL_SOURCES = egl_glx.c -EXTRA_DEFINES = -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" - -DRIVER_NAME = egl_glx.so - - -INCLUDE_DIRS = \ - -I. \ - -I/usr/include \ - $(shell pkg-config --cflags-only-I libdrm) \ +EGL_INCLUDES = \ -I$(TOP)/include \ - -I$(TOP)/include/GL/internal \ - -I$(TOP)/src/mesa/glapi \ - -I$(TOP)/src/mesa/drivers/dri/common \ - -I$(TOP)/src/mesa/main \ - -I$(TOP)/src/mesa \ - -I$(TOP)/src/egl/main \ - -I$(TOP)/src/glx/x11 - -SOURCES = egl_glx.c - -OBJECTS = $(SOURCES:.c=.o) - -DRM_LIB = `pkg-config --libs libdrm` - -MISC_LIBS = -ldl -lXext -lGL - - -.c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@ - - -.PHONY: library - - -default: depend library Makefile - - -library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) - - -# Make the egl_glx.so library -$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS) - $(TOP)/bin/mklib -o $(DRIVER_NAME) \ - -noprefix \ - -major 1 -minor 0 \ - -L$(TOP)/$(LIB_DIR) \ - -install $(TOP)/$(LIB_DIR) \ - $(OBJECTS) $(DRM_LIB) $(MISC_LIBS) - -install: - $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) - $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(DESTDIR)$(INSTALL_LIB_DIR) - -clean: - rm -f *.o - rm -f *.so - rm -f depend depend.bak - + -I$(TOP)/src/egl/main -depend: $(SOURCES) $(HEADERS) - @ echo "running $(MKDEP)" - @ rm -f depend - @ touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ - $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null +EGL_CFLAGS = +EGL_LIBS = -lX11 -lGL -include depend -# DO NOT DELETE +include ../Makefile.template diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c index 7c6e8637a1..af653b86ee 100644 --- a/src/egl/drivers/glx/egl_glx.c +++ b/src/egl/drivers/glx/egl_glx.c @@ -43,7 +43,7 @@ #include "eglcontext.h" #include "egldisplay.h" #include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "egllog.h" #include "eglsurface.h" @@ -54,13 +54,6 @@ #error "GL/glx.h must be equal to or greater than GLX 1.4" #endif -/* - * report OpenGL ES bits because apps usually forget to specify - * EGL_RENDERABLE_TYPE when choosing configs - */ -#define GLX_EGL_APIS (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT) - - /** subclass of _EGLDriver */ struct GLX_egl_driver { @@ -110,6 +103,8 @@ struct GLX_egl_surface Drawable drawable; GLXDrawable glx_drawable; + + void (*destroy)(Display *, GLXDrawable); }; @@ -244,7 +239,7 @@ convert_fbconfig(Display *dpy, GLXFBConfig fbconfig, GLX_conf->double_buffered = (mode.doubleBufferMode != 0); return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode, - GLX_EGL_APIS, GLX_EGL_APIS); + EGL_OPENGL_BIT, EGL_OPENGL_BIT); } @@ -364,7 +359,7 @@ convert_visual(Display *dpy, XVisualInfo *vinfo, GLX_conf->double_buffered = (mode.doubleBufferMode != 0); return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode, - GLX_EGL_APIS, GLX_EGL_APIS); + EGL_OPENGL_BIT, EGL_OPENGL_BIT); } @@ -559,7 +554,7 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp, } disp->DriverData = (void *) GLX_dpy; - disp->ClientAPIsMask = GLX_EGL_APIS; + disp->ClientAPIsMask = EGL_OPENGL_BIT; /* we're supporting EGL 1.4 */ *major = 1; @@ -638,6 +633,21 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, /** + * Destroy a surface. The display is allowed to be uninitialized. + */ +static void +destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) +{ + struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf); + + if (GLX_surf->destroy) + GLX_surf->destroy(disp->NativeDisplay, GLX_surf->glx_drawable); + + free(GLX_surf); +} + + +/** * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ static EGLBoolean @@ -650,8 +660,10 @@ GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx); GLXDrawable ddraw, rdraw; GLXContext cctx; + EGLBoolean ret = EGL_FALSE; - if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx)) + /* bind the new context and return the "orphaned" one */ + if (!_eglBindContext(&ctx, &dsurf, &rsurf)) return EGL_FALSE; ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None; @@ -659,11 +671,21 @@ GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, cctx = (GLX_ctx) ? GLX_ctx->context : NULL; if (GLX_dpy->have_make_current_read) - return glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx); + ret = glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx); else if (ddraw == rdraw) - return glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx); + ret = glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx); - return EGL_FALSE; + if (ret) { + if (dsurf && !_eglIsSurfaceLinked(dsurf)) + destroy_surface(disp, dsurf); + if (rsurf && rsurf != dsurf && !_eglIsSurfaceLinked(rsurf)) + destroy_surface(disp, rsurf); + } + else { + _eglBindContext(&ctx, &dsurf, &rsurf); + } + + return ret; } /** Get size of given window */ @@ -684,8 +706,9 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ static _EGLSurface * -GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, - NativeWindowType window, const EGLint *attrib_list) +GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, EGLNativeWindowType window, + const EGLint *attrib_list) { struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); struct GLX_egl_surface *GLX_surf; @@ -718,6 +741,9 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, return NULL; } + if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) + GLX_surf->destroy = glXDestroyWindow; + get_drawable_size(GLX_dpy->dpy, window, &width, &height); GLX_surf->Base.Width = width; GLX_surf->Base.Height = height; @@ -726,8 +752,9 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, } static _EGLSurface * -GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, - NativePixmapType pixmap, const EGLint *attrib_list) +GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, EGLNativePixmapType pixmap, + const EGLint *attrib_list) { struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); struct GLX_egl_surface *GLX_surf; @@ -774,6 +801,9 @@ GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, return NULL; } + GLX_surf->destroy = (GLX_dpy->have_1_3) ? + glXDestroyPixmap : glXDestroyGLXPixmap; + get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height); GLX_surf->Base.Width = width; GLX_surf->Base.Height = height; @@ -838,47 +868,18 @@ GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, return NULL; } + GLX_surf->destroy = (GLX_dpy->have_1_3) ? + glXDestroyPbuffer : GLX_dpy->glXDestroyGLXPbufferSGIX; + return &GLX_surf->Base; } + static EGLBoolean GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) { - struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); - if (!_eglIsSurfaceBound(surf)) { - struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf); - - if (GLX_dpy->have_1_3) { - switch (surf->Type) { - case EGL_WINDOW_BIT: - if (!GLX_dpy->glx_window_quirk) - glXDestroyWindow(GLX_dpy->dpy, GLX_surf->glx_drawable); - break; - case EGL_PBUFFER_BIT: - glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->glx_drawable); - break; - case EGL_PIXMAP_BIT: - glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable); - break; - default: - break; - } - } - else { - switch (surf->Type) { - case EGL_PBUFFER_BIT: - GLX_dpy->glXDestroyGLXPbufferSGIX(GLX_dpy->dpy, - GLX_surf->glx_drawable); - break; - case EGL_PIXMAP_BIT: - glXDestroyGLXPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable); - break; - default: - break; - } - } - free(surf); - } + if (!_eglIsSurfaceBound(surf)) + destroy_surface(disp, surf); return EGL_TRUE; } diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile index 4c1fc9071c..9120620dc5 100644 --- a/src/egl/drivers/xdri/Makefile +++ b/src/egl/drivers/xdri/Makefile @@ -1,78 +1,28 @@ # src/egl/drivers/xdri/Makefile -# Build XEGL DRI driver loader library: egl_xdri.so - - TOP = ../../../.. include $(TOP)/configs/current +EGL_DRIVER = egl_xdri.so -DRIVER_NAME = egl_xdri.so - - -INCLUDE_DIRS = \ - -I. \ - -I/usr/include \ +# steal sources from GLX +GLX_SOURCES = dri_common.c XF86dri.c dri2.c dri2_glx.c dri_glx.c drisw_glx.c +GLX_SOURCES := $(addprefix ../../../glx/x11/,$(GLX_SOURCES)) +GLX_INCLUDES = \ $(shell pkg-config --cflags-only-I libdrm) \ - -I$(TOP)/include \ -I$(TOP)/include/GL/internal \ - -I$(TOP)/src/mesa \ + -I$(TOP)/src/glx/x11 \ -I$(TOP)/src/mesa/glapi \ - -I$(TOP)/src/egl/main \ - -I$(TOP)/src/glx/x11 - -HEADERS = glxinit.h driinit.h -SOURCES = egl_xdri.c glxinit.c driinit.c - -DRI_SOURCES = dri_common.c XF86dri.c dri2.c dri2_glx.c dri_glx.c -DRI_SOURCES := $(addprefix ../../../glx/x11/,$(DRI_SOURCES)) - -SOURCES += $(DRI_SOURCES) - -OBJECTS = $(SOURCES:.c=.o) - -DRM_LIB = `pkg-config --libs libdrm` - -CFLAGS += -DGLX_DIRECT_RENDERING - -.c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ - - -.PHONY: library - - -default: depend library Makefile - - -library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) - - -# Make the egl_xdri.so library -$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS) - $(TOP)/bin/mklib -o $(DRIVER_NAME) \ - -noprefix \ - -major 1 -minor 0 \ - -L$(TOP)/$(LIB_DIR) \ - -install $(TOP)/$(LIB_DIR) \ - $(OBJECTS) $(DRM_LIB) $(GL_LIB_DEPS) - -install: - $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) - $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(DESTDIR)$(INSTALL_LIB_DIR) - -clean: - rm -f *.o - rm -f *.so - rm -f depend depend.bak + -I$(TOP)/src/mesa +GLX_CFLAGS = -DGLX_DIRECT_RENDERING +EGL_SOURCES = egl_xdri.c glxinit.c driinit.c $(GLX_SOURCES) +EGL_INCLUDES = \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main \ + $(GLX_INCLUDES) -depend: $(SOURCES) $(HEADERS) - @ echo "running $(MKDEP)" - @ rm -f depend - @ touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ - $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null +EGL_CFLAGS = $(GLX_CFLAGS) +EGL_LIBS = -lX11 -lGL -include depend -# DO NOT DELETE +include ../Makefile.template diff --git a/src/egl/drivers/xdri/driinit.c b/src/egl/drivers/xdri/driinit.c index 12da1bcd24..3e54f0bd4d 100644 --- a/src/egl/drivers/xdri/driinit.c +++ b/src/egl/drivers/xdri/driinit.c @@ -2,6 +2,7 @@ * DRI initialization. The DRI loaders are defined in src/glx/x11/. */ +#include <stdlib.h> #include <sys/time.h> #include "glxclient.h" @@ -42,18 +43,26 @@ __glXEnableDirectExtension(__GLXscreenConfigs * psc, const char *name) _X_HIDDEN __GLXDRIdisplay * __driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version) { - __GLXDRIdisplay *driDisplay; + __GLXDRIdisplay *driDisplay = NULL; int ver = 0; + char *env; + int force_sw; + + env = getenv("EGL_SOFTWARE"); + force_sw = (env && *env != '0'); /* try DRI2 first */ - driDisplay = dri2CreateDisplay(dpyPriv->dpy); - if (driDisplay) { - /* fill in the required field */ - dpyPriv->dri2Display = driDisplay; - ver = 2; + if (!force_sw) { + driDisplay = dri2CreateDisplay(dpyPriv->dpy); + if (driDisplay) { + /* fill in the required field */ + dpyPriv->dri2Display = driDisplay; + ver = 2; + } } - else { - /* try DRI */ + + /* and then DRI */ + if (!force_sw && !driDisplay) { driDisplay = driCreateDisplay(dpyPriv->dpy); if (driDisplay) { dpyPriv->driDisplay = driDisplay; @@ -61,6 +70,15 @@ __driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version) } } + /* and then DRISW */ + if (!driDisplay) { + driDisplay = driswCreateDisplay(dpyPriv->dpy); + if (driDisplay) { + dpyPriv->driDisplay = driDisplay; + ver = 0; + } + } + if (version) *version = ver; return driDisplay; diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c index 8425b3d11e..9c21576539 100644 --- a/src/egl/drivers/xdri/egl_xdri.c +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -52,7 +52,7 @@ #include "eglcontext.h" #include "egldisplay.h" #include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "egllog.h" #include "eglsurface.h" @@ -62,6 +62,7 @@ struct xdri_egl_driver { _EGLDriver Base; /**< base class */ + void (*FlushCurrentContext)(void); }; @@ -71,6 +72,7 @@ struct xdri_egl_display Display *dpy; __GLXdisplayPrivate *dpyPriv; __GLXDRIdisplay *driDisplay; + int driVersion; __GLXscreenConfigs *psc; EGLint scr; @@ -167,14 +169,10 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) static EGLBoolean convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m) { - static const EGLint all_apis = (EGL_OPENGL_ES_BIT | - EGL_OPENGL_ES2_BIT | - EGL_OPENVG_BIT | - EGL_OPENGL_BIT); EGLint val; _eglInitConfig(conf, id); - if (!_eglConfigFromContextModesRec(conf, m, all_apis, all_apis)) + if (!_eglConfigFromContextModesRec(conf, m, EGL_OPENGL_BIT, EGL_OPENGL_BIT)) return EGL_FALSE; if (m->doubleBufferMode) { @@ -215,6 +213,7 @@ convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m) static EGLint create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) { + struct xdri_egl_display *xdri_dpy = lookup_display(disp); int id = first_id; for (; m; m = m->next) { @@ -224,8 +223,15 @@ create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) if (!convert_config(&conf, id, m)) continue; - - rb = (m->doubleBufferMode) ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER; + if (m->doubleBufferMode) { + rb = EGL_BACK_BUFFER; + } + else { + /* ignore single-buffered mode for DRISW */ + if (xdri_dpy->driVersion == 0) + continue; + rb = EGL_SINGLE_BUFFER; + } xdri_conf = CALLOC_STRUCT(xdri_egl_config); if (xdri_conf) { @@ -275,7 +281,7 @@ xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } - driDisplay = __driCreateDisplay(dpyPriv, NULL); + driDisplay = __driCreateDisplay(dpyPriv, &xdri_dpy->driVersion); if (!driDisplay) { _eglLog(_EGL_WARNING, "failed to create DRI display"); free(xdri_dpy); @@ -297,16 +303,13 @@ xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } + dpy->DriverData = xdri_dpy; + dpy->ClientAPIsMask = EGL_OPENGL_BIT; + /* add visuals and fbconfigs */ first_id = create_configs(dpy, psc->visuals, first_id); create_configs(dpy, psc->configs, first_id); - dpy->DriverData = xdri_dpy; - dpy->ClientAPIsMask = (EGL_OPENGL_BIT | - EGL_OPENGL_ES_BIT | - EGL_OPENGL_ES2_BIT | - EGL_OPENVG_BIT); - /* we're supporting EGL 1.4 */ *minor = 1; *major = 4; @@ -342,7 +345,6 @@ xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) } xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay); - __glXRelease(xdri_dpy->dpyPriv); free(xdri_dpy); dpy->DriverData = NULL; @@ -417,19 +419,47 @@ xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, } -static EGLBoolean -xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +/** + * Destroy a context. + */ +static void +destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) { struct xdri_egl_display *xdri_dpy = lookup_display(dpy); struct xdri_egl_context *xdri_ctx = lookup_context(ctx); - if (!_eglIsContextBound(ctx)) { - xdri_ctx->driContext->destroyContext(xdri_ctx->driContext, - xdri_dpy->psc, xdri_dpy->dpy); - free(xdri_ctx->dummy_gc); - free(xdri_ctx); - } + /* FIXME a context might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); + xdri_ctx->driContext->destroyContext(xdri_ctx->driContext, + xdri_dpy->psc, xdri_dpy->dpy); + free(xdri_ctx->dummy_gc); + free(xdri_ctx); +} + + +/** + * Destroy a surface. + */ +static void +destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) +{ + struct xdri_egl_surface *xdri_surf = lookup_surface(surf); + + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); + + xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable); + free(xdri_surf); +} + + +static EGLBoolean +xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + if (!_eglIsContextBound(ctx)) + destroy_context(dpy, ctx); return EGL_TRUE; } @@ -441,13 +471,19 @@ static EGLBoolean xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, _EGLSurface *r, _EGLContext *context) { + struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv); struct xdri_egl_context *xdri_ctx = lookup_context(context); struct xdri_egl_surface *draw = lookup_surface(d); struct xdri_egl_surface *read = lookup_surface(r); - if (!_eglMakeCurrent(drv, dpy, d, r, context)) + /* bind the new context and return the "orphaned" one */ + if (!_eglBindContext(&context, &d, &r)) return EGL_FALSE; + /* flush before context switch */ + if (context && xdri_driver->FlushCurrentContext) + xdri_driver->FlushCurrentContext(); + /* the symbol is defined in libGL.so */ _glapi_check_multithread(); @@ -458,14 +494,18 @@ xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, return EGL_FALSE; } } - else { - _EGLContext *old = _eglGetCurrentContext(); - if (old) { - xdri_ctx = lookup_context(old); - xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); - } + else if (context) { + xdri_ctx = lookup_context(context); + xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); } + if (context && !_eglIsContextLinked(context)) + destroy_context(dpy, context); + if (d && !_eglIsSurfaceLinked(d)) + destroy_surface(dpy, d); + if (r && r != d && !_eglIsSurfaceLinked(r)) + destroy_surface(dpy, r); + return EGL_TRUE; } @@ -475,7 +515,8 @@ xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, */ static _EGLSurface * xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - NativeWindowType window, const EGLint *attrib_list) + EGLNativeWindowType window, + const EGLint *attrib_list) { struct xdri_egl_display *xdri_dpy = lookup_display(dpy); struct xdri_egl_config *xdri_config = lookup_config(conf); @@ -529,13 +570,8 @@ xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf static EGLBoolean xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { - struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - - if (!_eglIsSurfaceBound(&xdri_surf->Base)) { - xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable); - free(xdri_surf); - } - + if (!_eglIsSurfaceBound(surface)) + destroy_surface(dpy, surface); return EGL_TRUE; } @@ -559,9 +595,14 @@ xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, static EGLBoolean xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) { + struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv); struct xdri_egl_display *xdri_dpy = lookup_display(dpy); struct xdri_egl_surface *xdri_surf = lookup_surface(draw); + /* swapBuffers does not flush commands */ + if (draw->CurrentContext && xdri_driver->FlushCurrentContext) + xdri_driver->FlushCurrentContext(); + xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable, 0, 0, 0); return EGL_TRUE; @@ -606,5 +647,9 @@ _eglMain(const char *args) xdri_drv->Base.Name = "X/DRI"; xdri_drv->Base.Unload = xdri_Unload; + /* we need a way to flush commands */ + xdri_drv->FlushCurrentContext = + (void (*)(void)) xdri_eglGetProcAddress(&xdri_drv->Base, "glFlush"); + return &xdri_drv->Base; } diff --git a/src/egl/drivers/xdri/glxinit.c b/src/egl/drivers/xdri/glxinit.c index 7775009394..ba6132788a 100644 --- a/src/egl/drivers/xdri/glxinit.c +++ b/src/egl/drivers/xdri/glxinit.c @@ -1,8 +1,10 @@ /** * GLX initialization. Code based on glxext.c, glx_query.c, and - * glcontextmodes.c under src/glx/x11/. The major difference is that no DRI - * related code here. + * glcontextmodes.c under src/glx/x11/. The major difference is that DRI + * related code is stripped out. * + * If the maintenance of this file takes too much time, we should consider + * refactoring glxext.c. */ #include <assert.h> @@ -31,8 +33,26 @@ typedef struct GLXGenericGetString static char *__glXExtensionName = GLX_EXTENSION_NAME; static XExtensionInfo *__glXExtensionInfo = NULL; -static /* const */ XExtensionHooks __glXExtensionHooks = { NULL }; -static +static int +__glXCloseDisplay(Display * dpy, XExtCodes * codes) +{ + return XextRemoveDisplay(__glXExtensionInfo, dpy); +} + +static /* const */ XExtensionHooks __glXExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + __glXCloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, __glXExtensionName, &__glXExtensionHooks, __GLX_NUMBER_EVENTS, NULL) @@ -180,6 +200,30 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv) priv->screenConfigs = NULL; } +/* +** Release the private memory referred to in a display private +** structure. The caller will free the extension structure. +*/ +static int +__glXFreeDisplayPrivate(XExtData * extension) +{ + __GLXdisplayPrivate *priv; + + priv = (__GLXdisplayPrivate *) extension->private_data; + FreeScreenConfigs(priv); + if (priv->serverGLXvendor) { + Xfree((char *) priv->serverGLXvendor); + priv->serverGLXvendor = 0x0; /* to protect against double free's */ + } + if (priv->serverGLXversion) { + Xfree((char *) priv->serverGLXversion); + priv->serverGLXversion = 0x0; /* to protect against double free's */ + } + + Xfree((char *) priv); + return 0; +} + /************************************************************************/ /* @@ -570,40 +614,40 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) return GL_TRUE; } -_X_HIDDEN void -__glXRelease(__GLXdisplayPrivate *dpyPriv) -{ - FreeScreenConfigs(dpyPriv); - - if (dpyPriv->serverGLXvendor) { - Xfree((char *) dpyPriv->serverGLXvendor); - dpyPriv->serverGLXvendor = NULL; - } - if (dpyPriv->serverGLXversion) { - Xfree((char *) dpyPriv->serverGLXversion); - dpyPriv->serverGLXversion = NULL; - } - - Xfree(dpyPriv); -} - _X_HIDDEN __GLXdisplayPrivate * __glXInitialize(Display * dpy) { XExtDisplayInfo *info = __glXFindDisplay(dpy); + XExtData **privList, *private, *found; __GLXdisplayPrivate *dpyPriv; + XEDataObject dataObj; int major, minor; if (!XextHasExtension(info)) return NULL; + /* See if a display private already exists. If so, return it */ + dataObj.display = dpy; + privList = XEHeadOfExtensionList(dataObj); + found = XFindOnExtensionList(privList, info->codes->extension); + if (found) + return (__GLXdisplayPrivate *) found->private_data; + /* See if the versions are compatible */ if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) return NULL; + /* + ** Allocate memory for all the pieces needed for this buffer. + */ + private = (XExtData *) Xmalloc(sizeof(XExtData)); + if (!private) + return NULL; dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); - if (!dpyPriv) + if (!dpyPriv) { + Xfree(private); return NULL; + } /* ** Init the display private and then read in the screen config @@ -619,8 +663,20 @@ __glXInitialize(Display * dpy) if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { Xfree(dpyPriv); + Xfree(private); return NULL; } + /* + ** Fill in the private structure. This is the actual structure that + ** hangs off of the Display structure. Our private structure is + ** referred to by this structure. Got that? + */ + private->number = info->codes->extension; + private->next = 0; + private->free_private = __glXFreeDisplayPrivate; + private->private_data = (char *) dpyPriv; + XAddToExtensionList(privList, private); + return dpyPriv; } diff --git a/src/egl/drivers/xdri/glxinit.h b/src/egl/drivers/xdri/glxinit.h index 57206e627b..1cc7c460fe 100644 --- a/src/egl/drivers/xdri/glxinit.h +++ b/src/egl/drivers/xdri/glxinit.h @@ -8,7 +8,4 @@ extern void _gl_context_modes_destroy(__GLcontextModes * modes); -extern void -__glXRelease(__GLXdisplayPrivate *dpyPriv); - #endif /* GLXINIT_INCLUDED */ 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 26e0602453..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,9 +729,7 @@ 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++) { @@ -978,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(); @@ -994,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 080f2155e3..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,7 +38,7 @@ 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); @@ -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 4d149603ae..b974e40cce 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" @@ -224,7 +222,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, @@ -773,7 +772,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/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..d0c6b1b64c 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -5,7 +5,7 @@ #include "eglcontext.h" #include "egldisplay.h" #include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "eglsurface.h" @@ -58,20 +58,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 +126,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) - return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - if (draw->Config != ctx->Config || read->Config != ctx->Config) + /* this is easy */ + if (!ctx) { + if (draw || read) 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 +296,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..ebb50aa60e 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; @@ -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); @@ -65,4 +68,64 @@ _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. + */ +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..a19dcf4096 100644 --- a/src/egl/main/eglcurrent.c +++ b/src/egl/main/eglcurrent.c @@ -1,10 +1,10 @@ #include <stdlib.h> #include <string.h> -#include "eglcurrent.h" +#include "eglglobals.h" #include "eglcontext.h" #include "egllog.h" #include "eglmutex.h" -#include "eglglobals.h" +#include "eglcurrent.h" /* This should be kept in sync with _eglInitThreadInfo() */ @@ -227,50 +227,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..5897372fc5 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -10,7 +10,7 @@ #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" -#include "eglstring.h" +#include "eglcurrent.h" #include "eglmutex.h" #include "egllog.h" @@ -26,12 +26,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 +46,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 +114,7 @@ _eglUnlinkDisplay(_EGLDisplay *dpy) * linked displays. */ _EGLDisplay * -_eglFindDisplay(NativeDisplayType nativeDisplay) +_eglFindDisplay(EGLNativeDisplayType nativeDisplay) { _EGLDisplay *dpy; @@ -171,29 +141,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 +180,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 +211,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..b04b094d84 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,8 @@ struct _egl_extensions { EGLBoolean MESA_screen_surface; EGLBoolean MESA_copy_context; + EGLBoolean KHR_image_base; + EGLBoolean KHR_image_pixmap; char String[_EGL_MAX_EXTENSIONS_LEN]; }; @@ -26,7 +50,7 @@ struct _egl_display EGLNativeDisplayType NativeDisplay; - const char *DriverName; + EGLBoolean Initialized; /**< True if the display is initialized */ _EGLDriver *Driver; void *DriverData; /* private to driver */ @@ -48,9 +72,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 +81,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 +94,7 @@ _eglUnlinkDisplay(_EGLDisplay *dpy); extern _EGLDisplay * -_eglFindDisplay(NativeDisplayType nativeDisplay); +_eglFindDisplay(EGLNativeDisplayType nativeDisplay); PUBLIC void @@ -86,22 +105,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 +112,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 +128,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 +171,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..df36369ac2 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -13,15 +13,19 @@ #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" +#include "eglcurrent.h" #include "egllog.h" #include "eglmisc.h" #include "eglmode.h" #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> #endif @@ -49,10 +53,31 @@ close_library(HMODULE lib) } -#elif defined(_EGL_PLATFORM_X) +static const char * +library_suffix(void) +{ + return "dll"; +} + + +static EGLBoolean +make_library_path(char *buf, unsigned int size, const char *name) +{ + EGLBoolean need_suffix; + const char *suffix = ".dll"; + int ret; + + need_suffix = (strchr(name, '.') == NULL); + ret = snprintf(buf, size, "%s%s", name, (need_suffix) ? suffix : ""); + + return ((unsigned int) ret < size); +} + +#elif defined(_EGL_PLATFORM_POSIX) -static const char DefaultDriverName[] = "egl_softpipe"; + +static const char DefaultDriverName[] = "egl_glx"; typedef void * lib_handle; @@ -68,6 +93,32 @@ close_library(void *lib) dlclose(lib); } + +static const char * +library_suffix(void) +{ + return "so"; +} + + +static EGLBoolean +make_library_path(char *buf, unsigned int size, const char *name) +{ + EGLBoolean need_dir, need_suffix; + const char *suffix = ".so"; + int ret; + + need_dir = (strchr(name, '/') == NULL); + need_suffix = (strchr(name, '.') == NULL); + + ret = snprintf(buf, size, "%s%s%s", + (need_dir) ? _EGL_DRIVER_SEARCH_DIR"/" : "", name, + (need_suffix) ? suffix : ""); + + return ((unsigned int) ret < size); +} + + #else /* _EGL_PLATFORM_NO_OS */ static const char DefaultDriverName[] = "builtin"; @@ -86,67 +137,29 @@ 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) +static EGLBoolean +make_library_path(char *buf, unsigned int size, const char *name) { - 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 + int ret = snprintf(buf, size, name); + return ((unsigned int) ret < size); +} - 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; +#endif + - 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 +181,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 +221,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 +246,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,93 +267,182 @@ _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]; - - /* display specifies a driver */ - if (dpy->DriverName) { - if (strcmp(dpy->DriverName, drv->Name) == 0) - return drv; - } - else if (drv->Probe) { - if (drv->Probe(drv, dpy)) - return drv; - } - else { - if (!defaultDriver) - defaultDriver = drv; + 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 defaultDriver; + return best_drv; } /** - * Load a driver and save it. + * Preload a user driver. + * + * A user driver can be specified by EGL_DRIVER. */ -const char * -_eglPreloadDriver(_EGLDisplay *dpy) +static EGLBoolean +_eglPreloadUserDriver(void) { - char *path, *args; +#if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS) _EGLDriver *drv; - EGLint i; + char path[1024]; + char *env; - path = _eglChooseDriver(dpy, &args); - if (!path) - return NULL; + env = getenv("EGL_DRIVER"); + if (!env) + return EGL_FALSE; - 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 (!make_library_path(path, sizeof(path), env)) + return EGL_FALSE; - drv = _eglLoadDriver(path, args); - if (!drv) - return NULL; + drv = _eglLoadDriver(path, NULL); + if (!drv) { + _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver"); + return EGL_FALSE; + } _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; - return drv->Name; + return EGL_TRUE; +#else /* _EGL_PLATFORM_POSIX || _EGL_PLATFORM_WINDOWS */ + return EGL_FALSE; +#endif } /** - * 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; +#if defined(_EGL_PLATFORM_POSIX) + const char *dpy, *suffix; + char path[1024], prefix[32]; + DIR *dirp; + struct dirent *dirent; + + dpy = getenv("EGL_DISPLAY"); + if (!dpy || !dpy[0]) + dpy = _EGL_DEFAULT_DISPLAY; + if (!dpy || !dpy[0]) + return EGL_FALSE; + + snprintf(prefix, sizeof(prefix), "egl_%s_", dpy); + suffix = library_suffix(); + + dirp = opendir(_EGL_DRIVER_SEARCH_DIR); + if (!dirp) + return EGL_FALSE; + + while ((dirent = readdir(dirp))) { + _EGLDriver *drv; + const char *p; + + /* match the prefix */ + if (strncmp(dirent->d_name, prefix, strlen(prefix)) != 0) + continue; + + /* match the suffix */ + p = strrchr(dirent->d_name, '.'); + if ((p && !suffix) || (!p && suffix)) + continue; + else if (p && suffix && strcmp(p + 1, suffix) != 0) + continue; + + snprintf(path, sizeof(path), + _EGL_DRIVER_SEARCH_DIR"/%s", dirent->d_name); + + drv = _eglLoadDriver(path, NULL); + if (drv) + _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; + } + + closedir(dirp); + + return (_eglGlobal.NumDrivers > 0); +#else /* _EGL_PLATFORM_POSIX */ + return EGL_FALSE; +#endif } /** - * Close a preloaded driver. + * Preload the default driver. */ -EGLBoolean -_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy) +static EGLBoolean +_eglPreloadDefaultDriver(void) { + _EGLDriver *drv; + char path[1024]; + + if (!make_library_path(path, sizeof(path), DefaultDriverName)) + return EGL_FALSE; + + drv = _eglLoadDriver(path, NULL); + if (!drv) + return EGL_FALSE; + + _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; + return EGL_TRUE; } /** + * Preload drivers. + * + * This function loads the driver modules and creates the corresponding + * _EGLDriver objects. + */ +EGLBoolean +_eglPreloadDrivers(void) +{ + EGLBoolean loaded; + + /* already preloaded */ + if (_eglGlobal.NumDrivers) + return EGL_TRUE; + + loaded = (_eglPreloadUserDriver() || + _eglPreloadDisplayDrivers() || + _eglPreloadDefaultDriver()); + + return loaded; +} + + +/** * Unload preloaded drivers. */ void @@ -360,20 +472,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 +526,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..5149acd964 100644 --- a/src/egl/main/egldriver.h +++ b/src/egl/main/egldriver.h @@ -6,6 +6,9 @@ #include "eglapi.h" +typedef _EGLDriver *(*_EGLMain_t)(const char *args); + + /** * Base class for device drivers. */ @@ -16,9 +19,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 +45,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..5044112fa8 --- /dev/null +++ b/src/egl/main/eglimage.c @@ -0,0 +1,51 @@ +#include <assert.h> + +#include "eglimage.h" +#include "egldisplay.h" + + +#ifdef EGL_KHR_image_base + + +EGLBoolean +_eglInitImage(_EGLDriver *drv, _EGLImage *img, const EGLint *attrib_list) +{ + EGLint i; + + img->Preserved = EGL_FALSE; + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + case EGL_IMAGE_PRESERVED_KHR: + i++; + img->Preserved = attrib_list[i]; + break; + default: + /* not an error */ + break; + } + } + + 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..43107c23e9 --- /dev/null +++ b/src/egl/main/eglimage.h @@ -0,0 +1,94 @@ +#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; +}; + + +PUBLIC EGLBoolean +_eglInitImage(_EGLDriver *drv, _EGLImage *img, 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..907a057b44 100644 --- a/src/egl/main/eglmisc.c +++ b/src/egl/main/eglmisc.c @@ -33,7 +33,7 @@ #include <assert.h> #include <string.h> -#include "eglglobals.h" +#include "eglcurrent.h" #include "eglmisc.h" #include "egldisplay.h" @@ -54,6 +54,14 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy) strcat(exts, "EGL_MESA_screen_surface "); if (dpy->Extensions.MESA_copy_context) strcat(exts, "EGL_MESA_copy_context "); + + if (dpy->Extensions.KHR_image_base) + strcat(exts, "EGL_KHR_image_base "); + if (dpy->Extensions.KHR_image_pixmap) + strcat(exts, "EGL_KHR_image_pixmap "); + if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap) + strcat(exts, "EGL_KHR_image "); + assert(strlen(exts) < _EGL_MAX_EXTENSIONS_LEN); } 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..aa2da9dd09 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" @@ -237,7 +236,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 */ @@ -315,76 +314,34 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, /** - * 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; } diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index dacdf7e63c..0d64d20dd4 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -3,6 +3,7 @@ #include "egltypedefs.h" +#include "egldisplay.h" /** @@ -10,13 +11,11 @@ */ 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; @@ -26,8 +25,8 @@ struct _egl_surface EGLint MipmapTexture, MipmapLevel; EGLint SwapInterval; - /* If type == EGL_SCREEN_BIT: */ - EGLint VisibleRefCount; /* number of screens I'm displayed on */ + /* True if the surface is bound to an OpenGL ES texture */ + EGLBoolean BoundToTexture; #ifdef EGL_VERSION_1_2 EGLint SwapBehavior; /* one of EGL_BUFFER_PRESERVED/DESTROYED */ @@ -50,7 +49,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 +57,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 +99,72 @@ _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. */ 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. + */ +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 */ |