diff options
author | Julien Cristau <[email protected]> | 2007-02-01 11:50:36 +0100 |
---|---|---|
committer | Julien Cristau <[email protected]> | 2007-02-01 11:50:36 +0100 |
commit | 2634f06c2095b79d4252bb81c0b0272139dad890 (patch) | |
tree | 855ba634812939982daa999dc44365a4d889d11e /src/egl/drivers | |
parent | 7549426a168f3803d6023622dd9e630a5fa2faf6 (diff) | |
parent | eb667b979bc941f05b8f40a2fc39af6fac960ac5 (diff) |
Merge branch 'upstream-experimental' into debian-experimental
Conflicts:
progs/util/README
progs/util/glstate.c
progs/util/glstate.h
progs/util/sampleMakefile
src/glu/sgi/libnurbs/interface/bezierEval.h
src/glu/sgi/libnurbs/interface/bezierPatch.cc
src/glu/sgi/libnurbs/interface/bezierPatch.h
src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc
src/glu/sgi/libnurbs/interface/bezierPatchMesh.h
src/glu/sgi/libnurbs/interface/glcurveval.cc
src/glu/sgi/libnurbs/interface/glimports.h
src/glu/sgi/libnurbs/interface/glinterface.cc
src/glu/sgi/libnurbs/interface/glrenderer.h
src/glu/sgi/libnurbs/interface/incurveeval.cc
src/glu/sgi/libnurbs/interface/insurfeval.cc
src/glu/sgi/libnurbs/interface/mystdio.h
src/glu/sgi/libnurbs/interface/mystdlib.h
src/glu/sgi/libnurbs/internals/arc.h
src/glu/sgi/libnurbs/internals/arcsorter.cc
src/glu/sgi/libnurbs/internals/arcsorter.h
src/glu/sgi/libnurbs/internals/arctess.h
src/glu/sgi/libnurbs/internals/backend.cc
src/glu/sgi/libnurbs/internals/backend.h
src/glu/sgi/libnurbs/internals/basiccrveval.h
src/glu/sgi/libnurbs/internals/basicsurfeval.h
src/glu/sgi/libnurbs/internals/bezierarc.h
src/glu/sgi/libnurbs/internals/bin.cc
src/glu/sgi/libnurbs/internals/bin.h
src/glu/sgi/libnurbs/internals/bufpool.cc
src/glu/sgi/libnurbs/internals/bufpool.h
src/glu/sgi/libnurbs/internals/cachingeval.cc
src/glu/sgi/libnurbs/internals/cachingeval.h
src/glu/sgi/libnurbs/internals/ccw.cc
src/glu/sgi/libnurbs/internals/coveandtiler.h
src/glu/sgi/libnurbs/internals/curve.cc
src/glu/sgi/libnurbs/internals/curve.h
src/glu/sgi/libnurbs/internals/curvelist.cc
src/glu/sgi/libnurbs/internals/curvelist.h
src/glu/sgi/libnurbs/internals/curvesub.cc
src/glu/sgi/libnurbs/internals/dataTransform.cc
src/glu/sgi/libnurbs/internals/dataTransform.h
src/glu/sgi/libnurbs/internals/defines.h
src/glu/sgi/libnurbs/internals/displaylist.cc
src/glu/sgi/libnurbs/internals/displaylist.h
src/glu/sgi/libnurbs/internals/displaymode.h
src/glu/sgi/libnurbs/internals/flist.cc
src/glu/sgi/libnurbs/internals/flist.h
src/glu/sgi/libnurbs/internals/flistsorter.cc
src/glu/sgi/libnurbs/internals/flistsorter.h
src/glu/sgi/libnurbs/internals/gridline.h
src/glu/sgi/libnurbs/internals/gridtrimvertex.h
src/glu/sgi/libnurbs/internals/gridvertex.h
src/glu/sgi/libnurbs/internals/hull.cc
src/glu/sgi/libnurbs/internals/hull.h
src/glu/sgi/libnurbs/internals/intersect.cc
src/glu/sgi/libnurbs/internals/jarcloc.h
src/glu/sgi/libnurbs/internals/knotvector.h
src/glu/sgi/libnurbs/internals/mapdesc.cc
src/glu/sgi/libnurbs/internals/mapdesc.h
src/glu/sgi/libnurbs/internals/mapdescv.cc
src/glu/sgi/libnurbs/internals/maplist.cc
src/glu/sgi/libnurbs/internals/maplist.h
src/glu/sgi/libnurbs/internals/mesher.cc
src/glu/sgi/libnurbs/internals/mesher.h
src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc
src/glu/sgi/libnurbs/internals/monotonizer.cc
src/glu/sgi/libnurbs/internals/monotonizer.h
src/glu/sgi/libnurbs/internals/myassert.h
src/glu/sgi/libnurbs/internals/mycode.cc
src/glu/sgi/libnurbs/internals/mystring.h
src/glu/sgi/libnurbs/internals/nurbsconsts.h
src/glu/sgi/libnurbs/internals/nurbstess.cc
src/glu/sgi/libnurbs/internals/patch.cc
src/glu/sgi/libnurbs/internals/patch.h
src/glu/sgi/libnurbs/internals/patchlist.cc
src/glu/sgi/libnurbs/internals/patchlist.h
src/glu/sgi/libnurbs/internals/pwlarc.h
src/glu/sgi/libnurbs/internals/quilt.cc
src/glu/sgi/libnurbs/internals/quilt.h
src/glu/sgi/libnurbs/internals/reader.cc
src/glu/sgi/libnurbs/internals/reader.h
src/glu/sgi/libnurbs/internals/renderhints.cc
src/glu/sgi/libnurbs/internals/renderhints.h
src/glu/sgi/libnurbs/internals/simplemath.h
src/glu/sgi/libnurbs/internals/slicer.cc
src/glu/sgi/libnurbs/internals/slicer.h
src/glu/sgi/libnurbs/internals/sorter.cc
src/glu/sgi/libnurbs/internals/sorter.h
src/glu/sgi/libnurbs/internals/splitarcs.cc
src/glu/sgi/libnurbs/internals/subdivider.h
src/glu/sgi/libnurbs/internals/tobezier.cc
src/glu/sgi/libnurbs/internals/trimline.cc
src/glu/sgi/libnurbs/internals/trimline.h
src/glu/sgi/libnurbs/internals/trimregion.cc
src/glu/sgi/libnurbs/internals/trimregion.h
src/glu/sgi/libnurbs/internals/trimvertex.h
src/glu/sgi/libnurbs/internals/trimvertpool.cc
src/glu/sgi/libnurbs/internals/trimvertpool.h
src/glu/sgi/libnurbs/internals/types.h
src/glu/sgi/libnurbs/internals/uarray.cc
src/glu/sgi/libnurbs/internals/uarray.h
src/glu/sgi/libnurbs/internals/varray.cc
src/glu/sgi/libnurbs/internals/varray.h
src/glu/sgi/libnurbs/nurbtess/definitions.h
src/glu/sgi/libnurbs/nurbtess/directedLine.h
src/glu/sgi/libnurbs/nurbtess/glimports.h
src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
src/glu/sgi/libnurbs/nurbtess/gridWrap.h
src/glu/sgi/libnurbs/nurbtess/monoChain.cc
src/glu/sgi/libnurbs/nurbtess/monoChain.h
src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
src/glu/sgi/libnurbs/nurbtess/mystdio.h
src/glu/sgi/libnurbs/nurbtess/mystdlib.h
src/glu/sgi/libnurbs/nurbtess/partitionX.cc
src/glu/sgi/libnurbs/nurbtess/partitionX.h
src/glu/sgi/libnurbs/nurbtess/partitionY.cc
src/glu/sgi/libnurbs/nurbtess/partitionY.h
src/glu/sgi/libnurbs/nurbtess/polyDBG.h
src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
src/glu/sgi/libnurbs/nurbtess/polyUtil.h
src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
src/glu/sgi/libnurbs/nurbtess/quicksort.cc
src/glu/sgi/libnurbs/nurbtess/quicksort.h
src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
src/glu/sgi/libnurbs/nurbtess/rectBlock.h
src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
src/glu/sgi/libnurbs/nurbtess/sampleComp.h
src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
src/glu/sgi/libnurbs/nurbtess/sampledLine.h
src/glu/sgi/libnurbs/nurbtess/searchTree.cc
src/glu/sgi/libnurbs/nurbtess/searchTree.h
src/glu/sgi/libnurbs/nurbtess/zlassert.h
src/glu/sgi/libtess/README
src/glu/sgi/libtess/alg-outline
src/glu/sgi/libtess/dict-list.h
src/glu/sgi/libtess/dict.c
src/glu/sgi/libtess/dict.h
src/glu/sgi/libtess/geom.c
src/glu/sgi/libtess/memalloc.c
src/glu/sgi/libtess/memalloc.h
src/glu/sgi/libtess/mesh.c
src/glu/sgi/libtess/mesh.h
src/glu/sgi/libtess/normal.h
src/glu/sgi/libtess/priorityq-heap.c
src/glu/sgi/libtess/priorityq-heap.h
src/glu/sgi/libtess/priorityq-sort.h
src/glu/sgi/libtess/priorityq.c
src/glu/sgi/libtess/priorityq.h
src/glu/sgi/libtess/render.c
src/glu/sgi/libtess/render.h
src/glu/sgi/libtess/sweep.h
src/glu/sgi/libtess/tess.h
src/glu/sgi/libtess/tessmono.c
src/glu/sgi/libtess/tessmono.h
src/glu/sgi/libutil/error.c
src/glu/sgi/libutil/glue.c
src/glu/sgi/libutil/gluint.h
src/glu/sgi/libutil/project.c
src/glu/sgi/libutil/registry.c
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/demo/Makefile | 31 | ||||
-rw-r--r-- | src/egl/drivers/demo/demo.c | 316 | ||||
-rw-r--r-- | src/egl/drivers/dri/Makefile | 61 | ||||
-rw-r--r-- | src/egl/drivers/dri/egldri.c | 1138 | ||||
-rw-r--r-- | src/egl/drivers/dri/egldri.h | 113 |
5 files changed, 1659 insertions, 0 deletions
diff --git a/src/egl/drivers/demo/Makefile b/src/egl/drivers/demo/Makefile new file mode 100644 index 00000000000..5c05633df50 --- /dev/null +++ b/src/egl/drivers/demo/Makefile @@ -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: $(TOP)/$(LIB_DIR)/demodriver.so + + +$(TOP)/$(LIB_DIR)/demodriver.so: $(OBJECTS) + $(TOP)/bin/mklib -o demodriver.so -noprefix \ + -install $(TOP)/$(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 index 00000000000..45545755c00 --- /dev/null +++ b/src/egl/drivers/demo/demo.c @@ -0,0 +1,316 @@ +/* + * 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; + + /* Create a screen */ + scrn = calloc(1, sizeof(*scrn)); + _eglAddScreen(disp, scrn); + + /* Create the screen's modes - silly example */ + _eglAddNewMode(scrn, 1600, 1200, 72 * 1000, "1600x1200-72"); + _eglAddNewMode(scrn, 1280, 1024, 72 * 1000, "1280x1024-70"); + _eglAddNewMode(scrn, 1280, 1024, 70 * 1000, "1280x1024-70"); + _eglAddNewMode(scrn, 1024, 768, 72 * 1000, "1024x768-72"); + + /* Create the display's visual configs - silly example */ + for (i = 0; i < 4; i++) { + _EGLConfig config; + _eglInitConfig(&config, i + 1); + _eglSetConfigAttrib(&config, EGL_RED_SIZE, 8); + _eglSetConfigAttrib(&config, EGL_GREEN_SIZE, 8); + _eglSetConfigAttrib(&config, EGL_BLUE_SIZE, 8); + _eglSetConfigAttrib(&config, EGL_ALPHA_SIZE, 8); + _eglSetConfigAttrib(&config, EGL_BUFFER_SIZE, 32); + if (i & 1) { + _eglSetConfigAttrib(&config, EGL_DEPTH_SIZE, 32); + } + if (i & 2) { + _eglSetConfigAttrib(&config, EGL_STENCIL_SIZE, 8); + } + _eglSetConfigAttrib(&config, EGL_SURFACE_TYPE, + (EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)); + _eglAddConfig(disp, &config); + } + + 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; + 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(drv, dpy, &c->Base, config, attrib_list); + 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) +{ + DemoSurface *surf = (DemoSurface *) calloc(1, sizeof(DemoSurface)); + if (!surf) + return EGL_NO_SURFACE; + + if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT, + config, attrib_list)) { + free(surf); + return EGL_NO_SURFACE; + } + + /* a real driver would allocate the pbuffer memory here */ + + 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; +} + + +/** + * The bootstrap function. Return a new DemoDriver object and + * plug in API functions. + */ +_EGLDriver * +_eglMain(_EGLDisplay *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.API.Initialize = demoInitialize; + demo->Base.API.Terminate = demoTerminate; + demo->Base.API.CreateContext = demoCreateContext; + demo->Base.API.MakeCurrent = demoMakeCurrent; + demo->Base.API.CreateWindowSurface = demoCreateWindowSurface; + demo->Base.API.CreatePixmapSurface = demoCreatePixmapSurface; + demo->Base.API.CreatePbufferSurface = demoCreatePbufferSurface; + demo->Base.API.DestroySurface = demoDestroySurface; + demo->Base.API.DestroyContext = demoDestroyContext; + + /* enable supported extensions */ + demo->Base.Extensions.MESA_screen_surface = EGL_TRUE; + demo->Base.Extensions.MESA_copy_context = EGL_TRUE; + + return &demo->Base; +} diff --git a/src/egl/drivers/dri/Makefile b/src/egl/drivers/dri/Makefile new file mode 100644 index 00000000000..cb11971c640 --- /dev/null +++ b/src/egl/drivers/dri/Makefile @@ -0,0 +1,61 @@ +# src/egl/drivers/dri/Makefile + +TOP = ../../../.. +include $(TOP)/configs/current + + +### Include directories +INCLUDE_DIRS = \ + -I. \ + -I/usr/include \ + -I/usr/include/drm \ + -I$(TOP)/include \ + -I$(TOP)/include/GL/internal \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa/glapi \ + -I$(TOP)/src/mesa/math \ + -I$(TOP)/src/mesa/transform \ + -I$(TOP)/src/mesa/shader \ + -I$(TOP)/src/mesa/swrast \ + -I$(TOP)/src/mesa/swrast_setup \ + -I$(TOP)/src/egl/main \ + -I$(TOP)/src/mesa/drivers/dri/common + + +HEADERS = egldri.h + +SOURCES = egldri.c + +OBJECTS = $(SOURCES:.c=.o) + + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + + + +default: depend library Makefile + + +# EGLdri Library +library: $(TOP)/$(LIB_DIR)/libEGLdri.so + +$(TOP)/$(LIB_DIR)/libEGLdri.so: $(OBJECTS) + $(TOP)/bin/mklib -o EGLdri -major 1 -minor 0 \ + -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) + + +clean: + rm -f *.o + rm -f *.so + +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/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c new file mode 100644 index 00000000000..cab0be2bd18 --- /dev/null +++ b/src/egl/drivers/dri/egldri.c @@ -0,0 +1,1138 @@ +/** + * Generic EGL driver for DRI. + * + * This file contains all the code needed to interface DRI-based drivers + * with libEGL. + * + * There's a lot of dependencies on fbdev and the /sys/ filesystem. + */ + + +#include <dirent.h> +#include <stdio.h> +#include <string.h> +#include <linux/fb.h> +#include <assert.h> +#include <dlfcn.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/time.h> + +#include "egldriver.h" +#include "egldisplay.h" +#include "eglcontext.h" +#include "eglconfig.h" +#include "eglsurface.h" +#include "eglscreen.h" +#include "eglglobals.h" +#include "egllog.h" +#include "eglmode.h" + +#include "egldri.h" + +const char *sysfs = "/sys/class"; +#define None 0 +static const int empty_attribute_list[1] = { None }; + + +/** + * The bootstrap function. + * Return a new driDriver object and plug in API functions. + * This function, in turn, loads a specific DRI driver (ex: r200_dri.so). + */ +_EGLDriver * +_eglMain(_EGLDisplay *dpy) +{ + int length; + char path[NAME_MAX]; + struct dirent *dirent; +#if 1 + FILE *file; +#endif + DIR *dir; + _EGLDriver *driver = NULL;; + + snprintf(path, sizeof(path), "%s/drm", sysfs); + if (!(dir = opendir(path))) { + _eglLog(_EGL_WARNING, "%s DRM devices not found.", path); + return EGL_FALSE; + } + while ((dirent = readdir(dir))) { + + if (strncmp(&dirent->d_name[0], "card", 4) != 0) + continue; + if (strcmp(&dirent->d_name[4], &dpy->Name[1]) != 0) + continue; + + snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name", sysfs, &dpy->Name[1]); + _eglLog(_EGL_INFO, "Opening %s", path); +#if 1 + file = fopen(path, "r"); + if (!file) { + _eglLog(_EGL_WARNING, "Failed to open %s", path); + return NULL; + } + fgets(path, sizeof(path), file); + fclose(file); +#else + strcpy(path, "r200\n"); +#endif + if ((length = strlen(path)) > 0) + path[length - 1] = '\0'; /* remove the trailing newline from sysfs */ + strncat(path, "_dri", sizeof(path)); + + driver = _eglOpenDriver(dpy, path); + + break; + } + closedir(dir); + + return driver; +} + + +/** + * Called by eglCreateContext via drv->API.CreateContext(). + */ +static EGLContext +_eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + EGLContext share_list, const EGLint *attrib_list) +{ + driDisplay *disp = Lookup_driDisplay(dpy); + driContext *c, *share; + void *sharePriv; + _EGLConfig *conf; + __GLcontextModes visMode; + + c = (driContext *) calloc(1, sizeof(*c)); + if (!c) + return EGL_NO_CONTEXT; + + if (!_eglInitContext(drv, dpy, &c->Base, config, attrib_list)) { + free(c); + 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_FALSE; + } + } + share = Lookup_driContext(share_list); + if (share) + sharePriv = share->driContext.private; + else + sharePriv = NULL; + + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); + _eglConfigToContextModesRec(conf, &visMode); + + c->driContext.private = disp->driScreen.createNewContext(disp, &visMode, + GLX_WINDOW_BIT, sharePriv, &c->driContext); + if (!c->driContext.private) { + free(c); + return EGL_FALSE; + } + + /* generate handle and insert into hash table */ + _eglSaveContext(&c->Base); + + return c->Base.Handle; +} + + +static EGLBoolean +_eglDRIMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, + EGLSurface read, EGLContext context) +{ + driDisplay *disp = Lookup_driDisplay(dpy); + driContext *ctx = Lookup_driContext(context); + EGLBoolean b; + + b = _eglMakeCurrent(drv, dpy, draw, read, context); + if (!b) + return EGL_FALSE; + + if (ctx) { + ctx->driContext.bindContext(disp, 0, read, draw, &ctx->driContext); + } + else { + /* what's this??? */ + /* _mesa_make_current( NULL, NULL, NULL );*/ + } + return EGL_TRUE; +} + + +static EGLSurface +_eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + driSurface *surf; + + surf = (driSurface *) calloc(1, sizeof(*surf)); + if (!surf) { + return EGL_NO_SURFACE; + } + + if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT, + config, attrib_list)) { + free(surf); + return EGL_NO_SURFACE; + } + + /* create software-based pbuffer */ + { +#if 0 + GLcontext *ctx = NULL; /* this _should_ be OK */ +#endif + GLvisual visMode; + _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + assert(conf); /* bad config should be caught earlier */ + _eglConfigToContextModesRec(conf, &visMode); + +#if 0 + surf->mesa_framebuffer = _mesa_create_framebuffer(&visMode); + _mesa_add_soft_renderbuffers(surf->mesa_framebuffer, + GL_TRUE, /* color bufs */ + visMode.haveDepthBuffer, + visMode.haveStencilBuffer, + visMode.haveAccumBuffer, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */ ); + + /* set pbuffer/framebuffer size */ + _mesa_resize_framebuffer(ctx, surf->mesa_framebuffer, + surf->Base.Width, surf->Base.Height); +#endif + } + + _eglSaveSurface(&surf->Base); + + return surf->Base.Handle; +} + + +static EGLBoolean +_eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +{ + driDisplay *disp = Lookup_driDisplay(dpy); + driSurface *fs = Lookup_driSurface(surface); + + _eglRemoveSurface(&fs->Base); + + fs->drawable.destroyDrawable(disp, fs->drawable.private); + + if (fs->Base.IsBound) { + fs->Base.DeletePending = EGL_TRUE; + } + else { + free(fs); + } + return EGL_TRUE; +} + + +static EGLBoolean +_eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) +{ + driDisplay *disp = Lookup_driDisplay(dpy); + driContext *fc = Lookup_driContext(context); + + _eglRemoveContext(&fc->Base); + + fc->driContext.destroyContext(disp, 0, fc->driContext.private); + + if (fc->Base.IsBound) { + fc->Base.DeletePending = EGL_TRUE; + } + else { + free(fc); + } + return EGL_TRUE; +} + + +/** + * Create a drawing surface which can be directly displayed on a screen. + */ +static EGLSurface +_eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, + const EGLint *attrib_list) +{ + _EGLConfig *config = _eglLookupConfig(drv, dpy, cfg); + driDisplay *disp = Lookup_driDisplay(dpy); + driSurface *surface; + GLvisual visMode; + + surface = (driSurface *) calloc(1, sizeof(*surface)); + if (!surface) { + return EGL_NO_SURFACE; + } + + /* init base class, do error checking, etc. */ + if (!_eglInitSurface(drv, dpy, &surface->Base, EGL_SCREEN_BIT_MESA, + cfg, attrib_list)) { + free(surface); + return EGL_NO_SURFACE; + } + + _eglSaveSurface(&surface->Base); + + + /* + * XXX this is where we should allocate video memory for the surface! + */ + + + /* convert EGLConfig to GLvisual */ + _eglConfigToContextModesRec(config, &visMode); + + /* Create a new DRI drawable */ + if (!disp->driScreen.createNewDrawable(disp, &visMode, surface->Base.Handle, + &surface->drawable, GLX_WINDOW_BIT, + empty_attribute_list)) { + _eglRemoveSurface(&surface->Base); + free(surface); + return EGL_NO_SURFACE; + } + + return surface->Base.Handle; +} + + +/** + * Set the fbdev colormap to a simple linear ramp. + */ +static void +_eglDRILoadColormap(driScreen *scrn) +{ + char path[ NAME_MAX ]; + char *buffer; + int i, fd; + + /* cmap attribute uses 256 lines of 16 bytes. + * Allocate one extra char for the \0 added by sprintf() + */ + if ( !( buffer = malloc( 256 * 16 + 1 ) ) ) { + _eglLog(_EGL_WARNING, "Out of memory in _eglDRILoadColormap"); + return; + } + + /* cmap attribute uses 256 lines of 16 bytes */ + for ( i = 0; i < 256; i++ ) { + int c = (i << 8) | i; /* expand to 16-bit value */ + sprintf(&buffer[i * 16], "%02x%c%04x%04x%04x\n", i, ' ', c, c, c); + } + + snprintf(path, sizeof(path), "%s/graphics/%s/color_map", sysfs, scrn->fb); + if ( !( fd = open( path, O_RDWR ) ) ) { + _eglLog(_EGL_WARNING, "Unable to open %s to set colormap", path); + return; + } + write( fd, buffer, 256 * 16 ); + close( fd ); + + free( buffer ); +} + + +/** + * Show the given surface on the named screen. + * If surface is EGL_NO_SURFACE, disable the screen's output. + * Called via eglShowSurfaceMESA(). + */ +EGLBoolean +_eglDRIShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, + EGLScreenMESA screen, + EGLSurface surface, EGLModeMESA m) +{ + driDisplay *display = Lookup_driDisplay(dpy); + driScreen *scrn = Lookup_driScreen(dpy, screen); + driSurface *surf = Lookup_driSurface(surface); + _EGLMode *mode = _eglLookupMode(dpy, m); + FILE *file; + char fname[NAME_MAX], buffer[1000]; + int temp; + + _eglLog(_EGL_DEBUG, "Enter _eglDRIShowScreenSurface"); + + /* This will check that surface, screen, and mode are valid. + * Also, it checks that the surface is large enough for the mode, etc. + */ + if (!_eglShowScreenSurfaceMESA(drv, dpy, screen, surface, m)) + return EGL_FALSE; + + assert(surface == EGL_NO_SURFACE || surf); + assert(m == EGL_NO_MODE_MESA || mode); + assert(scrn); + + /* + * Blank/unblank screen depending on if m == EGL_NO_MODE_MESA + */ + snprintf(fname, sizeof(fname), "%s/graphics/%s/blank", sysfs, scrn->fb); + file = fopen(fname, "r+"); + if (!file) { + _eglLog(_EGL_WARNING, "kernel patch?? chown all fb sysfs attrib to allow" + " write - %s\n", fname); + return EGL_FALSE; + } + snprintf(buffer, sizeof(buffer), "%d", + (m == EGL_NO_MODE_MESA ? VESA_POWERDOWN : VESA_VSYNC_SUSPEND)); + fputs(buffer, file); + fclose(file); + + if (m == EGL_NO_MODE_MESA) { + /* all done! */ + return EGL_TRUE; + } + + _eglLog(_EGL_INFO, "Setting display mode to %d x %d, %d bpp", + mode->Width, mode->Height, display->bpp); + + /* + * Set the display mode + */ + snprintf(fname, sizeof(fname), "%s/graphics/%s/mode", sysfs, scrn->fb); + file = fopen(fname, "r+"); + if (!file) { + _eglLog(_EGL_WARNING, "Failed to open %s to set mode", fname); + return EGL_FALSE; + } + /* note: nothing happens without the \n! */ + snprintf(buffer, sizeof(buffer), "%s\n", mode->Name); + fputs(buffer, file); + fclose(file); + _eglLog(_EGL_INFO, "Set mode to %s in %s", mode->Name, fname); + + /* + * Set display bpp + */ + snprintf(fname, sizeof(fname), "%s/graphics/%s/bits_per_pixel", + sysfs, scrn->fb); + file = fopen(fname, "r+"); + if (!file) { + _eglLog(_EGL_WARNING, "Failed to open %s to set bpp", fname); + return EGL_FALSE; + } + display->bpp = GET_CONFIG_ATTRIB(surf->Base.Config, EGL_BUFFER_SIZE); + display->cpp = display->bpp / 8; + snprintf(buffer, sizeof(buffer), "%d", display->bpp); + fputs(buffer, file); + fclose(file); + + /* + * Unblank display + */ + snprintf(fname, sizeof(fname), "%s/graphics/%s/blank", sysfs, scrn->fb); + file = fopen(fname, "r+"); + if (!file) { + _eglLog(_EGL_WARNING, "Failed to open %s", fname); + return EGL_FALSE; + } + snprintf(buffer, sizeof(buffer), "%d", VESA_NO_BLANKING); + fputs(buffer, file); + fclose(file); + + /* + * Set fbdev buffer virtual size to surface's size. + */ + snprintf(fname, sizeof(fname), "%s/graphics/%s/virtual_size", sysfs, scrn->fb); + file = fopen(fname, "r+"); + snprintf(buffer, sizeof(buffer), "%d,%d", surf->Base.Width, surf->Base.Height); + fputs(buffer, file); + rewind(file); + fgets(buffer, sizeof(buffer), file); + sscanf(buffer, "%d,%d", &display->virtualWidth, &display->virtualHeight); + fclose(file); + + /* + * round up pitch as needed + */ + temp = display->virtualWidth; + switch (display->bpp / 8) { + case 1: temp = (display->virtualWidth + 127) & ~127; break; + case 2: temp = (display->virtualWidth + 31) & ~31; break; + case 3: + case 4: temp = (display->virtualWidth + 15) & ~15; break; + default: + _eglLog(_EGL_WARNING, "Bad display->bpp = %d in _eglDRIShowScreenSurface"); + } + display->virtualWidth = temp; + + /* + * sanity check + */ + if (surf->Base.Width < display->virtualWidth || + surf->Base.Height < display->virtualHeight) { + /* this case _should_ have been caught at the top of this function */ + _eglLog(_EGL_WARNING, "too small of surface in _eglDRIShowScreenSurfaceMESA " + "%d x %d < %d x %d", + surf->Base.Width, + surf->Base.Height, + display->virtualWidth, + display->virtualHeight); + /* + return EGL_FALSE; + */ + } + + /* This used to be done in the _eglDRICreateScreens routine. */ + _eglDRILoadColormap(scrn); + + return EGL_TRUE; +} + + +/** + * Called by eglSwapBuffers via the drv->API.SwapBuffers() pointer. + * + * If the backbuffer is on a videocard, this is extraordinarily slow! + */ +static EGLBoolean +_eglDRISwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +{ + driSurface *drawable = Lookup_driSurface(draw); + + /* this does error checking */ + if (!_eglSwapBuffers(drv, dpy, draw)) + return EGL_FALSE; + + drawable->drawable.swapBuffers(NULL, drawable->drawable.private); + + return EGL_TRUE; +} + + +EGLBoolean +_eglDRIGetDisplayInfo(driDisplay *dpy) +{ + char path[ NAME_MAX ]; + FILE *file; + int i, rc; + drmSetVersion sv; + drm_magic_t magic; + + snprintf( path, sizeof( path ), "%s/graphics/fb%d/device/device", sysfs, dpy->minor ); + file = fopen( path, "r" ); + if (!file) { + _eglLog(_EGL_WARNING, "Unable to open %s", path); + return EGL_FALSE; + } + fgets( path, sizeof( path ), file ); + sscanf( path, "%x", &dpy->chipset ); + fclose( file ); + + sprintf(path, DRM_DEV_NAME, DRM_DIR_NAME, dpy->minor); + if ( ( dpy->drmFD = open(path, O_RDWR, 0) ) < 0 ) { + _eglLog(_EGL_WARNING, "drmOpen failed."); + return EGL_FALSE; + } + + /* Set the interface version, asking for 1.2 */ + sv.drm_di_major = 1; + sv.drm_di_minor = 2; + sv.drm_dd_major = -1; + if ((rc = drmSetInterfaceVersion(dpy->drmFD, &sv))) + return EGL_FALSE; + + /* self authorize */ + if (drmGetMagic(dpy->drmFD, &magic)) + return EGL_FALSE; + if (drmAuthMagic(dpy->drmFD, magic)) + return EGL_FALSE; + + /* Map framebuffer and SAREA */ + for (i = 0; ; i++) { + drm_handle_t handle, offset; + drmSize size; + drmMapType type; + drmMapFlags flags; + int mtrr; + + if (drmGetMap(dpy->drmFD, i, &offset, &size, &type, &flags, + &handle, &mtrr)) + break; + + if (type == DRM_FRAME_BUFFER) { + rc = drmMap( dpy->drmFD, offset, size, (drmAddressPtr) &dpy->pFB); + if (rc < 0) { + _eglLog(_EGL_WARNING, "drmMap DRM_FAME_BUFFER failed"); + return EGL_FALSE; + } + dpy->fbSize = size; + _eglLog(_EGL_INFO, "Found framebuffer size: %d", dpy->fbSize); + } + else if (type == DRM_SHM) { + rc = drmMap(dpy->drmFD, offset, size, (drmAddressPtr) &dpy->pSAREA); + if (rc < 0 ) { + _eglLog(_EGL_WARNING, "drmMap DRM_SHM failed."); + return EGL_FALSE; + } + dpy->SAREASize = SAREA_MAX; + _eglLog(_EGL_DEBUG, "mapped SAREA 0x%08lx to %p, size %d", + (unsigned long) offset, dpy->pSAREA, dpy->SAREASize ); + } + } + + if (!dpy->pFB) { + _eglLog(_EGL_WARNING, "failed to map framebuffer"); + return EGL_FALSE; + } + + if (!dpy->pSAREA) { + /* if this happens, make sure you're using the most recent DRM modules */ + _eglLog(_EGL_WARNING, "failed to map SAREA"); + return EGL_FALSE; + } + + memset( dpy->pSAREA, 0, dpy->SAREASize ); + + return EGL_TRUE; +} + + + /* Return the DRI per screen structure */ +static __DRIscreen * +__eglFindDRIScreen(__DRInativeDisplay *ndpy, int scrn) +{ + driDisplay *disp = (driDisplay *)ndpy; + return &disp->driScreen; +} + + +static GLboolean +__eglCreateContextWithConfig(__DRInativeDisplay* ndpy, int screen, + int configID, void* context, + drm_context_t * hHWContext) +{ + __DRIscreen *pDRIScreen; + __DRIscreenPrivate *psp; + + pDRIScreen = __eglFindDRIScreen(ndpy, screen); + if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { + return GL_FALSE; + } + psp = (__DRIscreenPrivate *) pDRIScreen->private; + if (psp->fd) { + if (drmCreateContext(psp->fd, hHWContext)) { + _eglLog(_EGL_WARNING, "drmCreateContext failed."); + return GL_FALSE; + } + *(void**)context = (void*) *hHWContext; + } +#if 0 + __DRIscreen *pDRIScreen; + __DRIscreenPrivate *psp; + + pDRIScreen = __glXFindDRIScreen(dpy, screen); + if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { + return GL_FALSE; + } + + psp = (__DRIscreenPrivate *) pDRIScreen->private; + + if (psp->fd) { + if (drmCreateContext(psp->fd, hHWContext)) { + _eglLog(_EGL_WARNING, "drmCreateContext failed."); + return GL_FALSE; + } + *(void**)contextID = (void*) *hHWContext; + } +#endif + return GL_TRUE; +} + + +static GLboolean +__eglDestroyContext( __DRInativeDisplay * ndpy, int screen, __DRIid context ) +{ + __DRIscreen *pDRIScreen; + __DRIscreenPrivate *psp; + + pDRIScreen = __eglFindDRIScreen(ndpy, screen); + if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { + return GL_FALSE; + } + psp = (__DRIscreenPrivate *) pDRIScreen->private; + if (psp->fd) + drmDestroyContext(psp->fd, context); + + return GL_TRUE; +} + + +static GLboolean +__eglCreateDrawable(__DRInativeDisplay * ndpy, int screen, + __DRIid drawable, drm_drawable_t * hHWDrawable) +{ + __DRIscreen *pDRIScreen; + __DRIscreenPrivate *psp; + + pDRIScreen = __eglFindDRIScreen(ndpy, screen); + if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { + return GL_FALSE; + } + psp = (__DRIscreenPrivate *) pDRIScreen->private; + if (psp->fd) { + if (drmCreateDrawable(psp->fd, hHWDrawable)) { + _eglLog(_EGL_WARNING, "drmCreateDrawable failed."); + return GL_FALSE; + } + } + return GL_TRUE; +} + + +static GLboolean +__eglDestroyDrawable( __DRInativeDisplay * ndpy, int screen, __DRIid drawable ) +{ + __DRIscreen *pDRIScreen; + __DRIscreenPrivate *psp; + + pDRIScreen = __eglFindDRIScreen(ndpy, screen); + if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { + return GL_FALSE; + } + psp = (__DRIscreenPrivate *) pDRIScreen->private; + if (psp->fd) + drmDestroyDrawable(psp->fd, drawable); + + return GL_TRUE; +} + +static GLboolean +__eglGetDrawableInfo(__DRInativeDisplay * ndpy, int screen, __DRIid drawable, + unsigned int* index, unsigned int* stamp, + int* X, int* Y, int* W, int* H, + int* numClipRects, drm_clip_rect_t ** pClipRects, + int* backX, int* backY, + int* numBackClipRects, drm_clip_rect_t ** pBackClipRects ) +{ + __DRIscreen *pDRIScreen; + __DRIscreenPrivate *psp; + driSurface *surf = Lookup_driSurface(drawable); + + pDRIScreen = __eglFindDRIScreen(ndpy, screen); + + if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { + return GL_FALSE; + } + psp = (__DRIscreenPrivate *) pDRIScreen->private; + *X = 0; + *Y = 0; + *W = surf->Base.Width; + *H = surf->Base.Height; + + *backX = 0; + *backY = 0; + *numBackClipRects = 0; + *pBackClipRects = NULL; + + *numClipRects = 1; + *pClipRects = malloc(sizeof(**pClipRects)); + **pClipRects = (drm_clip_rect_t){0, 0, surf->Base.Width, surf->Base.Height}; + + psp->pSAREA->drawableTable[0].stamp = 1; + *stamp = 1; +#if 0 + GLXDrawable drawable = (GLXDrawable) draw; + drm_clip_rect_t * cliprect; + Display* display = (Display*)dpy; + __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)CurrentContext->driContext.private; + if (drawable == 0) { + return GL_FALSE; + } + + cliprect = (drm_clip_rect_t*) _mesa_malloc(sizeof(drm_clip_rect_t)); + cliprect->x1 = drawable->x; + cliprect->y1 = drawable->y; + cliprect->x2 = drawable->x + drawable->w; + cliprect->y2 = drawable->y + drawable->h; + + /* the drawable index is by client id */ + *index = display->clientID; + + *stamp = pcp->driScreenPriv->pSAREA->drawableTable[display->clientID].stamp; + *x = drawable->x; + *y = drawable->y; + *width = drawable->w; + *height = drawable->h; + *numClipRects = 1; + *pClipRects = cliprect; + + *backX = drawable->x; + *backY = drawable->y; + *numBackClipRects = 0; + *pBackClipRects = 0; +#endif + return GL_TRUE; +} + + +/** + * Implement \c __DRIinterfaceMethods::getProcAddress. + */ +static __DRIfuncPtr +get_proc_address(const char * proc_name) +{ + return NULL; +} + + +/** + * Destroy a linked list of \c __GLcontextModes structures created by + * \c _gl_context_modes_create. + * + * \param modes Linked list of structures to be destroyed. All structres + * in the list will be freed. + */ +static void +__egl_context_modes_destroy(__GLcontextModes *modes) +{ + while ( modes != NULL ) { + __GLcontextModes * const next = modes->next; + + free( modes ); + modes = next; + } +} + + +/** + * Allocate a linked list of \c __GLcontextModes structures. The fields of + * each structure will be initialized to "reasonable" default values. In + * most cases this is the default value defined by table 3.4 of the GLX + * 1.3 specification. This means that most values are either initialized to + * zero or \c GLX_DONT_CARE (which is -1). As support for additional + * extensions is added, the new values will be initialized to appropriate + * values from the extension specification. + * + * \param count Number of structures to allocate. + * \param minimum_size Minimum size of a structure to allocate. This allows + * for differences in the version of the + * \c __GLcontextModes stucture used in libGL and in a + * DRI-based driver. + * \returns A pointer to the first element in a linked list of \c count + * stuctures on success, or \c NULL on failure. + * + * \warning Use of \c minimum_size does \b not guarantee binary compatibility. + * The fundamental assumption is that if the \c minimum_size + * specified by the driver and the size of the \c __GLcontextModes + * structure in libGL is the same, then the meaning of each byte in + * the structure is the same in both places. \b Be \b careful! + * Basically this means that fields have to be added in libGL and + * then propagated to drivers. Drivers should \b never arbitrarilly + * extend the \c __GLcontextModes data-structure. + */ +static __GLcontextModes * +__egl_context_modes_create(unsigned count, size_t minimum_size) +{ + const size_t size = (minimum_size > sizeof( __GLcontextModes )) + ? minimum_size : sizeof( __GLcontextModes ); + __GLcontextModes * base = NULL; + __GLcontextModes ** next; + unsigned i; + + next = & base; + for ( i = 0 ; i < count ; i++ ) { + *next = (__GLcontextModes *) malloc( size ); + if ( *next == NULL ) { + __egl_context_modes_destroy( base ); + base = NULL; + break; + } + + (void) memset( *next, 0, size ); + (*next)->visualID = GLX_DONT_CARE; + (*next)->visualType = GLX_DONT_CARE; + (*next)->visualRating = GLX_NONE; + (*next)->transparentPixel = GLX_NONE; + (*next)->transparentRed = GLX_DONT_CARE; + (*next)->transparentGreen = GLX_DONT_CARE; + (*next)->transparentBlue = GLX_DONT_CARE; + (*next)->transparentAlpha = GLX_DONT_CARE; + (*next)->transparentIndex = GLX_DONT_CARE; + (*next)->xRenderable = GLX_DONT_CARE; + (*next)->fbconfigID = GLX_DONT_CARE; + (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; + + next = & ((*next)->next); + } + + return base; +} + + +static GLboolean +__eglWindowExists(__DRInativeDisplay *dpy, __DRIid draw) +{ + return EGL_TRUE; +} + + +/** + * Get the unadjusted system time (UST). Currently, the UST is measured in + * microseconds since Epoc. The actual resolution of the UST may vary from + * system to system, and the units may vary from release to release. + * Drivers should not call this function directly. They should instead use + * \c glXGetProcAddress to obtain a pointer to the function. + * + * \param ust Location to store the 64-bit UST + * \returns Zero on success or a negative errno value on failure. + * + * \sa glXGetProcAddress, PFNGLXGETUSTPROC + * + * \since Internal API version 20030317. + */ +static int +__eglGetUST(int64_t *ust) +{ + struct timeval tv; + + if ( ust == NULL ) { + return -EFAULT; + } + + if ( gettimeofday( & tv, NULL ) == 0 ) { + ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; + return 0; + } + else { + return -errno; + } +} + +/** + * Determine the refresh rate of the specified drawable and display. + * + * \param dpy Display whose refresh rate is to be determined. + * \param drawable Drawable whose refresh rate is to be determined. + * \param numerator Numerator of the refresh rate. + * \param demoninator Denominator of the refresh rate. + * \return If the refresh rate for the specified display and drawable could + * be calculated, True is returned. Otherwise False is returned. + * + * \note This function is implemented entirely client-side. A lot of other + * functionality is required to export GLX_OML_sync_control, so on + * XFree86 this function can be called for direct-rendering contexts + * when GLX_OML_sync_control appears in the client extension string. + */ +static GLboolean +__eglGetMSCRate(__DRInativeDisplay * dpy, __DRIid drawable, + int32_t * numerator, int32_t * denominator) +{ + return EGL_TRUE; +} + + +/** + * Table of functions exported by the loader to the driver. + */ +static const __DRIinterfaceMethods interface_methods = { + get_proc_address, + + __egl_context_modes_create, + __egl_context_modes_destroy, + + __eglFindDRIScreen, + __eglWindowExists, + + __eglCreateContextWithConfig, + __eglDestroyContext, + + __eglCreateDrawable, + __eglDestroyDrawable, + __eglGetDrawableInfo, + + __eglGetUST, + __eglGetMSCRate, +}; + + +static int +__glXGetInternalVersion(void) +{ + return 20050725; +} + +static const char createNewScreenName[] = "__driCreateNewScreen_20050727"; + + +/** + * Do per-display initialization. + */ +EGLBoolean +_eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer) +{ + PFNCREATENEWSCREENFUNC createNewScreen; + int api_ver = __glXGetInternalVersion(); + __DRIversion ddx_version; + __DRIversion dri_version; + __DRIversion drm_version; + drmVersionPtr version; + + version = drmGetVersion( dpy->drmFD ); + if ( version ) { + drm_version.major = version->version_major; + drm_version.minor = version->version_minor; + drm_version.patch = version->version_patchlevel; + drmFreeVersion( version ); + } + else { + drm_version.major = -1; + drm_version.minor = -1; + drm_version.patch = -1; + } + + /* + * Get device name (like "tdfx") and the ddx version numbers. + * We'll check the version in each DRI driver's "createScreen" + * function. + */ + ddx_version.major = 4; + ddx_version.minor = 0; + ddx_version.patch = 0; + + /* + * Get the DRI X extension version. + */ + dri_version.major = 4; + dri_version.minor = 0; + dri_version.patch = 0; + + createNewScreen = ( PFNCREATENEWSCREENFUNC ) dlsym( dpy->Base.Driver->LibHandle, createNewScreenName ); + if ( !createNewScreen ) { + _eglLog(_EGL_WARNING, "Couldn't find %s function in the driver.", + createNewScreenName ); + return EGL_FALSE; + } + + dpy->driScreen.private = createNewScreen( dpy, 0, &dpy->driScreen, NULL, + &ddx_version, &dri_version, + &drm_version, framebuffer, + dpy->pSAREA, dpy->drmFD, + api_ver, + & interface_methods, + NULL); + if (!dpy->driScreen.private) + return EGL_FALSE; + + DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext ); + + return EGL_TRUE; +} + + +/** + * Create all the EGL screens for the given display. + */ +EGLBoolean +_eglDRICreateScreens(driDisplay *dpy) +{ + const int numScreens = 1; /* XXX fix this someday */ + int i; + + for (i = 0; i < numScreens; i++) { + char path[ NAME_MAX ]; + FILE *file; + driScreen *s; + + /* Create a screen */ + if ( !( s = ( driScreen * ) calloc( 1, sizeof( *s ) ) ) ) + return EGL_FALSE; + + snprintf( s->fb, NAME_MAX, "fb%d", dpy->minor ); + _eglInitScreen( &s->Base ); + + _eglAddScreen( &dpy->Base, &s->Base ); + + /* Create the screen's mode list */ + snprintf( path, sizeof( path ), "%s/graphics/%s/modes", sysfs, s->fb ); + file = fopen( path, "r" ); + while ( fgets( path, sizeof( path ), file ) ) { + unsigned int x, y, r; + char c; + path[ strlen( path ) - 1 ] = '\0'; /* strip off \n from sysfs */ + sscanf( path, "%c:%ux%u-%u", &c, &x, &y, &r ); + _eglAddNewMode( &s->Base, x, y, r * 1000, path ); + } + fclose( file ); + + /* + * NOTE: we used to set the colormap here, but that didn't work reliably. + * Some entries near the start of the table would get corrupted by later + * mode changes. + */ + } + + return EGL_TRUE; +} + + +EGLBoolean +_eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy, + EGLint *major, EGLint *minor) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + driDisplay *display; + + assert(disp); + + /* Create new driDisplay object to replace the _EGLDisplay that was + * previously created. + */ + display = calloc(1, sizeof(*display)); + display->Base = *disp; + _eglHashInsert(_eglGlobal.Displays, disp->Handle, display); + free(disp); + + *major = 1; + *minor = 0; + + sscanf(&disp->Name[1], "%d", &display->minor); + + drv->Initialized = EGL_TRUE; + return EGL_TRUE; +} + + +static EGLBoolean +_eglDRITerminate(_EGLDriver *drv, EGLDisplay dpy) +{ + driDisplay *display = Lookup_driDisplay(dpy); + _eglCleanupDisplay(&display->Base);/*rename that function*/ + free(display); + free(drv); + return EGL_TRUE; +} + + +/** + * Plug in the DRI-specific functions into the driver's dispatch table. + * Also, enable some EGL extensions. + */ +void +_eglDRIInitDriverFallbacks(_EGLDriver *drv) +{ + _eglInitDriverFallbacks(drv); + + drv->API.Initialize = _eglDRIInitialize; + drv->API.Terminate = _eglDRITerminate; + drv->API.CreateContext = _eglDRICreateContext; + drv->API.MakeCurrent = _eglDRIMakeCurrent; + drv->API.CreatePbufferSurface = _eglDRICreatePbufferSurface; + drv->API.DestroySurface = _eglDRIDestroySurface; + drv->API.DestroyContext = _eglDRIDestroyContext; + drv->API.CreateScreenSurfaceMESA = _eglDRICreateScreenSurfaceMESA; + drv->API.ShowScreenSurfaceMESA = _eglDRIShowScreenSurfaceMESA; + drv->API.SwapBuffers = _eglDRISwapBuffers; + + /* enable supported extensions */ + drv->Extensions.MESA_screen_surface = EGL_TRUE; + drv->Extensions.MESA_copy_context = EGL_TRUE; +} diff --git a/src/egl/drivers/dri/egldri.h b/src/egl/drivers/dri/egldri.h new file mode 100644 index 00000000000..34b12d64fcd --- /dev/null +++ b/src/egl/drivers/dri/egldri.h @@ -0,0 +1,113 @@ +#ifndef EGLDRI_INCLUDED +#define EGLDRI_INCLUDED + +#include "egldisplay.h" +#include "eglscreen.h" +#include "eglsurface.h" +#include "eglcontext.h" +#include "mtypes.h" +#include "dri_util.h" +#include "drm_sarea.h" + +/** + * dri display-specific driver class derived from _EGLDisplay + */ +typedef struct dri_display +{ + _EGLDisplay Base; /* base class/object */ + void *pFB; + int drmFD; /**< \brief DRM device file descriptor */ + int minor; + unsigned long hFrameBuffer; + + int virtualWidth; + int virtualHeight; + int fbSize; + int bpp; + int cpp; + int card_type; + int SAREASize; + drm_sarea_t *pSAREA; + unsigned int serverContext; /**< \brief DRM context only active on server */ + unsigned long FBStart; /**< \brief physical address of the framebuffer */ + void *driverClientMsg; + int driverClientMsgSize; + int chipset; + void *driverPrivate; + drm_magic_t magic; + + __DRIscreen driScreen; + +} driDisplay; + + +/** + * dri driver-specific screen class derived from _EGLScreen + */ +typedef struct dri_screen +{ + _EGLScreen Base; + char fb[NAME_MAX]; /** the screen name, like "fb0" */ +} driScreen; + + +/** + * dri driver-specific surface class derived from _EGLSurface + */ +typedef struct dri_surface +{ + _EGLSurface Base; /* base class/object */ + __DRIdrawable drawable; +} driSurface; + + +/** + * dri driver-specific context class derived from _EGLContext + */ +typedef struct dri_context +{ + _EGLContext Base; /* base class/object */ + __DRIcontext driContext; /**< \brief context dependent methods */ +} driContext; + + + +static inline driDisplay * +Lookup_driDisplay(EGLDisplay dpy) +{ + _EGLDisplay *d = _eglLookupDisplay(dpy); + return (driDisplay *) d; +} + + +static inline driScreen * +Lookup_driScreen(EGLDisplay dpy, EGLScreenMESA screen) +{ + _EGLScreen *s = _eglLookupScreen(dpy, screen); + return (driScreen *) s; +} + + +static inline driContext * +Lookup_driContext(EGLContext ctx) +{ + _EGLContext *c = _eglLookupContext(ctx); + return (driContext *) c; +} + + +static inline driSurface * +Lookup_driSurface(EGLSurface surf) +{ + _EGLSurface *s = _eglLookupSurface(surf); + return (driSurface *) s; +} + +extern void _eglDRIInitDriverFallbacks(_EGLDriver *drv); +extern EGLBoolean _eglDRIShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA m); +extern EGLBoolean _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor); +extern EGLBoolean _eglDRIGetDisplayInfo(driDisplay *dpy); +extern EGLBoolean _eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer); +extern EGLBoolean _eglDRICreateScreens(driDisplay *dpy); + +#endif /* EGLDRI_INCLUDED */ |