mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-31 20:40:09 +01:00
gbm: Add map/unmap functions
This adds map and unmap functions to GBM utilizing the DRIimage extension mapImage/unmapImage functions or existing internal mapping for dumb buffers. Unlike prior attempts, this version provides a region to map and usage flags for the mapping. The operation follows the same semantics as the gallium transfer_map() function. This was tested with GBM based gralloc on Android. Signed-off-by: Rob Herring <robh@kernel.org> [Emil Velikov: drop no longer relevant hunk from commit message.] Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
1f4869a208
commit
8aeb6d768b
7 changed files with 165 additions and 2 deletions
|
|
@ -41,10 +41,12 @@ libgbm_la_SOURCES += \
|
|||
|
||||
AM_CFLAGS += \
|
||||
-DDEFAULT_DRIVER_DIR='"$(DRI_DRIVER_SEARCH_DIR)"' \
|
||||
$(LIBDRM_CFLAGS)
|
||||
$(LIBDRM_CFLAGS) \
|
||||
$(PTHREADSTUBS_CFLAGS)
|
||||
|
||||
libgbm_la_LIBADD += \
|
||||
$(LIBDRM_LIBS)
|
||||
$(LIBDRM_LIBS) \
|
||||
$(PTHREADSTUBS_LIBS)
|
||||
endif
|
||||
|
||||
TESTS = gbm-symbols-check
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -924,6 +925,60 @@ failed:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
gbm_dri_bo_map(struct gbm_bo *_bo,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t flags, uint32_t *stride, void **map_data)
|
||||
{
|
||||
struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
|
||||
struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
|
||||
|
||||
/* If it's a dumb buffer, we already have a mapping */
|
||||
if (bo->map) {
|
||||
*map_data = (char *)bo->map + (bo->base.base.stride * y) + (x * 4);
|
||||
*stride = bo->base.base.stride;
|
||||
return *map_data;
|
||||
}
|
||||
|
||||
if (!dri->image || dri->image->base.version < 12) {
|
||||
errno = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mtx_lock(&dri->mutex);
|
||||
if (!dri->context)
|
||||
dri->context = dri->dri2->createNewContext(dri->screen, NULL,
|
||||
NULL, NULL);
|
||||
assert(dri->context);
|
||||
mtx_unlock(&dri->mutex);
|
||||
|
||||
/* GBM flags and DRI flags are the same, so just pass them on */
|
||||
return dri->image->mapImage(dri->context, bo->image, x, y,
|
||||
width, height, flags, (int *)stride,
|
||||
map_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data)
|
||||
{
|
||||
struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
|
||||
struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
|
||||
|
||||
/* Check if it's a dumb buffer and check the pointer is in range */
|
||||
if (bo->map) {
|
||||
assert(map_data >= bo->map);
|
||||
assert(map_data < (bo->map + bo->size));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dri->context || !dri->image || dri->image->base.version < 12)
|
||||
return;
|
||||
|
||||
dri->image->unmapImage(dri->context, bo->image, map_data);
|
||||
}
|
||||
|
||||
|
||||
static struct gbm_surface *
|
||||
gbm_dri_surface_create(struct gbm_device *gbm,
|
||||
uint32_t width, uint32_t height,
|
||||
|
|
@ -958,6 +1013,9 @@ dri_destroy(struct gbm_device *gbm)
|
|||
struct gbm_dri_device *dri = gbm_dri_device(gbm);
|
||||
unsigned i;
|
||||
|
||||
if (dri->context)
|
||||
dri->core->destroyContext(dri->context);
|
||||
|
||||
dri->core->destroyScreen(dri->screen);
|
||||
for (i = 0; dri->driver_configs[i]; i++)
|
||||
free((__DRIconfig *) dri->driver_configs[i]);
|
||||
|
|
@ -981,6 +1039,8 @@ dri_device_create(int fd)
|
|||
dri->base.base.fd = fd;
|
||||
dri->base.base.bo_create = gbm_dri_bo_create;
|
||||
dri->base.base.bo_import = gbm_dri_bo_import;
|
||||
dri->base.base.bo_map = gbm_dri_bo_map;
|
||||
dri->base.base.bo_unmap = gbm_dri_bo_unmap;
|
||||
dri->base.base.is_format_supported = gbm_dri_is_format_supported;
|
||||
dri->base.base.bo_write = gbm_dri_bo_write;
|
||||
dri->base.base.bo_get_fd = gbm_dri_bo_get_fd;
|
||||
|
|
@ -992,6 +1052,8 @@ dri_device_create(int fd)
|
|||
dri->base.type = GBM_DRM_DRIVER_TYPE_DRI;
|
||||
dri->base.base.name = "drm";
|
||||
|
||||
mtx_init(&dri->mutex, mtx_plain);
|
||||
|
||||
force_sw = getenv("GBM_ALWAYS_SOFTWARE") != NULL;
|
||||
if (!force_sw) {
|
||||
ret = dri_screen_create(dri);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <sys/mman.h>
|
||||
#include "gbmint.h"
|
||||
#include "c11/threads.h"
|
||||
|
||||
#include "common_drm.h"
|
||||
|
||||
|
|
@ -45,6 +46,8 @@ struct gbm_dri_device {
|
|||
void *driver;
|
||||
|
||||
__DRIscreen *screen;
|
||||
__DRIcontext *context;
|
||||
mtx_t mutex;
|
||||
|
||||
const __DRIcoreExtension *core;
|
||||
const __DRIdri2Extension *dri2;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ gbm_device_destroy
|
|||
gbm_create_device
|
||||
gbm_bo_create
|
||||
gbm_bo_import
|
||||
gbm_bo_map
|
||||
gbm_bo_unmap
|
||||
gbm_bo_get_width
|
||||
gbm_bo_get_height
|
||||
gbm_bo_get_stride
|
||||
|
|
|
|||
|
|
@ -385,6 +385,59 @@ gbm_bo_import(struct gbm_device *gbm,
|
|||
return gbm->bo_import(gbm, type, buffer, usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a region of a gbm buffer object for cpu access
|
||||
*
|
||||
* This function maps a region of a gbm bo for cpu read and/or write
|
||||
* access.
|
||||
*
|
||||
* \param bo The buffer object
|
||||
* \param x The X (top left origin) starting position of the mapped region for
|
||||
* the buffer
|
||||
* \param y The Y (top left origin) starting position of the mapped region for
|
||||
* the buffer
|
||||
* \param width The width of the mapped region for the buffer
|
||||
* \param height The height of the mapped region for the buffer
|
||||
* \param flags The union of the GBM_BO_TRANSFER_* flags for this buffer
|
||||
* \param stride Ptr for returned stride in bytes of the mapped region
|
||||
* \param map_data Returned opaque ptr for the mapped region
|
||||
*
|
||||
* \return Address of the mapped buffer that should be unmapped with
|
||||
* gbm_bo_unmap() when no longer needed. On error, %NULL is returned
|
||||
* and errno is set.
|
||||
*
|
||||
* \sa enum gbm_bo_transfer_flags for the list of flags
|
||||
*/
|
||||
GBM_EXPORT void *
|
||||
gbm_bo_map(struct gbm_bo *bo,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t flags, uint32_t *stride, void **map_data)
|
||||
{
|
||||
if (!bo || width == 0 || height == 0 || !stride || !map_data) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bo->gbm->bo_map(bo, x, y, width, height,
|
||||
flags, stride, map_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmap a previously mapped region of a gbm buffer object
|
||||
*
|
||||
* This function unmaps a region of a gbm bo for cpu read and/or write
|
||||
* access.
|
||||
*
|
||||
* \param bo The buffer object
|
||||
* \param map_data opaque ptr returned from prior gbm_bo_map
|
||||
*/
|
||||
GBM_EXPORT void
|
||||
gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
|
||||
{
|
||||
bo->gbm->bo_unmap(bo, map_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a surface object
|
||||
*
|
||||
|
|
|
|||
|
|
@ -253,6 +253,41 @@ struct gbm_bo *
|
|||
gbm_bo_import(struct gbm_device *gbm, uint32_t type,
|
||||
void *buffer, uint32_t usage);
|
||||
|
||||
/**
|
||||
* Flags to indicate the type of mapping for the buffer - these are
|
||||
* passed into gbm_bo_map(). The caller must set the union of all the
|
||||
* flags that are appropriate.
|
||||
*
|
||||
* These flags are independent of the GBM_BO_USE_* creation flags. However,
|
||||
* mapping the buffer may require copying to/from a staging buffer.
|
||||
*
|
||||
* See also: pipe_transfer_usage
|
||||
*/
|
||||
enum gbm_bo_transfer_flags {
|
||||
/**
|
||||
* Buffer contents read back (or accessed directly) at transfer
|
||||
* create time.
|
||||
*/
|
||||
GBM_BO_TRANSFER_READ = (1 << 0),
|
||||
/**
|
||||
* Buffer contents will be written back at unmap time
|
||||
* (or modified as a result of being accessed directly).
|
||||
*/
|
||||
GBM_BO_TRANSFER_WRITE = (1 << 1),
|
||||
/**
|
||||
* Read/modify/write
|
||||
*/
|
||||
GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE),
|
||||
};
|
||||
|
||||
void *
|
||||
gbm_bo_map(struct gbm_bo *bo,
|
||||
uint32_t x, uint32_t y, uint32_t width, uint32_t height,
|
||||
uint32_t flags, uint32_t *stride, void **map_data);
|
||||
|
||||
void
|
||||
gbm_bo_unmap(struct gbm_bo *bo, void *map_data);
|
||||
|
||||
uint32_t
|
||||
gbm_bo_get_width(struct gbm_bo *bo);
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ struct gbm_device {
|
|||
uint32_t usage);
|
||||
struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,
|
||||
void *buffer, uint32_t usage);
|
||||
void *(*bo_map)(struct gbm_bo *bo,
|
||||
uint32_t x, uint32_t y,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t flags, uint32_t *stride,
|
||||
void **map_data);
|
||||
void (*bo_unmap)(struct gbm_bo *bo, void *map_data);
|
||||
int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
|
||||
int (*bo_get_fd)(struct gbm_bo *bo);
|
||||
void (*bo_destroy)(struct gbm_bo *bo);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue