initial EGL code
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 22 Apr 2005 21:09:39 +0000 (21:09 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 22 Apr 2005 21:09:39 +0000 (21:09 +0000)
24 files changed:
src/egl/Makefile [new file with mode: 0644]
src/egl/drivers/demo/Makefile [new file with mode: 0644]
src/egl/drivers/demo/demo.c [new file with mode: 0644]
src/egl/main/Makefile [new file with mode: 0644]
src/egl/main/eglapi.c [new file with mode: 0644]
src/egl/main/eglconfig.c [new file with mode: 0644]
src/egl/main/eglconfig.h [new file with mode: 0644]
src/egl/main/eglcontext.c [new file with mode: 0644]
src/egl/main/eglcontext.h [new file with mode: 0644]
src/egl/main/egldisplay.c [new file with mode: 0644]
src/egl/main/egldisplay.h [new file with mode: 0644]
src/egl/main/egldriver.c [new file with mode: 0644]
src/egl/main/egldriver.h [new file with mode: 0644]
src/egl/main/eglglobals.c [new file with mode: 0644]
src/egl/main/eglglobals.h [new file with mode: 0644]
src/egl/main/eglhash.c [new file with mode: 0644]
src/egl/main/eglhash.h [new file with mode: 0644]
src/egl/main/eglmode.c [new file with mode: 0644]
src/egl/main/eglmode.h [new file with mode: 0644]
src/egl/main/eglscreen.c [new file with mode: 0644]
src/egl/main/eglscreen.h [new file with mode: 0644]
src/egl/main/eglsurface.c [new file with mode: 0644]
src/egl/main/eglsurface.h [new file with mode: 0644]
src/egl/main/egltypedefs.h [new file with mode: 0644]

diff --git a/src/egl/Makefile b/src/egl/Makefile
new file mode 100644 (file)
index 0000000..75df390
--- /dev/null
@@ -0,0 +1,24 @@
+# src/egl/Makefile
+
+TOP = ../..
+
+SUBDIRS = main drivers/demo
+
+
+default: subdirs
+
+
+subdirs:
+       @for dir in $(SUBDIRS) ; do \
+               if [ -d $$dir ] ; then \
+                       (cd $$dir ; $(MAKE)) || exit 1 ; \
+               fi \
+       done
+
+
+clean:
+       @for dir in $(SUBDIRS) ; do \
+               if [ -d $$dir ] ; then \
+                       (cd $$dir ; $(MAKE) clean) ; \
+               fi \
+       done
diff --git a/src/egl/drivers/demo/Makefile b/src/egl/drivers/demo/Makefile
new file mode 100644 (file)
index 0000000..fd587b7
--- /dev/null
@@ -0,0 +1,31 @@
+# src/egl/drivers/demo/Makefile
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main
+
+
+SOURCES = demo.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+.c.o:
+       $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+
+default: $(LIB_DIR)/demodriver.so
+
+
+$(LIB_DIR)/demodriver.so: $(OBJECTS)
+       $(TOP)/bin/mklib -o demodriver.so -noprefix \
+               -install $(LIB_DIR) $(OBJECTS)
+
+
+
+clean:
+       rm -f *.o
+       rm -f *.so
diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c
new file mode 100644 (file)
index 0000000..041884b
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * 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 */
+   GLuint 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 */
+   GLuint DemoStuff;
+} DemoSurface;
+
+
+/**
+ * Demo driver-specific context class derived from _EGLContext
+ */
+typedef struct demo_context
+{
+   _EGLContext Base;  /* base class/object */
+   GLuint DemoStuff;
+} DemoContext;
+
+
+
+static EGLBoolean
+demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLScreen *scrn;
+   EGLint i;
+
+   disp->NumScreens = 1;
+   disp->Screens = (_EGLScreen *) calloc(disp->NumScreens, sizeof(_EGLScreen));
+   scrn = disp->Screens + 0;
+   scrn->NumModes = 4;
+   scrn->Modes = (_EGLMode *) calloc(scrn->NumModes, sizeof(_EGLMode));
+   scrn->Modes[0].Width = 1600;
+   scrn->Modes[0].Height = 1200;
+   scrn->Modes[0].Depth = 32;
+   scrn->Modes[0].RefreshRate = 72 * 1000;
+   scrn->Modes[1].Width = 1280;
+   scrn->Modes[1].Height = 1024;
+   scrn->Modes[1].Depth = 32;
+   scrn->Modes[1].RefreshRate = 72 * 1000;
+   scrn->Modes[2].Width = 1280;
+   scrn->Modes[2].Height = 1024;
+   scrn->Modes[2].Depth = 16;
+   scrn->Modes[2].RefreshRate = 72 * 1000;
+   scrn->Modes[3].Width = 1024;
+   scrn->Modes[3].Height = 768;
+   scrn->Modes[3].Depth = 16;
+   scrn->Modes[3].RefreshRate = 72 * 1000;
+   for (i = 0; i < scrn->NumModes; i++)
+      scrn->Modes[i].Handle = i + 1;
+
+   /* Create list of visual configs - this is a silly example */
+   disp->NumConfigs = 4;
+   disp->Configs = (_EGLConfig *) calloc(disp->NumConfigs, sizeof(_EGLConfig));
+   for (i = 0; i < disp->NumConfigs; i++) {
+      _EGLConfig *config = disp->Configs + i;
+      _eglInitConfig(config, i + 1);
+      SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, 8);
+      SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, 8);
+      SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, 8);
+      SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, 8);
+      SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, 32);
+
+      if (i & 1) {
+         SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, 32);
+      }
+      if (i & 2) {
+         SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, 8);
+      }
+
+      SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE,
+                        (EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT));
+   }
+
+   drv->Initialized = EGL_TRUE;
+
+   *major = 1;
+   *minor = 0;
+
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
+demoTerminate(_EGLDriver *drv, EGLDisplay dpy)
+{
+   /*DemoDriver *demo = DEMO_DRIVER(dpy);*/
+   free(drv);
+   return EGL_TRUE;
+}
+
+
+static DemoContext *
+LookupDemoContext(EGLContext ctx)
+{
+   _EGLContext *c = _eglLookupContext(ctx);
+   return (DemoContext *) c;
+}
+
+
+static DemoSurface *
+LookupDemoSurface(EGLSurface surf)
+{
+   _EGLSurface *s = _eglLookupSurface(surf);
+   return (DemoSurface *) s;
+}
+
+
+
+static EGLContext
+demoCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
+{
+   _EGLConfig *conf;
+   DemoContext *c;
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   int i;
+
+   conf = _eglLookupConfig(drv, dpy, config);
+   if (!conf) {
+      _eglError(EGL_BAD_CONFIG, "eglCreateContext");
+      return EGL_NO_CONTEXT;
+   }
+
+   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 EGL_NO_CONTEXT;
+      }
+   }
+
+   c = (DemoContext *) calloc(1, sizeof(DemoContext));
+   if (!c)
+      return EGL_NO_CONTEXT;
+
+   _eglInitContext(&c->Base);
+   c->Base.Display = disp;
+   c->Base.Config = conf;
+   c->Base.DrawSurface = EGL_NO_SURFACE;
+   c->Base.ReadSurface = EGL_NO_SURFACE;
+   c->DemoStuff = 1;
+   printf("demoCreateContext\n");
+
+   /* generate handle and insert into hash table */
+   _eglSaveContext(&c->Base);
+   assert(c->Base.Handle);
+
+   return c->Base.Handle;
+}
+
+
+static EGLSurface
+demoCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, 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 EGL_NO_SURFACE;
+      }
+   }
+   printf("eglCreateWindowSurface()\n");
+   /* XXX unfinished */
+
+   return EGL_NO_SURFACE;
+}
+
+
+static EGLSurface
+demoCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
+{
+   _EGLConfig *conf;
+   EGLint i;
+
+   conf = _eglLookupConfig(drv, dpy, config);
+   if (!conf) {
+      _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface");
+      return EGL_NO_SURFACE;
+   }
+
+   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 EGL_NO_SURFACE;
+      }
+   }
+
+   if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
+      _eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
+      return EGL_NO_SURFACE;
+   }
+
+   printf("eglCreatePixmapSurface()\n");
+   return EGL_NO_SURFACE;
+}
+
+
+static EGLSurface
+demoCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+   _EGLConfig *conf;
+   EGLint i, width = 0, height = 0, largest, texFormat, texTarget, mipmapTex;
+   DemoSurface *surf;
+
+   conf = _eglLookupConfig(drv, dpy, config);
+   if (!conf) {
+      _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface");
+      return EGL_NO_SURFACE;
+   }
+
+   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;
+      case EGL_LARGEST_PBUFFER:
+         largest = attrib_list[++i];
+         break;
+      case EGL_TEXTURE_FORMAT:
+         texFormat = attrib_list[++i];
+         break;
+      case EGL_TEXTURE_TARGET:
+         texTarget = attrib_list[++i];
+         break;
+      case EGL_MIPMAP_TEXTURE:
+         mipmapTex = attrib_list[++i];
+         break;
+      default:
+         _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
+         return EGL_NO_SURFACE;
+      }
+   }
+
+   if (width <= 0 || height <= 0) {
+      _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface(width or height)");
+      return EGL_NO_SURFACE;
+   }
+
+   surf = (DemoSurface *) calloc(1, sizeof(DemoSurface));
+   if (!surf)
+      return EGL_NO_SURFACE;
+
+   surf->Base.Config = conf;
+   surf->Base.Type = EGL_PBUFFER_BIT;
+   surf->Base.Width = width;
+   surf->Base.Height = height;
+   surf->Base.TextureFormat = texFormat;
+   surf->Base.TextureTarget = texTarget;
+   surf->Base.MipmapTexture = mipmapTex;
+   surf->Base.MipmapLevel = 0;
+   surf->Base.SwapInterval = 0;
+
+   printf("eglCreatePbufferSurface()\n");
+
+   /* insert into hash table */
+   _eglSaveSurface(&surf->Base);
+   assert(surf->Base.Handle);
+
+   return surf->Base.Handle;
+}
+
+
+static EGLBoolean
+demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+{
+   DemoSurface *fs = LookupDemoSurface(surface);
+   _eglRemoveSurface(&fs->Base);
+   if (fs->Base.IsBound) {
+      fs->Base.DeletePending = EGL_TRUE;
+   }
+   else {
+      free(fs);
+   }
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
+demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
+{
+   DemoContext *fc = LookupDemoContext(context);
+   _eglRemoveContext(&fc->Base);
+   if (fc->Base.IsBound) {
+      fc->Base.DeletePending = EGL_TRUE;
+   }
+   else {
+      free(fc);
+   }
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
+demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
+{
+   /*DemoDriver *demo = DEMO_DRIVER(dpy);*/
+   DemoSurface *readSurf = LookupDemoSurface(read);
+   DemoSurface *drawSurf = LookupDemoSurface(draw);
+   DemoContext *ctx = LookupDemoContext(context);
+   EGLBoolean b;
+
+   b = _eglMakeCurrent(drv, dpy, draw, read, context);
+   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 const char *
+demoQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
+{
+   if (name == EGL_EXTENSIONS) {
+      return "EGL_MESA_screen_surface";
+   }
+   else {
+      return _eglQueryString(drv, dpy, name);
+   }
+}
+
+
+
+
+/*
+ * Just to silence warning
+ */
+extern _EGLDriver *
+_eglMain(NativeDisplayType dpy);
+
+
+/**
+ * The bootstrap function.  Return a new DemoDriver object and
+ * plug in API functions.
+ */
+_EGLDriver *
+_eglMain(NativeDisplayType dpy)
+{
+   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.Initialize = demoInitialize;
+   demo->Base.Terminate = demoTerminate;
+   demo->Base.CreateContext = demoCreateContext;
+   demo->Base.MakeCurrent = demoMakeCurrent;
+   demo->Base.CreateWindowSurface = demoCreateWindowSurface;
+   demo->Base.CreatePixmapSurface = demoCreatePixmapSurface;
+   demo->Base.CreatePbufferSurface = demoCreatePbufferSurface;
+   demo->Base.DestroySurface = demoDestroySurface;
+   demo->Base.DestroyContext = demoDestroyContext;
+   demo->Base.QueryString = demoQueryString;
+   return &demo->Base;
+}
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
new file mode 100644 (file)
index 0000000..4bb1ffc
--- /dev/null
@@ -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 (file)
index 0000000..d9c8845
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+/**#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 (file)
index 0000000..765e2e3
--- /dev/null
@@ -0,0 +1,286 @@
+#include <string.h>
+#include <assert.h>
+#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 (file)
index 0000000..0bd0ce6
--- /dev/null
@@ -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 (file)
index 0000000..e7d833e
--- /dev/null
@@ -0,0 +1,226 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..0063507
--- /dev/null
@@ -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 (file)
index 0000000..0f29810
--- /dev/null
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..a2831e6
--- /dev/null
@@ -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 (file)
index 0000000..5b65b80
--- /dev/null
@@ -0,0 +1,226 @@
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#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 (file)
index 0000000..4ced794
--- /dev/null
@@ -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 (file)
index 0000000..102e550
--- /dev/null
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#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 (file)
index 0000000..fbf2813
--- /dev/null
@@ -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 (file)
index 0000000..8e3da2e
--- /dev/null
@@ -0,0 +1,347 @@
+/**
+ * \file hash.c
+ * Generic hash table. 
+ *
+ * This code taken from Mesa and adapted.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#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 (file)
index 0000000..1d6db95
--- /dev/null
@@ -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 (file)
index 0000000..201ddb1
--- /dev/null
@@ -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 (file)
index 0000000..b3c268d
--- /dev/null
@@ -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 (file)
index 0000000..c3c1a47
--- /dev/null
@@ -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 <assert.h>
+#include <stdlib.h>
+#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 (file)
index 0000000..1dbb766
--- /dev/null
@@ -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 (file)
index 0000000..b9902c7
--- /dev/null
@@ -0,0 +1,246 @@
+/**
+ * Surface-related functions.
+ *
+ * See the eglcontext.c file for comments that also apply here.
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..2f0e07c
--- /dev/null
@@ -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 (file)
index 0000000..bf5e9c3
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef EGLTYPEDEFS_INCLUDED
+#define EGLTYPEDEFS_INCLUDED
+
+
+#include <GL/egl.h>
+
+
+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 */