summaryrefslogtreecommitdiffstats
path: root/src/egl
diff options
context:
space:
mode:
authorDavid Nusinow <[email protected]>2006-09-24 21:11:46 +0000
committerDavid Nusinow <[email protected]>2006-09-24 21:11:46 +0000
commiteadb76b3f8e0e9b82da762bd29e53895bf9e6351 (patch)
treeb9f68fc763f9ea055287c366e61de84191b200ce /src/egl
parentb3f7313ae4f4cd418522595e90e7d06ef6992f0a (diff)
Bump to latest mesa in Debian
Diffstat (limited to 'src/egl')
-rw-r--r--src/egl/Makefile24
-rw-r--r--src/egl/docs/EGL_MESA_screen_surface578
-rw-r--r--src/egl/drivers/demo/Makefile31
-rw-r--r--src/egl/drivers/demo/demo.c316
-rw-r--r--src/egl/drivers/dri/Makefile64
-rw-r--r--src/egl/drivers/dri/egldri.c1138
-rw-r--r--src/egl/drivers/dri/egldri.h113
-rw-r--r--src/egl/main/Makefile66
-rw-r--r--src/egl/main/eglapi.c586
-rw-r--r--src/egl/main/eglapi.h119
-rw-r--r--src/egl/main/eglconfig.c638
-rw-r--r--src/egl/main/eglconfig.h67
-rw-r--r--src/egl/main/eglcontext.c276
-rw-r--r--src/egl/main/eglcontext.h71
-rw-r--r--src/egl/main/egldisplay.c71
-rw-r--r--src/egl/main/egldisplay.h44
-rw-r--r--src/egl/main/egldriver.c272
-rw-r--r--src/egl/main/egldriver.h81
-rw-r--r--src/egl/main/eglglobals.c148
-rw-r--r--src/egl/main/eglglobals.h68
-rw-r--r--src/egl/main/eglhash.c347
-rw-r--r--src/egl/main/eglhash.h39
-rw-r--r--src/egl/main/egllog.c57
-rw-r--r--src/egl/main/egllog.h16
-rw-r--r--src/egl/main/eglmode.c431
-rw-r--r--src/egl/main/eglmode.h54
-rw-r--r--src/egl/main/eglscreen.c328
-rw-r--r--src/egl/main/eglscreen.h90
-rw-r--r--src/egl/main/eglsurface.c530
-rw-r--r--src/egl/main/eglsurface.h117
-rw-r--r--src/egl/main/egltypedefs.h34
31 files changed, 6814 insertions, 0 deletions
diff --git a/src/egl/Makefile b/src/egl/Makefile
new file mode 100644
index 00000000000..931e9d0cb86
--- /dev/null
+++ b/src/egl/Makefile
@@ -0,0 +1,24 @@
+# src/egl/Makefile
+
+TOP = ../..
+
+SUBDIRS = main drivers/demo drivers/dri
+
+
+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/docs/EGL_MESA_screen_surface b/src/egl/docs/EGL_MESA_screen_surface
new file mode 100644
index 00000000000..3a11da7ac9b
--- /dev/null
+++ b/src/egl/docs/EGL_MESA_screen_surface
@@ -0,0 +1,578 @@
+Name
+
+ MESA_screen_surface
+
+Name Strings
+
+ EGL_MESA_screen_surface
+
+Contact
+
+ Brian Paul
+
+ To discuss, join the [email protected] list.
+
+Status
+
+ Preliminary - totally subject to change.
+
+Version
+
+ 10 (10 August 2005)
+
+Number
+
+ TBD
+
+Dependencies
+
+ EGL 1.0 or later.
+
+Overview
+
+ EGL 1.1 supports three types of drawing surfaces:
+ * Window surfaces
+ * Pixmap surfaces
+ * Pbuffer surfaces
+ This extension defines a fourth type of drawing surface:
+ * Screen surface
+
+ A screen surface is a surface for which the (front) color buffer can
+ be directly displayed (i.e. scanned out) on a monitor (such as a flat
+ panel or CRT). In particular the color buffer memory will be allocated
+ at a location in VRAM (and in a suitable format) which can be displayed
+ by the graphics hardware.
+
+ Note that the width and height of the screen surface need not exactly
+ match the monitor's current resolution. For example, while the monitor
+ may be configured to to show 1024x768 pixels, the associated screen
+ surface may be larger, such as 1200x1000. The "screen origin" attribute
+ will specify which region of the screen surface which is visible on the
+ monitor. The screen surface can be scrolled by changing this origin.
+
+ This extension also defines functions for controlling the monitor's
+ display mode (width, height, refresh rate, etc), and specifing which
+ screen surface is to be displayed on a monitor.
+
+ The new EGLModeMESA type and related functions are very similar to the
+ EGLConfig type and related functions. The user may get a list of
+ supported modes for a screen and specify the mode to be used when
+ displaying a screen surface.
+
+
+Issues
+
+ 1. Should EGL_INTERLACE be a supported mode attribute?
+
+ Arguments against:
+
+ No, this should be provided by another extension which would
+ also provide the mechanisms needed to play back interlaced video
+ material correctly on hardware that supports it.
+ This extension should prefer non-interlaced modes. [M. Danzer]
+
+ Arguments for:
+
+ An interlaced display can be of use without considering video
+ material. Being able to query whether a screen is operating in
+ interlaced mode can be used by applications to control their
+ drawing. For example: avoid drawing 1-pixel-wide horizontal lines
+ if screen is interlaced. [B. Paul]
+
+ Resolution: Defer for future extension?
+
+
+ 2. Should EGL_REFRESH_RATE be a supported mode attribute?
+
+ Arguments for:
+
+ Yes, it's been shown that applications and/or users need to select
+ modes by this. [M. Danzer]
+
+ Many examples have been given in which it's desirable to let the
+ user choose from a variety of refresh rates without having to
+ restart/reconfigure. [B. Paul]
+
+ Arguments against:
+
+ TBD.
+
+ Resolution: Yes.
+
+
+ 3. Exactly how should the list of modes returned by eglChooseConfigMESA
+ be sorted?
+
+ Current method is described in the text below. Subject to change.
+
+ Alternately, leave the sorting order undefined so that each
+ implementation can return the modes in order of "most desirable"
+ to "least desirable" which may depend on the display technology
+ (CRT vs LCD, etc) or other factors.
+
+
+ 4. How should screen blanking be supported? Note that a screen can be
+ disabled or turned off by calling eglShowSurface(dpy, scrn,
+ EGL_NO_SURFACE, EGL_NO_MODE_MESA). But what about power-save mode?
+
+ I would defer this to other extensions that depend on this one.
+ I can imagine people wanting different semantics not just in
+ relation to the power management API being exposed (DPMS or whatever)
+ but also relating to what events can trigger EGL_CONTEXT_LOST. Also
+ I'm not sure whether power management commands are properly operations
+ on the Display or on a screen surface. [A. Jackson]
+
+
+ 5. Should the EGL_PHYSICAL_SIZE_EGL query be kept? The size information
+ isn't always reliable (consider video projectors) but can still be
+ used to determine the pixel aspect ratio.
+
+ Arguments for:
+
+ X supports a similar query with DisplayWidthMM(), DisplayHeightMM().
+ If this information can be easily queried with EDID, why not
+ make it available to the user?
+
+ Arguments against:
+
+ Historically, these values aren't always accurate. Also, they're
+ not always applicable to the display device.
+
+ Other options:
+
+ Perhaps just a pixel aspect ratio should be supported. [M. Danzer]
+
+ Postpone for a future extension, if needed. [A. Jackson]
+
+
+ 6. Should detailed mode timing information be exposed by this API?
+
+ Probably not. Instead, offer that information in a layered extension.
+
+
+ 7. How should the notion of a screen's "native" mode be expressed?
+ For example, LCD panels have a native resolution and refresh rate
+ that looks best but other sub-optimal resolutions may be supported.
+
+ The mode attribute EGL_OPTIMAL_MESA will be set for modes which
+ best match the screen. [M. Danzer]
+
+
+ 8. Should eglQueryModeStringMESA() be included? This function returns
+ a human-readable string which corresponds to an EGLMode.
+
+ Arguments for:
+
+ A mode name such as "HDTV-720P" might mean more to users than
+ "1280x720@60Hz" if the later were generated via code.
+
+ Arguments against:
+
+ There's no standard syntax for the strings. May cause more
+ trouble than it's worth.
+
+ Postpone for future extension. [A. Jackson]
+
+ Latest discussion leaning toward omitting this function.
+
+
+ 9. Should we use "Get" or "Query" for functions which return state?
+ The EGL 1.x specification doesn't seem to be totally consistent
+ in this regard, but "Query" is used more often.
+
+ Use "Get" for mode-related queries (as for EGLConfigs) but "Query"
+ for everything else.
+
+
+ 10. What should be the default size for screen surfaces?
+
+ For Pbuffer surfaces the default width and height are zero.
+ We'll do the same for screen surfaces. Since there's no function
+ to resize surfaces it's useless to have a 0x0 screen, but this isn't
+ a situation that'll normally be encountered.
+
+
+ 11. Should there be a function for resizing a screen surface?
+
+ Suppose one wants to change the screen's size in the EGL application.
+ Also suppose there's a hardware restriction such that only one screen
+ surface can exist at a time (either for lack of memory or because of
+ memory layout restrictions).
+
+ The basic idea is that the currently displayed screen surface must
+ be deallocated before a new one can be created. Perhaps a resize
+ function would work better?
+
+
+ 12. How should sub-pixel LCD color information be made available?
+ What about the display's gamma value?
+
+ Perhaps expose as additional read-only mode attributes.
+
+ Perhaps postpone for a layered extension.
+
+
+ 13. What happens if the user attempts to delete a screen surface that
+ is currently being shown?
+
+ Spec currently says that's illegal and that an error (TBD) will be
+ generated.
+
+
+ 14. What if the physical screen size can't be determined? Should
+ a query of EGL_PHYSICAL_SIZE_MESA return [0,0]?
+
+ TBD.
+
+
+ 15. Suppose the device's number of RAMDACs is different from the
+ number of output ports. For example, a graphics card with
+ two RAMDACs but three ports (VGA, DVI, TV).
+
+ Address this in a follow-on extension. [Matthias Hopf]
+
+
+ 16. How should we deal with on-the-fly device changes? For example,
+ the monitor being unplugged and replaced by another with different
+ characteristics?
+
+ A HAL event could be received via DBUS in the application [J. Smirl,
+ A. Jackson].
+
+ Should there be an EGL mechanism for detecting this? Maybe an
+ EGL_SCREEN_LOST error (similar to EGL_CONTEXT_LOST) can be recorded
+ when there's a screen change. At least then the application can
+ poll to detect this situation.
+
+ Maybe leave that to a future extension.
+
+ See also the EGL_SCREEN_COUNT_MESA query.
+
+
+ 17. What if pixel-accurate panning is not supported (see
+ eglScreenPositionMESA)? [M. Danzer]
+
+ Is this a common problem? Can we ignore it for now?
+
+
+ 18. Should eglShowSurfaceMESA be renamed to eglShowScreenSurfaceMESA?
+
+ Probably.
+
+
+
+New Procedures and Functions
+
+ EGLBoolean eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ const EGLint *attrib_list,
+ EGLModeMESA *modes, EGLint modes_size,
+ EGLint *num_modes)
+
+ EGLBoolean eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLModeMESA *modes, EGLint modes_size,
+ EGLint *num_modes)
+
+ EGLBoolean eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
+ EGLint attrib, EGLint *value)
+
+
+ EGLBoolean eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
+ EGLint screens_size, EGLint *num_screens)
+
+ EGLSurface eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
+
+ EGLBoolean eglShowSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLSurface surface, EGLModeMESA mode)
+
+ EGLBoolean eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLint x, EGLint y)
+
+
+ EGLBoolean eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLint attrib, EGLint *value);
+
+ EGLBoolean eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLSurface *surface)
+
+ EGLBoolean eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLModeMESA *mode)
+
+ const char *eglQueryModeStringMESA(EGLDisplay dpy, EGLMode mode);
+
+
+New Types
+
+ EGLModeMESA
+ EGLScreenMESA
+
+New Tokens
+
+ New error codes:
+
+ EGL_BAD_SCREEN_MESA
+ EGL_BAD_MODE_MESA
+
+ Screen-related tokens:
+
+ EGL_SCREEN_COUNT_MESA
+ EGL_SCREEN_POSITION_MESA
+ EGL_PHYSICAL_SIZE_MESA
+ EGL_SCREEN_BIT_MESA
+ EGL_SCREEN_POSITION_GRANULARITY_MESA
+
+ Mode-related tokens:
+
+ EGL_MODE_ID_MESA
+ EGL_REFRESH_RATE_MESA
+ EGL_INTERLACED_MESA
+ EGL_OPTIMAL_MESA
+ EGL_NO_MODE_MESA
+
+
+Additions to Chapter X of the EGL 1.1 Specification
+
+ [XXX this all has to be rewritten to fit into the EGL specification
+ and match the conventions of an EGL extension. For now, just list
+ all the functions with brief descriptions.]
+
+
+ EGLBoolean eglChooseModeMESA(EGLDisplay dpy, const EGLScreenMESA screen,
+ EGLint *attrib_list, EGLModeMESA *modes,
+ EGLint modes_size, EGLint *num_modes)
+
+ Like eglChooseConfig, returns a list of EGLModes which match the given
+ attribute list. This does not set the screen's current display mode.
+ The attribute list is a list of token/value pairs terminated with
+ EGL_NONE. Supported attributes include:
+
+ Name Description
+ --------------------- ---------------------------------------------
+ EGL_WIDTH Mode width (resolution)
+ EGL_HEIGHT Mode height (resolution)
+ EGL_REFRESH_RATE_MESA The mode's refresh rate, multiplied by 1000
+ EGL_INTERLACED_MESA 1 indicates an interlaced mode, 0 otherwise
+ EGL_OPTIMAL_MESA Set if the most is especially optimal for the
+ screen (ex. for particular LCD resolutions)
+
+ Any other token will generate the error EGL_BAD_ATTRIBUTE.
+
+ The list of modes returned by eglChooseModeMESA will be sorted
+ according to the following criteria. See the discussion of table 3.3
+ in the EGL specification for more information.
+
+ Selection Sort Sort
+ Attribute Default Criteria Order Priority
+ -------------------- -------------- ----------- ------ --------
+ EGL_OPTIMAL_MESA EGL_DONT_CARE Exact 1,0 1
+ EGL_INTERLACED_MESA EGL_DONT_CARE Exact 0,1 2
+ EGL_REFRESH_RATE EGL_DONT_CARE AtLeast Larger 3
+ EGL_WIDTH EGL_DONT_CARE AtLeast Larger 4
+ EGL_HEIGHT EGL_DONT_CARE AtLeast Larger 5
+ EGL_MODE_ID_MESA EGL_DONT_CARE Exact Smaller 6
+
+
+ EGLBoolean eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLModeMESA *modes, EGLint modes_size,
+ EGLint *num_modes)
+
+ Like eglGetConfigs, returns a list of all modes supported by the
+ given screen. The returned modes will be sorted in the same manner
+ as for eglChooseModeMESA().
+
+
+
+ EGLBoolean eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
+ EGLint attrib, EGLint *value)
+
+ Used to query mode attributes. The following attributes are supported:
+
+ Name Return value description
+ --------------------- ----------------------------------------------
+ EGL_OPTIMAL_MESA 1 indicates an optimal mode, 0 otherwise
+ EGL_INTERLACED_MESA 1 indicates an interlaced mode, 0 otherwise
+ EGL_REFRESH_RATE_MESA The mode's refresh rate, multiplied by 1000
+ EGL_WIDTH Mode width (resolution)
+ EGL_HEIGHT Mode height (resolution)
+ EGL_MODE_ID_MESA A unique small integer identifier for the mode
+
+ Any other token will generate the error EGL_BAD_ATTRIBUTE.
+
+
+
+ EGLBoolean eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
+ EGLint screens_size, EGLint *num_screens)
+
+ This function returns an array of all available screen handles.
+ <screens_size> is the maximum number of screens to return in the
+ <screens> array. <num_screens> will return the number of screen handles
+ placed in the array, even if <screens> is NULL.
+
+ The number of screens and the availability of each may change over
+ time (hot-plugging). Screen handles will not be reused. When a
+ screen handle becomes invalid, function calls which reference an
+ invalid handle will generate EGL_BAD_SCREEN_MESA.
+
+ The first screen handle returned will be considered to be the primary
+ one.
+
+
+
+ EGLSurface eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
+
+ Create a surface that can be displayed on a screen. <attrib_list> is
+ an array of token/value pairs terminated with EGL_NONE. Valid tokens
+ include:
+
+ Name Description
+ ---------------- --------------------------------
+ EGL_WIDTH desired surface width in pixels
+ EGL_HEIGHT desired surface height in pixels
+
+ Any other token will generate the error EGL_BAD_ATTRIBUTE.
+ The default width and height are zero.
+
+
+
+ EGLBoolean eglShowSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLSurface surface, EGLModeMESA mode)
+
+ This function causes a screen to show the given surface (or more
+ precisely, the surface's front color buffer) with the given mode.
+
+ If the surface is in any way incompatible with the mode, the error
+ EGL_BAD_MATCH will be generated, EGL_FALSE will be returned, and the
+ previous screen state will remain in effect. This might occur when
+ the bandwidth of the video-out subsystem is exceeded, or if the mode
+ specifies a width or height that's greater than the width or height
+ of the surface.
+
+ To disable a screen, the values EGL_NO_SURFACE and EGL_NO_MODE_MESA
+ be passed as the <surface> and <mode> parameters.
+
+ The values of EGL_SCREEN_POSITION_MESA are clamped to the new valid
+ range computed from the screen size and surface size. If the new
+ surface is EGL_NO_SURFACE, EGL_SCREEN_POSITION_MESA is set to [0, 0].
+
+
+ Attempting to delete a screen surface which is currently being
+ displayed will result in the error EGL_BAD_ACCESS being generated.
+
+
+
+ EGLBoolean eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLint x, EGLint y)
+
+ Specifies the origin of the screen's view into the surface, if the
+ surface is larger than the screen. Valid values for x and y are
+ [0, surfaceWidth - screenWidth] and [0, surfaceHeight - screenHeight],
+ respectively.
+
+ The x and y values are also constrained to be integer multiples of the
+ EGL_SCREEN_POSITION_GRANULARITY_MESA values.
+
+
+
+
+ EGLBoolean eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLint attrib, EGLint *value);
+
+ Used to query screen attributes. <attrib> may be one of the following:
+
+ Name Return value description
+ ------------------------ ---------------------------------------------
+ EGL_SCREEN_POSITION_MESA x, y position of the screen's origin with
+ respect to the surface. If no surface is
+ attached to the screen, [0, 0] is returned.
+ EGL_SCREEN_POSITION_GRANULARITY_MESA
+ Returns the granularity, in pixels, for
+ which the screen position is constrained.
+ EGL_PHYSICAL_SIZE_MESA Physical width and height of the screen
+ in millimeters
+
+ Any other token will generate the error EGL_BAD_ATTRIBUTE.
+
+
+
+
+ EGLBoolean eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLSurface *surface)
+
+ Returns the surface currently displayed on the given screen. <surface>
+ may be EGL_NO_SURFACE if the screen isn't currently showing any surface.
+
+
+
+
+ EGLBoolean eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
+ EGLModeMESA *mode)
+
+ Returns the given screen's current display mode. The mode may be
+ EGL_NO_MODE_MESA if the screen is currently disabled.
+
+
+
+ const char *eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode);
+
+ Returns a human-readable string for the given mode. The string is a
+ zero-terminated C string which the user should not attempt to free.
+ There is no standard syntax for mode strings. Applications should
+ not directly rely on mode strings.
+
+
+
+Version History
+
+ 1. 15 March 2005 - BrianP
+ Initial version
+
+ 2. 16 March 2005 - BrianP
+ Removed EGL_DEPTH_MESA
+ Added EGL_PHYSICAL_WIDTH_MESA, EGL_PHYSICAL_HEIGHT_MESA queries
+ Added EGL_OPTIMAL_MESA for width/height/refresh rate selection
+ Added possible eglQueryModeStringMESA() function
+ More details of the new functions explained.
+
+ 3. 18 March 2005 - BrianP
+ Added screen_number to eglChooseModeMESA().
+ Fix off by one mistake in value range for ORIGIN attributes
+ Added Issues section
+
+ 4. 21 March 2005 - BrianP
+ Removed eglScreenAttribsMESA().
+ Added eglScreenPositionMESA() to set screen origin.
+ Replaced EGL_SCREEN_X/Y_OFFSET_MESA with EGL_SCREEN_POSITION_MESA.
+ Replaced EGL_PHYSICAL_WIDTH/HEIGHT_MESA with EGL_PHYSICAL_SIZE_MESA.
+ Use EGL_OPTIMAL_MESA as a new mode attribute. (Michel Danzer)
+ Added a few more issues.
+
+ 5. 6 April 2005 - BrianP
+ More language for eglGetModeStringMESA().
+ Added issues 10, 11, 12, 13, 14.
+ Updated issue 3 discussion about mode sorting.
+
+ 6. 22 April 2005 - BrianP
+ Fixed "LDC" typo.
+ Added issues 15, 16.
+ Changed dependency on EGL 1.1 to EGL 1.0
+ s/EGL_NUM_SCREENS_MESA/EGL_SCREEN_COUNT_MESA/
+ Added eglQueryDisplayMESA() to New Functions section.
+ Clarified language for the EGL_SCREEN_COUNT_MESA query.
+
+ 7. 29 April 2005 - BrianP
+ Added EGLScreenMESA type and eglGetScreensMESA() function. [J. Smirl].
+ Replaced EGLint screen_number parameters with EGLScreenMESA screen.
+ Added issue 17 (pixel-accurate panning)
+
+ 8. 2 May 2005 - BrianP
+ Removed eglQueryDisplayMESA.
+ Fixed a few more EGLint -> EGLScreenMESA changes.
+
+ 9. 20 May 2005 - BrianP
+ Fixed a few typos.
+ Updated some open issues text.
+
+ 10. 10 August 2005 - BrianP
+ Added EGL_SCREEN_POSITION_GRANULARITY_MESA.
+
diff --git a/src/egl/drivers/demo/Makefile b/src/egl/drivers/demo/Makefile
new file mode 100644
index 00000000000..fd587b79e27
--- /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: $(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
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..6b50959a5ab
--- /dev/null
+++ b/src/egl/drivers/dri/Makefile
@@ -0,0 +1,64 @@
+# src/egl/drivers/dri/Makefile
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+### Include directories
+INCLUDE_DIRS = \
+ -I. \
+ -I$(DRM_SOURCE_PATH)/shared-core \
+ -I$(DRM_SOURCE_PATH)/libdrm \
+ -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 \
+ $(DRM_SOURCE_PATH)/libdrm/xf86drm.c \
+ $(DRM_SOURCE_PATH)/libdrm/xf86drmHash.c \
+ $(DRM_SOURCE_PATH)/libdrm/xf86drmRandom.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+
+default: depend library Makefile
+
+
+# EGLdri Library
+library: $(LIB_DIR)/libEGLdri.so
+
+$(LIB_DIR)/libEGLdri.so: $(OBJECTS)
+ $(TOP)/bin/mklib -o EGLdri -major 1 -minor 0 \
+ -install $(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 */
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
new file mode 100644
index 00000000000..45a4fb39b8b
--- /dev/null
+++ b/src/egl/main/Makefile
@@ -0,0 +1,66 @@
+# 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 \
+ egllog.h \
+ eglhash.h \
+ eglmode.h \
+ eglscreen.h \
+ eglsurface.h
+
+SOURCES = \
+ eglapi.c \
+ eglconfig.c \
+ eglcontext.c \
+ egldisplay.c \
+ egldriver.c \
+ eglglobals.c \
+ egllog.c \
+ eglhash.c \
+ eglmode.c \
+ eglscreen.c \
+ eglsurface.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+
+default: depend library
+
+
+# EGL Library
+library: $(LIB_DIR)/libEGL.so
+
+$(LIB_DIR)/libEGL.so: $(OBJECTS)
+ $(TOP)/bin/mklib -o EGL -major 1 -minor 0 \
+ -install $(LIB_DIR) -ldl $(OBJECTS)
+
+
+
+clean:
+ rm -f *.o *.so*
+ rm -f core.*
+
+
+depend: $(SOURCES) $(HEADERS)
+ @ echo "running $(MKDEP)"
+ @ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
+ $(SOURCES) $(HEADERS) > /dev/null
+
+include depend
+# DO NOT DELETE
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
new file mode 100644
index 00000000000..bfa580e6c3f
--- /dev/null
+++ b/src/egl/main/eglapi.c
@@ -0,0 +1,586 @@
+/**
+ * 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 <stdlib.h>
+#include <string.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->API.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->API.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->API.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->API.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->API.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->API.CreateContext(drv, dpy, config, share_list, attrib_list);
+}
+
+
+EGLBoolean APIENTRY
+eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.DestroyContext(drv, dpy, ctx);
+}
+
+
+EGLBoolean APIENTRY
+eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.MakeCurrent(drv, dpy, draw, read, ctx);
+}
+
+
+EGLBoolean APIENTRY
+eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.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->API.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->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list);
+}
+
+
+EGLSurface APIENTRY
+eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list);
+}
+
+
+EGLBoolean APIENTRY
+eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.DestroySurface(drv, dpy, surface);
+}
+
+
+EGLBoolean APIENTRY
+eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.QuerySurface(drv, dpy, surface, attribute, value);
+}
+
+
+EGLBoolean APIENTRY
+eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value);
+}
+
+
+EGLBoolean APIENTRY
+eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.BindTexImage(drv, dpy, surface, buffer);
+}
+
+
+EGLBoolean APIENTRY
+eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.ReleaseTexImage(drv, dpy, surface, buffer);
+}
+
+
+EGLBoolean APIENTRY
+eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.SwapInterval(drv, dpy, interval);
+}
+
+
+EGLBoolean APIENTRY
+eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.SwapBuffers(drv, dpy, draw);
+}
+
+
+EGLBoolean APIENTRY
+eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.CopyBuffers(drv, dpy, surface, target);
+}
+
+
+EGLBoolean APIENTRY
+eglWaitGL(void)
+{
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ if (dpy != EGL_NO_DISPLAY) {
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.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->API.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)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint e = t->LastError;
+ t->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 */
+#ifdef EGL_MESA_screen_surface
+ { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
+ { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
+ { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA },
+ { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA },
+ { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA },
+ { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA },
+ { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA },
+ { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA },
+ { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA },
+ { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA },
+ { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
+ { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
+#endif /* EGL_MESA_screen_surface */
+#ifdef EGL_VERSION_1_2
+ { "eglBindAPI", (_EGLProc) eglBindAPI },
+ { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
+ { "eglQueryAPI", (_EGLProc) eglQueryAPI },
+ { "eglReleaseThread", (_EGLProc) eglReleaseThread },
+ { "eglWaitClient", (_EGLProc) eglWaitClient },
+#endif /* EGL_VERSION_1_2 */
+ { 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, EGLScreenMESA screen,
+ const EGLint *attrib_list, EGLModeMESA *modes,
+ EGLint modes_size, EGLint *num_modes)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ if (drv)
+ return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes);
+ else
+ return EGL_FALSE;
+}
+
+
+EGLBoolean APIENTRY
+eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ if (drv)
+ return drv->API.GetModesMESA(drv, dpy, screen, 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->API.GetModeAttribMESA(drv, dpy, mode, attribute, value);
+ else
+ return EGL_FALSE;
+}
+
+
+EGLBoolean APIENTRY
+eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ if (drv)
+ return drv->API.CopyContextMESA(drv, dpy, source, dest, mask);
+ else
+ return EGL_FALSE;
+}
+
+
+EGLBoolean
+eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ if (drv)
+ return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens);
+ else
+ return EGL_FALSE;
+}
+
+
+EGLSurface
+eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list);
+}
+
+
+EGLBoolean
+eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode);
+}
+
+
+EGLBoolean
+eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y);
+}
+
+
+EGLBoolean
+eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value);
+}
+
+
+EGLBoolean
+eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface);
+}
+
+
+EGLBoolean
+eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode);
+}
+
+
+const char *
+eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.QueryModeStringMESA(drv, dpy, mode);
+}
+
+
+/**
+ ** EGL 1.2
+ **/
+
+#ifdef EGL_VERSION_1_2
+
+EGLBoolean
+eglBindAPI(EGLenum api)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+
+ switch (api) {
+ case EGL_OPENGL_ES_API:
+ if (_eglGlobal.OpenGLESAPISupported) {
+ t->CurrentAPI = api;
+ return EGL_TRUE;
+ }
+ _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
+ return EGL_FALSE;
+ case EGL_OPENVG_API:
+ if (_eglGlobal.OpenVGAPISupported) {
+ t->CurrentAPI = api;
+ return EGL_TRUE;
+ }
+ _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
+ return EGL_FALSE;
+ default:
+ return EGL_FALSE;
+ }
+ return EGL_TRUE;
+}
+
+
+EGLSurface
+eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
+ EGLClientBuffer buffer, EGLConfig config,
+ const EGLint *attrib_list)
+{
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.CreatePbufferFromClientBuffer(drv, dpy, buftype, buffer,
+ config, attrib_list);
+}
+
+
+EGLenum
+eglQueryAPI(void)
+{
+ /* returns one of EGL_OPENGL_ES_API or EGL_OPENVG_API */
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ return t->CurrentAPI;
+}
+
+
+EGLBoolean
+eglReleaseThread(void)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ if (dpy) {
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ /* unbind context */
+ (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+ _eglDeleteThreadData(t);
+ return EGL_TRUE;
+}
+
+
+EGLBoolean
+eglWaitClient(void)
+{
+ EGLDisplay dpy = eglGetCurrentDisplay();
+ if (dpy != EGL_NO_DISPLAY) {
+ _EGLDriver *drv = _eglLookupDriver(dpy);
+ return drv->API.WaitClient(drv, dpy);
+ }
+ else
+ return EGL_FALSE;
+}
+
+#endif /* EGL_VERSION_1_2 */
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
new file mode 100644
index 00000000000..555aa5dd9ef
--- /dev/null
+++ b/src/egl/main/eglapi.h
@@ -0,0 +1,119 @@
+#ifndef EGLAPI_INCLUDED
+#define EGLAPI_INCLUDED
+
+/**
+ * Typedefs for all EGL API entrypoint functions.
+ */
+
+
+/* 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);
+
+
+#ifdef EGL_MESA_screen_surface
+typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode);
+typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
+typedef EGLBoolean (*CopyContextMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
+typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
+typedef EGLSurface (*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+typedef EGLBoolean (*ShowScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode);
+typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
+typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
+typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
+typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
+typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode);
+#endif /* EGL_MESA_screen_surface */
+
+
+#ifdef EGL_VERSION_1_2
+typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, EGLDisplay dpy);
+typedef EGLSurface (*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+#endif /* EGL_VERSION_1_2 */
+
+
+
+/**
+ * The API dispatcher jumps through these functions
+ */
+struct _egl_api
+{
+ 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;
+ CopyContextMESA_t CopyContextMESA;
+ GetScreensMESA_t GetScreensMESA;
+ CreateScreenSurfaceMESA_t CreateScreenSurfaceMESA;
+ ShowScreenSurfaceMESA_t ShowScreenSurfaceMESA;
+ ScreenPositionMESA_t ScreenPositionMESA;
+ QueryScreenMESA_t QueryScreenMESA;
+ QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA;
+ QueryScreenModeMESA_t QueryScreenModeMESA;
+ QueryModeStringMESA_t QueryModeStringMESA;
+
+#ifdef EGL_VERSION_1_2
+ WaitClient_t WaitClient;
+ CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
+#endif
+};
+
+#endif /* EGLAPI_INCLUDED */
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
new file mode 100644
index 00000000000..c180e30d7fa
--- /dev/null
+++ b/src/egl/main/eglconfig.c
@@ -0,0 +1,638 @@
+/**
+ * EGL Configuration (pixel format) functions.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "eglconfig.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "egllog.h"
+
+
+#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
+
+
+/**
+ * Convert an _EGLConfig to a __GLcontextModes object.
+ * NOTE: This routine may be incomplete - we're only making sure that
+ * the fields needed by Mesa (for _mesa_create_context/framebuffer) are
+ * set correctly.
+ */
+void
+_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
+{
+ memset(mode, 0, sizeof(*mode));
+
+ mode->rgbMode = GL_TRUE; /* no color index */
+ mode->colorIndexMode = GL_FALSE;
+ mode->doubleBufferMode = GL_TRUE; /* always DB for now */
+ mode->stereoMode = GL_FALSE;
+
+ mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
+ mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
+ mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
+ mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
+ mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);
+
+ /* no rgba masks - fix? */
+
+ mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
+ mode->haveDepthBuffer = mode->depthBits > 0;
+
+ mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
+ mode->haveStencilBuffer = mode->stencilBits > 0;
+
+ /* no accum */
+
+ mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
+ mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
+ mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
+
+ /* surface type - not really needed */
+ mode->visualType = GLX_TRUE_COLOR;
+ mode->renderType = GLX_RGBA_BIT;
+}
+
+
+void
+_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val)
+{
+ assert(attr >= FIRST_ATTRIB);
+ assert(attr < FIRST_ATTRIB + MAX_ATTRIBS);
+ config->Attrib[attr - FIRST_ATTRIB] = val;
+}
+
+
+/**
+ * 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;
+ _eglSetConfigAttrib(config, EGL_CONFIG_ID, id);
+ _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE,
+ EGL_SCREEN_BIT_MESA | EGL_PBUFFER_BIT |
+ EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
+ _eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE);
+ _eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE);
+ _eglSetConfigAttrib(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE);
+#ifdef EGL_VERSION_1_2
+ _eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+ _eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
+#endif /* EGL_VERSION_1_2 */
+}
+
+
+/**
+ * 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;
+}
+
+
+/**
+ * Add the given _EGLConfig to the given display.
+ */
+_EGLConfig *
+_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config)
+{
+ _EGLConfig *newConfigs;
+ EGLint n;
+
+ n = display->NumConfigs;
+
+ newConfigs = (_EGLConfig *) realloc(display->Configs,
+ (n + 1) * sizeof(_EGLConfig));
+ if (newConfigs) {
+ display->Configs = newConfigs;
+ display->Configs[n] = *config; /* copy struct */
+ display->Configs[n].Handle = n;
+ display->NumConfigs++;
+ return display->Configs + n;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/**
+ * Parse the attrib_list to fill in the fields of the given _eglConfig
+ * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
+ */
+EGLBoolean
+_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
+{
+ EGLint i;
+
+ /* set all config attribs to EGL_DONT_CARE */
+ for (i = 0; i < MAX_ATTRIBS; i++) {
+ config->Attrib[i] = EGL_DONT_CARE;
+ }
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ const EGLint attr = attrib_list[i];
+ if (attr >= EGL_BUFFER_SIZE &&
+ attr <= EGL_MAX_SWAP_INTERVAL) {
+ EGLint k = attr - FIRST_ATTRIB;
+ assert(k >= 0);
+ assert(k < MAX_ATTRIBS);
+ config->Attrib[k] = attrib_list[++i];
+ }
+#ifdef EGL_VERSION_1_2
+ else if (attr == EGL_COLOR_BUFFER_TYPE) {
+ EGLint bufType = attrib_list[++i];
+ if (bufType != EGL_RGB_BUFFER && bufType != EGL_LUMINANCE_BUFFER) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
+ return EGL_FALSE;
+ }
+ _eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, bufType);
+ }
+ else if (attr == EGL_RENDERABLE_TYPE) {
+ EGLint renType = attrib_list[++i];
+ if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT)) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
+ return EGL_FALSE;
+ }
+ _eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, renType);
+ }
+ else if (attr == EGL_ALPHA_MASK_SIZE ||
+ attr == EGL_LUMINANCE_SIZE) {
+ EGLint value = attrib_list[++i];
+ _eglSetConfigAttrib(config, attr, value);
+ }
+#endif /* EGL_VERSION_1_2 */
+ 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.
+ *
+ * XXX To do: EGL 1.2 attribs
+ */
+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.
+ */
+static 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.
+ * Used by qsort().
+ */
+static int
+_eglCompareConfigs(const void *a, const void *b)
+{
+ const _EGLConfig *aConfig = (const _EGLConfig *) a;
+ const _EGLConfig *bConfig = (const _EGLConfig *) b;
+ EGLint i;
+
+ for (i = 0; SortInfo[i].Attribute != 0; i++) {
+ const EGLint aVal = GET_CONFIG_ATTRIB(aConfig, SortInfo[i].Attribute);
+ const EGLint bVal = GET_CONFIG_ATTRIB(bConfig, SortInfo[i].Attribute);
+ if (SortInfo[i].SortOrder == SMALLER) {
+ if (aVal < bVal)
+ return -1;
+ else if (aVal > bVal)
+ 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 (aVal < bVal)
+ return -1;
+ else if (aVal > bVal)
+ 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 (aVal > bVal)
+ return -1;
+ else if (aVal < bVal)
+ return 1;
+ }
+ else {
+ assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE);
+ if (aVal < bVal)
+ return -1;
+ else if (aVal > bVal)
+ return 1;
+ }
+ }
+ else {
+ assert(SortInfo[i].SortOrder == NONE);
+ /* continue examining attribute values */
+ }
+ }
+
+ /* all attributes identical */
+ return 0;
+}
+
+
+/**
+ * Typical fallback routine for eglChooseConfig
+ */
+EGLBoolean
+_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
+ EGLConfig *configs, EGLint config_size, EGLint *num_configs)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLConfig **configList, criteria;
+ EGLint i, count;
+
+ /* parse the attrib_list to initialize criteria */
+ if (!_eglParseConfigAttribs(&criteria, attrib_list)) {
+ return EGL_FALSE;
+ }
+
+ /* allocate array of config pointers */
+ configList = (_EGLConfig **) malloc(config_size * sizeof(_EGLConfig *));
+ if (!configList) {
+ _eglError(EGL_BAD_CONFIG, "eglChooseConfig(out of memory)");
+ return EGL_FALSE;
+ }
+
+ /* make array of pointers to qualifying configs */
+ for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) {
+ if (_eglConfigQualifies(disp->Configs + i, &criteria)) {
+ configList[count++] = disp->Configs + i;
+ }
+ }
+
+ /* sort array of pointers */
+ qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs);
+
+ /* copy config handles to output array */
+ for (i = 0; i < count; i++) {
+ configs[i] = configList[i]->Handle;
+ }
+
+ free(configList);
+
+ *num_configs = count;
+
+ 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;
+ }
+
+ if (configs) {
+ EGLint i;
+ *num_config = MIN2(disp->NumConfigs, config_size);
+ for (i = 0; i < *num_config; i++) {
+ configs[i] = disp->Configs[i].Handle;
+ }
+ }
+ else {
+ /* just return total number of supported configs */
+ *num_config = disp->NumConfigs;
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Creates a set of \c __GLcontextModes that a driver will expose.
+ *
+ * A set of \c __GLcontextModes will be created based on the supplied
+ * parameters. The number of modes processed will be 2 *
+ * \c num_depth_stencil_bits * \c num_db_modes.
+ *
+ * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
+ * \c db_modes, and \c visType into each \c __GLcontextModes element.
+ * However, the meanings of \c fb_format and \c fb_type require further
+ * explanation. The \c fb_format specifies which color components are in
+ * each pixel and what the default order is. For example, \c GL_RGB specifies
+ * that red, green, blue are available and red is in the "most significant"
+ * position and blue is in the "least significant". The \c fb_type specifies
+ * the bit sizes of each component and the actual ordering. For example, if
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
+ * are the blue value, bits [10:5] are the green value, and bits [4:0] are
+ * the red value.
+ *
+ * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
+ * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
+ * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
+ * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
+ * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
+ * still uses 32-bits.
+ *
+ * If in doubt, look at the tables used in the function.
+ *
+ * \param ptr_to_modes Pointer to a pointer to a linked list of
+ * \c __GLcontextModes. Upon completion, a pointer to
+ * the next element to be process will be stored here.
+ * If the function fails and returns \c GL_FALSE, this
+ * value will be unmodified, but some elements in the
+ * linked list may be modified.
+ * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
+ * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
+ * \param fb_type Type of the pixels in the framebuffer. Currently only
+ * \c GL_UNSIGNED_SHORT_5_6_5,
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV,
+ * \c GL_UNSIGNED_INT_8_8_8_8, and
+ * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
+ * \param depth_bits Array of depth buffer sizes to be exposed.
+ * \param stencil_bits Array of stencil buffer sizes to be exposed.
+ * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
+ * \c stencil_bits.
+ * \param db_modes Array of buffer swap modes. If an element has a
+ * value of \c GLX_NONE, then it represents a
+ * single-buffered mode. Other valid values are
+ * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
+ * \c GLX_SWAP_UNDEFINED_OML. See the
+ * GLX_OML_swap_method extension spec for more details.
+ * \param num_db_modes Number of entries in \c db_modes.
+ * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR.
+ *
+ * \returns
+ * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
+ * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
+ * \c fb_type).
+ *
+ * \todo
+ * There is currently no way to support packed RGB modes (i.e., modes with
+ * exactly 3 bytes per pixel) or floating-point modes. This could probably
+ * be done by creating some new, private enums with clever names likes
+ * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
+ * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
+ */
+GLboolean
+_eglFillInConfigs(_EGLConfig * configs,
+ GLenum fb_format, GLenum fb_type,
+ const u_int8_t * depth_bits, const u_int8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ int visType)
+{
+ static const u_int8_t bits_table[3][4] = {
+ /* R G B A */
+ { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
+ { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
+ { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
+ };
+
+ /* The following arrays are all indexed by the fb_type masked with 0x07.
+ * Given the four supported fb_type values, this results in valid array
+ * indices of 3, 4, 5, and 7.
+ */
+ static const u_int32_t masks_table_rgb[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
+ {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
+ };
+
+ static const u_int32_t masks_table_rgba[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
+ {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
+ };
+
+ static const u_int32_t masks_table_bgr[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
+ {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
+ };
+
+ static const u_int32_t masks_table_bgra[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
+ {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
+ };
+
+ static const u_int8_t bytes_per_pixel[8] = {
+ 0, 0, 0, 2, 2, 4, 0, 4
+ };
+
+ const u_int8_t * bits;
+ const u_int32_t * masks;
+ const int index = fb_type & 0x07;
+ _EGLConfig *config;
+ unsigned i;
+ unsigned j;
+ unsigned k;
+
+ if ( bytes_per_pixel[index] == 0 ) {
+ _eglLog(_EGL_INFO,
+ "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
+ __FUNCTION__, __LINE__, fb_type);
+ return GL_FALSE;
+ }
+
+ /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
+ * the _REV versions.
+ *
+ * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
+ */
+ switch ( fb_format ) {
+ case GL_RGB:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
+ masks = masks_table_rgb[index];
+ break;
+
+ case GL_RGBA:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
+ masks = masks_table_rgba[index];
+ break;
+
+ case GL_BGR:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
+ masks = masks_table_bgr[index];
+ break;
+
+ case GL_BGRA:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
+ masks = masks_table_bgra[index];
+ break;
+
+ default:
+ _eglLog(_EGL_WARNING,
+ "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
+ __FUNCTION__, __LINE__, fb_format);
+ return GL_FALSE;
+ }
+
+ config = configs;
+ for (k = 0; k < num_depth_stencil_bits; k++) {
+ for (i = 0; i < num_db_modes; i++) {
+ for (j = 0; j < 2; j++) {
+ _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
+ _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
+ _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
+ _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
+ _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
+ bits[0] + bits[1] + bits[2] + bits[3]);
+
+ _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
+ _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
+
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
+ EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
+
+ config++;
+ }
+ }
+ }
+ return GL_TRUE;
+}
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
new file mode 100644
index 00000000000..1fb976e5b4b
--- /dev/null
+++ b/src/egl/main/eglconfig.h
@@ -0,0 +1,67 @@
+#ifndef EGLCONFIG_INCLUDED
+#define EGLCONFIG_INCLUDED
+
+
+#include "egltypedefs.h"
+#include "GL/internal/glcore.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 _EGLConfig *
+_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config);
+
+
+extern EGLBoolean
+_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list);
+
+
+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);
+
+
+extern void
+_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val);
+
+extern GLboolean
+_eglFillInConfigs( _EGLConfig *configs,
+ GLenum fb_format, GLenum fb_type,
+ const u_int8_t * depth_bits, const u_int8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ int visType );
+
+extern void
+_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
+
+
+#endif /* EGLCONFIG_INCLUDED */
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
new file mode 100644
index 00000000000..374c006dae7
--- /dev/null
+++ b/src/egl/main/eglcontext.c
@@ -0,0 +1,276 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglhash.h"
+#include "eglsurface.h"
+
+
+/**
+ * Initialize the given _EGLContext object to defaults.
+ */
+EGLBoolean
+_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
+ EGLConfig config, const EGLint *attrib_list)
+{
+ _EGLConfig *conf;
+ _EGLDisplay *display = _eglLookupDisplay(dpy);
+ EGLint i;
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, "eglCreateContext");
+ return EGL_FALSE;
+ }
+
+ 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;
+ }
+ }
+
+ memset(ctx, 0, sizeof(_EGLContext));
+ ctx->Display = display;
+ ctx->Config = conf;
+ ctx->DrawSurface = EGL_NO_SURFACE;
+ ctx->ReadSurface = EGL_NO_SURFACE;
+
+ return EGL_TRUE;
+}
+
+
+/*
+ * 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)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ return t->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)
+{
+#if 0 /* example code */
+ _EGLContext *context;
+
+ context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
+ if (!context)
+ return EGL_NO_CONTEXT;
+
+ if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
+ free(context);
+ return EGL_NO_CONTEXT;
+ }
+
+ _eglSaveContext(context);
+ return context->Handle;
+#endif
+ 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;
+#ifdef EGL_VERSION_1_2
+ case EGL_CONTEXT_CLIENT_TYPE:
+ *value = c->ClientAPI;
+ return EGL_FALSE;
+#endif /* EGL_VERSION_1_2 */
+ 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)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ _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->API.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->API.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->API.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;
+ }
+
+ t->CurrentContext = ctx;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * This is defined by the EGL_MESA_copy_context extension.
+ */
+EGLBoolean
+_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
+ EGLContext dest, EGLint mask)
+{
+ /* This function will always have to be overridden/implemented in the
+ * device driver. If the driver is based on Mesa, use _mesa_copy_context().
+ */
+ return EGL_FALSE;
+}
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
new file mode 100644
index 00000000000..82bfde151f3
--- /dev/null
+++ b/src/egl/main/eglcontext.h
@@ -0,0 +1,71 @@
+
+#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;
+#ifdef EGL_VERSION_1_2
+ EGLint ClientAPI; /* Either EGL_OPENGL_ES_API or EGL_OPENVG_API */
+#endif /* EGL_VERSION_1_2 */
+};
+
+
+extern EGLBoolean
+_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
+ EGLConfig config, const EGLint *attrib_list);
+
+
+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);
+
+
+extern EGLBoolean
+_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
+
+#endif /* EGLCONTEXT_INCLUDED */
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
new file mode 100644
index 00000000000..074a85bf26b
--- /dev/null
+++ b/src/egl/main/egldisplay.c
@@ -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 *) calloc(1, 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
+_eglCleanupDisplay(_EGLDisplay *disp)
+{
+ /* XXX incomplete */
+ free(disp->Configs);
+ free(disp->Name);
+ /* driver deletes _EGLDisplay */
+}
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
new file mode 100644
index 00000000000..1a03fdd4ad9
--- /dev/null
+++ b/src/egl/main/egldisplay.h
@@ -0,0 +1,44 @@
+#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
+_eglCleanupDisplay(_EGLDisplay *disp);
+
+
+extern EGLBoolean
+_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value);
+
+
+
+#endif /* EGLDISPLAY_INCLUDED */
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
new file mode 100644
index 00000000000..bda06dd827d
--- /dev/null
+++ b/src/egl/main/egldriver.c
@@ -0,0 +1,272 @@
+#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 "egllog.h"
+#include "eglmode.h"
+#include "eglscreen.h"
+#include "eglsurface.h"
+
+
+const char *DefaultDriverName = "demodriver";
+
+
+/**
+ * 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]) {
+ /* XXX probe hardware here to determine which driver to open */
+ driverName = "libEGLdri";
+ }
+ else if (name[0] == '!') {
+ /* use specified driver name */
+ driverName = name + 1;
+ }
+ else {
+ /* Maybe display was returned by XOpenDisplay? */
+ _eglLog(_EGL_FATAL, "eglChooseDriver() bad name");
+ }
+
+ _eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName);
+
+ 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)
+{
+ _EGLDriver *drv;
+ _EGLMain_t mainFunc;
+ void *lib;
+ char driverFilename[1000];
+
+ /* XXX also prepend a directory path??? */
+ sprintf(driverFilename, "%s.so", driverName);
+
+ _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
+ lib = dlopen(driverFilename, RTLD_NOW);
+ if (!lib) {
+ _eglLog(_EGL_WARNING, "Could not open %s (%s)",
+ driverFilename, dlerror());
+ return NULL;
+ }
+
+ mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
+ if (!mainFunc) {
+ _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
+ dlclose(lib);
+ return NULL;
+ }
+
+ drv = mainFunc(dpy);
+ if (!drv) {
+ dlclose(lib);
+ return NULL;
+ }
+ /* with a recurvise open you want the inner most handle */
+ if (!drv->LibHandle)
+ drv->LibHandle = lib;
+ else
+ dlclose(lib);
+
+ drv->Display = dpy;
+ return drv;
+}
+
+
+EGLBoolean
+_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
+{
+ void *handle = drv->LibHandle;
+ EGLBoolean b;
+
+ _eglLog(_EGL_INFO, "Closing driver");
+
+ /*
+ * XXX check for currently bound context/surfaces and delete them?
+ */
+
+ b = drv->API.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->API.Initialize = NULL;
+ drv->API.Terminate = NULL;
+
+ drv->API.GetConfigs = _eglGetConfigs;
+ drv->API.ChooseConfig = _eglChooseConfig;
+ drv->API.GetConfigAttrib = _eglGetConfigAttrib;
+
+ drv->API.CreateContext = _eglCreateContext;
+ drv->API.DestroyContext = _eglDestroyContext;
+ drv->API.MakeCurrent = _eglMakeCurrent;
+ drv->API.QueryContext = _eglQueryContext;
+
+ drv->API.CreateWindowSurface = _eglCreateWindowSurface;
+ drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
+ drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
+ drv->API.DestroySurface = _eglDestroySurface;
+ drv->API.QuerySurface = _eglQuerySurface;
+ drv->API.SurfaceAttrib = _eglSurfaceAttrib;
+ drv->API.BindTexImage = _eglBindTexImage;
+ drv->API.ReleaseTexImage = _eglReleaseTexImage;
+ drv->API.SwapInterval = _eglSwapInterval;
+ drv->API.SwapBuffers = _eglSwapBuffers;
+ drv->API.CopyBuffers = _eglCopyBuffers;
+
+ drv->API.QueryString = _eglQueryString;
+ drv->API.WaitGL = _eglWaitGL;
+ drv->API.WaitNative = _eglWaitNative;
+
+#ifdef EGL_MESA_screen_surface
+ drv->API.ChooseModeMESA = _eglChooseModeMESA;
+ drv->API.GetModesMESA = _eglGetModesMESA;
+ drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
+ drv->API.GetScreensMESA = _eglGetScreensMESA;
+ drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
+ drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
+ drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
+ drv->API.QueryScreenMESA = _eglQueryScreenMESA;
+ drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
+ drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
+ drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
+#endif /* EGL_MESA_screen_surface */
+
+#ifdef EGL_VERSION_1_2
+ drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
+#endif /* EGL_VERSION_1_2 */
+}
+
+
+/**
+ * Examine the individual extension enable/disable flags and recompute
+ * the driver's Extensions string.
+ */
+static void
+_eglUpdateExtensionsString(_EGLDriver *drv)
+{
+ drv->Extensions.String[0] = 0;
+
+ if (drv->Extensions.MESA_screen_surface)
+ strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
+ if (drv->Extensions.MESA_copy_context)
+ strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
+ assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN);
+}
+
+
+
+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:
+ _eglUpdateExtensionsString(drv);
+ return drv->Extensions.String;
+#ifdef EGL_VERSION_1_2
+ case EGL_CLIENT_APIS:
+ /* XXX need to initialize somewhere */
+ return drv->ClientAPIs;
+#endif
+ 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;
+ switch (engine) {
+ case EGL_CORE_NATIVE_ENGINE:
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
new file mode 100644
index 00000000000..88526e973d1
--- /dev/null
+++ b/src/egl/main/egldriver.h
@@ -0,0 +1,81 @@
+#ifndef EGLDRIVER_INCLUDED
+#define EGLDRIVER_INCLUDED
+
+
+#include "egltypedefs.h"
+#include "eglapi.h"
+
+/* should probably use a dynamic-length string, but this will do */
+#define MAX_EXTENSIONS_LEN 1000
+
+
+/**
+ * Optional EGL extensions info.
+ */
+struct _egl_extensions
+{
+ EGLBoolean MESA_screen_surface;
+ EGLBoolean MESA_copy_context;
+
+ char String[MAX_EXTENSIONS_LEN];
+};
+
+
+/**
+ * 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 */
+ const char *ClientAPIs;
+
+ _EGLAPI API;
+
+ _EGLExtensions Extensions;
+};
+
+
+extern _EGLDriver *_eglMain(_EGLDisplay *dpy);
+
+
+extern _EGLDriver *
+_eglChooseDriver(EGLDisplay dpy);
+
+
+extern _EGLDriver *
+_eglOpenDriver(_EGLDisplay *dpy, const char *driverName);
+
+
+extern EGLBoolean
+_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy);
+
+
+extern _EGLDriver *
+_eglLookupDriver(EGLDisplay d);
+
+
+extern void
+_eglInitDriverFallbacks(_EGLDriver *drv);
+
+
+extern const char *
+_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
+
+
+extern EGLBoolean
+_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy);
+
+
+extern EGLBoolean
+_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
+
+
+
+#endif /* EGLDRIVER_INCLUDED */
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
new file mode 100644
index 00000000000..608311d7494
--- /dev/null
+++ b/src/egl/main/eglglobals.c
@@ -0,0 +1,148 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "eglglobals.h"
+
+
+struct _egl_global _eglGlobal = { .Initialized = 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.FreeScreenHandle = 1;
+ _eglGlobal.Initialized = EGL_TRUE;
+
+ _eglGlobal.OpenGLESAPISupported = EGL_TRUE;
+ _eglGlobal.OpenVGAPISupported = EGL_FALSE;
+
+ /* XXX temporary */
+ _eglGlobal.ThreadInfo = _eglNewThreadInfo();
+ }
+}
+
+
+/**
+ * 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);
+}
+
+
+/**
+ * Allocate and init a new _EGLThreadInfo object.
+ */
+_EGLThreadInfo *
+_eglNewThreadInfo(void)
+{
+ _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo));
+ if (t) {
+ t->CurrentContext = EGL_NO_CONTEXT;
+ t->LastError = EGL_SUCCESS;
+ t->CurrentAPI = EGL_NONE;
+ }
+ return t;
+}
+
+
+/**
+ * Delete/free a _EGLThreadInfo object.
+ */
+void
+_eglDeleteThreadData(_EGLThreadInfo *t)
+{
+ free(t);
+}
+
+
+
+/**
+ * Return pointer to calling thread's _EGLThreadInfo object.
+ * Create a new one if needed.
+ * Should never return NULL.
+ */
+_EGLThreadInfo *
+_eglGetCurrentThread(void)
+{
+ _eglInitGlobals();
+
+ /* XXX temporary */
+ return _eglGlobal.ThreadInfo;
+}
+
+
+/**
+ * Record EGL error code.
+ */
+void
+_eglError(EGLint errCode, const char *msg)
+{
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ const char *s;
+
+ if (t->LastError == EGL_SUCCESS) {
+ t->LastError = errCode;
+
+ switch (errCode) {
+ case EGL_BAD_ACCESS:
+ s = "EGL_BAD_ACCESS";
+ break;
+ case EGL_BAD_ALLOC:
+ s = "EGL_BAD_ALLOC";
+ break;
+ case EGL_BAD_ATTRIBUTE:
+ s = "EGL_BAD_ATTRIBUTE";
+ break;
+ case EGL_BAD_CONFIG:
+ s = "EGL_BAD_CONFIG";
+ break;
+ case EGL_BAD_CONTEXT:
+ s = "EGL_BAD_CONTEXT";
+ break;
+ case EGL_BAD_CURRENT_SURFACE:
+ s = "EGL_BAD_CURRENT_SURFACE";
+ break;
+ case EGL_BAD_DISPLAY:
+ s = "EGL_BAD_DISPLAY";
+ break;
+ case EGL_BAD_MATCH:
+ s = "EGL_BAD_MATCH";
+ break;
+ case EGL_BAD_NATIVE_PIXMAP:
+ s = "EGL_BAD_NATIVE_PIXMAP";
+ break;
+ case EGL_BAD_NATIVE_WINDOW:
+ s = "EGL_BAD_NATIVE_WINDOW";
+ break;
+ case EGL_BAD_PARAMETER:
+ s = "EGL_BAD_PARAMETER";
+ break;
+ case EGL_BAD_SURFACE:
+ s = "EGL_BAD_SURFACE";
+ break;
+ case EGL_BAD_SCREEN_MESA:
+ s = "EGL_BAD_SCREEN_MESA";
+ break;
+ case EGL_BAD_MODE_MESA:
+ s = "EGL_BAD_MODE_MESA";
+ break;
+ default:
+ s = "other";
+ }
+ /* XXX temporary */
+ fprintf(stderr, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
+ }
+}
diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h
new file mode 100644
index 00000000000..c16baa2d6bd
--- /dev/null
+++ b/src/egl/main/eglglobals.h
@@ -0,0 +1,68 @@
+#ifndef EGLGLOBALS_INCLUDED
+#define EGLGLOBALS_INCLUDED
+
+#include "egltypedefs.h"
+#include "eglhash.h"
+
+
+/**
+ * Per-thread info
+ */
+struct _egl_thread_info
+{
+ EGLint LastError;
+ _EGLContext *CurrentContext;
+ EGLenum CurrentAPI;
+};
+
+
+/**
+ * Global library data
+ */
+struct _egl_global
+{
+ EGLBoolean Initialized;
+
+ _EGLHashtable *Displays;
+ _EGLHashtable *Contexts;
+ _EGLHashtable *Surfaces;
+
+ EGLScreenMESA FreeScreenHandle;
+
+ /* XXX these may be temporary */
+ EGLBoolean OpenGLESAPISupported;
+ EGLBoolean OpenVGAPISupported;
+
+ /* XXX temporary - should be thread-specific data (TSD) */
+ _EGLThreadInfo *ThreadInfo;
+};
+
+
+extern struct _egl_global _eglGlobal;
+
+
+extern void
+_eglInitGlobals(void);
+
+
+extern void
+_eglDestroyGlobals(void);
+
+
+extern _EGLThreadInfo *
+_eglNewThreadInfo(void);
+
+
+extern void
+_eglDeleteThreadData(_EGLThreadInfo *t);
+
+
+extern _EGLThreadInfo *
+_eglGetCurrentThread(void);
+
+
+extern void
+_eglError(EGLint errCode, const char *msg);
+
+
+#endif /* EGLGLOBALS_INCLUDED */
diff --git a/src/egl/main/eglhash.c b/src/egl/main/eglhash.c
new file mode 100644
index 00000000000..8e3da2e9061
--- /dev/null
+++ b/src/egl/main/eglhash.c
@@ -0,0 +1,347 @@
+/**
+ * \file hash.c
+ * Generic hash table.
+ *
+ * This code taken from Mesa and adapted.
+ */
+
+#include <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
index 00000000000..1d6db9598ce
--- /dev/null
+++ b/src/egl/main/eglhash.h
@@ -0,0 +1,39 @@
+/**
+ * \file eglhash.h
+ * Generic hash table.
+ */
+
+
+#ifndef EGLHASH_INCLUDED
+#define EGLHASH_INCLUDED
+
+
+/* XXX move this? */
+typedef unsigned int EGLuint;
+
+
+typedef struct _egl_hashtable _EGLHashtable;
+
+
+extern _EGLHashtable *_eglNewHashTable(void);
+
+extern void _eglDeleteHashTable(_EGLHashtable *table);
+
+extern void *_eglHashLookup(const _EGLHashtable *table, EGLuint key);
+
+extern void _eglHashInsert(_EGLHashtable *table, EGLuint key, void *data);
+
+extern void _eglHashRemove(_EGLHashtable *table, EGLuint key);
+
+extern EGLuint _eglHashFirstEntry(_EGLHashtable *table);
+
+extern EGLuint _eglHashNextEntry(const _EGLHashtable *table, EGLuint key);
+
+extern void _eglHashPrint(const _EGLHashtable *table);
+
+extern EGLuint _eglHashGenKey(_EGLHashtable *table);
+
+extern void _egltest_hash_functions(void);
+
+
+#endif /* EGLHASH_INCLUDED */
diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c
new file mode 100644
index 00000000000..59b1d2684e3
--- /dev/null
+++ b/src/egl/main/egllog.c
@@ -0,0 +1,57 @@
+/**
+ * Logging facility for debug/info messages.
+ */
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "egllog.h"
+
+#define MAXSTRING 1000
+
+
+/* XXX init this with an env var or something */
+static EGLint ReportingLevel = _EGL_DEBUG;
+
+
+/**
+ * Log a message to stderr.
+ * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
+ */
+void
+_eglLog(EGLint level, const char *fmtStr, ...)
+{
+ va_list args;
+ char msg[MAXSTRING];
+ const char *levelStr;
+
+ if (level <= ReportingLevel) {
+ switch (level) {
+ case _EGL_FATAL:
+ levelStr = "Fatal";
+ break;
+ case _EGL_WARNING:
+ levelStr = "Warning";
+ break;
+ case _EGL_INFO:
+ levelStr = "Info";
+ break;
+ case _EGL_DEBUG:
+ levelStr = "Debug";
+ break;
+ default:
+ levelStr = "";
+ }
+
+ va_start(args, fmtStr);
+ vsnprintf(msg, MAXSTRING, fmtStr, args);
+ va_end(args);
+
+ fprintf(stderr, "EGL %s: %s\n", levelStr, msg);
+
+ if (level == _EGL_FATAL) {
+ exit(1); /* or abort()? */
+ }
+ }
+}
diff --git a/src/egl/main/egllog.h b/src/egl/main/egllog.h
new file mode 100644
index 00000000000..2fa352f155d
--- /dev/null
+++ b/src/egl/main/egllog.h
@@ -0,0 +1,16 @@
+#ifndef EGLLOG_INCLUDED
+#define EGLLOG_INCLUDED
+
+#include "egltypedefs.h"
+
+#define _EGL_FATAL 0 /* unrecoverable error */
+#define _EGL_WARNING 1 /* recoverable error/problem */
+#define _EGL_INFO 2 /* just useful info */
+#define _EGL_DEBUG 3 /* useful info for debugging */
+
+
+extern void
+_eglLog(EGLint level, const char *fmtStr, ...);
+
+
+#endif /* EGLLOG_INCLUDED */
diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c
new file mode 100644
index 00000000000..786432234bb
--- /dev/null
+++ b/src/egl/main/eglmode.c
@@ -0,0 +1,431 @@
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglmode.h"
+#include "eglglobals.h"
+#include "eglscreen.h"
+
+
+#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
+
+
+static char *
+my_strdup(const char *s)
+{
+ if (s) {
+ int l = strlen(s);
+ char *s2 = malloc(l + 1);
+ if (s2)
+ strcpy(s2, s);
+ return s2;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/**
+ * Given an EGLModeMESA handle, return the corresponding _EGLMode object
+ * or null if non-existant.
+ */
+_EGLMode *
+_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode)
+{
+ const _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ EGLint scrnum;
+
+ /* loop over all screens on the display */
+ for (scrnum = 0; scrnum < disp->NumScreens; scrnum++) {
+ const _EGLScreen *scrn = disp->Screens[scrnum];
+ EGLint i;
+ /* search list of modes for handle */
+ for (i = 0; i < scrn->NumModes; i++) {
+ if (scrn->Modes[i].Handle == mode) {
+ return scrn->Modes + i;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Add a new mode with the given attributes (width, height, depth, refreshRate)
+ * to the given screen.
+ * Assign a new mode ID/handle to the mode as well.
+ * \return pointer to the new _EGLMode
+ */
+_EGLMode *
+_eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height,
+ EGLint refreshRate, const char *name)
+{
+ EGLint n;
+ _EGLMode *newModes;
+
+ assert(screen);
+ assert(width > 0);
+ assert(height > 0);
+ assert(refreshRate > 0);
+
+ n = screen->NumModes;
+ newModes = (_EGLMode *) realloc(screen->Modes, (n+1) * sizeof(_EGLMode));
+ if (newModes) {
+ screen->Modes = newModes;
+ screen->Modes[n].Handle = n + 1;
+ screen->Modes[n].Width = width;
+ screen->Modes[n].Height = height;
+ screen->Modes[n].RefreshRate = refreshRate;
+ screen->Modes[n].Optimal = EGL_FALSE;
+ screen->Modes[n].Interlaced = EGL_FALSE;
+ screen->Modes[n].Name = my_strdup(name);
+ screen->NumModes++;
+ return screen->Modes + n;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+
+/**
+ * Parse the attrib_list to fill in the fields of the given _eglMode
+ * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
+ */
+static EGLBoolean
+_eglParseModeAttribs(_EGLMode *mode, const EGLint *attrib_list)
+{
+ EGLint i;
+
+ /* init all attribs to EGL_DONT_CARE */
+ mode->Handle = EGL_DONT_CARE;
+ mode->Width = EGL_DONT_CARE;
+ mode->Height = EGL_DONT_CARE;
+ mode->RefreshRate = EGL_DONT_CARE;
+ mode->Optimal = EGL_DONT_CARE;
+ mode->Interlaced = EGL_DONT_CARE;
+ mode->Name = NULL;
+
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ case EGL_MODE_ID_MESA:
+ mode->Handle = attrib_list[++i];
+ if (mode->Handle <= 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(handle)");
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_WIDTH:
+ mode->Width = attrib_list[++i];
+ if (mode->Width <= 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(width)");
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_HEIGHT:
+ mode->Height = attrib_list[++i];
+ if (mode->Height <= 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(height)");
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_REFRESH_RATE_MESA:
+ mode->RefreshRate = attrib_list[++i];
+ if (mode->RefreshRate <= 0) {
+ _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(refresh rate)");
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_INTERLACED_MESA:
+ mode->Interlaced = attrib_list[++i];
+ if (mode->Interlaced != EGL_TRUE && mode->Interlaced != EGL_FALSE) {
+ _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(interlaced)");
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_OPTIMAL_MESA:
+ mode->Optimal = attrib_list[++i];
+ if (mode->Optimal != EGL_TRUE && mode->Optimal != EGL_FALSE) {
+ _eglError(EGL_BAD_PARAMETER, "eglChooseModeMESA(optimal)");
+ return EGL_FALSE;
+ }
+ break;
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglChooseModeMESA");
+ return EGL_FALSE;
+ }
+ }
+ return EGL_TRUE;
+}
+
+
+/**
+ * Determine if the candidate mode's attributes are at least as good
+ * as the minimal mode's.
+ * \return EGL_TRUE if qualifies, EGL_FALSE otherwise
+ */
+static EGLBoolean
+_eglModeQualifies(const _EGLMode *c, const _EGLMode *min)
+{
+ if (min->Handle != EGL_DONT_CARE && c->Handle != min->Handle)
+ return EGL_FALSE;
+ if (min->Width != EGL_DONT_CARE && c->Width < min->Width)
+ return EGL_FALSE;
+ if (min->Height != EGL_DONT_CARE && c->Height < min->Height)
+ return EGL_FALSE;
+ if (min->RefreshRate != EGL_DONT_CARE && c->RefreshRate < min->RefreshRate)
+ return EGL_FALSE;
+ if (min->Optimal != EGL_DONT_CARE && c->Optimal != min->Optimal)
+ return EGL_FALSE;
+ if (min->Interlaced != EGL_DONT_CARE && c->Interlaced != min->Interlaced)
+ return EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Return value of given mode attribute, or -1 if bad attrib.
+ */
+static EGLint
+getModeAttrib(const _EGLMode *m, EGLint attrib)
+{
+ switch (attrib) {
+ case EGL_MODE_ID_MESA:
+ return m->Handle;
+ case EGL_WIDTH:
+ return m->Width;
+ case EGL_HEIGHT:
+ return m->Height;
+ case EGL_REFRESH_RATE_MESA:
+ return m->RefreshRate;
+ case EGL_OPTIMAL_MESA:
+ return m->Optimal;
+ case EGL_INTERLACED_MESA:
+ return m->Interlaced;
+ default:
+ return -1;
+ }
+}
+
+
+#define SMALLER 1
+#define LARGER 2
+
+struct sort_info {
+ EGLint Attrib;
+ EGLint Order; /* SMALLER or LARGER */
+};
+
+/* the order of these entries is the priority */
+static struct sort_info SortInfo[] = {
+ { EGL_OPTIMAL_MESA, LARGER },
+ { EGL_INTERLACED_MESA, SMALLER },
+ { EGL_WIDTH, LARGER },
+ { EGL_HEIGHT, LARGER },
+ { EGL_REFRESH_RATE_MESA, LARGER },
+ { EGL_MODE_ID_MESA, SMALLER },
+ { 0, 0 }
+};
+
+
+/**
+ * Compare modes 'a' and 'b' and return -1 if a belongs before b, or 1 if a
+ * belongs after b, or 0 if they're equal.
+ * Used by qsort().
+ */
+static int
+_eglCompareModes(const void *a, const void *b)
+{
+ const _EGLMode *aMode = *((const _EGLMode **) a);
+ const _EGLMode *bMode = *((const _EGLMode **) b);
+ EGLint i;
+
+ for (i = 0; SortInfo[i].Attrib; i++) {
+ const EGLint aVal = getModeAttrib(aMode, SortInfo[i].Attrib);
+ const EGLint bVal = getModeAttrib(bMode, SortInfo[i].Attrib);
+ if (aVal == bVal) {
+ /* a tie */
+ continue;
+ }
+ else if (SortInfo[i].Order == SMALLER) {
+ return (aVal < bVal) ? -1 : 1;
+ }
+ else if (SortInfo[i].Order == LARGER) {
+ return (aVal > bVal) ? -1 : 1;
+ }
+ }
+
+ /* all attributes identical */
+ return 0;
+}
+
+
+/**
+ * Search for EGLModes which match the given attribute list.
+ * Called via eglChooseModeMESA API function.
+ */
+EGLBoolean
+_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+ const EGLint *attrib_list, EGLModeMESA *modes,
+ EGLint modes_size, EGLint *num_modes)
+{
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+ _EGLMode **modeList, min;
+ EGLint i, count;
+
+ if (!scrn) {
+ _eglError(EGL_BAD_SCREEN_MESA, "eglChooseModeMESA");
+ return EGL_FALSE;
+ }
+
+ if (!_eglParseModeAttribs(&min, attrib_list)) {
+ /* error code will have been recorded */
+ return EGL_FALSE;
+ }
+
+ /* allocate array of mode pointers */
+ modeList = (_EGLMode **) malloc(modes_size * sizeof(_EGLMode *));
+ if (!modeList) {
+ _eglError(EGL_BAD_MODE_MESA, "eglChooseModeMESA(out of memory)");
+ return EGL_FALSE;
+ }
+
+ /* make array of pointers to qualifying modes */
+ for (i = count = 0; i < scrn->NumModes && count < modes_size; i++) {
+ if (_eglModeQualifies(scrn->Modes + i, &min)) {
+ modeList[count++] = scrn->Modes + i;
+ }
+ }
+
+ /* sort array of pointers */
+ qsort(modeList, count, sizeof(_EGLMode *), _eglCompareModes);
+
+ /* copy mode handles to output array */
+ for (i = 0; i < count; i++) {
+ modes[i] = modeList[i]->Handle;
+ }
+
+ free(modeList);
+
+ *num_modes = count;
+
+ return EGL_TRUE;
+}
+
+
+
+/**
+ * Return all possible modes for the given screen. No sorting of results.
+ * Called via eglGetModesMESA() API function.
+ */
+EGLBoolean
+_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+ EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes)
+{
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+
+ if (!scrn) {
+ _eglError(EGL_BAD_SCREEN_MESA, "eglGetModesMESA");
+ return EGL_FALSE;
+ }
+
+ if (modes) {
+ EGLint i;
+ *num_modes = MIN2(scrn->NumModes, modes_size);
+ for (i = 0; i < *num_modes; i++) {
+ modes[i] = scrn->Modes[i].Handle;
+ }
+ }
+ else {
+ /* just return total number of supported modes */
+ *num_modes = scrn->NumModes;
+ }
+
+ 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);
+ EGLint v;
+
+ if (!m) {
+ _eglError(EGL_BAD_MODE_MESA, "eglGetModeAttribMESA");
+ return EGL_FALSE;
+ }
+
+ v = getModeAttrib(m, attribute);
+ if (v < 0) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglGetModeAttribMESA");
+ return EGL_FALSE;
+ }
+ *value = v;
+ return EGL_TRUE;
+}
+
+
+/**
+ * Return human-readable string for given mode.
+ * This is the default function called by eglQueryModeStringMESA().
+ */
+const char *
+_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode)
+{
+ _EGLMode *m = _eglLookupMode(dpy, mode);
+ if (!m) {
+ _eglError(EGL_BAD_MODE_MESA, "eglQueryModeStringMESA");
+ return NULL;
+ }
+ return m->Name;
+}
+
+
+#if 0
+static int
+_eglRand(int max)
+{
+ return rand() % max;
+}
+
+void
+_eglTestModeModule(void)
+{
+ EGLint count = 30;
+ _EGLMode *modes = (_EGLMode *) malloc(count * sizeof(_EGLMode));
+ _EGLMode **modeList = (_EGLMode **) malloc(count * sizeof(_EGLMode*));
+ EGLint i;
+
+ for (i = 0; i < count; i++) {
+ modes[i].Handle = _eglRand(20);
+ modes[i].Width = 512 + 256 * _eglRand(2);
+ modes[i].Height = 512 + 256 * _eglRand(2);
+ modes[i].RefreshRate = 50 + 5 * _eglRand(3);
+ modes[i].Interlaced = _eglRand(2);
+ modes[i].Optimal = _eglRand(4) == 0;
+ modeList[i] = modes + i;
+ }
+
+ /* sort array of pointers */
+ qsort(modeList, count, sizeof(_EGLMode *), compareModes);
+
+ for (i = 0; i < count; i++) {
+ _EGLMode *m = modeList[i];
+ printf("%2d: %3d %4d x %4d @ %3d opt %d int %d\n", i,
+ m->Handle, m->Width, m->Height, m->RefreshRate,
+ m->Optimal, m->Interlaced);
+ }
+}
+#endif
diff --git a/src/egl/main/eglmode.h b/src/egl/main/eglmode.h
new file mode 100644
index 00000000000..e70da857595
--- /dev/null
+++ b/src/egl/main/eglmode.h
@@ -0,0 +1,54 @@
+#ifndef EGLMODE_INCLUDED
+#define EGLMODE_INCLUDED
+
+#include "egltypedefs.h"
+
+
+/**
+ * Data structure which corresponds to an EGLModeMESA.
+ */
+struct _egl_mode
+{
+ EGLModeMESA Handle; /* the public/opaque handle which names this mode */
+ EGLint Width, Height; /* size in pixels */
+ EGLint RefreshRate; /* rate * 1000.0 */
+ EGLint Optimal;
+ EGLint Interlaced;
+ const char *Name;
+
+ /* Other possible attributes */
+ /* interlaced */
+ /* external sync */
+};
+
+
+extern _EGLMode *
+_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode);
+
+
+extern _EGLMode *
+_eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height,
+ EGLint refreshRate, const char *name);
+
+
+extern EGLBoolean
+_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+ const EGLint *attrib_list, EGLModeMESA *modes,
+ EGLint modes_size, EGLint *num_modes);
+
+
+extern EGLBoolean
+_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+ EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+
+
+extern EGLBoolean
+_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode,
+ EGLint attribute, EGLint *value);
+
+
+extern const char *
+_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode);
+
+
+#endif /* EGLMODE_INCLUDED */
diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c
new file mode 100644
index 00000000000..9c9a8377bf2
--- /dev/null
+++ b/src/egl/main/eglscreen.c
@@ -0,0 +1,328 @@
+/*
+ * Ideas for screen management extension to EGL.
+ *
+ * Each EGLDisplay has one or more screens (CRTs, Flat Panels, etc).
+ * The screens' handles can be obtained with eglGetScreensMESA().
+ *
+ * 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 <string.h>
+
+#include "egldisplay.h"
+#include "eglglobals.h"
+#include "eglmode.h"
+#include "eglconfig.h"
+#include "eglsurface.h"
+#include "eglscreen.h"
+
+
+/**
+ * Return a new screen handle/ID.
+ * NOTE: we never reuse these!
+ */
+EGLScreenMESA
+_eglAllocScreenHandle(void)
+{
+ EGLScreenMESA s = _eglGlobal.FreeScreenHandle;
+ _eglGlobal.FreeScreenHandle++;
+ return s;
+}
+
+
+/**
+ * Initialize an _EGLScreen object to default values.
+ */
+void
+_eglInitScreen(_EGLScreen *screen)
+{
+ memset(screen, 0, sizeof(_EGLScreen));
+ screen->StepX = 1;
+ screen->StepY = 1;
+}
+
+
+/**
+ * Given a public screen handle, return the internal _EGLScreen object.
+ */
+_EGLScreen *
+_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen)
+{
+ EGLint i;
+ _EGLDisplay *display = _eglLookupDisplay(dpy);
+
+ if (!display)
+ return NULL;
+
+ for (i = 0; i < display->NumScreens; i++) {
+ if (display->Screens[i]->Handle == screen)
+ return display->Screens[i];
+ }
+ return NULL;
+}
+
+
+/**
+ * Add the given _EGLScreen to the display's list of screens.
+ */
+void
+_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
+{
+ EGLint n;
+
+ assert(display);
+ assert(screen);
+
+ screen->Handle = _eglAllocScreenHandle();
+ n = display->NumScreens;
+ display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
+ display->Screens[n] = screen;
+ display->NumScreens++;
+}
+
+
+
+EGLBoolean
+_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens,
+ EGLint max_screens, EGLint *num_screens)
+{
+ _EGLDisplay *display = _eglLookupDisplay(dpy);
+ EGLint n;
+
+ if (!display) {
+ _eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA");
+ return EGL_FALSE;
+ }
+
+ if (display->NumScreens > max_screens) {
+ n = max_screens;
+ }
+ else {
+ n = display->NumScreens;
+ }
+
+ if (screens) {
+ EGLint i;
+ for (i = 0; i < n; i++)
+ screens[i] = display->Screens[i]->Handle;
+ }
+ if (num_screens)
+ *num_screens = n;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Example function - drivers should do a proper implementation.
+ */
+EGLSurface
+_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
+{
+#if 0 /* THIS IS JUST EXAMPLE CODE */
+ _EGLSurface *surf;
+
+ surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
+ if (!surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA,
+ config, attrib_list)) {
+ free(surf);
+ return EGL_NO_SURFACE;
+ }
+
+ _eglSaveSurface(surf);
+
+ return surf->Handle;
+#endif
+ return EGL_NO_SURFACE;
+}
+
+
+/**
+ * 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
+_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
+ EGLScreenMESA screen, EGLSurface surface,
+ EGLModeMESA m)
+{
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+ _EGLMode *mode = _eglLookupMode(dpy, m);
+
+ if (!scrn) {
+ _eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA");
+ return EGL_FALSE;
+ }
+ if (!mode && (m != EGL_NO_MODE_MESA )) {
+ _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA");
+ 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;
+ scrn->CurrentMode = mode;
+ }
+ 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, EGLScreenMESA screen,
+ EGLModeMESA mode)
+{
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+
+ 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,
+ EGLScreenMESA screen, EGLint x, EGLint y)
+{
+ _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+ if (!scrn) {
+ _eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA");
+ return EGL_FALSE;
+ }
+
+ scrn->OriginX = x;
+ scrn->OriginY = y;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Query a screen's current surface.
+ */
+EGLBoolean
+_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
+ EGLScreenMESA screen, EGLSurface *surface)
+{
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+ 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, EGLScreenMESA screen,
+ EGLModeMESA *mode)
+{
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+ if (scrn->CurrentMode)
+ *mode = scrn->CurrentMode->Handle;
+ else
+ *mode = EGL_NO_MODE_MESA;
+ return EGL_TRUE;
+}
+
+
+EGLBoolean
+_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
+ EGLint attribute, EGLint *value)
+{
+ const _EGLScreen *scrn = _eglLookupScreen(dpy, screen);
+
+ 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;
+ case EGL_SCREEN_POSITION_GRANULARITY_MESA:
+ value[0] = scrn->StepX;
+ value[1] = scrn->StepY;
+ break;
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglQueryScreenMESA");
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Delete the modes associated with given screen.
+ */
+void
+_eglDestroyScreenModes(_EGLScreen *scrn)
+{
+ EGLint i;
+ for (i = 0; i < scrn->NumModes; i++) {
+ if (scrn->Modes[i].Name)
+ free((char *) scrn->Modes[i].Name); /* cast away const */
+ }
+ if (scrn->Modes)
+ free(scrn->Modes);
+ scrn->Modes = NULL;
+ scrn->NumModes = 0;
+}
+
+
+/**
+ * Default fallback routine - drivers should usually override this.
+ */
+void
+_eglDestroyScreen(_EGLScreen *scrn)
+{
+ _eglDestroyScreenModes(scrn);
+ free(scrn);
+}
+
diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h
new file mode 100644
index 00000000000..833439b4107
--- /dev/null
+++ b/src/egl/main/eglscreen.h
@@ -0,0 +1,90 @@
+#ifndef EGLSCREEN_INCLUDED
+#define EGLSCREEN_INCLUDED
+
+
+/**
+ * Per-screen information.
+ * Note that an EGL screen doesn't have a size. A screen may be set to
+ * one of several display modes (width/height/scanrate). The screen
+ * then displays a drawing surface. The drawing surface must be at least
+ * as large as the display mode's resolution. If it's larger, the
+ * OriginX and OriginY fields control what part of the surface is visible
+ * on the screen.
+ */
+struct _egl_screen
+{
+ EGLScreenMESA Handle; /* The public/opaque handle which names this object */
+
+ _EGLMode *CurrentMode;
+ _EGLSurface *CurrentSurface;
+
+ EGLint OriginX, OriginY; /**< Origin of scan-out region w.r.t. surface */
+ EGLint StepX, StepY; /**< Screen position/origin granularity */
+
+ EGLint NumModes;
+ _EGLMode *Modes; /**< array [NumModes] */
+};
+
+
+extern EGLScreenMESA
+_eglAllocScreenHandle(void);
+
+
+extern void
+_eglInitScreen(_EGLScreen *screen);
+
+
+extern _EGLScreen *
+_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen);
+
+
+extern void
+_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen);
+
+
+extern EGLBoolean
+_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
+
+
+extern EGLSurface
+_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+
+
+extern EGLBoolean
+_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode);
+
+
+extern EGLBoolean
+_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA mode);
+
+
+extern EGLBoolean
+_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
+
+
+extern EGLBoolean
+_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attribute, EGLint *value);
+
+
+extern EGLBoolean
+_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy,
+ EGLScreenMESA screen, EGLSurface *surface);
+
+
+extern EGLBoolean
+_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
+
+
+extern EGLBoolean
+_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
+
+
+extern void
+_eglDestroyScreenModes(_EGLScreen *scrn);
+
+
+extern void
+_eglDestroyScreen(_EGLScreen *scrn);
+
+
+#endif /* EGLSCREEN_INCLUDED */
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
new file mode 100644
index 00000000000..874f318e966
--- /dev/null
+++ b/src/egl/main/eglsurface.c
@@ -0,0 +1,530 @@
+/**
+ * Surface-related functions.
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "eglcontext.h"
+#include "eglconfig.h"
+#include "eglglobals.h"
+#include "eglhash.h"
+#include "egllog.h"
+#include "eglsurface.h"
+
+
+/**
+ * Do error check on parameters and initialize the given _EGLSurface object.
+ * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
+ */
+EGLBoolean
+_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
+ _EGLSurface *surf, EGLint type, EGLConfig config,
+ const EGLint *attrib_list)
+{
+ const char *func;
+ _EGLConfig *conf;
+ EGLint width = 0, height = 0, largest = 0;
+ EGLint texFormat = 0, texTarget = 0, mipmapTex = 0;
+ EGLint renderBuffer = EGL_BACK_BUFFER;
+#ifdef EGL_VERSION_1_2
+ EGLint colorspace = EGL_COLORSPACE_sRGB;
+ EGLint alphaFormat = EGL_ALPHA_FORMAT_NONPRE;
+#endif
+ EGLint i;
+
+ switch (type) {
+ case EGL_WINDOW_BIT:
+ func = "eglCreateWindowSurface";
+ break;
+ case EGL_PIXMAP_BIT:
+ func = "eglCreatePixmapSurface";
+ renderBuffer = EGL_SINGLE_BUFFER;
+ break;
+ case EGL_PBUFFER_BIT:
+ func = "eglCreatePBufferSurface";
+ break;
+ case EGL_SCREEN_BIT_MESA:
+ func = "eglCreateScreenSurface";
+ renderBuffer = EGL_SINGLE_BUFFER; /* XXX correct? */
+ break;
+ default:
+ _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
+ return EGL_FALSE;
+ }
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ if (!conf) {
+ _eglError(EGL_BAD_CONFIG, func);
+ return EGL_FALSE;
+ }
+
+ /*
+ * Parse attribute list. Different kinds of surfaces support different
+ * attributes.
+ */
+ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
+ switch (attrib_list[i]) {
+ case EGL_WIDTH:
+ if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
+ width = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_HEIGHT:
+ if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
+ height = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_LARGEST_PBUFFER:
+ if (type == EGL_PBUFFER_BIT) {
+ largest = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_TEXTURE_FORMAT:
+ if (type == EGL_PBUFFER_BIT) {
+ texFormat = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_TEXTURE_TARGET:
+ if (type == EGL_PBUFFER_BIT) {
+ texTarget = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ if (type == EGL_PBUFFER_BIT) {
+ mipmapTex = attrib_list[++i];
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+#ifdef EGL_VERSION_1_2
+ case EGL_RENDER_BUFFER:
+ if (type == EGL_WINDOW_BIT) {
+ renderBuffer = attrib_list[++i];
+ if (renderBuffer != EGL_BACK_BUFFER &&
+ renderBuffer != EGL_SINGLE_BUFFER) {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_COLORSPACE:
+ if (type == EGL_WINDOW_BIT ||
+ type == EGL_PBUFFER_BIT ||
+ type == EGL_PIXMAP_BIT) {
+ colorspace = attrib_list[++i];
+ if (colorspace != EGL_COLORSPACE_sRGB &&
+ colorspace != EGL_COLORSPACE_LINEAR) {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+ case EGL_ALPHA_FORMAT:
+ if (type == EGL_WINDOW_BIT ||
+ type == EGL_PBUFFER_BIT ||
+ type == EGL_PIXMAP_BIT) {
+ alphaFormat = attrib_list[++i];
+ if (alphaFormat != EGL_ALPHA_FORMAT_NONPRE &&
+ alphaFormat != EGL_ALPHA_FORMAT_PRE) {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ }
+ else {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ break;
+
+#endif /* EGL_VERSION_1_2 */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+ }
+
+ if (width <= 0 || height <= 0) {
+ _eglError(EGL_BAD_ATTRIBUTE, func);
+ return EGL_FALSE;
+ }
+
+ memset(surf, 0, sizeof(_EGLSurface));
+ surf->Config = conf;
+ surf->Type = type;
+ surf->Width = width;
+ surf->Height = height;
+ surf->TextureFormat = texFormat;
+ surf->TextureTarget = texTarget;
+ surf->MipmapTexture = mipmapTex;
+ surf->MipmapLevel = 0;
+ surf->SwapInterval = 0;
+#ifdef EGL_VERSION_1_2
+ surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */
+ surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */
+ surf->VerticalResolution = EGL_UNKNOWN; /* set by caller */
+ surf->AspectRatio = EGL_UNKNOWN; /* set by caller */
+ surf->RenderBuffer = renderBuffer;
+ surf->AlphaFormat = alphaFormat;
+ surf->Colorspace = colorspace;
+#endif
+
+ return EGL_TRUE;
+}
+
+
+void
+_eglSaveSurface(_EGLSurface *surf)
+{
+ assert(surf);
+ assert(!surf->Handle);
+ surf->Handle = _eglHashGenKey(_eglGlobal.Contexts);
+ assert(surf->Handle);
+ _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 here. Drivers have to do the
+ * actual buffer swap.
+ */
+ _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)
+{
+ /* copy surface to native pixmap */
+ /* All implementation burdon for this is in the device driver */
+ 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;
+ /*XXX case EGL_LARGEST_PBUFFER:*/
+ case EGL_SURFACE_TYPE:
+ *value = surface->Type;
+ return EGL_TRUE;
+#ifdef EGL_VERSION_1_1
+ 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;
+#endif /* EGL_VERSION_1_1 */
+#ifdef EGL_VERSION_1_2
+ case EGL_SWAP_BEHAVIOR:
+ *value = surface->SwapBehavior;
+ return EGL_TRUE;
+ case EGL_RENDER_BUFFER:
+ *value = surface->RenderBuffer;
+ return EGL_TRUE;
+ case EGL_PIXEL_ASPECT_RATIO:
+ *value = surface->AspectRatio;
+ return EGL_TRUE;
+ case EGL_HORIZONTAL_RESOLUTION:
+ *value = surface->HorizontalResolution;
+ return EGL_TRUE;
+ case EGL_VERTICAL_RESOLUTION:
+ *value = surface->VerticalResolution;
+ return EGL_TRUE;
+ case EGL_ALPHA_FORMAT:
+ *value = surface->AlphaFormat;
+ return EGL_TRUE;
+ case EGL_COLORSPACE:
+ *value = surface->Colorspace;
+ return EGL_TRUE;
+#endif /* EGL_VERSION_1_2 */
+ default:
+ _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
+ return EGL_FALSE;
+ }
+}
+
+
+/**
+ * Example function - drivers should do a proper implementation.
+ */
+EGLSurface
+_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ NativeWindowType window, const EGLint *attrib_list)
+{
+#if 0 /* THIS IS JUST EXAMPLE CODE */
+ _EGLSurface *surf;
+
+ surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
+ if (!surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) {
+ free(surf);
+ return EGL_NO_SURFACE;
+ }
+
+ _eglSaveSurface(surf);
+
+ return surf->Handle;
+#endif
+ return EGL_NO_SURFACE;
+}
+
+
+/**
+ * Example function - drivers should do a proper implementation.
+ */
+EGLSurface
+_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ NativePixmapType pixmap, const EGLint *attrib_list)
+{
+#if 0 /* THIS IS JUST EXAMPLE CODE */
+ _EGLSurface *surf;
+
+ surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
+ if (!surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) {
+ free(surf);
+ return EGL_NO_SURFACE;
+ }
+
+ _eglSaveSurface(surf);
+
+ return surf->Handle;
+#endif
+ return EGL_NO_SURFACE;
+}
+
+
+/**
+ * Example function - drivers should do a proper implementation.
+ */
+EGLSurface
+_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
+{
+#if 0 /* THIS IS JUST EXAMPLE CODE */
+ _EGLSurface *surf;
+
+ surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
+ if (!surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) {
+ free(surf);
+ return EGL_NO_SURFACE;
+ }
+
+ _eglSaveSurface(surf);
+
+ return surf->Handle;
+#endif
+ 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;
+}
+
+
+#ifdef EGL_VERSION_1_2
+
+/**
+ * Example function - drivers should do a proper implementation.
+ */
+EGLSurface
+_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
+ EGLenum buftype, EGLClientBuffer buffer,
+ EGLConfig config, const EGLint *attrib_list)
+{
+ if (buftype != EGL_OPENVG_IMAGE) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
+ return EGL_NO_SURFACE;
+ }
+
+ return EGL_NO_SURFACE;
+}
+
+#endif /* EGL_VERSION_1_2 */
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
new file mode 100644
index 00000000000..79abeca0b2a
--- /dev/null
+++ b/src/egl/main/eglsurface.h
@@ -0,0 +1,117 @@
+#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 */
+
+#ifdef EGL_VERSION_1_2
+ EGLint SwapBehavior; /* one of EGL_BUFFER_PRESERVED/DESTROYED */
+ EGLint HorizontalResolution, VerticalResolution;
+ EGLint AspectRatio;
+ EGLint RenderBuffer; /* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER */
+ EGLint AlphaFormat; /* EGL_ALPHA_FORMAT_NONPRE or EGL_ALPHA_FORMAT_PRE */
+ EGLint Colorspace; /* EGL_COLORSPACE_sRGB or EGL_COLORSPACE_LINEAR */
+#endif /* EGL_VERSION_1_2 */
+};
+
+
+extern EGLBoolean
+_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
+ _EGLSurface *surf, EGLint type, EGLConfig config,
+ const EGLint *attrib_list);
+
+
+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);
+
+
+#ifdef EGL_VERSION_1_2
+
+extern EGLSurface
+_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
+ EGLenum buftype, EGLClientBuffer buffer,
+ EGLConfig config, const EGLint *attrib_list);
+
+#endif /* EGL_VERSION_1_2 */
+
+
+
+#endif /* EGLSURFACE_INCLUDED */
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
new file mode 100644
index 00000000000..fa8cb496f8d
--- /dev/null
+++ b/src/egl/main/egltypedefs.h
@@ -0,0 +1,34 @@
+#ifndef EGLTYPEDEFS_INCLUDED
+#define EGLTYPEDEFS_INCLUDED
+
+
+#include <GLES/egl.h>
+
+
+typedef struct _egl_api _EGLAPI;
+
+typedef struct _egl_config _EGLConfig;
+
+typedef struct _egl_context _EGLContext;
+
+typedef struct _egl_display _EGLDisplay;
+
+typedef struct _egl_driver _EGLDriver;
+
+typedef struct _egl_extensions _EGLExtensions;
+
+typedef struct _egl_mode _EGLMode;
+
+typedef struct _egl_screen _EGLScreen;
+
+typedef struct _egl_surface _EGLSurface;
+
+typedef struct _egl_thread_info _EGLThreadInfo;
+
+
+typedef void (*_EGLProc)();
+
+typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy);
+
+
+#endif /* EGLTYPEDEFS_INCLUDED */