summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2009-08-18 16:36:10 +0800
committerChia-I Wu <olvaffe@gmail.com>2009-09-14 13:39:19 +0800
commit5f32756254034ee162f3b17e7488c660c9fa90b0 (patch)
tree6204a481280055d7f7e5a4cf5882ea3732d9da2c
parent9e9a4cf4711e72a5eba81476205392097b107e07 (diff)
egl_xdri: Implement eglCreateImageKHR.
-rw-r--r--include/EGL/internal/eglimage_dri.h27
-rw-r--r--src/egl/drivers/xdri/egl_xdri.c191
2 files changed, 218 insertions, 0 deletions
diff --git a/include/EGL/internal/eglimage_dri.h b/include/EGL/internal/eglimage_dri.h
new file mode 100644
index 0000000000..ea13951a9f
--- /dev/null
+++ b/include/EGL/internal/eglimage_dri.h
@@ -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 */
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
index 518091a2d1..42d8726d71 100644
--- a/src/egl/drivers/xdri/egl_xdri.c
+++ b/src/egl/drivers/xdri/egl_xdri.c
@@ -54,7 +54,11 @@
#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;