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[] = {