summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2012-05-02 15:30:13 -0400
committerKristian Høgsberg <krh@bitplanet.net>2012-05-03 10:57:32 -0400
commit4fddb2ba21add1c1968330e5224ecead59da3995 (patch)
tree20b7a7e683f135f90e2fb5b67f1856e0f038e44b
parentb4789860c4416ba700ac5edeb692b59e33d45276 (diff)
gbm: Add gbm_bo_write entry point
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. Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
-rw-r--r--include/GL/internal/dri_interface.h10
-rw-r--r--src/gbm/backends/dri/gbm_dri.c18
-rw-r--r--src/gbm/main/gbm.c19
-rw-r--r--src/gbm/main/gbm.h9
-rw-r--r--src/gbm/main/gbmint.h1
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.h1
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c32
7 files changed, 87 insertions, 3 deletions
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index eafbe10f9b..e37917eda9 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 4df6e8fcf0..e5ddfb6ce6 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 987e96500f..3994f86aaf 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 cf3d4752c3..af5dc5aee8 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 0e98bdf3d8..8eb8671aeb 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_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h
index 4ea970ad6d..af3a059560 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.h
+++ b/src/mesa/drivers/dri/intel/intel_regions.h
@@ -132,6 +132,7 @@ void _mesa_copy_rect(GLubyte * dst,
struct __DRIimageRec {
struct intel_region *region;
GLenum internal_format;
+ uint32_t usage;
uint32_t dri_format;
GLuint format;
GLenum data_type;
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 9db56064be..458178fe92 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -305,10 +305,16 @@ 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;
+ image->usage = use;
image->dri_format = format;
switch (format) {
@@ -392,6 +398,7 @@ intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
}
image->internal_format = orig_image->internal_format;
+ image->usage = orig_image->usage;
image->dri_format = orig_image->dri_format;
image->format = orig_image->format;
image->data_type = orig_image->data_type;
@@ -408,18 +415,39 @@ intel_validate_usage(__DRIimage *image, unsigned int use)
return GL_FALSE;
}
+ /* We only support write for cursor drm images */
+ if ((use & __DRI_IMAGE_USE_WRITE) &&
+ use != (__DRI_IMAGE_USE_WRITE | __DRI_IMAGE_USE_CURSOR))
+ return GL_FALSE;
+
return GL_TRUE;
}
+static int
+intel_image_write(__DRIimage *image, const void *buf, size_t count)
+{
+ if (image->region->map_refcount)
+ return -1;
+ if (!(image->usage & __DRI_IMAGE_USE_WRITE))
+ 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[] = {