From adbff7e977c7c768e752a24fb643d68bdf961bfe Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 22 Apr 2005 21:09:39 +0000 Subject: initial EGL code --- src/egl/main/Makefile | 64 +++++++ src/egl/main/eglapi.c | 462 +++++++++++++++++++++++++++++++++++++++++++++ src/egl/main/eglconfig.c | 286 ++++++++++++++++++++++++++++ src/egl/main/eglconfig.h | 56 ++++++ src/egl/main/eglcontext.c | 226 ++++++++++++++++++++++ src/egl/main/eglcontext.h | 64 +++++++ src/egl/main/egldisplay.c | 71 +++++++ src/egl/main/egldisplay.h | 39 ++++ src/egl/main/egldriver.c | 226 ++++++++++++++++++++++ src/egl/main/egldriver.h | 141 ++++++++++++++ src/egl/main/eglglobals.c | 51 +++++ src/egl/main/eglglobals.h | 38 ++++ src/egl/main/eglhash.c | 347 ++++++++++++++++++++++++++++++++++ src/egl/main/eglhash.h | 39 ++++ src/egl/main/eglmode.c | 130 +++++++++++++ src/egl/main/eglmode.h | 41 ++++ src/egl/main/eglscreen.c | 259 +++++++++++++++++++++++++ src/egl/main/eglscreen.h | 61 ++++++ src/egl/main/eglsurface.c | 246 ++++++++++++++++++++++++ src/egl/main/eglsurface.h | 96 ++++++++++ src/egl/main/egltypedefs.h | 28 +++ 21 files changed, 2971 insertions(+) create mode 100644 src/egl/main/Makefile create mode 100644 src/egl/main/eglapi.c create mode 100644 src/egl/main/eglconfig.c create mode 100644 src/egl/main/eglconfig.h create mode 100644 src/egl/main/eglcontext.c create mode 100644 src/egl/main/eglcontext.h create mode 100644 src/egl/main/egldisplay.c create mode 100644 src/egl/main/egldisplay.h create mode 100644 src/egl/main/egldriver.c create mode 100644 src/egl/main/egldriver.h create mode 100644 src/egl/main/eglglobals.c create mode 100644 src/egl/main/eglglobals.h create mode 100644 src/egl/main/eglhash.c create mode 100644 src/egl/main/eglhash.h create mode 100644 src/egl/main/eglmode.c create mode 100644 src/egl/main/eglmode.h create mode 100644 src/egl/main/eglscreen.c create mode 100644 src/egl/main/eglscreen.h create mode 100644 src/egl/main/eglsurface.c create mode 100644 src/egl/main/eglsurface.h create mode 100644 src/egl/main/egltypedefs.h (limited to 'src/egl/main') diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile new file mode 100644 index 0000000000..4bb1ffc9e8 --- /dev/null +++ b/src/egl/main/Makefile @@ -0,0 +1,64 @@ +# src/egl/main/Makefile + +TOP = ../../.. +include $(TOP)/configs/current + + +INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi + +HEADERS = \ + eglconfig.h \ + eglcontext.h \ + egldisplay.h \ + egldriver.h \ + eglglobals.h \ + eglhash.h \ + eglmode.h \ + eglscreen.h \ + eglsurface.h + +SOURCES = \ + eglapi.c \ + eglconfig.c \ + eglcontext.c \ + egldisplay.c \ + egldriver.c \ + eglglobals.c \ + eglhash.c \ + eglmode.c \ + eglscreen.c \ + eglsurface.c + +OBJECTS = $(SOURCES:.c=.o) + + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + + + +default: depend library + + +# EGL Library +library: $(LIB_DIR)/libEGL.so + +$(LIB_DIR)/libEGL.so: $(OBJECTS) + $(TOP)/bin/mklib -o EGL -major 1 -minor 0 \ + -install $(LIB_DIR) -ldl $(OBJECTS) + + + +clean: + rm -f *.o *.so* + rm -f core.* + + +depend: $(SOURCES) $(HEADERS) + @ echo "running $(MKDEP)" + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ + $(SOURCES) $(HEADERS) > /dev/null + +include depend +# DO NOT DELETE diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c new file mode 100644 index 0000000000..d9c8845aa4 --- /dev/null +++ b/src/egl/main/eglapi.c @@ -0,0 +1,462 @@ +/** + * Public EGL API entrypoints + * + * Generally, we use the EGLDisplay parameter as a key to lookup the + * appropriate device driver handle, then jump though the driver's + * dispatch table to handle the function. + * + * That allows us the option of supporting multiple, simultaneous, + * heterogeneous hardware devices in the future. + * + * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are + * opaque handles implemented with 32-bit unsigned integers. + * It's up to the driver function or fallback function to look up the + * handle and get an object. + * By using opaque handles, we leave open the possibility of having + * indirect rendering in the future, like GLX. + * + * + * Notes on naming conventions: + * + * eglFooBar - public EGL function + * EGL_FOO_BAR - public EGL token + * EGLDatatype - public EGL datatype + * + * _eglFooBar - private EGL function + * _EGLDatatype - private EGL datatype, typedef'd struct + * _egl_struct - private EGL struct, non-typedef'd + * + */ + + + +#include +#include +/**#include "glapi.h"**/ +#include "eglcontext.h" +#include "egldisplay.h" +#include "egltypedefs.h" +#include "eglglobals.h" +#include "egldriver.h" +#include "eglsurface.h" + + + +/** + * NOTE: displayName is treated as a string in _eglChooseDriver()!!! + * This will probably change! + * See _eglChooseDriver() for details! + */ +EGLDisplay APIENTRY +eglGetDisplay(NativeDisplayType displayName) +{ + _EGLDisplay *dpy; + _eglInitGlobals(); + dpy = _eglNewDisplay(displayName); + if (dpy) + return dpy->Handle; + else + return EGL_NO_DISPLAY; +} + + +EGLBoolean APIENTRY +eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + if (dpy) { + _EGLDriver *drv = _eglChooseDriver(dpy); + if (drv) + return drv->Initialize(drv, dpy, major, minor); + } + return EGL_FALSE; +} + + +EGLBoolean APIENTRY +eglTerminate(EGLDisplay dpy) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + if (drv) + return _eglCloseDriver(drv, dpy); + else + return EGL_FALSE; +} + + +const char * APIENTRY +eglQueryString(EGLDisplay dpy, EGLint name) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + if (drv) + return drv->QueryString(drv, dpy, name); + else + return NULL; +} + + +EGLBoolean APIENTRY +eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + /* XXX check drv for null in remaining functions */ + return drv->GetConfigs(drv, dpy, configs, config_size, num_config); +} + + +EGLBoolean APIENTRY +eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config); +} + + +EGLBoolean APIENTRY +eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->GetConfigAttrib(drv, dpy, config, attribute, value); +} + + +EGLContext APIENTRY +eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->CreateContext(drv, dpy, config, share_list, attrib_list); +} + + +EGLBoolean APIENTRY +eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->DestroyContext(drv, dpy, ctx); +} + + +EGLBoolean APIENTRY +eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->MakeCurrent(drv, dpy, draw, read, ctx); +} + + +EGLBoolean APIENTRY +eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QueryContext(drv, dpy, ctx, attribute, value); +} + + +EGLSurface APIENTRY +eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->CreateWindowSurface(drv, dpy, config, window, attrib_list); +} + + +EGLSurface APIENTRY +eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list); +} + + +EGLSurface APIENTRY +eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->CreatePbufferSurface(drv, dpy, config, attrib_list); +} + + +EGLBoolean APIENTRY +eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->DestroySurface(drv, dpy, surface); +} + + +EGLBoolean APIENTRY +eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->QuerySurface(drv, dpy, surface, attribute, value); +} + + +EGLBoolean APIENTRY +eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->SurfaceAttrib(drv, dpy, surface, attribute, value); +} + + +EGLBoolean APIENTRY +eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->BindTexImage(drv, dpy, surface, buffer); +} + + +EGLBoolean APIENTRY +eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->ReleaseTexImage(drv, dpy, surface, buffer); +} + + +EGLBoolean APIENTRY +eglSwapInterval(EGLDisplay dpy, EGLint interval) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->SwapInterval(drv, dpy, interval); +} + + +EGLBoolean APIENTRY +eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->SwapBuffers(drv, dpy, draw); +} + + +EGLBoolean APIENTRY +eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->CopyBuffers(drv, dpy, surface, target); +} + + +EGLBoolean APIENTRY +eglWaitGL(void) +{ + EGLDisplay dpy = eglGetCurrentDisplay(); + if (dpy != EGL_NO_DISPLAY) { + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->WaitGL(drv, dpy); + } + else + return EGL_FALSE; +} + + +EGLBoolean APIENTRY +eglWaitNative(EGLint engine) +{ + EGLDisplay dpy = eglGetCurrentDisplay(); + if (dpy != EGL_NO_DISPLAY) { + _EGLDriver *drv = _eglLookupDriver(dpy); + return drv->WaitNative(drv, dpy, engine); + } + else + return EGL_FALSE; +} + + +EGLDisplay APIENTRY +eglGetCurrentDisplay(void) +{ + _EGLDisplay *dpy = _eglGetCurrentDisplay(); + if (dpy) + return dpy->Handle; + else + return EGL_NO_DISPLAY; +} + + +EGLContext APIENTRY +eglGetCurrentContext(void) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + if (ctx) + return ctx->Handle; + else + return EGL_NO_CONTEXT; +} + + +EGLSurface APIENTRY +eglGetCurrentSurface(EGLint readdraw) +{ + _EGLSurface *s = _eglGetCurrentSurface(readdraw); + if (s) + return s->Handle; + else + return EGL_NO_SURFACE; +} + + +EGLint APIENTRY +eglGetError(void) +{ + EGLint e = _eglGlobal.LastError; + _eglGlobal.LastError = EGL_SUCCESS; + return e; +} + + +void (* APIENTRY eglGetProcAddress(const char *procname))() +{ + typedef void (*genericFunc)(); + struct name_function { + const char *name; + _EGLProc function; + }; + static struct name_function egl_functions[] = { + /* alphabetical order */ + { "eglBindTexImage", (_EGLProc) eglBindTexImage }, + { "eglChooseConfig", (_EGLProc) eglChooseConfig }, + { "eglCopyBuffers", (_EGLProc) eglCopyBuffers }, + { "eglCreateContext", (_EGLProc) eglCreateContext }, + { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface }, + { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface }, + { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface }, + { "eglDestroyContext", (_EGLProc) eglDestroyContext }, + { "eglDestroySurface", (_EGLProc) eglDestroySurface }, + { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib }, + { "eglGetConfigs", (_EGLProc) eglGetConfigs }, + { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext }, + { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay }, + { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface }, + { "eglGetDisplay", (_EGLProc) eglGetDisplay }, + { "eglGetError", (_EGLProc) eglGetError }, + { "eglGetProcAddress", (_EGLProc) eglGetProcAddress }, + { "eglInitialize", (_EGLProc) eglInitialize }, + { "eglMakeCurrent", (_EGLProc) eglMakeCurrent }, + { "eglQueryContext", (_EGLProc) eglQueryContext }, + { "eglQueryString", (_EGLProc) eglQueryString }, + { "eglQuerySurface", (_EGLProc) eglQuerySurface }, + { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage }, + { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib }, + { "eglSwapBuffers", (_EGLProc) eglSwapBuffers }, + { "eglSwapInterval", (_EGLProc) eglSwapInterval }, + { "eglTerminate", (_EGLProc) eglTerminate }, + { "eglWaitGL", (_EGLProc) eglWaitGL }, + { "eglWaitNative", (_EGLProc) eglWaitNative }, + /* Extensions */ + { "eglShowSurfaceMESA", (_EGLProc) NULL }, + { "eglGetModesMESA", (_EGLProc) NULL }, + { NULL, NULL } + }; + EGLint i; + for (i = 0; egl_functions[i].name; i++) { + if (strcmp(egl_functions[i].name, procname) == 0) { + return (genericFunc) egl_functions[i].function; + } + } +#if 0 + /* XXX enable this code someday */ + return (genericFunc) _glapi_get_proc_address(procname); +#else + return NULL; +#endif +} + + +/* + * EGL_MESA_screen extension + */ + +EGLBoolean APIENTRY +eglChooseModeMESA(EGLDisplay dpy, EGLint screen_number, + const EGLint *attrib_list, EGLModeMESA *modes, + EGLint modes_size, EGLint *num_modes) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + if (drv) + return drv->ChooseModeMESA(drv, dpy, screen_number, attrib_list, modes, modes_size, num_modes); + else + return EGL_FALSE; +} + + +EGLBoolean APIENTRY +eglGetModesMESA(EGLDisplay dpy, EGLint screen_number, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + if (drv) + return drv->GetModesMESA(drv, dpy, screen_number, modes, mode_size, num_mode); + else + return EGL_FALSE; +} + + +EGLBoolean APIENTRY +eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value) +{ + _EGLDriver *drv = _eglLookupDriver(dpy); + if (drv) + return drv->GetModeAttribMESA(drv, dpy, mode, attribute, value); + else + return EGL_FALSE; +} + + +EGLSurface +eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglShowSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglScreenModeMESA(EGLDisplay dpy, EGLint screen_number, EGLModeMESA mode) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglScreenAttribsMESA(EGLDisplay dpy, EGLint screen, const EGLint *attrib_list) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglQueryDisplayMESA(EGLDisplay dpy, EGLint attribute, EGLint *value) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLint screen_number, EGLSurface *surface) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglQueryScreenModeMESA(EGLDisplay dpy, EGLint screen_number, EGLModeMESA *mode) +{ + return EGL_FALSE; +} + + +EGLBoolean +eglQueryScreenMESA( EGLDisplay dpy, EGLint screen_number, EGLint attribute, EGLint *value) +{ + return EGL_FALSE; +} + + diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c new file mode 100644 index 0000000000..765e2e3dbe --- /dev/null +++ b/src/egl/main/eglconfig.c @@ -0,0 +1,286 @@ +#include +#include +#include "eglconfig.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" + + +#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) + + +/** + * Init the given _EGLconfig to default values. + * \param id the configuration's ID. + */ +void +_eglInitConfig(_EGLConfig *config, EGLint id) +{ + memset(config, 0, sizeof(*config)); + config->Handle = id; + SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); + SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE); + SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE); + SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE); +} + + +/** + * Given an EGLConfig handle, return the corresponding _EGLConfig object. + */ +_EGLConfig * +_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config) +{ + EGLint i; + _EGLDisplay *disp = _eglLookupDisplay(dpy); + for (i = 0; i < disp->NumConfigs; i++) { + if (disp->Configs[i].Handle == config) { + return disp->Configs + i; + } + } + return NULL; +} + + + +/** + * Parse the attrib_list to fill in the fields of the given _egl_config + * Return EGL_FALSE if any errors, EGL_TRUE otherwise. + */ +EGLBoolean +_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list) +{ + EGLint i; + + /* XXX set all config attribs to EGL_DONT_CARE */ + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + EGLint k = attrib_list[i] - FIRST_ATTRIB; + if (k >= 0 && k < MAX_ATTRIBS) { + config->Attrib[k] = attrib_list[++i]; + } + else { + _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); + return EGL_FALSE; + } + } + return EGL_TRUE; +} + + +#define EXACT 1 +#define ATLEAST 2 +#define MASK 3 +#define SMALLER 4 +#define SPECIAL 5 +#define NONE 6 + +struct sort_info { + EGLint Attribute; + EGLint MatchCriteria; + EGLint SortOrder; +}; + +/* This encodes the info from Table 3.5 of the EGL spec, ordered by + * Sort Priority. + */ +static struct sort_info SortInfo[] = { + { EGL_CONFIG_CAVEAT, EXACT, SPECIAL }, + { EGL_RED_SIZE, ATLEAST, SPECIAL }, + { EGL_GREEN_SIZE, ATLEAST, SPECIAL }, + { EGL_BLUE_SIZE, ATLEAST, SPECIAL }, + { EGL_ALPHA_SIZE, ATLEAST, SPECIAL }, + { EGL_BUFFER_SIZE, ATLEAST, SMALLER }, + { EGL_SAMPLE_BUFFERS, ATLEAST, SMALLER }, + { EGL_SAMPLES, ATLEAST, SMALLER }, + { EGL_DEPTH_SIZE, ATLEAST, SMALLER }, + { EGL_STENCIL_SIZE, ATLEAST, SMALLER }, + { EGL_NATIVE_VISUAL_TYPE, EXACT, SPECIAL }, + { EGL_CONFIG_ID, EXACT, SMALLER }, + { EGL_BIND_TO_TEXTURE_RGB, EXACT, NONE }, + { EGL_BIND_TO_TEXTURE_RGBA, EXACT, NONE }, + { EGL_LEVEL, EXACT, NONE }, + { EGL_NATIVE_RENDERABLE, EXACT, NONE }, + { EGL_MAX_SWAP_INTERVAL, EXACT, NONE }, + { EGL_MIN_SWAP_INTERVAL, EXACT, NONE }, + { EGL_SURFACE_TYPE, MASK, NONE }, + { EGL_TRANSPARENT_TYPE, EXACT, NONE }, + { EGL_TRANSPARENT_RED_VALUE, EXACT, NONE }, + { EGL_TRANSPARENT_GREEN_VALUE, EXACT, NONE }, + { EGL_TRANSPARENT_BLUE_VALUE, EXACT, NONE }, + { 0, 0, 0 } +}; + + +/** + * Return EGL_TRUE if the attributes of c meet or exceed the minimums + * specified by min. + */ +EGLBoolean +_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min) +{ + EGLint i; + for (i = 0; SortInfo[i].Attribute != 0; i++) { + const EGLint mv = GET_CONFIG_ATTRIB(min, SortInfo[i].Attribute); + if (mv != EGL_DONT_CARE) { + const EGLint cv = GET_CONFIG_ATTRIB(c, SortInfo[i].Attribute); + if (SortInfo[i].MatchCriteria == EXACT) { + if (cv != mv) { + return EGL_FALSE; + } + } + else if (SortInfo[i].MatchCriteria == ATLEAST) { + if (cv < mv) { + return EGL_FALSE; + } + } + else { + assert(SortInfo[i].MatchCriteria == MASK); + if ((mv & cv) != mv) { + return EGL_FALSE; + } + } + } + } + return EGL_TRUE; +} + + +/** + * Compare configs 'a' and 'b' and return -1 if a belongs before b, + * 1 if a belongs after b, or 0 if they're equal. + */ +EGLint +_eglCompareConfigs(const _EGLConfig *a, const _EGLConfig *b) +{ + EGLint i; + for (i = 0; SortInfo[i].Attribute != 0; i++) { + const EGLint av = GET_CONFIG_ATTRIB(a, SortInfo[i].Attribute); + const EGLint bv = GET_CONFIG_ATTRIB(b, SortInfo[i].Attribute); + if (SortInfo[i].SortOrder == SMALLER) { + if (av < bv) + return -1; + else if (av > bv) + return 1; + /* else, continue examining attribute values */ + } + else if (SortInfo[i].SortOrder == SPECIAL) { + if (SortInfo[i].Attribute == EGL_CONFIG_CAVEAT) { + /* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */ + if (av < bv) + return -1; + else if (av > bv) + return 1; + } + else if (SortInfo[i].Attribute == EGL_RED_SIZE || + SortInfo[i].Attribute == EGL_GREEN_SIZE || + SortInfo[i].Attribute == EGL_BLUE_SIZE || + SortInfo[i].Attribute == EGL_ALPHA_SIZE) { + if (av > bv) + return -1; + else if (av < bv) + return 1; + } + else { + assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE); + if (av < bv) + return -1; + else if (av > bv) + return 1; + } + } + else { + assert(SortInfo[i].SortOrder == NONE); + /* continue examining attribute values */ + } + } + return 0; +} + + +/** + * Typical fallback routine for eglChooseConfig + */ +EGLBoolean +_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig criteria; + EGLint i; + + /* parse the attrib_list to initialize criteria */ + if (!_eglParseConfigAttribs(&criteria, attrib_list)) { + return EGL_FALSE; + } + + *num_config = 0; + for (i = 0; i < disp->NumConfigs; i++) { + const _EGLConfig *conf = disp->Configs + i; + if (_eglConfigQualifies(conf, &criteria)) { + if (*num_config < config_size) { + /* save */ + configs[*num_config] = conf->Handle; + (*num_config)++; + } + else { + break; + } + } + } + + /* XXX sort the list here */ + + return EGL_TRUE; +} + + +/** + * Fallback for eglGetConfigAttrib. + */ +EGLBoolean +_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +{ + const _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + const EGLint k = attribute - FIRST_ATTRIB; + if (k >= 0 && k < MAX_ATTRIBS) { + *value = conf->Attrib[k]; + return EGL_TRUE; + } + else { + _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); + return EGL_FALSE; + } +} + + +/** + * Fallback for eglGetConfigs. + */ +EGLBoolean +_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + + if (!drv->Initialized) { + _eglError(EGL_NOT_INITIALIZED, "eglGetConfigs"); + return EGL_FALSE; + } + + *num_config = MIN2(disp->NumConfigs, config_size); + if (configs) { + EGLint i; + for (i = 0; i < *num_config; i++) { + configs[i] = disp->Configs[i].Handle; + } + } + return EGL_TRUE; +} diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h new file mode 100644 index 0000000000..0bd0ce650a --- /dev/null +++ b/src/egl/main/eglconfig.h @@ -0,0 +1,56 @@ +#ifndef EGLCONFIG_INCLUDED +#define EGLCONFIG_INCLUDED + + +#include "egltypedefs.h" + + +#define MAX_ATTRIBS 100 +#define FIRST_ATTRIB EGL_BUFFER_SIZE + + +struct _egl_config +{ + EGLConfig Handle; /* the public/opaque handle which names this config */ + EGLint Attrib[MAX_ATTRIBS]; +}; + + + +#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL) +#define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB]) + + +extern void +_eglInitConfig(_EGLConfig *config, EGLint id); + + +extern _EGLConfig * +_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config); + + +extern EGLBoolean +_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list); + + +extern EGLBoolean +_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min); + + +extern EGLint +_eglCompareConfigs(const _EGLConfig *a, const _EGLConfig *b); + + +extern EGLBoolean +_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); + + +extern EGLBoolean +_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); + + +extern EGLBoolean +_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); + + +#endif /* EGLCONFIG_INCLUDED */ diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c new file mode 100644 index 0000000000..e7d833e24f --- /dev/null +++ b/src/egl/main/eglcontext.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "eglhash.h" +#include "eglsurface.h" + + +/** + * Initialize the given _EGLContext object to defaults. + */ +void +_eglInitContext(_EGLContext *ctx) +{ + /* just init to zer for now */ + memset(ctx, 0, sizeof(_EGLContext)); +} + + +/* + * Assign an EGLContext handle to the _EGLContext object then put it into + * the hash table. + */ +void +_eglSaveContext(_EGLContext *ctx) +{ + assert(ctx); + ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts); + _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx); +} + + +/** + * Remove the given _EGLContext object from the hash table. + */ +void +_eglRemoveContext(_EGLContext *ctx) +{ + _eglHashRemove(_eglGlobal.Contexts, ctx->Handle); +} + + +/** + * Return the _EGLContext object that corresponds to the given + * EGLContext handle. + */ +_EGLContext * +_eglLookupContext(EGLContext ctx) +{ + _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx); + return c; +} + + +/** + * Return the currently bound _EGLContext object, or NULL. + */ +_EGLContext * +_eglGetCurrentContext(void) +{ + /* XXX this should be per-thread someday */ + return _eglGlobal.CurrentContext; +} + + +/** + * Just a placeholder/demo function. Real driver will never use this! + */ +EGLContext +_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +{ + _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreateContext"); + return EGL_NO_CONTEXT; + } + + if (share_list != EGL_NO_CONTEXT) { + _EGLContext *shareCtx = _eglLookupContext(share_list); + if (!shareCtx) { + _eglError(EGL_BAD_CONTEXT, "eglCreateContext(share_list)"); + return EGL_NO_CONTEXT; + } + } + + return EGL_NO_CONTEXT; +} + + +/** + * Default fallback routine - drivers should usually override this. + */ +EGLBoolean +_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) +{ + _EGLContext *context = _eglLookupContext(ctx); + if (context) { + _eglHashRemove(_eglGlobal.Contexts, ctx); + if (context->IsBound) { + context->DeletePending = EGL_TRUE; + } + else { + free(context); + } + return EGL_TRUE; + } + else { + _eglError(EGL_BAD_CONTEXT, "eglDestroyContext"); + return EGL_TRUE; + } +} + + +EGLBoolean +_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +{ + _EGLContext *c = _eglLookupContext(ctx); + + (void) drv; + (void) dpy; + + if (!c) { + _eglError(EGL_BAD_CONTEXT, "eglQueryContext"); + return EGL_FALSE; + } + + switch (attribute) { + case EGL_CONFIG_ID: + *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID); + return EGL_TRUE; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); + return EGL_FALSE; + } +} + + +/** + * Drivers will typically call this to do the error checking and + * update the various IsBound and DeletePending flags. + * Then, the driver will do its device-dependent Make-Current stuff. + */ +EGLBoolean +_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, EGLSurface r, EGLContext context) +{ + _EGLContext *ctx = _eglLookupContext(context); + _EGLSurface *draw = _eglLookupSurface(d); + _EGLSurface *read = _eglLookupSurface(r); + + _EGLContext *oldContext = _eglGetCurrentContext(); + _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW); + _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ); + + /* error checking */ + if (ctx) { + if (draw == NULL || read == NULL) { + _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + return EGL_FALSE; + } + if (draw->Config != ctx->Config) { + _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + return EGL_FALSE; + } + if (read->Config != ctx->Config) { + _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + return EGL_FALSE; + } + } + + /* + * check if the old context or surfaces need to be deleted + */ + if (oldDrawSurface != NULL) { + oldDrawSurface->IsBound = EGL_FALSE; + if (oldDrawSurface->DeletePending) { + /* make sure we don't try to rebind a deleted surface */ + if (draw == oldDrawSurface || draw == oldReadSurface) { + draw = NULL; + } + /* really delete surface now */ + drv->DestroySurface(drv, dpy, oldDrawSurface->Handle); + } + } + if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) { + oldReadSurface->IsBound = EGL_FALSE; + if (oldReadSurface->DeletePending) { + /* make sure we don't try to rebind a deleted surface */ + if (read == oldDrawSurface || read == oldReadSurface) { + read = NULL; + } + /* really delete surface now */ + drv->DestroySurface(drv, dpy, oldReadSurface->Handle); + } + } + if (oldContext != NULL) { + oldContext->IsBound = EGL_FALSE; + if (oldContext->DeletePending) { + /* make sure we don't try to rebind a deleted context */ + if (ctx == oldContext) { + ctx = NULL; + } + /* really delete context now */ + drv->DestroyContext(drv, dpy, oldContext->Handle); + } + } + + if (ctx) { + /* check read/draw again, in case we deleted them above */ + if (draw == NULL || read == NULL) { + _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + return EGL_FALSE; + } + ctx->DrawSurface = draw; + ctx->ReadSurface = read; + ctx->IsBound = EGL_TRUE; + draw->IsBound = EGL_TRUE; + read->IsBound = EGL_TRUE; + } + + _eglGlobal.CurrentContext = ctx; + + return EGL_TRUE; +} diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h new file mode 100644 index 0000000000..0063507420 --- /dev/null +++ b/src/egl/main/eglcontext.h @@ -0,0 +1,64 @@ + +#ifndef EGLCONTEXT_INCLUDED +#define EGLCONTEXT_INCLUDED + + +#include "egltypedefs.h" + + +/** + * "Base" class for device driver contexts. + */ +struct _egl_context +{ + EGLContext Handle; /* The public/opaque handle which names this object */ + + _EGLDisplay *Display; /* who do I belong to? */ + + _EGLConfig *Config; + + _EGLSurface *DrawSurface; + _EGLSurface *ReadSurface; + + EGLBoolean IsBound; + EGLBoolean DeletePending; +}; + + +extern void +_eglInitContext(_EGLContext *ctx); + + +extern void +_eglSaveContext(_EGLContext *ctx); + + +extern void +_eglRemoveContext(_EGLContext *ctx); + + +extern _EGLContext * +_eglLookupContext(EGLContext ctx); + + +extern _EGLContext * +_eglGetCurrentContext(void); + + +extern EGLContext +_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); + + +extern EGLBoolean +_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx); + + +extern EGLBoolean +_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); + + +extern EGLBoolean +_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); + + +#endif /* EGLCONTEXT_INCLUDED */ diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c new file mode 100644 index 0000000000..0f298108c3 --- /dev/null +++ b/src/egl/main/egldisplay.c @@ -0,0 +1,71 @@ +#include +#include +#include "eglcontext.h" +#include "egldisplay.h" +#include "eglglobals.h" +#include "eglhash.h" + + +static char * +my_strdup(const char *s) +{ + int l = strlen(s); + char *s2 = malloc(l + 1); + strcpy(s2, s); + return s2; +} + + +/** + * We're assuming that the NativeDisplayType parameter is actually + * a string. + * Return a new _EGLDisplay object for the given displayName + */ +_EGLDisplay * +_eglNewDisplay(NativeDisplayType displayName) +{ + _EGLDisplay *dpy = (_EGLDisplay *) malloc(sizeof(_EGLDisplay)); + if (dpy) { + dpy->Handle = _eglHashGenKey(_eglGlobal.Displays); + _eglHashInsert(_eglGlobal.Displays, dpy->Handle, dpy); + if (displayName) + dpy->Name = my_strdup(displayName); + else + dpy->Name = NULL; + dpy->Driver = NULL; /* this gets set later */ + } + return dpy; +} + + +/** + * Return the _EGLDisplay object that corresponds to the given public/ + * opaque display handle. + */ +_EGLDisplay * +_eglLookupDisplay(EGLDisplay dpy) +{ + _EGLDisplay *d = (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, dpy); + return d; +} + + +_EGLDisplay * +_eglGetCurrentDisplay(void) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + if (ctx) + return ctx->Display; + else + return NULL; +} + + +void +_eglDeleteDisplay(_EGLDisplay *disp) +{ + /* XXX incomplete */ + free(disp->Configs); + free(disp); +} + diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h new file mode 100644 index 0000000000..a2831e65a4 --- /dev/null +++ b/src/egl/main/egldisplay.h @@ -0,0 +1,39 @@ +#ifndef EGLDISPLAY_INCLUDED +#define EGLDISPLAY_INCLUDED + + +#include "egltypedefs.h" + + +struct _egl_display +{ + EGLDisplay Handle; + + char *Name; + _EGLDriver *Driver; + + EGLint NumScreens; + _EGLScreen *Screens; /* array [NumScreens] */ + + EGLint NumConfigs; + _EGLConfig *Configs; /* array [NumConfigs] */ +}; + + +extern _EGLDisplay * +_eglNewDisplay(NativeDisplayType displayName); + + +extern _EGLDisplay * +_eglLookupDisplay(EGLDisplay dpy); + + +extern _EGLDisplay * +_eglGetCurrentDisplay(void); + + +extern void +_eglDeleteDisplay(_EGLDisplay *disp); + + +#endif /* EGLDISPLAY_INCLUDED */ diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c new file mode 100644 index 0000000000..5b65b80ea4 --- /dev/null +++ b/src/egl/main/egldriver.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "eglmode.h" +#include "eglsurface.h" + + +const char *DefaultDriverName = "demo"; + + +/** + * Choose and open/init the hardware driver for the given EGLDisplay. + * Previously, the EGLDisplay was created with _eglNewDisplay() where + * we recorded the user's NativeDisplayType parameter. + * + * Now we'll use the NativeDisplayType value. + * + * Currently, the native display value is treated as a string. + * If the first character is ':' we interpret it as a screen or card index + * number (i.e. ":0" or ":1", etc) + * Else if the first character is '!' we interpret it as specific driver name + * (i.e. "!r200" or "!i830". + */ +_EGLDriver * +_eglChooseDriver(EGLDisplay display) +{ + _EGLDisplay *dpy = _eglLookupDisplay(display); + _EGLDriver *drv; + const char *driverName = DefaultDriverName; + const char *name; + + assert(dpy); + + name = dpy->Name; + if (!name) { + /* use default */ + } + else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) { + printf("EGL: Use driver for screen: %s\n", name); + /* XXX probe hardware here to determine which driver to open */ + /* driverName = "something"; */ + } + else if (name[0] == '!') { + /* use specified driver name */ + driverName = name + 1; + printf("EGL: Use driver named %s\n", driverName); + } + else { + /* Maybe display was returned by XOpenDisplay? */ + printf("EGL: can't parse display pointer\n"); + } + + drv = _eglOpenDriver(dpy, driverName); + dpy->Driver = drv; + + return drv; +} + + +/** + * Open/load the named driver and call its bootstrap function: _eglMain(). + * \return new _EGLDriver object. + */ +_EGLDriver * +_eglOpenDriver(_EGLDisplay *dpy, const char *driverName) +{ + void *lib; + char driverFilename[1000]; + + /* XXX also prepend a directory path??? */ + sprintf(driverFilename, "%sdriver.so", driverName); + +#if 1 + lib = dlopen(driverFilename, RTLD_NOW); + if (lib) { + _EGLDriver *drv; + _EGLMain_t mainFunc; + + mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain"); + if (!mainFunc) { + fprintf(stderr, "_eglMain not found in %s", (char *) driverFilename); + dlclose(lib); + return NULL; + } + + drv = mainFunc(dpy); + if (!drv) { + dlclose(lib); + return NULL; + } + + drv->LibHandle = lib; + drv->Display = dpy; + return drv; + } + else { + fprintf(stderr, "EGLdebug: Error opening %s: %s\n", + driverFilename, dlerror()); + return NULL; + } +#else + /* use built-in driver */ + return _eglDefaultMain(d); +#endif +} + + +EGLBoolean +_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy) +{ + void *handle = drv->LibHandle; + EGLBoolean b; + fprintf(stderr, "EGL debug: Closing driver\n"); + + /* + * XXX check for currently bound context/surfaces and delete them? + */ + + b = drv->Terminate(drv, dpy); + dlclose(handle); + return b; +} + + +/** + * 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. + */ +void +_eglInitDriverFallbacks(_EGLDriver *drv) +{ + /* If a pointer is set to NULL, then the device driver _really_ has + * to implement it. + */ + drv->Initialize = NULL; + drv->Terminate = NULL; + + drv->GetConfigs = _eglGetConfigs; + drv->ChooseConfig = _eglChooseConfig; + drv->GetConfigAttrib = _eglGetConfigAttrib; + + drv->CreateContext = _eglCreateContext; + drv->DestroyContext = _eglDestroyContext; + drv->MakeCurrent = _eglMakeCurrent; + drv->QueryContext = _eglQueryContext; + + drv->CreateWindowSurface = _eglCreateWindowSurface; + drv->CreatePixmapSurface = _eglCreatePixmapSurface; + drv->CreatePbufferSurface = _eglCreatePbufferSurface; + drv->DestroySurface = _eglDestroySurface; + drv->QuerySurface = _eglQuerySurface; + drv->SurfaceAttrib = _eglSurfaceAttrib; + drv->BindTexImage = _eglBindTexImage; + drv->ReleaseTexImage = _eglReleaseTexImage; + drv->SwapInterval = _eglSwapInterval; + drv->SwapBuffers = _eglSwapBuffers; + drv->CopyBuffers = _eglCopyBuffers; + + drv->QueryString = _eglQueryString; + drv->WaitGL = _eglWaitGL; + drv->WaitNative = _eglWaitNative; + + /* EGL_MESA_screen */ + drv->GetModesMESA = _eglGetModesMESA; + drv->GetModeAttribMESA = _eglGetModeAttribMESA; +} + + +const char * +_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name) +{ + (void) drv; + (void) dpy; + switch (name) { + case EGL_VENDOR: + return "Mesa Project"; + case EGL_VERSION: + return "1.0"; + case EGL_EXTENSIONS: + return ""; + default: + _eglError(EGL_BAD_PARAMETER, "eglQueryString"); + return NULL; + } +} + + +EGLBoolean +_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy) +{ + /* just a placeholder */ + (void) drv; + (void) dpy; + return EGL_TRUE; +} + + +EGLBoolean +_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine) +{ + /* just a placeholder */ + (void) drv; + (void) dpy; + (void) engine; + return EGL_TRUE; +} diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h new file mode 100644 index 0000000000..4ced7941d3 --- /dev/null +++ b/src/egl/main/egldriver.h @@ -0,0 +1,141 @@ +#ifndef EGLDRIVER_INCLUDED +#define EGLDRIVER_INCLUDED + + +#include "egltypedefs.h" + + +/* driver funcs */ +typedef EGLBoolean (*Initialize_t)(_EGLDriver *, EGLDisplay dpy, EGLint *major, EGLint *minor); +typedef EGLBoolean (*Terminate_t)(_EGLDriver *, EGLDisplay dpy); + +/* config funcs */ +typedef EGLBoolean (*GetConfigs_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +typedef EGLBoolean (*ChooseConfig_t)(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); + +/* 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); +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 (*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); +typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); +typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); +typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint interval); +typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw); +typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target); + +/* misc funcs */ +typedef const char *(*QueryString_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint name); +typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, EGLDisplay dpy); +typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint engine); + + +/* EGL_MESA_screen extension */ +typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes); +typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode); +typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value); + + + + +/** + * Base class for device drivers. + */ +struct _egl_driver +{ + EGLBoolean Initialized; /* set by driver after initialized */ + + void *LibHandle; /* dlopen handle */ + + _EGLDisplay *Display; + + int ABIversion; + int APImajor, APIminor; /* returned through eglInitialize */ + + /* + * The API dispatcher jumps through these functions + */ + Initialize_t Initialize; + Terminate_t Terminate; + + GetConfigs_t GetConfigs; + ChooseConfig_t ChooseConfig; + GetConfigAttrib_t GetConfigAttrib; + + CreateContext_t CreateContext; + DestroyContext_t DestroyContext; + MakeCurrent_t MakeCurrent; + QueryContext_t QueryContext; + + CreateWindowSurface_t CreateWindowSurface; + CreatePixmapSurface_t CreatePixmapSurface; + CreatePbufferSurface_t CreatePbufferSurface; + DestroySurface_t DestroySurface; + QuerySurface_t QuerySurface; + SurfaceAttrib_t SurfaceAttrib; + BindTexImage_t BindTexImage; + ReleaseTexImage_t ReleaseTexImage; + SwapInterval_t SwapInterval; + SwapBuffers_t SwapBuffers; + CopyBuffers_t CopyBuffers; + + QueryString_t QueryString; + WaitGL_t WaitGL; + WaitNative_t WaitNative; + + /* EGL_MESA_screen extension */ + ChooseModeMESA_t ChooseModeMESA; + GetModesMESA_t GetModesMESA; + GetModeAttribMESA_t GetModeAttribMESA; +}; + + + + +extern _EGLDriver * +_eglDefaultMain(NativeDisplayType d); + + +extern _EGLDriver * +_eglChooseDriver(EGLDisplay dpy); + + +extern _EGLDriver * +_eglOpenDriver(_EGLDisplay *dpy, const char *driverName); + + +extern EGLBoolean +_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy); + + +extern _EGLDriver * +_eglLookupDriver(EGLDisplay d); + + +extern void +_eglInitDriverFallbacks(_EGLDriver *drv); + + +extern const char * +_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name); + + +extern EGLBoolean +_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy); + + +extern EGLBoolean +_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine); + + + +#endif /* EGLDRIVER_INCLUDED */ diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c new file mode 100644 index 0000000000..102e550620 --- /dev/null +++ b/src/egl/main/eglglobals.c @@ -0,0 +1,51 @@ +#include +#include "eglglobals.h" + + +struct _egl_global _eglGlobal = { EGL_FALSE }; + + +/** + * Init the fields in the _eglGlobal struct + * May be safely called more than once. + */ +void +_eglInitGlobals(void) +{ + if (!_eglGlobal.Initialized) { + _eglGlobal.Displays = _eglNewHashTable(); + _eglGlobal.Contexts = _eglNewHashTable(); + _eglGlobal.Surfaces = _eglNewHashTable(); + _eglGlobal.CurrentContext = EGL_NO_CONTEXT; + _eglGlobal.LastError = EGL_SUCCESS; + _eglGlobal.Initialized = EGL_TRUE; + } +} + + +/** + * Should call this via an atexit handler. + */ +void +_eglDestroyGlobals(void) +{ + /* XXX TODO walk over table entries, deleting each */ + _eglDeleteHashTable(_eglGlobal.Displays); + _eglDeleteHashTable(_eglGlobal.Contexts); + _eglDeleteHashTable(_eglGlobal.Surfaces); +} + + + +/** + * Record EGL error code. + */ +void +_eglError(EGLint errCode, const char *msg) +{ + if (_eglGlobal.LastError == EGL_SUCCESS) { + _eglGlobal.LastError = errCode; + /* XXX temporary */ + fprintf(stderr, "EGL Error 0x%x in %s\n", errCode, msg); + } +} diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h new file mode 100644 index 0000000000..fbf2813f7a --- /dev/null +++ b/src/egl/main/eglglobals.h @@ -0,0 +1,38 @@ +#ifndef EGLGLOBALS_INCLUDED +#define EGLGLOBALS_INCLUDED + +#include "egltypedefs.h" +#include "eglhash.h" + + +struct _egl_global +{ + EGLBoolean Initialized; + + _EGLHashtable *Displays; + _EGLHashtable *Contexts; + _EGLHashtable *Surfaces; + + EGLint LastError; + + /* XXX this should be per-thread someday */ + _EGLContext *CurrentContext; +}; + + +extern struct _egl_global _eglGlobal; + + +extern void +_eglInitGlobals(void); + + +extern void +_eglDestroyGlobals(void); + + +extern void +_eglError(EGLint errCode, const char *msg); + + +#endif /* EGLGLOBALS_INCLUDED */ diff --git a/src/egl/main/eglhash.c b/src/egl/main/eglhash.c new file mode 100644 index 0000000000..8e3da2e906 --- /dev/null +++ b/src/egl/main/eglhash.c @@ -0,0 +1,347 @@ +/** + * \file hash.c + * Generic hash table. + * + * This code taken from Mesa and adapted. + */ + +#include +#include +#include +#include "eglhash.h" + + +#define TABLE_SIZE 1023 /**< Size of lookup table/array */ + +#define HASH_FUNC(K) ((K) % TABLE_SIZE) + + +/* + * Unfinished mutex stuff + */ + +typedef int _EGLMutex; + +static void +_eglInitMutex(_EGLMutex m) +{ +} + +static void +_eglDestroyMutex(_EGLMutex m) +{ +} + +static void +_eglLockMutex(_EGLMutex m) +{ +} + +static void +_eglUnlockMutex(_EGLMutex m) +{ +} + + + +typedef struct _egl_hashentry _EGLHashentry; + +struct _egl_hashentry +{ + EGLuint Key; /**< the entry's key */ + void *Data; /**< the entry's data */ + _EGLHashentry *Next; /**< pointer to next entry */ +}; + + +struct _egl_hashtable +{ + _EGLHashentry *Table[TABLE_SIZE]; /**< the lookup table */ + EGLuint MaxKey; /**< highest key inserted so far */ + _EGLMutex Mutex; /**< mutual exclusion lock */ +}; + + +/** + * Create a new hash table. + * + * \return pointer to a new, empty hash table. + */ +_EGLHashtable * +_eglNewHashTable(void) +{ + _EGLHashtable *table = (_EGLHashtable *) calloc(1, sizeof(_EGLHashtable)); + if (table) { + _eglInitMutex(table->Mutex); + table->MaxKey = 1; + } + return table; +} + + + +/** + * Delete a hash table. + * Frees each entry on the hash table and then the hash table structure itself. + * Note that the caller should have already traversed the table and deleted + * the objects in the table (i.e. We don't free the entries' data pointer). + * + * \param table the hash table to delete. + */ +void +_eglDeleteHashTable(_EGLHashtable *table) +{ + EGLuint i; + assert(table); + for (i = 0; i < TABLE_SIZE; i++) { + _EGLHashentry *entry = table->Table[i]; + while (entry) { + _EGLHashentry *next = entry->Next; + free(entry); + entry = next; + } + } + _eglDestroyMutex(table->Mutex); + free(table); +} + + + +/** + * Lookup an entry in the hash table. + * + * \param table the hash table. + * \param key the key. + * + * \return pointer to user's data or NULL if key not in table + */ +void * +_eglHashLookup(const _EGLHashtable *table, EGLuint key) +{ + EGLuint pos; + const _EGLHashentry *entry; + + assert(table); + + if (!key) + return NULL; + + pos = HASH_FUNC(key); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + return entry->Data; + } + entry = entry->Next; + } + return NULL; +} + + + +/** + * Insert a key/pointer pair into the hash table. + * If an entry with this key already exists we'll replace the existing entry. + * + * \param table the hash table. + * \param key the key (not zero). + * \param data pointer to user data. + */ +void +_eglHashInsert(_EGLHashtable *table, EGLuint key, void *data) +{ + /* search for existing entry with this key */ + EGLuint pos; + _EGLHashentry *entry; + + assert(table); + assert(key); + + _eglLockMutex(table->Mutex); + + if (key > table->MaxKey) + table->MaxKey = key; + + pos = HASH_FUNC(key); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + /* replace entry's data */ + entry->Data = data; + _eglUnlockMutex(table->Mutex); + return; + } + entry = entry->Next; + } + + /* alloc and insert new table entry */ + entry = (_EGLHashentry *) malloc(sizeof(_EGLHashentry)); + entry->Key = key; + entry->Data = data; + entry->Next = table->Table[pos]; + table->Table[pos] = entry; + + _eglUnlockMutex(table->Mutex); +} + + + +/** + * Remove an entry from the hash table. + * + * \param table the hash table. + * \param key key of entry to remove. + * + * While holding the hash table's lock, searches the entry with the matching + * key and unlinks it. + */ +void +_eglHashRemove(_EGLHashtable *table, EGLuint key) +{ + EGLuint pos; + _EGLHashentry *entry, *prev; + + assert(table); + assert(key); + + _eglLockMutex(table->Mutex); + + pos = HASH_FUNC(key); + prev = NULL; + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + /* found it! */ + if (prev) { + prev->Next = entry->Next; + } + else { + table->Table[pos] = entry->Next; + } + free(entry); + _eglUnlockMutex(table->Mutex); + return; + } + prev = entry; + entry = entry->Next; + } + + _eglUnlockMutex(table->Mutex); +} + + + +/** + * Get the key of the "first" entry in the hash table. + * + * This is used in the course of deleting all display lists when + * a context is destroyed. + * + * \param table the hash table + * + * \return key for the "first" entry in the hash table. + * + * While holding the lock, walks through all table positions until finding + * the first entry of the first non-empty one. + */ +EGLuint +_eglHashFirstEntry(_EGLHashtable *table) +{ + EGLuint pos; + assert(table); + _eglLockMutex(table->Mutex); + for (pos = 0; pos < TABLE_SIZE; pos++) { + if (table->Table[pos]) { + _eglUnlockMutex(table->Mutex); + return table->Table[pos]->Key; + } + } + _eglUnlockMutex(table->Mutex); + return 0; +} + + +/** + * Given a hash table key, return the next key. This is used to walk + * over all entries in the table. Note that the keys returned during + * walking won't be in any particular order. + * \return next hash key or 0 if end of table. + */ +EGLuint +_eglHashNextEntry(const _EGLHashtable *table, EGLuint key) +{ + const _EGLHashentry *entry; + EGLuint pos; + + assert(table); + assert(key); + + /* Find the entry with given key */ + pos = HASH_FUNC(key); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + break; + } + entry = entry->Next; + } + + if (!entry) { + /* the key was not found, we can't find next entry */ + return 0; + } + + if (entry->Next) { + /* return next in linked list */ + return entry->Next->Key; + } + else { + /* look for next non-empty table slot */ + pos++; + while (pos < TABLE_SIZE) { + if (table->Table[pos]) { + return table->Table[pos]->Key; + } + pos++; + } + return 0; + } +} + + +/** + * Dump contents of hash table for debugging. + * + * \param table the hash table. + */ +void +_eglHashPrint(const _EGLHashtable *table) +{ + EGLuint i; + assert(table); + for (i = 0; i < TABLE_SIZE; i++) { + const _EGLHashentry *entry = table->Table[i]; + while (entry) { + printf("%u %p\n", entry->Key, entry->Data); + entry = entry->Next; + } + } +} + + + +/** + * Return a new, unused hash key. + */ +EGLuint +_eglHashGenKey(_EGLHashtable *table) +{ + EGLuint k; + + _eglLockMutex(table->Mutex); + k = table->MaxKey; + table->MaxKey++; + _eglUnlockMutex(table->Mutex); + return k; +} + diff --git a/src/egl/main/eglhash.h b/src/egl/main/eglhash.h new file mode 100644 index 0000000000..1d6db9598c --- /dev/null +++ b/src/egl/main/eglhash.h @@ -0,0 +1,39 @@ +/** + * \file eglhash.h + * Generic hash table. + */ + + +#ifndef EGLHASH_INCLUDED +#define EGLHASH_INCLUDED + + +/* XXX move this? */ +typedef unsigned int EGLuint; + + +typedef struct _egl_hashtable _EGLHashtable; + + +extern _EGLHashtable *_eglNewHashTable(void); + +extern void _eglDeleteHashTable(_EGLHashtable *table); + +extern void *_eglHashLookup(const _EGLHashtable *table, EGLuint key); + +extern void _eglHashInsert(_EGLHashtable *table, EGLuint key, void *data); + +extern void _eglHashRemove(_EGLHashtable *table, EGLuint key); + +extern EGLuint _eglHashFirstEntry(_EGLHashtable *table); + +extern EGLuint _eglHashNextEntry(const _EGLHashtable *table, EGLuint key); + +extern void _eglHashPrint(const _EGLHashtable *table); + +extern EGLuint _eglHashGenKey(_EGLHashtable *table); + +extern void _egltest_hash_functions(void); + + +#endif /* EGLHASH_INCLUDED */ diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c new file mode 100644 index 0000000000..201ddb17f7 --- /dev/null +++ b/src/egl/main/eglmode.c @@ -0,0 +1,130 @@ +#include "egldisplay.h" +#include "egldriver.h" +#include "eglmode.h" +#include "eglglobals.h" +#include "eglscreen.h" + + +#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) + + +_EGLMode * +_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode) +{ + const _EGLDisplay *disp = _eglLookupDisplay(dpy); + EGLint scrnum; + + for (scrnum = 0; scrnum < disp->NumScreens; scrnum++) { + const _EGLScreen *scrn = disp->Screens + scrnum; + EGLint i; + for (i = 0; i < scrn->NumModes; i++) { + if (scrn->Modes[i].Handle == mode) { + return scrn->Modes + i; + } + } + } + return NULL; +} + + +/** + * Search for the EGLMode that best matches the given attribute list. + */ +EGLBoolean +_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + const EGLint *attrib_list, EGLModeMESA *modes, + EGLint modes_size, EGLint *num_modes) +{ + EGLint i; + + /* XXX incomplete */ + + for (i = 0; attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + case EGL_WIDTH: + i++; + break; + case EGL_HEIGHT: + i++; + break; + case EGL_REFRESH_RATE_MESA: + i++; + break; +#if 0 + case EGL_STEREO_MESA: + i++; + break; +#endif + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglChooseMode"); + return EGL_FALSE; + } + } + + return EGL_TRUE; +} + + + +/** + * Return all possible modes for the given screen + */ +EGLBoolean +_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes) +{ + _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + EGLint i; + + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, "eglGetModes"); + return EGL_FALSE; + } + + *num_modes = MIN2(modes_size, scrn->NumModes); + for (i = 0; i < *num_modes; i++) { + modes[i] = scrn->Modes[i].Handle; + } + + return EGL_TRUE; +} + + +/** + * Query an attribute of a mode. + */ +EGLBoolean +_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, + EGLModeMESA mode, EGLint attribute, EGLint *value) +{ + _EGLMode *m = _eglLookupMode(dpy, mode); + + switch (attribute) { + case EGL_MODE_ID_MESA: + *value = m->Handle; + break; + case EGL_WIDTH: + *value = m->Width; + break; + case EGL_HEIGHT: + *value = m->Height; + break; +#if 0 + case EGL_DEPTH_MESA: + *value = m->Depth; + break; +#endif + case EGL_REFRESH_RATE_MESA: + *value = m->RefreshRate; + break; +#if 0 + case EGL_STEREO_MESA: + *value = m->Stereo; + break; +#endif + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglGetModeAttrib"); + return EGL_FALSE; + } + return EGL_TRUE; +} diff --git a/src/egl/main/eglmode.h b/src/egl/main/eglmode.h new file mode 100644 index 0000000000..b3c268d1fb --- /dev/null +++ b/src/egl/main/eglmode.h @@ -0,0 +1,41 @@ +#ifndef EGLMODE_INCLUDED +#define EGLMODE_INCLUDED + +#include "egltypedefs.h" + +struct _egl_mode +{ + EGLConfig Handle; /* the public/opaque handle which names this mode */ + EGLint Width, Height; /* size in pixels */ + EGLint Depth; /* bits per pixel */ + EGLint RefreshRate; /* rate * 1000.0 */ + EGLBoolean Stereo; + + /* Other possible attributes */ + /* interlaced */ + /* external sync */ +}; + + +extern _EGLMode * +_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode); + + +extern EGLBoolean +_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + const EGLint *attrib_list, EGLModeMESA *modes, + EGLint modes_size, EGLint *num_modes); + + +extern EGLBoolean +_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes); + + +extern EGLBoolean +_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, + EGLint attribute, EGLint *value); + + + +#endif /* EGLMODE_INCLUDED */ diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c new file mode 100644 index 0000000000..c3c1a47984 --- /dev/null +++ b/src/egl/main/eglscreen.c @@ -0,0 +1,259 @@ +/* + * Ideas for screen management extension to EGL. + * + * Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc). + * The number of screens can be queried with eglQueryDisplay(EGL_SCREEN_COUNT). + * + * A new kind of EGLSurface is possible- one which can be directly scanned + * out on a screen. Such a surface is created with eglCreateScreenSurface(). + * + * To actually display a screen surface on a screen, the eglShowSurface() + * function is called. + * + */ + +#include +#include +#include "egldisplay.h" +#include "eglglobals.h" +#include "eglmode.h" +#include "eglsurface.h" +#include "eglscreen.h" + + +_EGLScreen * +_eglLookupScreen(EGLDisplay dpy, GLint screenNumber) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + if (!disp || screenNumber < 0 || screenNumber >= disp->NumScreens) { + return NULL; + } + else { + return disp->Screens + screenNumber; + } +} + + +/** + * Create a drawing surface which can be directly displayed on a screen. + */ +EGLSurface +_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + _EGLSurface *surf; + EGLint width = 0, height = 0; + EGLint i; + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + case EGL_WIDTH: + width = attrib_list[++i]; + break; + case EGL_HEIGHT: + height = attrib_list[++i]; + break; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreateScreenSurfaceMESA"); + return EGL_NO_SURFACE; + } + } + + if (width <= 0 || height <= 0) { + _eglError(EGL_BAD_ATTRIBUTE, + "eglCreateScreenSurfaceMESA(width or height)"); + return EGL_NO_SURFACE; + } + + surf = (_EGLSurface *) malloc(sizeof(_EGLSurface)); + _eglInitSurface(surf); + surf->Width = width; + surf->Height = height; + surf->Type = EGL_SCREEN_BIT_MESA; + + /* insert into hash table */ + _eglSaveSurface(surf); + assert(surf->Handle); + + return surf->Handle; +} + + +/** + * Show the given surface on the named screen. + * If surface is EGL_NO_SURFACE, disable the screen's output. + * + * This is just a placeholder function; drivers will always override + * this with code that _really_ shows the surface. + */ +EGLBoolean +_eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + EGLSurface surface) +{ + _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + _EGLMode *mode; + + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA"); + return EGL_FALSE; + } + + /* + * XXX: Check if the surface's configuration is compatible with the + * current screen mode. + */ + + mode = scrn->CurrentMode; + if (mode == EGL_NO_MODE_MESA) { + _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA(no current mode)"); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) { + scrn->CurrentSurface = NULL; + } + else { + _EGLSurface *surf = _eglLookupSurface(surface); + if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) { + _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA"); + return EGL_FALSE; + } + if (surf->Width < mode->Width || surf->Height < mode->Height) { + _eglError(EGL_BAD_SURFACE, + "eglShowSurfaceMESA(surface smaller than screen size)"); + return EGL_FALSE; + } + + scrn->CurrentSurface = surf; + } + + return EGL_TRUE; +} + + +/** + * Set a screen's current display mode. + * Note: mode = EGL_NO_MODE is valid (turns off the screen) + * + * This is just a placeholder function; drivers will always override + * this with code that _really_ sets the mode. + */ +EGLBoolean +_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + EGLModeMESA mode) +{ + _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA"); + return EGL_FALSE; + } + + scrn->CurrentMode = _eglLookupMode(dpy, mode); + + return EGL_TRUE; +} + + +/** + * Set a screen's surface origin. + */ +EGLBoolean +_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, + EGLint screen_number, EGLint x, EGLint y) +{ + _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA"); + return EGL_FALSE; + } + + scrn->OriginX = x; + scrn->OriginY = y; + + return EGL_TRUE; +} + + +EGLBoolean +_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, + EGLint attribute, EGLint *value) +{ + const _EGLDisplay *display = _eglLookupDisplay(dpy); + switch (attribute) { + case EGL_SCREEN_COUNT_MESA: + *value = display->NumScreens; + break; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglQueryDisplayMESA"); + return EGL_FALSE; + } + return EGL_TRUE; +} + + +/** + * Query a screen's current surface. + */ +EGLBoolean +_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, + EGLint screen_number, EGLSurface *surface) +{ + const _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + if (scrn->CurrentSurface) + *surface = scrn->CurrentSurface->Handle; + else + *surface = EGL_NO_SURFACE; + return EGL_TRUE; +} + + +/** + * Query a screen's current mode. + */ +EGLBoolean +_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + EGLModeMESA *mode) +{ + const _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + if (scrn->CurrentMode) + *mode = scrn->CurrentMode->Handle; + else + *mode = EGL_NO_MODE_MESA; + return EGL_TRUE; +} + + +EGLBoolean +_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, + EGLint attribute, EGLint *value) +{ + const _EGLScreen *scrn = _eglLookupScreen(dpy, screen_number); + + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA"); + return EGL_FALSE; + } + + switch (attribute) { + case EGL_SCREEN_POSITION_MESA: + value[0] = scrn->OriginX; + value[1] = scrn->OriginY; + break; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA"); + return EGL_FALSE; + } + + return EGL_TRUE; +} + + + +void +_eglDeleteScreen(_EGLScreen *scrn) +{ + free(scrn->Modes); + free(scrn); +} + diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h new file mode 100644 index 0000000000..1dbb766dc6 --- /dev/null +++ b/src/egl/main/eglscreen.h @@ -0,0 +1,61 @@ +#ifndef EGLSCREEN_INCLUDED +#define EGLSCREEN_INCLUDED + + +/* NOTE: there is no public EGLScreen type, we refers to screens with + * an integer. + */ + +struct _egl_screen +{ + _EGLMode *CurrentMode; + _EGLSurface *CurrentSurface; + EGLint OriginX, OriginY; + + EGLint NumModes; + _EGLMode *Modes; /* array [NumModes] */ +}; + + +extern _EGLScreen * +_eglLookupScreen(EGLDisplay dpy, GLint screenNumber); + + +extern EGLSurface +_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); + + +extern EGLBoolean +_eglShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen, EGLSurface surface); + + +extern EGLBoolean +_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, EGLModeMESA mode); + + +extern EGLBoolean +_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, EGLint x, EGLint y); + + +extern EGLBoolean +_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attribute, EGLint *value); + + +extern EGLBoolean +_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, + EGLint screen_number, EGLSurface *surface); + + +extern EGLBoolean +_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, EGLModeMESA *mode); + + +extern EGLBoolean +_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint screen_number, EGLint attribute, EGLint *value); + + +extern void +_eglDeleteScreen(_EGLScreen *scrn); + + +#endif /* EGLSCREEN_INCLUDED */ diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c new file mode 100644 index 0000000000..b9902c7af0 --- /dev/null +++ b/src/egl/main/eglsurface.c @@ -0,0 +1,246 @@ +/** + * Surface-related functions. + * + * See the eglcontext.c file for comments that also apply here. + */ + + +#include +#include +#include +#include "eglcontext.h" +#include "eglconfig.h" +#include "eglsurface.h" +#include "eglglobals.h" +#include "eglhash.h" + + +void +_eglInitSurface(_EGLSurface *surf) +{ + /* XXX fix this up */ + memset(surf, 0, sizeof(_EGLSurface)); +} + + +void +_eglSaveSurface(_EGLSurface *surf) +{ + assert(surf); + surf->Handle = _eglHashGenKey(_eglGlobal.Contexts); + _eglHashInsert(_eglGlobal.Surfaces, surf->Handle, surf); +} + + +void +_eglRemoveSurface(_EGLSurface *surf) +{ + _eglHashRemove(_eglGlobal.Surfaces, surf->Handle); +} + + +_EGLSurface * +_eglLookupSurface(EGLSurface surf) +{ + _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, surf); + return c; +} + + +_EGLSurface * +_eglGetCurrentSurface(EGLint readdraw) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + if (ctx) { + switch (readdraw) { + case EGL_DRAW: + return ctx->DrawSurface; + case EGL_READ: + return ctx->ReadSurface; + default: + return NULL; + } + } + return NULL; +} + + +EGLBoolean +_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +{ + /* Basically just do error checking */ + _EGLContext *context = _eglGetCurrentContext(); + _EGLSurface *surface = _eglLookupSurface(draw); + if (context && context->DrawSurface != surface) { + _eglError(EGL_BAD_SURFACE, "eglSwapBuffers"); + return EGL_FALSE; + } + if (surface == NULL) { + _eglError(EGL_BAD_SURFACE, "eglSwapBuffers"); + return EGL_FALSE; + } + return EGL_TRUE; +} + + +EGLBoolean +_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target) +{ + /* XXX unfinished */ + return EGL_FALSE; +} + + +EGLBoolean +_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint *value) +{ + _EGLSurface *surface = _eglLookupSurface(surf); + if (surface == NULL) { + _eglError(EGL_BAD_SURFACE, "eglQuerySurface"); + return EGL_FALSE; + } + switch (attribute) { + case EGL_WIDTH: + *value = surface->Width; + return EGL_TRUE; + case EGL_HEIGHT: + *value = surface->Height; + return EGL_TRUE; + case EGL_CONFIG_ID: + *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID); + return EGL_TRUE; + case EGL_TEXTURE_FORMAT: + /* texture attributes: only for pbuffers, no error otherwise */ + if (surface->Type == EGL_PBUFFER_BIT) + *value = surface->TextureFormat; + return EGL_TRUE; + case EGL_TEXTURE_TARGET: + if (surface->Type == EGL_PBUFFER_BIT) + *value = surface->TextureTarget; + return EGL_TRUE; + case EGL_MIPMAP_TEXTURE: + if (surface->Type == EGL_PBUFFER_BIT) + *value = surface->MipmapTexture; + return EGL_TRUE; + case EGL_MIPMAP_LEVEL: + if (surface->Type == EGL_PBUFFER_BIT) + *value = surface->MipmapLevel; + return EGL_TRUE; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); + return EGL_FALSE; + } +} + + +/** + * Default fallback routine - drivers should usually override this. + */ +EGLSurface +_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +{ + /* nothing - just a placeholder */ + return EGL_NO_SURFACE; +} + + +/** + * Default fallback routine - drivers should usually override this. + */ +EGLSurface +_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +{ + /* nothing - just a placeholder */ + return EGL_NO_SURFACE; +} + + +/** + * Default fallback routine - drivers should usually override this. + */ +EGLSurface +_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + /* nothing - just a placeholder */ + return EGL_NO_SURFACE; +} + + +/** + * Default fallback routine - drivers should usually override this. + */ +EGLBoolean +_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +{ + _EGLSurface *surf = _eglLookupSurface(surface); + if (surf) { + _eglHashRemove(_eglGlobal.Surfaces, surface); + if (surf->IsBound) { + surf->DeletePending = EGL_TRUE; + } + else { + free(surf); + } + return EGL_TRUE; + } + else { + _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); + return EGL_FALSE; + } +} + + +/** + * Default fallback routine - drivers might override this. + */ +EGLBoolean +_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value) +{ + _EGLSurface *surface = _eglLookupSurface(surf); + + if (surface == NULL) { + _eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib"); + return EGL_FALSE; + } + + switch (attribute) { + case EGL_MIPMAP_LEVEL: + surface->MipmapLevel = value; + break; + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib"); + return EGL_FALSE; + } + return EGL_TRUE; +} + + +EGLBoolean +_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + /* XXX unfinished */ + return EGL_FALSE; +} + + +EGLBoolean +_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + /* XXX unfinished */ + return EGL_FALSE; +} + + +EGLBoolean +_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval) +{ + _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW); + if (surf == NULL) { + _eglError(EGL_BAD_SURFACE, "eglSwapInterval"); + return EGL_FALSE; + } + surf->SwapInterval = interval; + return EGL_TRUE; +} + + diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h new file mode 100644 index 0000000000..2f0e07c53c --- /dev/null +++ b/src/egl/main/eglsurface.h @@ -0,0 +1,96 @@ +#ifndef EGLSURFACE_INCLUDED +#define EGLSURFACE_INCLUDED + + +#include "egltypedefs.h" + + +/** + * "Base" class for device driver surfaces. + */ +struct _egl_surface +{ + EGLSurface Handle; /* The public/opaque handle which names this object */ + _EGLConfig *Config; + + /* May need reference counting here */ + EGLBoolean IsBound; + EGLBoolean DeletePending; + + EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */ + EGLint Width, Height; + EGLint TextureFormat, TextureTarget; + EGLint MipmapTexture, MipmapLevel; + EGLint SwapInterval; + + /* If type == EGL_SCREEN_BIT: */ + EGLint VisibleRefCount; /* number of screens I'm displayed on */ +}; + + +extern void +_eglInitSurface(_EGLSurface *surf); + + +extern void +_eglSaveSurface(_EGLSurface *surf); + + +extern void +_eglRemoveSurface(_EGLSurface *surf); + + +extern _EGLSurface * +_eglLookupSurface(EGLSurface surf); + + +extern _EGLSurface * +_eglGetCurrentSurface(EGLint readdraw); + + +extern EGLBoolean +_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw); + + +extern EGLBoolean +_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target); + + +extern EGLBoolean +_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); + + +extern EGLSurface +_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list); + + +extern EGLSurface +_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list); + + +extern EGLSurface +_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); + + +extern EGLBoolean +_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface); + + +extern EGLBoolean +_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); + + +extern EGLBoolean +_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); + + +extern EGLBoolean +_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); + + +extern EGLBoolean +_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval); + + + +#endif /* EGLSURFACE_INCLUDED */ diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h new file mode 100644 index 0000000000..bf5e9c3119 --- /dev/null +++ b/src/egl/main/egltypedefs.h @@ -0,0 +1,28 @@ +#ifndef EGLTYPEDEFS_INCLUDED +#define EGLTYPEDEFS_INCLUDED + + +#include + + +typedef struct _egl_config _EGLConfig; + +typedef struct _egl_context _EGLContext; + +typedef struct _egl_display _EGLDisplay; + +typedef struct _egl_driver _EGLDriver; + +typedef struct _egl_mode _EGLMode; + +typedef struct _egl_screen _EGLScreen; + +typedef struct _egl_surface _EGLSurface; + + +typedef void (*_EGLProc)(); + +typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy); + + +#endif /* EGLTYPEDEFS_INCLUDED */ -- cgit v1.2.3