OSDN Git Service

egl_android: Add untested support for EGLImage.
authorChia-I Wu <olvaffe@gmail.com>
Fri, 18 Sep 2009 09:13:20 +0000 (17:13 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 18 Sep 2009 10:36:14 +0000 (18:36 +0800)
src/egl/drivers/android/droid.h
src/egl/drivers/android/droid_intel.c
src/egl/drivers/android/droid_loader.c
src/egl/drivers/android/egl_android.c

index bed5e8c..1793f6a 100644 (file)
@@ -40,6 +40,7 @@
 struct droid_loader;
 struct droid_context;
 struct droid_drawable;
+struct droid_image;
 struct droid_surface;
 
 struct droid_backend {
@@ -61,6 +62,9 @@ struct droid_backend {
    struct droid_surface *(*create_window_surface)(struct droid_backend *backend,
                                                   _EGLSurface *surf,
                                                   NativeWindowType win);
+   struct droid_surface *(*create_image_surface)(struct droid_backend *backend,
+                                                 NativePixmapType pix,
+                                                 int *depth);
    void (*destroy_surface)(struct droid_backend *backend, struct droid_surface *surf);
    void (*swap_native_buffers)(struct droid_backend *backend,
                                struct droid_surface *surf);
@@ -75,6 +79,9 @@ struct droid_screen {
 
    const __DRIconfig **dri_configs;
    int num_dri_configs;
+
+#define DROID_MAX_IMAGE_DEPTH 32
+   const __DRIconfig *image_configs[DROID_MAX_IMAGE_DEPTH + 1];
 };
 
 struct droid_backend *
@@ -107,6 +114,10 @@ droid_screen_create_drawable(struct droid_screen *screen,
                              const __DRIconfig *conf,
                              struct droid_surface *surf);
 
+void *
+droid_screen_get_drawable_data(struct droid_screen *screen,
+                               struct droid_drawable *drawable);
+
 void
 droid_screen_destroy_drawable(struct droid_screen *screen,
                               struct droid_drawable *drawable);
index 2f1b26c..d9ff0d5 100644 (file)
@@ -46,6 +46,7 @@
 
 enum {
    INTEL_SURFACE_TYPE_WINDOW,
+   INTEL_SURFACE_TYPE_IMAGE,
 };
 
 struct droid_backend_intel {
@@ -58,6 +59,7 @@ struct droid_surface_intel {
    int type;
    union {
       NativeWindowType win;
+      NativePixmapType pix;
    } native;
    __DRIbuffer native_buffer;
    unsigned int native_width, native_height;
@@ -219,11 +221,20 @@ intel_get_surface_buffers(struct droid_backend *backend,
       }
       else {
          buffers[num].attachment = att;
-         handles[num] = create_buffer(intel->fd,
-                                          isurf->native_width,
-                                          isurf->native_height,
-                                          cpp,
-                                          &buffers[num]);
+
+         if (isurf->type == INTEL_SURFACE_TYPE_IMAGE &&
+             att == __DRI_BUFFER_FRONT_LEFT) {
+            buffers[num] = isurf->native_buffer;
+            buffers[num].attachment = att;
+            handles[num] = 0;
+         } else {
+            buffers[num].attachment = att;
+            handles[num] = create_buffer(intel->fd,
+                                             isurf->native_width,
+                                             isurf->native_height,
+                                             cpp,
+                                             &buffers[num]);
+         }
       }
       num++;
    }
@@ -258,6 +269,13 @@ update_native_buffer(struct droid_surface *surf)
       width = isurf->native.win->width;
       height = isurf->native.win->height;
       break;
+   case INTEL_SURFACE_TYPE_IMAGE:
+      name = isurf->native.pix->reserved;
+      cpp = ui_bytes_per_pixel(isurf->native.pix->format);
+      pitch = isurf->native.pix->stride * cpp;
+      width = isurf->native.pix->width;
+      height = isurf->native.pix->height;
+      break;
    default:
       name = cpp = pitch = width = height = 0;
       break;
@@ -316,6 +334,50 @@ intel_create_window_surface(struct droid_backend *backend,
    return (struct droid_surface *) isurf;
 }
 
+static struct droid_surface *
+intel_create_image_surface(struct droid_backend *backend,
+                           NativePixmapType pix, int *depth)
+{
+   struct droid_surface_intel *isurf;
+   int cpp;
+
+   if (!pix) {
+      LOGE("invalid native pixmap");
+      _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCreateImage");
+      return NULL;
+   }
+
+   /* TODO lift this limitation */
+   if (!pix->reserved) {
+      LOGE("TODO support for non-gem based pixmap");
+      _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCreateImage");
+      return NULL;
+   }
+
+   cpp = ui_bytes_per_pixel(pix->format);
+   if (cpp * 8 > DROID_MAX_IMAGE_DEPTH) {
+      LOGE("pixmap of depth %d is not supported", cpp * 8);
+      _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCreateImage");
+      return NULL;
+   }
+
+   isurf = calloc(1, sizeof(*isurf));
+   if (!isurf) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
+      return NULL;
+   }
+
+   isurf->type = INTEL_SURFACE_TYPE_IMAGE;
+   isurf->native.pix = pix;
+
+   update_native_buffer((struct droid_surface *) isurf);
+
+   if (depth)
+      *depth = cpp * 8;
+
+   return (struct droid_surface *) isurf;
+}
+
 static void
 intel_destroy_surface(struct droid_backend *backend, struct droid_surface *surf)
 {
@@ -400,6 +462,7 @@ droid_backend_create_intel(const char *dev)
    intel->base.get_surface_buffers = intel_get_surface_buffers;
 
    intel->base.create_window_surface = intel_create_window_surface;
+   intel->base.create_image_surface = intel_create_image_surface;
    intel->base.destroy_surface = intel_destroy_surface;
    intel->base.swap_native_buffers = intel_swap_native_buffers;
 
index 1d02b49..67e8e9f 100644 (file)
@@ -33,6 +33,7 @@
 #include <assert.h>
 
 #include "droid.h"
+#include "EGL/internal/eglimage_dri.h"
 
 #ifndef DROID_DRIVER_PATH
 #define DROID_DRIVER_PATH "/system/lib"
@@ -57,6 +58,8 @@ struct droid_drawable {
    struct droid_surface *surface;
 
    __DRIdrawable *dri_drawable;
+   const __DRIconfig *dri_config;
+   __DRIEGLImage *dri_image;
 };
 
 static __DRIbuffer *
@@ -206,6 +209,48 @@ droid_backend_destroy(struct droid_backend *backend)
    backend->destroy(backend);
 }
 
+static void
+screen_find_image_configs(struct droid_screen *screen)
+{
+   struct droid_loader *loader = screen->loader;
+   int depth, i;
+
+   for (depth = 0; depth < DROID_MAX_IMAGE_DEPTH + 1; depth++) {
+      for (i = 0; i < screen->num_dri_configs; i++) {
+         const __DRIconfig *conf = screen->dri_configs[i];
+         _EGLConfig egl_conf;
+         EGLint rgba, val;
+
+         droid_screen_convert_config(screen, conf, &egl_conf);
+
+         val = GET_CONFIG_ATTRIB(&egl_conf, EGL_CONFIG_CAVEAT);
+         if (val == EGL_SLOW_CONFIG)
+            continue;
+
+         rgba  = GET_CONFIG_ATTRIB(&egl_conf, EGL_RED_SIZE);
+         rgba += GET_CONFIG_ATTRIB(&egl_conf, EGL_GREEN_SIZE);
+         rgba += GET_CONFIG_ATTRIB(&egl_conf, EGL_BLUE_SIZE);
+         rgba += GET_CONFIG_ATTRIB(&egl_conf, EGL_ALPHA_SIZE);
+         if (depth != rgba)
+            continue;
+
+         if (depth == 32) {
+            val = GET_CONFIG_ATTRIB(&egl_conf, EGL_BIND_TO_TEXTURE_RGBA);
+            if (val) {
+               screen->image_configs[depth] = conf;
+               break;
+            }
+         }
+
+         val = GET_CONFIG_ATTRIB(&egl_conf, EGL_BIND_TO_TEXTURE_RGB);
+         if (val) {
+            screen->image_configs[depth] = conf;
+            break;
+         }
+      }
+   }
+}
+
 struct droid_screen *
 droid_screen_create(struct droid_backend *backend)
 {
@@ -268,6 +313,8 @@ droid_screen_create(struct droid_backend *backend)
       ;
    screen->num_dri_configs = i;
 
+   screen_find_image_configs(screen);
+
    return screen;
 
 fail:
@@ -400,6 +447,7 @@ droid_screen_create_drawable(struct droid_screen *screen,
    /* needed in GetBuffers */
    drawable->loader = loader;
    drawable->surface = surf;
+   drawable->dri_config = conf;
 
    drawable->dri_drawable =
       loader->dri2->createNewDrawable(screen->dri_screen,
@@ -413,11 +461,40 @@ droid_screen_create_drawable(struct droid_screen *screen,
    return drawable;
 }
 
+void *
+droid_screen_get_drawable_data(struct droid_screen *screen,
+                               struct droid_drawable *drawable)
+{
+   struct droid_loader *loader = screen->loader;
+   __DRIEGLImage *img = drawable->dri_image;
+
+   if (!img) {
+      unsigned int val;
+
+      img = calloc(1, sizeof(__DRIEGLImage));
+      if (!img)
+         return NULL;
+
+      img->magic = __DRI_EGL_IMAGE_MAGIC;
+      img->drawable = drawable->dri_drawable;
+      img->level = 0;
+      if (loader->core->getConfigAttrib(drawable->dri_config,
+                                        EGL_BIND_TO_TEXTURE_RGBA, &val))
+         img->texture_format_rgba = val;
+
+      drawable->dri_image = img;
+   }
+
+   return (void *) img;
+}
+
 void
 droid_screen_destroy_drawable(struct droid_screen *screen,
                               struct droid_drawable *drawable)
 {
    struct droid_loader *loader = screen->loader;
+   if (drawable->dri_image)
+      free(drawable->dri_image);
    loader->core->destroyDrawable(drawable->dri_drawable);
    free(drawable);
 }
index 10c0aea..e9e0114 100644 (file)
@@ -32,8 +32,6 @@
 #include "eglsurface.h"
 #include "eglimage.h"
 
-#include "EGL/internal/eglimage_dri.h"
-
 #include "droid.h"
 
 #ifndef DROID_DEVICE_PATH
@@ -73,6 +71,12 @@ struct droid_egl_surface {
    struct droid_surface *surface;
 };
 
+struct droid_egl_image {
+   _EGLImage base;
+   struct droid_drawable *drawable;
+   struct droid_surface *surface;
+};
+
 struct droid_egl_config {
    _EGLConfig base;
    const __DRIconfig *config;
@@ -102,6 +106,12 @@ lookup_surface(_EGLSurface *surface)
    return (struct droid_egl_surface *) surface;
 }
 
+static INLINE struct droid_egl_image *
+lookup_image(_EGLImage *image)
+{
+   return (struct droid_egl_image *) image;
+}
+
 static INLINE struct droid_egl_config *
 lookup_config(_EGLConfig *conf)
 {
@@ -184,6 +194,14 @@ droid_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
       droid_create_configs(dpy, droid_dpy, droid_dpy->screen->dri_configs,
                            droid_dpy->screen->num_dri_configs);
 
+#if EGL_KHR_image_base
+      if (droid_dpy->backend->create_image_surface) {
+         dpy->Extensions.KHR_image = EGL_TRUE;
+         dpy->Extensions.KHR_image_base = EGL_TRUE;
+         dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
+      }
+#endif
+
       droid_drv->default_display = droid_dpy;
    }
 
@@ -380,6 +398,83 @@ droid_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
    return EGL_TRUE;
 }
 
+#if EGL_KHR_image_base
+
+static _EGLImage *
+droid_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
+                       EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   struct droid_egl_display *droid_dpy = lookup_display(dpy);
+   struct droid_egl_image *droid_img;
+   const __DRIconfig *dri_conf;
+   int depth;
+
+   if (target != EGL_NATIVE_PIXMAP_KHR || ctx) {
+      _eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
+      return NULL;
+   }
+
+   droid_img = calloc(1, sizeof(*droid_img));
+   if (!droid_img) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
+      return NULL;
+   }
+
+   if (!_eglInitImage(drv, &droid_img->base, attr_list)) {
+      free(droid_img);
+      return NULL;
+   }
+
+   droid_img->surface = 
+      droid_dpy->backend->create_image_surface(droid_dpy->backend,
+                                               (NativePixmapType) buffer,
+                                               &depth);
+   if (!droid_img->surface) {
+      free(droid_img);
+      return NULL;
+   }
+
+   dri_conf = droid_dpy->screen->image_configs[depth];
+   if (!dri_conf) {
+      droid_dpy->backend->destroy_surface(droid_dpy->backend,
+                                          droid_img->surface);
+      free(droid_img);
+      return NULL;
+   }
+
+   droid_img->drawable =
+      droid_screen_create_drawable(droid_dpy->screen, dri_conf,
+                                   droid_img->surface);
+
+   if (!droid_img->drawable) {
+      droid_dpy->backend->destroy_surface(droid_dpy->backend,
+                                          droid_img->surface);
+      free(droid_img);
+      return NULL;
+   }
+
+   droid_img->base.ClientData =
+      droid_screen_get_drawable_data(droid_dpy->screen, droid_img->drawable);
+
+   return &droid_img->base;
+}
+
+
+static EGLBoolean
+droid_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
+{
+   struct droid_egl_display *droid_dpy = lookup_display(dpy);
+   struct droid_egl_image *droid_img = lookup_image(img);
+
+   droid_screen_destroy_drawable(droid_dpy->screen, droid_img->drawable);
+   droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_img->surface);
+   free(droid_img);
+
+   return EGL_TRUE;
+}
+
+#endif /* EGL_KHR_image_base */
+
 static EGLBoolean
 droid_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy)
 {
@@ -446,6 +541,10 @@ _eglMain(const char *args)
    droid_drv->base.API.CreateWindowSurface = droid_eglCreateWindowSurface;
    droid_drv->base.API.DestroySurface = droid_eglDestroySurface;
    droid_drv->base.API.SwapBuffers = droid_eglSwapBuffers;
+#if EGL_KHR_image_base
+   droid_drv->base.API.CreateImageKHR = droid_eglCreateImageKHR;
+   droid_drv->base.API.DestroyImageKHR = droid_eglDestroyImageKHR;
+#endif /* EGL_KHR_image_base */
    droid_drv->base.API.WaitClient = droid_eglWaitClient;
    droid_drv->base.API.WaitNative = droid_eglWaitNative;