[Mesa-dev] [PATCH] gbm: Add gbm_bo_write entry point

Kristian Høgsberg krh at bitplanet.net
Wed May 2 12:32:42 PDT 2012


This new gbm entry point allows writing data into a gbm bo.  The bo has
to be created with the GBM_BO_USE_WRITE flag, and it's only required to
work for GBM_BO_USE_CURSOR_64X64 bos.

The gbm API is designed to be the glue layer between EGL and KMS, but there
was never a mechanism initialize a buffer suitable for use with KMS
hw cursors.  The hw cursor bo is typically not compatible with anything EGL
can render to, and thus there's no way to get data into such a bo.

gbm_bo_write() fills that gap while staying out of the efficient
cpu->gpu pixel transfer business.
---
 include/GL/internal/dri_interface.h       |   10 +++++++++-
 src/gbm/backends/dri/gbm_dri.c            |   18 ++++++++++++++++++
 src/gbm/main/gbm.c                        |   19 +++++++++++++++++++
 src/gbm/main/gbm.h                        |    9 +++++++++
 src/gbm/main/gbmint.h                     |    1 +
 src/mesa/drivers/dri/intel/intel_screen.c |   24 ++++++++++++++++++++++--
 6 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index eafbe10..e37917e 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -894,7 +894,7 @@ struct __DRIdri2ExtensionRec {
  * extensions.
  */
 #define __DRI_IMAGE "DRI_IMAGE"
-#define __DRI_IMAGE_VERSION 3
+#define __DRI_IMAGE_VERSION 4
 
 /**
  * These formats correspond to the similarly named MESA_FORMAT_*
@@ -911,6 +911,7 @@ struct __DRIdri2ExtensionRec {
 #define __DRI_IMAGE_USE_SHARE		0x0001
 #define __DRI_IMAGE_USE_SCANOUT		0x0002
 #define __DRI_IMAGE_USE_CURSOR		0x0004
+#define __DRI_IMAGE_USE_WRITE		0x0008
 
 /**
  * queryImage attributes
@@ -955,6 +956,13 @@ struct __DRIimageExtensionRec {
     * \since 2
     */
    GLboolean (*validateUsage)(__DRIimage *image, unsigned int use);
+
+   /**
+    * Write data into image.
+    *
+    * \since 4
+    */
+   int (*write)(__DRIimage *image, const void *buf, size_t count);
 };
 
 
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index 4df6e8f..e5ddfb6 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -291,6 +291,18 @@ gbm_dri_is_format_supported(struct gbm_device *gbm,
    return 1;
 }
 
+static int
+gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count)
+{
+   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
+   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
+
+   if (dri->image->base.version < 4)
+      return -1;
+
+   return dri->image->write(bo->image, buf, count);
+}
+
 static void
 gbm_dri_bo_destroy(struct gbm_bo *_bo)
 {
@@ -390,6 +402,9 @@ gbm_dri_bo_create(struct gbm_device *gbm,
    int dri_format;
    unsigned dri_use = 0;
 
+   if (dri->image->base.version < 4 && (usage & GBM_BO_USE_WRITE))
+      return NULL;
+
    bo = calloc(1, sizeof *bo);
    if (bo == NULL)
       return NULL;
@@ -421,6 +436,8 @@ gbm_dri_bo_create(struct gbm_device *gbm,
       dri_use |= __DRI_IMAGE_USE_SCANOUT;
    if (usage & GBM_BO_USE_CURSOR_64X64)
       dri_use |= __DRI_IMAGE_USE_CURSOR;
+   if (usage & GBM_BO_USE_WRITE)
+      dri_use |= __DRI_IMAGE_USE_WRITE;
 
    bo->image =
       dri->image->createImage(dri->screen,
@@ -491,6 +508,7 @@ dri_device_create(int fd)
    dri->base.base.bo_create = gbm_dri_bo_create;
    dri->base.base.bo_create_from_egl_image = gbm_dri_bo_create_from_egl_image;
    dri->base.base.is_format_supported = gbm_dri_is_format_supported;
+   dri->base.base.bo_write = gbm_dri_bo_write;
    dri->base.base.bo_destroy = gbm_dri_bo_destroy;
    dri->base.base.destroy = dri_destroy;
    dri->base.base.surface_create = gbm_dri_surface_create;
diff --git a/src/gbm/main/gbm.c b/src/gbm/main/gbm.c
index 987e965..3994f86 100644
--- a/src/gbm/main/gbm.c
+++ b/src/gbm/main/gbm.c
@@ -231,6 +231,25 @@ gbm_bo_get_handle(struct gbm_bo *bo)
    return bo->handle;
 }
 
+/** Write data into the buffer object
+ *
+ * If the buffer object was created with the GBM_BO_USE_WRITE flag,
+ * this function can used to write data into the buffer object.  The
+ * data is copied directly into the object and it's the responsiblity
+ * of the caller to make sure the data represents valid pixel data,
+ * according to the width, height, stride and format of the buffer object.
+ *
+ * \param bo The buffer object
+ * \param buf The data to write
+ * \param count The number of bytes to write
+ * \return Returns -1 on error, 0 otherwise
+ */
+GBM_EXPORT int
+gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count)
+{
+   return bo->gbm->bo_write(bo, buf, count);
+}
+
 /** Get the gbm device used to create the buffer object
  *
  * \param bo The buffer object
diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h
index cf3d475..af5dc5a 100644
--- a/src/gbm/main/gbm.h
+++ b/src/gbm/main/gbm.h
@@ -201,6 +201,12 @@ enum gbm_bo_flags {
     * as the storage for a color buffer
     */
    GBM_BO_USE_RENDERING    = (1 << 2),
+   /**
+    * Buffer can be used for gbm_bo_write.  This is guaranteed to work
+    * with GBM_BO_USE_CURSOR_64X64. but may not work for other
+    * combinations.
+    */
+   GBM_BO_USE_WRITE    = (1 << 3),
 };
 
 int
@@ -248,6 +254,9 @@ gbm_bo_get_device(struct gbm_bo *bo);
 union gbm_bo_handle
 gbm_bo_get_handle(struct gbm_bo *bo);
 
+int
+gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count);
+
 void
 gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
 		     void (*destroy_user_data)(struct gbm_bo *, void *));
diff --git a/src/gbm/main/gbmint.h b/src/gbm/main/gbmint.h
index 0e98bdf..8eb8671 100644
--- a/src/gbm/main/gbmint.h
+++ b/src/gbm/main/gbmint.h
@@ -70,6 +70,7 @@ struct gbm_device {
                                               void *egl_dpy, void *egl_img,
                                               uint32_t width, uint32_t height,
                                               uint32_t usage);
+   int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
    void (*bo_destroy)(struct gbm_bo *bo);
 
    struct gbm_surface *(*surface_create)(struct gbm_device *gbm,
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 9db5606..e945d14 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -305,6 +305,11 @@ intel_create_image(__DRIscreen *screen,
       tiling = I915_TILING_NONE;
    }
 
+   /* We only support write for cursor drm images */
+   if ((use & __DRI_IMAGE_USE_WRITE) &&
+       use != (__DRI_IMAGE_USE_WRITE | __DRI_IMAGE_USE_CURSOR))
+      return NULL;
+
    image = CALLOC(sizeof *image);
    if (image == NULL)
       return NULL;
@@ -411,15 +416,30 @@ intel_validate_usage(__DRIimage *image, unsigned int use)
    return GL_TRUE;
 }
 
+static int
+intel_image_write(__DRIimage *image, const void *buf, size_t count)
+{
+   if (image->region->map_refcount)
+      return -1;
+   /* if use != WRITE || region->map_refcount; return -1; */
+
+   drm_intel_bo_map(image->region->bo, true);
+   memcpy(image->region->bo->virtual, buf, count);
+   drm_intel_bo_unmap(image->region->bo);
+
+   return 0;
+}
+
 static struct __DRIimageExtensionRec intelImageExtension = {
-    { __DRI_IMAGE, 3 },
+    { __DRI_IMAGE, 4 },
     intel_create_image_from_name,
     intel_create_image_from_renderbuffer,
     intel_destroy_image,
     intel_create_image,
     intel_query_image,
     intel_dup_image,
-    intel_validate_usage
+    intel_validate_usage,
+    intel_image_write
 };
 
 static const __DRIextension *intelScreenExtensions[] = {
-- 
1.7.10



More information about the mesa-dev mailing list