[Mesa-dev] [PATCH 6/6] st/egl: WIP support for new drm EGLImage extensions

Jakob Bornecrantz wallbraker at gmail.com
Sat May 29 05:56:34 PDT 2010


---
 src/gallium/state_trackers/egl/common/egl_g3d.c    |   16 +++
 .../state_trackers/egl/common/egl_g3d_api.c        |    4 +
 .../state_trackers/egl/common/egl_g3d_image.c      |   59 ++++++++++++
 .../state_trackers/egl/common/egl_g3d_image.h      |    3 +
 src/gallium/state_trackers/egl/common/native.h     |    8 ++
 src/gallium/state_trackers/egl/drm/drm_display.c   |   15 +++
 src/gallium/state_trackers/egl/drm/drm_image.c     |  100 +++++++++++++++++++-
 src/gallium/state_trackers/egl/kms/native_kms.c    |   43 +++++++++
 src/gallium/state_trackers/egl/x11/native_dri2.c   |   43 +++++++++
 9 files changed, 289 insertions(+), 2 deletions(-)

diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index d63b81a..5f1f6e0 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -510,6 +510,21 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
    if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
       dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
 
+#ifdef EGL_MESA_create_image
+   dpy->Extensions.MESA_create_image = EGL_TRUE;
+#endif
+#ifdef EGL_MESA_get_image_attrib
+   dpy->Extensions.MESA_get_image_attrib = EGL_TRUE;
+#endif
+#ifdef EGL_MESA_image_system_use
+   if (gdpy->native->get_drm_attrib)
+      dpy->Extensions.MESA_image_system_use = EGL_TRUE;
+#endif
+#ifdef EGL_MESA_drm_image
+   if (gdpy->native->get_drm_attrib)
+      dpy->Extensions.MESA_drm_image = EGL_TRUE;
+#endif
+
    if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
       goto fail;
@@ -548,6 +563,7 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
    return (_EGLProc) NULL;
 }
 
+
 static EGLint
 egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
 {
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
index 4615a58..30bc676 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
@@ -717,6 +717,10 @@ egl_g3d_init_driver_api(_EGLDriver *drv)
    drv->API.CreateImageKHR = egl_g3d_create_image;
    drv->API.DestroyImageKHR = egl_g3d_destroy_image;
 
+#ifdef EGL_MESA_get_image_attrib
+   drv->API.GetImageAttribMESA = egl_g3d_get_image_attrib;
+#endif
+
 #ifdef EGL_MESA_screen_surface
    drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
    drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
index b1fe30a..74d17e5 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -37,6 +37,35 @@
 #include "egl_g3d_api.h"
 #include "egl_g3d_image.h"
 
+#ifdef EGL_MESA_create_image
+/**
+ * Create a new texture resource
+ */
+static struct pipe_resource *
+egl_g3d_create_image_new(struct egl_g3d_display *gdpy, struct egl_g3d_image *gimg, const EGLint *attr_list)
+{
+   struct pipe_screen *screen = gdpy->native->screen;
+   struct pipe_resource tmplt;
+
+   memset(&tmplt, 0, sizeof(tmplt));
+   tmplt.target = PIPE_TEXTURE_2D;
+   tmplt.last_level = 0;
+   tmplt.width0 = gimg->base.Width;
+   tmplt.height0 = gimg->base.Height;
+   tmplt.depth0 = 1;
+   tmplt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+   tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; /* XXX format */
+
+   if (gimg->base.UseSystem & EGL_SYSTEM_SCANOUT_BIT_MESA)
+      tmplt.bind |= PIPE_BIND_SCANOUT;
+
+   if (gimg->base.UseSystem & EGL_SYSTEM_SHARABLE_BIT_MESA)
+      tmplt.bind |= PIPE_BIND_SHARED;
+
+   return screen->resource_create(screen, &tmplt);
+}
+#endif /* EGL_MESA_create_image */
+
 /**
  * Reference and return the front left buffer of the native pixmap.
  */
@@ -72,6 +101,7 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                      EGLenum target, EGLClientBuffer buffer,
                      const EGLint *attribs)
 {
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
    struct pipe_resource *ptex;
    struct egl_g3d_image *gimg;
    unsigned face = 0, level = 0, zslice = 0;
@@ -92,6 +122,11 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
       ptex = egl_g3d_reference_native_pixmap(dpy,
             (EGLNativePixmapType) buffer);
       break;
+#ifdef EGL_MESA_create_image
+   case EGL_NEW_IMAGE_MESA:
+      ptex = egl_g3d_create_image_new(gdpy, gimg, attribs);
+      break;
+#endif
    default:
       ptex = NULL;
       break;
@@ -134,3 +169,27 @@ egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
 
    return EGL_TRUE;
 }
+
+#ifdef EGL_MESA_get_image_attrib
+EGLBoolean
+egl_g3d_get_image_attrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, EGLenum attrib, EGLint *out)
+{
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   struct egl_g3d_image *gimg = egl_g3d_image(img);
+
+   switch(attrib) {
+   case EGL_DRM_STRIDE_MESA:
+   case EGL_DRM_KMS_HANDLE_MESA:
+   case EGL_DRM_SHARED_HANDLE_MESA:
+      if (!gdpy->native->get_drm_attrib) {
+         _eglError(EGL_BAD_PARAMETER, "eglGetImageAttribMESA");
+         return EGL_FALSE;
+      }
+      return gdpy->native->get_drm_attrib(gdpy->native,
+                                          gimg->texture,
+                                          attrib, out);
+   default:
+      return _eglGetImageAttribMESA(drv, dpy, img, attrib, out);
+   }
+}
+#endif /* EGL_MESA_get_image_attrib */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.h b/src/gallium/state_trackers/egl/common/egl_g3d_image.h
index adda933..cd2461c 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h
@@ -37,6 +37,9 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                      const EGLint *attribs);
 
 EGLBoolean
+egl_g3d_get_image_attrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, EGLenum attrib, EGLint *out);
+
+EGLBoolean
 egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
 
 #endif /* _EGL_G3D_IMAGE_H_ */
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index 3f60348..d6b3643 100644
--- a/src/gallium/state_trackers/egl/common/native.h
+++ b/src/gallium/state_trackers/egl/common/native.h
@@ -181,6 +181,14 @@ struct native_display {
                                                    EGLNativePixmapType pix,
                                                    const struct native_config *nconf);
 
+   /*
+    * Used by eglGetImageAttrib for the EGL_MESA_drm_image extension.
+    */
+   EGLBoolean (*get_drm_attrib)(struct native_display *ndpy,
+                                struct pipe_resource *res,
+                                EGLenum attrib,
+                                EGLint *out);
+                                
    const struct native_display_modeset *modeset;
 };
 
diff --git a/src/gallium/state_trackers/egl/drm/drm_display.c b/src/gallium/state_trackers/egl/drm/drm_display.c
index 5692f79..319ecce 100644
--- a/src/gallium/state_trackers/egl/drm/drm_display.c
+++ b/src/gallium/state_trackers/egl/drm/drm_display.c
@@ -48,6 +48,9 @@ _eglMain(const char *args)
 
    drv->API.CreateImageKHR = drm_create_image;
    drv->API.DestroyImageKHR = drm_destroy_image;
+#ifdef EGL_MESA_get_image_attrib
+   drv->API.GetImageAttribMESA = drm_get_image_attrib;
+#endif
 
    drv->Name = "DRM/Gallium/Win";
    drv->Unload = drm_unload;
@@ -120,6 +123,18 @@ drm_initialize(_EGLDriver *drv, _EGLDisplay *dpy, EGLint *major, EGLint *minor)
    dpy->ClientAPIsMask = EGL_OPENGL_BIT;
 
    dpy->Extensions.KHR_image_base = EGL_TRUE;
+#ifdef EGL_MESA_create_image
+   dpy->Extensions.MESA_create_image = EGL_TRUE;
+#endif
+#ifdef EGL_MESA_get_image_attrib
+   dpy->Extensions.MESA_get_image_attrib = EGL_TRUE;
+#endif
+#ifdef EGL_MESA_image_system_use
+   dpy->Extensions.MESA_image_system_use = EGL_TRUE;
+#endif
+#ifdef EGL_MESA_drm_image
+   dpy->Extensions.MESA_drm_image = EGL_TRUE;
+#endif
 
    *major = 1;
    *minor = 4;
diff --git a/src/gallium/state_trackers/egl/drm/drm_image.c b/src/gallium/state_trackers/egl/drm/drm_image.c
index a25f486..b95a3be 100644
--- a/src/gallium/state_trackers/egl/drm/drm_image.c
+++ b/src/gallium/state_trackers/egl/drm/drm_image.c
@@ -4,11 +4,44 @@
 
 #include "drm_tracker.h"
 
+#include "state_tracker/drm_api.h"
+
+#include "pipe/p_screen.h"
 #include "util/u_memory.h"
+#include "util/u_rect.h"
+#include "util/u_inlines.h"
 
-/*
- * Stub
+#ifdef EGL_MESA_create_image
+/**
+ * Create a new texture resource
  */
+static struct pipe_resource *
+drm_create_image_new(struct drm_device *dev, struct drm_image *img, const EGLint *attr_list)
+{
+   struct pipe_screen *screen = dev->manager.screen;
+   struct pipe_resource tmplt;
+
+   memset(&tmplt, 0, sizeof(tmplt));
+   tmplt.target = PIPE_TEXTURE_2D;
+   tmplt.last_level = 0;
+   tmplt.width0 = img->base.Width;
+   tmplt.height0 = img->base.Height;
+   tmplt.depth0 = 1;
+   tmplt.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+   tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; /* XXX format */
+
+#ifdef EGL_MESA_image_system_use
+   if (img->base.UseSystem & EGL_SYSTEM_SCANOUT_BIT_MESA)
+      tmplt.bind |= PIPE_BIND_SCANOUT;
+
+   if (img->base.UseSystem & EGL_SYSTEM_SHARABLE_BIT_MESA)
+      tmplt.bind |= PIPE_BIND_SHARED;
+#endif
+
+   return screen->resource_create(screen, &tmplt);
+}
+#endif /* EGL_MESA_create_image */
+
 _EGLImage *
 drm_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                  EGLenum target, EGLClientBuffer buffer,
@@ -26,6 +59,11 @@ drm_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
       goto out_free;
 
    switch (target) {
+#ifdef EGL_MESA_create_image
+   case EGL_NEW_IMAGE_MESA:
+      res = drm_create_image_new(dev, img, attribs);
+      break;
+#endif
    default:
       res = NULL;
    }
@@ -84,3 +122,61 @@ drm_get_egl_image(struct st_manager *manager,
 
    return TRUE;
 }
+
+
+#ifdef EGL_MESA_get_image_attrib
+/**
+ * Get the handle or stride from a pipe_resource.
+ *
+ * Helper function for drm_get_image_attrib to make
+ * switch case more readable.
+ */
+static INLINE EGLBoolean
+drm_get_handle(struct pipe_screen *screen,
+               struct pipe_resource *res,
+               unsigned type, EGLBoolean stride,
+               EGLint *out)
+{
+   struct winsys_handle whandle;
+   EGLBoolean ret;
+
+   whandle.type = type;
+
+   ret = screen->resource_get_handle(screen, res, &whandle);
+
+   if (ret)
+      *out = stride ? whandle.stride : whandle.handle;
+   else
+      _eglError(EGL_BAD_ALLOC, "eglGetImageAttribMESA");
+   return ret;
+}
+
+/**
+ * Implement EGL_MESA_get_image_attrib extension need special case for
+ * EGL_MESA_drm_image getters the rest is handled by common egl code.
+ */
+EGLBoolean
+drm_get_image_attrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image, EGLenum attrib, EGLint *out)
+{
+   struct drm_device *dev = lookup_drm_device(dpy);
+   struct drm_image *img = lookup_drm_image(image);
+   struct pipe_screen *screen = dev->manager.screen;
+
+   switch(attrib) {
+   case EGL_DRM_STRIDE_MESA:
+      return drm_get_handle(screen, img->res,
+                            DRM_API_HANDLE_TYPE_KMS,
+                            EGL_TRUE, out);
+   case EGL_DRM_KMS_HANDLE_MESA:
+      return drm_get_handle(screen, img->res,
+                            DRM_API_HANDLE_TYPE_KMS,
+                            EGL_FALSE, out);
+   case EGL_DRM_SHARED_HANDLE_MESA:
+      return drm_get_handle(screen, img->res,
+                            DRM_API_HANDLE_TYPE_SHARED,
+                            EGL_FALSE, out);
+   default:
+      return _eglGetImageAttribMESA(drv, dpy, image, attrib, out);
+   }
+}
+#endif /* EGL_MESA_get_image_attrib */
diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c
index d7e7b2b..07eb71b 100644
--- a/src/gallium/state_trackers/egl/kms/native_kms.c
+++ b/src/gallium/state_trackers/egl/kms/native_kms.c
@@ -726,6 +726,48 @@ static struct native_display_modeset kms_display_modeset = {
    .program = kms_display_program
 };
 
+static EGLBoolean
+kms_get_drm_attrib(struct native_display *ndpy,
+                   struct pipe_resource *res,
+                   EGLenum attrib, EGLint *out)
+{
+   struct kms_display *kdpy = kms_display(ndpy);
+   struct winsys_handle whandle;
+   boolean ret;
+
+   memset(&whandle, 0, sizeof(whandle));
+
+   switch(attrib) {
+   case EGL_DRM_STRIDE_MESA:
+      /* check which type to use */
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      ret = kdpy->base.screen->resource_get_handle(
+         kdpy->base.screen, res, &whandle);
+      if (ret)
+         *out = whandle.stride;
+      return ret;
+
+   case EGL_DRM_KMS_HANDLE_MESA:
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      ret = kdpy->base.screen->resource_get_handle(
+         kdpy->base.screen, res, &whandle);
+      if (ret)
+         *out = whandle.handle;
+      return ret;
+
+   case EGL_DRM_SHARED_HANDLE_MESA:
+      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      ret = kdpy->base.screen->resource_get_handle(
+         kdpy->base.screen, res, &whandle);
+      if (ret)
+         *out = whandle.handle;
+      return ret;
+
+   default:
+      return EGL_FALSE;
+   }
+}
+
 static struct native_display *
 kms_create_display(EGLNativeDisplayType dpy,
                    struct native_event_handler *event_handler,
@@ -776,6 +818,7 @@ kms_create_display(EGLNativeDisplayType dpy,
    kdpy->base.destroy = kms_display_destroy;
    kdpy->base.get_param = kms_display_get_param;
    kdpy->base.get_configs = kms_display_get_configs;
+   kdpy->base.get_drm_attrib = kms_get_drm_attrib;
 
    kdpy->base.modeset = &kms_display_modeset;
 
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index 3f802dd..4ed8367 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -740,6 +740,48 @@ dri2_display_hash_table_compare(void *key1, void *key2)
    return (key1 - key2);
 }
 
+static EGLBoolean
+dri2_get_drm_attrib(struct native_display *ndpy,
+                    struct pipe_resource *res,
+                    EGLenum attrib, EGLint *out)
+{
+   struct dri2_display *dri2dpy = dri2_display(ndpy);
+   struct winsys_handle whandle;
+   boolean ret;
+
+   memset(&whandle, 0, sizeof(whandle));
+
+   switch(attrib) {
+   case EGL_DRM_STRIDE_MESA:
+      /* check which type to use */
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      ret = dri2dpy->base.screen->resource_get_handle(
+         dri2dpy->base.screen, res, &whandle);
+      if (ret)
+         *out = whandle.stride;
+      return ret;
+
+   case EGL_DRM_KMS_HANDLE_MESA:
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      ret = dri2dpy->base.screen->resource_get_handle(
+         dri2dpy->base.screen, res, &whandle);
+      if (ret)
+         *out = whandle.handle;
+      return ret;
+
+   case EGL_DRM_SHARED_HANDLE_MESA:
+      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      ret = dri2dpy->base.screen->resource_get_handle(
+         dri2dpy->base.screen, res, &whandle);
+      if (ret)
+         *out = whandle.handle;
+      return ret;
+
+   default:
+      return EGL_FALSE;
+   }
+}
+
 struct native_display *
 x11_create_dri2_display(EGLNativeDisplayType dpy,
                         struct native_event_handler *event_handler,
@@ -789,6 +831,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy,
    dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
    dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
    dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
+   dri2dpy->base.get_drm_attrib = dri2_get_drm_attrib;
 
    return &dri2dpy->base;
 }
-- 
1.7.0.4



More information about the mesa-dev mailing list