[Mesa-dev] [PATCH 1/6] egl: Add MESA_typed_display infrastructure

Kristian Høgsberg krh at bitplanet.net
Fri Jun 4 06:46:23 PDT 2010


This extensions introduces a new entry point that allows an application
to pass in different types of displays along with an integer to identify
the type of display.  This allows one EGL library to support multiple
display types and lets applications clearly identify which one they want
to use.
---
 docs/MESA_typed_display.spec    |  121 +++++++++++++++++++++++++++++++++++++++
 include/EGL/eglext.h            |   15 +++++
 src/egl/drivers/dri2/egl_dri2.c |   68 ++++++++++++++-------
 src/egl/drivers/glx/egl_glx.c   |    5 ++
 src/egl/main/eglapi.c           |   14 ++++-
 src/egl/main/egldisplay.c       |    8 ++-
 src/egl/main/egldisplay.h       |    9 +++-
 7 files changed, 211 insertions(+), 29 deletions(-)
 create mode 100644 docs/MESA_typed_display.spec

diff --git a/docs/MESA_typed_display.spec b/docs/MESA_typed_display.spec
new file mode 100644
index 0000000..8a8f279
--- /dev/null
+++ b/docs/MESA_typed_display.spec
@@ -0,0 +1,121 @@
+Name
+
+    MESA_typed_display
+
+Name Strings
+
+    EGL_MESA_typed_display
+
+Contact
+
+    Kristian Høgsberg <krh at bitplanet.net>
+
+Status
+
+    Proposal
+
+Version
+
+    Version 2, June 2, 2010
+
+Number
+
+    EGL Extension #not assigned
+
+Dependencies
+
+    Reguires EGL 1.4 or later.  This extension is written against the
+    wording of the EGL 1.4 specification.
+
+Overview
+
+    The EGL platform mechanism was designed to support one type of display
+    per platform.  On Unix, the native display type is an X11 Display
+    pointer, on Windows, the native display type is a handle to a device
+    context (HDC).
+
+    A platform may provide different types of displays.  Under Linux, for
+    example, one might want to initialize an EGL display from an XCB
+    connection or a DRM file descriptor.  However, there is only one EGL
+    entry point for initializing the display and it takes an
+    EGLNativeDisplayType.  To support multiple displays on one platform, one
+    would need multiple EGL libraries.
+
+    This extensions introduces a new entry point that allows an application
+    to pass in different types of displays along with an integer to identify
+    the type of display.  This allows one EGL library to support multiple
+    display types and lets applications clearly identify which one they want
+    to use.
+
+IP Status
+
+    Open-source; freely implementable.
+
+Issues
+
+    1) Should we use official EGL tokens for the display types or just
+    sequential numbers?  Using tokens helps avoiding clashes, but we'll need
+    to allocate those.
+
+    2) We can't detect this as a regular EGL extension as we can't get the
+    extension string until we have an EGL display.  It should be sufficient
+    to just require applications to use eglGetProcAddress() to find out
+    whether or not the eglGetDisplayMESA() entry point is available.  Should
+    we advertise the extension in the EGL extension string anyway?  It's not
+    useful once you have an EGL display.
+
+New Procedures and Functions
+
+    EGLDisplay eglGetTypedDisplayMESA(EGLenum type, void *display);
+
+New Tokens
+
+    Accepted by the <type> parameter of eglGetTypedDisplayMESA:
+
+        EGL_X11_DISPLAY_TYPE_MESA          0xcc00
+        EGL_WIN32_DISPLAY_TYPE_MESA        0xcc01
+        EGL_DRM_DISPLAY_TYPE_MESA          0xcc02
+
+Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
+
+    Add to section 3.2 Initialization:
+
+    Alternatively, the function
+
+	 EGLDisplay eglGetTypedDisplayMESA(EGLenum type, void *display);
+
+    may be used to obtain an EGL display for an alternative type of native
+    display.  'type' identifies the type of native display and 'display'
+    provides the details of the native display.  This extension defines
+    three types of native display types: EGL_X11_DISPLAY_TYPE_MESA,
+    EGL_WIN32_DISPLAY_TYPE_MESA, and EGL_DRM_DISPLAY_TYPE_MESA.
+
+    When type is EGL_X11_DISPLAY_TYPE_MESA, the value of 'display' will be
+    interpreted as an X11 Display pointer.  In other words, this is
+    equivalent to calling eglGetDisplay with the value of 'display' under
+    the X11 platform.
+
+    When type is EGL_WIN32_DISPLAY_TYPE_MESA, the value of 'display' will be
+    interpreted as an Win32 device context handle.  In other words, this is
+    equivalent to calling eglGetDisplay with the value of 'display' under
+    the Win32 platform.
+
+    When type is EGL_DRM_DISPLAY_TYPE_MESA, the value of 'display' will be
+    interpreted as an integer file descriptor cast to a void pointer.  The
+    file descriptor will be assumed to refer to a DRM device under Linux
+    (typically /dev/dri/card0 or such).
+
+    If no display matching type and display is available, EGL_NO_DISPLAY is
+    returned; no error condition is raised in this case.
+
+Revision History
+
+    May 27, 2010
+        Initial draft (Kristian Høgsberg)
+
+    June 3, 2010
+        Change extension name to MESA_typed_display and change
+        entrypoint to eglGetTypedDisplayMESA.  Change display types to
+        be enums.  Drop native display type and add explicit X11 and
+        Win32 types.  Change display tokens to be of the form
+        EGL_<type>_DISPLAY_TYPE_MESA. (Kristian Høgsberg)
diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index ce1dca3..bb6f6e7 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -246,6 +246,21 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG
 #endif /* EGL_NOK_texture_from_pixmap */
 
 
+#ifndef EGL_MESA_typed_display
+#define EGL_MESA_typed_display 1
+
+#define EGL_X11_DISPLAY_TYPE_MESA          0xcc00
+#define EGL_WIN32_DISPLAY_TYPE_MESA        0xcc01
+#define EGL_DRM_DISPLAY_TYPE_MESA          0xcc02
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetTypedDisplayMESA(EGLenum type, void *display);
+#endif
+
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETTYPEDDISPLAYMESA) (EGLenum type, void *display);
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index aa384cb..82aa8bf 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -691,22 +691,14 @@ dri2_load_driver(_EGLDisplay *disp)
 }
 
 
-/**
- * Called via eglInitialize(), GLX_drv->API.Initialize().
- */
 static EGLBoolean
-dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
-		EGLint *major, EGLint *minor)
+dri2_initialize_xcb(_EGLDisplay *disp)
 {
    const __DRIextension **extensions;
    struct dri2_egl_display *dri2_dpy;
    unsigned int api_mask;
 
-   dri2_dpy = malloc(sizeof *dri2_dpy);
-   if (!dri2_dpy)
-      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
-
-   disp->DriverData = (void *) dri2_dpy;
+   dri2_dpy = disp->DriverData;
    if (disp->NativeDisplay == NULL) {
       dri2_dpy->conn = xcb_connect(0, 0);
    } else {
@@ -718,10 +710,8 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
       goto cleanup_dpy;
    }
 
-   if (dri2_dpy->conn) {
-      if (!dri2_connect(dri2_dpy))
-	 goto cleanup_conn;
-   }
+   if (!dri2_connect(dri2_dpy))
+      goto cleanup_conn;
 
    if (!dri2_load_driver(disp))
       goto cleanup_conn;
@@ -730,14 +720,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    if (dri2_dpy->fd == -1) {
       _eglLog(_EGL_WARNING,
 	      "DRI2: could not open %s (%s)", dri2_dpy->device_name,
-              strerror(errno));
+	      strerror(errno));
       goto cleanup_driver;
    }
 
-   if (dri2_dpy->conn) {
-      if (!dri2_authenticate(dri2_dpy))
-	 goto cleanup_fd;
-   }
+   if (!dri2_authenticate(dri2_dpy))
+      goto cleanup_fd;
 
    if (dri2_dpy->dri2_minor >= 1) {
       dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER;
@@ -800,10 +788,6 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    disp->Extensions.NOK_swap_region = EGL_TRUE;
    disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
 
-   /* we're supporting EGL 1.4 */
-   *major = 1;
-   *minor = 4;
-
    return EGL_TRUE;
 
  cleanup_configs:
@@ -824,6 +808,44 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
 }
 
 /**
+ * Called via eglInitialize(), GLX_drv->API.Initialize().
+ */
+static EGLBoolean
+dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
+		EGLint *major, EGLint *minor)
+{
+   struct dri2_egl_display *dri2_dpy;
+
+   dri2_dpy = malloc(sizeof *dri2_dpy);
+   if (!dri2_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+   disp->DriverData = dri2_dpy;
+   switch (disp->DisplayType) {                                                
+   case EGL_X11_DISPLAY_TYPE_MESA:
+      if (!dri2_initialize_xcb(disp))
+	 goto cleanup_dpy;
+      break;
+
+   default:
+      _eglLog(_EGL_WARNING,
+	      "DRI2: unknown display type: %d", disp->DisplayType);
+      goto cleanup_dpy;
+   }
+
+   /* we're supporting EGL 1.4 */
+   *major = 1;
+   *minor = 4;
+
+   return EGL_TRUE;
+
+ cleanup_dpy:
+   free(dri2_dpy);
+
+   return EGL_FALSE;
+}
+
+/**
  * Called via eglTerminate(), drv->API.Terminate().
  */
 static EGLBoolean
diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
index e08ef5f..6985618 100644
--- a/src/egl/drivers/glx/egl_glx.c
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -502,6 +502,11 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
    if (!GLX_dpy)
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
 
+   if (disp->DisplayType != EGL_X11_DISPLAY_TYPE_MESA) {
+      _eglLog(_EGL_WARNING, "GLX: Unsupported display type");
+      return EGL_FALSE;
+   }
+
    GLX_dpy->dpy = (Display *) disp->NativeDisplay;
    if (!GLX_dpy->dpy) {
       GLX_dpy->dpy = XOpenDisplay(NULL);
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 9912043..7c4846c 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -242,7 +242,6 @@ _eglUnlockDisplay(_EGLDisplay *dpy)
    _eglUnlockMutex(&dpy->Mutex);
 }
 
-
 /**
  * This is typically the first EGL function that an application calls.
  * It associates a private _EGLDisplay object to the native display.
@@ -250,7 +249,8 @@ _eglUnlockDisplay(_EGLDisplay *dpy)
 EGLDisplay EGLAPIENTRY
 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
 {
-   _EGLDisplay *dpy = _eglFindDisplay(nativeDisplay);
+   _EGLDisplay *dpy =
+      _eglFindDisplay(EGL_NATIVE_DISPLAY_TYPE_MESA, (void *) nativeDisplay);
    return _eglGetDisplayHandle(dpy);
 }
 
@@ -813,6 +813,13 @@ eglGetError(void)
    return e;
 }
 
+EGLDisplay EGLAPIENTRY
+eglGetTypedDisplayMESA(EGLenum type, void *display)
+{
+   _EGLDisplay *dpy = _eglFindDisplay(type, display);
+
+   return _eglGetDisplayHandle(dpy);
+}
 
 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
 eglGetProcAddress(const char *procname)
@@ -843,6 +850,9 @@ eglGetProcAddress(const char *procname)
 #ifdef EGL_NOK_swap_region
       { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
 #endif
+#ifdef EGL_MESA_typed_display
+      { "eglGetTypedDisplayMESA", (_EGLProc) eglGetTypedDisplayMESA },
+#endif
       { NULL, NULL }
    };
    EGLint i;
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 5dc5fd9..bd2113b 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -49,7 +49,7 @@ _eglFiniDisplay(void)
  * new one.
  */
 _EGLDisplay *
-_eglFindDisplay(EGLNativeDisplayType nativeDisplay)
+_eglFindDisplay(EGLint type, void *nativeDisplay)
 {
    _EGLDisplay *dpy;
 
@@ -58,7 +58,7 @@ _eglFindDisplay(EGLNativeDisplayType nativeDisplay)
    /* search the display list first */
    dpy = _eglGlobal.DisplayList;
    while (dpy) {
-      if (dpy->NativeDisplay == nativeDisplay)
+      if (dpy->DisplayType == type && dpy->VoidDisplay == nativeDisplay)
          break;
       dpy = dpy->Next;
    }
@@ -68,7 +68,9 @@ _eglFindDisplay(EGLNativeDisplayType nativeDisplay)
       dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
       if (dpy) {
          _eglInitMutex(&dpy->Mutex);
-         dpy->NativeDisplay = nativeDisplay;
+         dpy->NativeDisplay = (EGLNativeDisplayType) nativeDisplay;
+	 dpy->VoidDisplay = nativeDisplay;
+	 dpy->DisplayType = type;
 
          /* add to the display list */ 
          dpy->Next = _eglGlobal.DisplayList;
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 42e305f..0749edd 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -6,6 +6,11 @@
 #include "egldefines.h"
 #include "eglmutex.h"
 
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#define EGL_NATIVE_DISPLAY_TYPE_MESA EGL_WIN32_DISPLAY_TYPE_MESA
+#elif defined(__unix__) || defined(__unix)
+#define EGL_NATIVE_DISPLAY_TYPE_MESA EGL_X11_DISPLAY_TYPE_MESA
+#endif
 
 enum _egl_resource_type {
    _EGL_RESOURCE_CONTEXT,
@@ -61,6 +66,8 @@ struct _egl_display
    _EGLMutex Mutex;
 
    EGLNativeDisplayType NativeDisplay;
+   EGLint DisplayType;
+   void *VoidDisplay;
 
    EGLBoolean Initialized; /**< True if the display is initialized */
    _EGLDriver *Driver;
@@ -92,7 +99,7 @@ _eglFiniDisplay(void);
 
 
 extern _EGLDisplay *
-_eglFindDisplay(EGLNativeDisplayType displayName);
+_eglFindDisplay(EGLint type, void *display);
 
 
 PUBLIC void
-- 
1.7.1



More information about the mesa-dev mailing list