From 5f32756254034ee162f3b17e7488c660c9fa90b0 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 18 Aug 2009 16:36:10 +0800 Subject: egl_xdri: Implement eglCreateImageKHR. --- include/EGL/internal/eglimage_dri.h | 27 +++++ src/egl/drivers/xdri/egl_xdri.c | 191 ++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 include/EGL/internal/eglimage_dri.h 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; @@ -529,10 +618,108 @@ 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; -- cgit v1.2.3