OSDN Git Service

egl_xdri: Implement eglCreateImageKHR.
authorChia-I Wu <olvaffe@gmail.com>
Tue, 18 Aug 2009 08:36:10 +0000 (16:36 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 14 Sep 2009 05:39:19 +0000 (13:39 +0800)
include/EGL/internal/eglimage_dri.h [new file with mode: 0644]
src/egl/drivers/xdri/egl_xdri.c

diff --git a/include/EGL/internal/eglimage_dri.h b/include/EGL/internal/eglimage_dri.h
new file mode 100644 (file)
index 0000000..ea13951
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef EGLIMAGE_DRI_INCLUDED
+#define EGLIMAGE_DRI_INCLUDED
+
+#include "GL/internal/dri_interface.h"
+
+#define __DRI_EGL_IMAGE_MAGIC \
+   (('D' << 24) | \
+    ('R' << 16) | \
+    ('I' <<  8) | \
+    ('0'))
+
+typedef void *__DRIEGLImageHandle;
+typedef struct __DRIEGLImageRec __DRIEGLImage;
+
+struct __DRIEGLImageRec {
+   GLint magic;
+
+   __DRIdrawable *drawable;
+
+   GLboolean texture_format_rgba;
+   GLint level;
+   GLint __pad[4];
+};
+
+extern __DRIEGLImage *_eglClientGetImageData(__DRIEGLImageHandle handle);
+
+#endif /* EGLIMAGE_DRI_INCLUDED */
index 518091a..42d8726 100644 (file)
 #include "eglglobals.h"
 #include "egllog.h"
 #include "eglsurface.h"
+#include "eglimage.h"
 
+#include "EGL/internal/eglimage_dri.h"
+
+#define MAX_DEPTH 32
 #define CALLOC_STRUCT(T)   (struct T *) calloc(1, sizeof(struct T))
 
 /** subclass of _EGLDriver */
@@ -73,6 +77,8 @@ struct xdri_egl_display
 
    __GLXscreenConfigs *psc;
    EGLint scr;
+
+   const __GLcontextModes *imageConfigs[MAX_DEPTH + 1];
 };
 
 
@@ -98,6 +104,16 @@ struct xdri_egl_surface
 };
 
 
+/** subclass of _EGLImage */
+struct xdri_egl_image
+{
+   _EGLImage Base;   /**< base class */
+
+   Drawable pixmap;
+   __GLXDRIdrawable *driDrawable;
+};
+
+
 /** subclass of _EGLConfig */
 struct xdri_egl_config
 {
@@ -147,6 +163,14 @@ lookup_config(_EGLConfig *conf)
 }
 
 
+/** Map EGLImage handle to xdri_egl_image object */
+static INLINE struct xdri_egl_image *
+lookup_image(_EGLImage *img)
+{
+   return (struct xdri_egl_image *) img;
+}
+
+
 /** Get size of given window */
 static Status
 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
@@ -162,6 +186,62 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
 }
 
 
+#if EGL_KHR_image_base
+/** Get depth of given window */
+static Status
+get_drawable_depth(Display *dpy, Drawable d, uint *depth_ret)
+{
+   Window root;
+   Status stat;
+   int xpos, ypos;
+   unsigned int w, h, bw, depth;
+   stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+   *depth_ret = depth;
+   return stat;
+}
+
+
+/**
+ * The config of a pixmap must be guessed from its depth.  Do the guess once
+ * for all depths.
+ */
+static void
+find_image_configs(_EGLDisplay *dpy, const __GLcontextModes *modes)
+{
+   struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+   EGLint depth;
+
+   for (depth = 0; depth < MAX_DEPTH + 1; depth++) {
+      const __GLcontextModes *m;
+
+      for (m = modes; m; m = m->next) {
+         /* the depth of a pixmap might not include alpha */
+         if (m->rgbBits != depth && (m->rgbBits - m->alphaBits) != depth)
+            continue;
+         if (!m->visualID)
+            continue;
+
+         if (depth == 32) {
+            if (m->bindToTextureRgba) {
+               xdri_dpy->imageConfigs[depth] = m;
+               break;
+            }
+         }
+
+         if (m->bindToTextureRgb) {
+            xdri_dpy->imageConfigs[depth] = m;
+            break;
+         }
+      }
+
+      if (m)
+         _eglLog(_EGL_DEBUG, "Use mode 0x%02x for depth %d",
+                 m->visualID, depth);
+   }
+}
+#endif /* EGL_KHR_image_base */
+
+
 /**
  * Produce a set of EGL configs.
  */
@@ -275,6 +355,15 @@ xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
                           EGL_OPENGL_ES2_BIT |
                           EGL_OPENVG_BIT);
 
+#if EGL_KHR_image_base
+   /* must be called after DriverData is set */
+   find_image_configs(dpy, psc->configs);
+
+   dpy->Extensions.KHR_image = EGL_TRUE;
+   dpy->Extensions.KHR_image_base = EGL_TRUE;
+   dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
+#endif
+
    /* we're supporting EGL 1.4 */
    *minor = 1;
    *major = 4;
@@ -530,9 +619,107 @@ xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
    xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable);
 
    return EGL_TRUE;
+} 
+
+
+#if EGL_KHR_image_base
+
+
+static _EGLImage *
+xdri_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+                       EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
+   struct xdri_egl_image *xdri_img;
+   __DRIEGLImage *driImage;
+   EGLint err = EGL_SUCCESS;
+   const __GLcontextModes *mode;
+   uint depth;
+
+   xdri_img = CALLOC_STRUCT(xdri_egl_image);
+   if (!xdri_img) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
+      return NULL;
+   }
+
+   switch (target) {
+   case EGL_NATIVE_PIXMAP_KHR:
+      if (ctx) {
+         err = EGL_BAD_PARAMETER;
+         break;
+      }
+      xdri_img->pixmap = (Pixmap) buffer;
+      break;
+   default:
+      err = EGL_BAD_PARAMETER;
+      break;
+   }
+
+   if (err != EGL_SUCCESS) {
+      _eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
+      free(xdri_img);
+      return NULL;
+   }
+
+   if (!_eglInitImage(drv, &xdri_img->Base, attr_list)) {
+      free(xdri_img);
+      return NULL;
+   }
+   if (!get_drawable_depth(xdri_dpy->dpy, xdri_img->pixmap, &depth) ||
+       depth > MAX_DEPTH) {
+      free(xdri_img);
+      return NULL;
+   }
+   mode = xdri_dpy->imageConfigs[depth];
+   if (!mode) {
+      free(xdri_img);
+      return NULL;
+   }
+
+   driImage = CALLOC_STRUCT(__DRIEGLImageRec);
+   if (!driImage) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
+      free(xdri_img);
+      return NULL;
+   }
+
+   xdri_img->driDrawable =
+      xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc,
+                                               (XID) xdri_img->pixmap,
+                                               (GLXDrawable) xdri_img->pixmap,
+                                               mode);
+   if (!xdri_img->driDrawable) {
+      free(driImage);
+      free(xdri_img);
+      return NULL;
+   }
+
+   driImage->magic = __DRI_EGL_IMAGE_MAGIC;
+   driImage->drawable = xdri_img->driDrawable->driDrawable;
+   driImage->texture_format_rgba = (depth == 32 && mode->bindToTextureRgba);
+   driImage->level = 0;
+
+   xdri_img->Base.ClientData = (void *) driImage;
+
+   return &xdri_img->Base;
+}
+
+
+static EGLBoolean
+xdri_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
+{
+   struct xdri_egl_image *xdri_img = lookup_image(img);
+
+   free(xdri_img->Base.ClientData);
+   xdri_img->driDrawable->destroyDrawable(xdri_img->driDrawable);
+   free(xdri_img);
+   return EGL_TRUE;
 }
 
 
+#endif /* EGL_KHR_image_base */
+
+
 static void
 xdri_Unload(_EGLDriver *drv)
 {
@@ -567,6 +754,10 @@ _eglMain(const char *args)
    xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
    xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
    xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
+#if EGL_KHR_image_base
+   xdri_drv->Base.API.CreateImageKHR = xdri_eglCreateImageKHR;
+   xdri_drv->Base.API.DestroyImageKHR = xdri_eglDestroyImageKHR;
+#endif /* EGL_KHR_image_base */
 
    xdri_drv->Base.Name = "X/DRI";
    xdri_drv->Base.Unload = xdri_Unload;