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>
This commit is contained in:
Kristian Høgsberg 2012-05-02 15:30:13 -04:00
parent b4789860c4
commit 4fddb2ba21
7 changed files with 87 additions and 3 deletions

View File

@ -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);
};

View File

@ -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;

View File

@ -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

View File

@ -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 *));

View File

@ -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,

View File

@ -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;

View File

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