CLGL: Refine the hack of gbm extension initialization.
authorZhigang Gong <zhigang.gong@linux.intel.com>
Thu, 4 Jul 2013 12:15:08 +0000 (20:15 +0800)
committerZhigang Gong <zhigang.gong@linux.intel.com>
Fri, 5 Jul 2013 09:43:57 +0000 (17:43 +0800)
Previous implementation need to refer a EGL internal symbol.
This refinement is also a hack. It just avoid use the EGL internal
symbol, but it does use the internal EGL data structure.

Anyway, before we made some changes to gbm to support our use
model, this ugly method seems the only way to achive sharing
gl 2d/3d textures.

This patch also fix the bug when it failed to get a valid egl
context it may crash.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
src/intel/intel_driver.c
src/x11/gbm_dri2_x11_platform.c
utests/compiler_fill_gl_image.cpp
utests/utest_helper.cpp

index ebc4961..6c6b9fb 100644 (file)
@@ -208,6 +208,7 @@ intel_driver_open(intel_driver_t *intel, cl_context_prop props)
 
 #if defined(HAS_GBM) && defined(HAS_EGL)
   if (props && props->gl_type == CL_GL_EGL_DISPLAY) {
+    assert(props->egl_display);
     intel->gbm = gbm_create_device(intel->fd);
     if (intel->gbm == NULL) {
       printf("GBM device create failed.\n");
index 56b2467..481f407 100644 (file)
@@ -1,11 +1,93 @@
+#include <string.h>
 #include "GL/gl.h" /* dri_interface need gl types definitions. */
 #include "GL/internal/dri_interface.h"
 #include "gbm_deps/gbm_driint.h"
 #include "gbm_deps/gbmint.h"
 #include "dricommon.h"
 
-/* image_lookup_extension is from egl_dri2.c. */
-extern const __DRIimageLookupExtension image_lookup_extension;
+typedef struct EGLDisplay _EGLDisplay;
+typedef struct EGLDriver  _EGLDriver;
+/* XXX should check whether we support pthread.*/
+typedef pthread_mutex_t _EGLMutex;
+
+enum _egl_platform_type {
+   _EGL_PLATFORM_WINDOWS,
+   _EGL_PLATFORM_X11,
+   _EGL_PLATFORM_WAYLAND,
+   _EGL_PLATFORM_DRM,
+   _EGL_PLATFORM_FBDEV,
+   _EGL_PLATFORM_NULL,
+   _EGL_PLATFORM_ANDROID,
+
+   _EGL_NUM_PLATFORMS,
+   _EGL_INVALID_PLATFORM = -1
+};
+typedef enum _egl_platform_type _EGLPlatformType;
+typedef unsigned int EGLBoolean;
+typedef int32_t EGLint;
+
+struct _hack_egl_display
+{
+   /* used to link displays */
+   _EGLDisplay *Next;
+
+   _EGLMutex Mutex;
+
+   _EGLPlatformType Platform; /**< The type of the platform display */
+   void *PlatformDisplay;     /**< A pointer to the platform display */
+
+   _EGLDriver *Driver;        /**< Matched driver of the display */
+
+   EGLBoolean Initialized;    /**< True if the display is initialized */
+
+   /* options that affect how the driver initializes the display */
+   struct {
+      EGLBoolean TestOnly;    /**< Driver should not set fields when true */
+      EGLBoolean UseFallback; /**< Use fallback driver (sw or less features) */
+   } Options;
+
+   /* these fields are set by the driver during init */
+   void *DriverData;          /**< Driver private data */
+   EGLint VersionMajor;       /**< EGL major version */
+   EGLint VersionMinor;       /**< EGL minor version */
+   EGLint ClientAPIs;         /**< Bitmask of APIs supported (EGL_xxx_BIT) */
+};
+
+struct _hack_dri2_egl_display
+{
+   int                       dri2_major;
+   int                       dri2_minor;
+   __DRIscreen              *dri_screen;
+   int                       own_dri_screen;
+   const __DRIconfig       **driver_configs;
+   void                     *driver;
+   __DRIcoreExtension       *core;
+   __DRIdri2Extension       *dri2;
+   __DRIswrastExtension     *swrast;
+   __DRI2flushExtension     *flush;
+   __DRItexBufferExtension  *tex_buffer;
+   __DRIimageExtension      *image;
+   __DRIrobustnessExtension *robustness;
+   __DRI2configQueryExtension *config;
+   int                       fd;
+
+   int                       own_device;
+   int                       swap_available;
+   int                       invalidate_available;
+   int                       min_swap_interval;
+   int                       max_swap_interval;
+   int                       default_swap_interval;
+   struct gbm_dri_device    *gbm_dri;
+
+   char                     *device_name;
+   char                     *driver_name;
+
+   __DRIdri2LoaderExtension    dri2_loader_extension;
+   __DRIswrastLoaderExtension  swrast_loader_extension;
+   const __DRIextension     *extensions[4];
+};
+
+static __DRIimageLookupExtension *image_lookup_extension;
 
 /* We are use DRI2 x11 platform, and by default, gbm doesn't register
  * a valid image extension, and actually, it doesn't know how to register
@@ -13,8 +95,21 @@ extern const __DRIimageLookupExtension image_lookup_extension;
 void cl_gbm_set_image_extension(struct gbm_device *gbm, void *display)
 {
   struct gbm_dri_device *gbm_dri = gbm_dri_device(gbm);
-  if (gbm_dri->lookup_image == NULL) {
-    gbm_dri->lookup_image = image_lookup_extension.lookupEGLImage;
+  struct _hack_egl_display *egl_dpy = (struct _hack_egl_display*)display;
+  struct _hack_dri2_egl_display *dri2_dpy = (struct _hack_dri2_egl_display*)egl_dpy->DriverData;
+  int i;
+
+  if (gbm_dri->lookup_image == NULL
+      && egl_dpy->Platform == _EGL_PLATFORM_X11) {
+    for(i = 0; i < 4; i++)
+     if (dri2_dpy->extensions[i]
+         && ((strncmp(dri2_dpy->extensions[i]->name,
+                      __DRI_IMAGE_LOOKUP,
+                      sizeof(__DRI_IMAGE_LOOKUP))) == 0))
+       break;
+    if (i >= 4) return;
+    image_lookup_extension = (__DRIimageLookupExtension*)dri2_dpy->extensions[i];
+    gbm_dri->lookup_image = image_lookup_extension->lookupEGLImage;
     gbm_dri->lookup_user_data = display;
   }
 }
index b070b8f..437fcf4 100644 (file)
@@ -33,6 +33,10 @@ static void compiler_fill_gl_image(void)
   uint32_t *resultColor;
   GLuint tex;
 
+  if (eglContext == EGL_NO_CONTEXT) {
+    fprintf(stderr, "There is no valid egl context. Ignore this case.\n");
+    return;
+  }
   // Setup kernel and images
   glGenTextures(1, &tex);
   glBindTexture(GL_TEXTURE_2D, tex);
index 941b5f9..504f80f 100644 (file)
@@ -89,6 +89,7 @@ bool init_egl_window(int width, int height) {
     EGLConfig  ecfg;
     EGLint     numConfig;
 
+    eglContext = EGL_NO_CONTEXT;
     xDisplay = XOpenDisplay(NULL);
     if (xDisplay == NULL) {
       fprintf(stderr, "Failed to open DISPLAY.\n");
@@ -343,15 +344,17 @@ cl_ocl_init(void)
 
 #ifdef HAS_EGL
   if (hasGLExt) {
-    init_egl_window(EGL_WINDOW_WIDTH, EGL_WINDOW_HEIGHT);
+    int i = 0;
     props = new cl_context_properties[7];
-    props[0] = CL_CONTEXT_PLATFORM;
-    props[1] = (cl_context_properties)platform;
-    props[2] = CL_EGL_DISPLAY_KHR;
-    props[3] = (cl_context_properties)eglGetCurrentDisplay();
-    props[4] = CL_GL_CONTEXT_KHR;
-    props[5] = (cl_context_properties)eglGetCurrentContext();
-    props[6] = 0;
+    props[i++] = CL_CONTEXT_PLATFORM;
+    props[i++] = (cl_context_properties)platform;
+    if (init_egl_window(EGL_WINDOW_WIDTH, EGL_WINDOW_HEIGHT)) {
+      props[i++] = CL_EGL_DISPLAY_KHR;
+      props[i++] = (cl_context_properties)eglGetCurrentDisplay();
+      props[i++] = CL_GL_CONTEXT_KHR;
+      props[i++] = (cl_context_properties)eglGetCurrentContext();
+    }
+    props[i++] = 0;
   }
 #endif
   /* Now create a context */