From: Kristian Høgsberg Date: Wed, 2 May 2012 19:30:13 +0000 (-0400) Subject: gbm: Add gbm_bo_write entry point X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4fddb2ba21add1c1968330e5224ecead59da3995;p=mesa.git 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 --- diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index eafbe10f9b0..e37917eda99 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 4df6e8fcf06..e5ddfb6ce69 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 987e96500f8..3994f86aafc 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 cf3d4752c36..af5dc5aee8c 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 0e98bdf3d8d..8eb8671aeb2 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 4ea970ad6d1..af3a059560a 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 9db56064bea..458178fe927 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[] = {