From: Ander Conselvan de Oliveira <ander.conselvan.de.olive...@intel.com>
Add gbm_bo_map() and gbm_bo_unmap(). This lets a user access the contents of a bo using the CPU. v2: - improve documentation to clarify this is an optional interface; - make gbm_bo_create() fail with ENOSYS if the GBM_BO_USE_MAP flag was supplied and gbm_bo_map() is not implemented. --- src/gbm/backends/dri/gbm_dri.c | 3 +++ src/gbm/backends/intel/gbm_intel.c | 24 +++++++++++++++++ src/gbm/backends/intel/gbm_intel.h | 2 ++ src/gbm/main/gbm.c | 53 ++++++++++++++++++++++++++++++++++++++ src/gbm/main/gbm.h | 11 ++++++++ src/gbm/main/gbmint.h | 2 ++ 6 files changed, 95 insertions(+) diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c index cbb4c8c..8295a25 100644 --- a/src/gbm/backends/dri/gbm_dri.c +++ b/src/gbm/backends/dri/gbm_dri.c @@ -346,6 +346,9 @@ gbm_dri_is_format_supported(struct gbm_device *gbm, usage & GBM_BO_USE_RENDERING) return 0; + if (usage & GBM_BO_USE_MAP) + return 0; + return 1; } diff --git a/src/gbm/backends/intel/gbm_intel.c b/src/gbm/backends/intel/gbm_intel.c index c897f70..ced75d5 100644 --- a/src/gbm/backends/intel/gbm_intel.c +++ b/src/gbm/backends/intel/gbm_intel.c @@ -76,6 +76,24 @@ gbm_intel_bo_write(struct gbm_bo *bo, const void *buf, size_t count) return drm_intel_bo_unmap(ibo->bo); } +static void * +gbm_intel_bo_map(struct gbm_bo *bo) +{ + struct gbm_intel_bo *ibo = gbm_intel_bo(bo); + + drm_intel_bo_map(ibo->bo, 1); + + return ibo->bo->virtual; +} + +static void +gbm_intel_bo_unmap(struct gbm_bo *bo) +{ + struct gbm_intel_bo *ibo = gbm_intel_bo(bo); + + drm_intel_bo_unmap(ibo->bo); +} + static void gbm_intel_bo_destroy(struct gbm_bo *_bo) { @@ -99,6 +117,7 @@ gbm_intel_bo_create_with_bo(struct gbm_device *gbm, return NULL; ibo->bo = bo; + ibo->usage = usage; ibo->base.base.gbm = gbm; ibo->base.base.width = width; @@ -141,6 +160,9 @@ gbm_intel_bo_create(struct gbm_device *gbm, tiling = I915_TILING_NONE; } + if (usage & GBM_BO_USE_MAP) + tiling = I915_TILING_NONE; + if (usage & GBM_BO_USE_RENDERING) flags |= BO_ALLOC_FOR_RENDER; @@ -233,6 +255,8 @@ gbm_intel_device_create(int fd) igbm->base.base.is_format_supported = gbm_intel_is_format_supported; igbm->base.base.bo_write = gbm_intel_bo_write; igbm->base.base.bo_get_fd = gbm_intel_bo_get_fd; + igbm->base.base.bo_map = gbm_intel_bo_map; + igbm->base.base.bo_unmap = gbm_intel_bo_unmap; igbm->base.base.bo_destroy = gbm_intel_bo_destroy; igbm->base.base.destroy = gbm_intel_destroy; igbm->base.base.surface_create = gbm_intel_surface_create; diff --git a/src/gbm/backends/intel/gbm_intel.h b/src/gbm/backends/intel/gbm_intel.h index af0689b..1958355 100644 --- a/src/gbm/backends/intel/gbm_intel.h +++ b/src/gbm/backends/intel/gbm_intel.h @@ -46,6 +46,8 @@ struct gbm_intel_device { struct gbm_intel_bo { struct gbm_drm_bo base; + uint32_t usage; + drm_intel_bo *bo; }; diff --git a/src/gbm/main/gbm.c b/src/gbm/main/gbm.c index 907ca3c..42d0d78 100644 --- a/src/gbm/main/gbm.c +++ b/src/gbm/main/gbm.c @@ -267,6 +267,49 @@ gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count) return bo->gbm->bo_write(bo, buf, count); } +/** Map a buffer object in CPU accesible memory + * + * \remark A GBM backend may not implement this interface. Users should + * implement a fallback path. + * + * This makes the content of the bo available for CPU access until + * \ref gbm_bo_unmap() is called. Synchronization between CPU and GPU + * will be done at unmap time, so the caller shouldn't assume coherency + * for mapped buffers. + * + * A GBM backend may choose not to implement this functionality. In that + * case, both this function and \ref gbm_bo_create() with the \ref + * GBM_BO_USE_MAP flag should fail, and errno set to ENOSYS. + * + * \param bo The buffer object to be mapped + * \return Pointer to the mapped buffer object or NULL on failure + */ +GBM_EXPORT void * +gbm_bo_map(struct gbm_bo *bo) +{ + if (!bo->gbm->bo_map) { + errno = ENOSYS; + return NULL; + } + + return bo->gbm->bo_map(bo); +} + +/** Unmap a previously mapped buffer object + * + * Unmaps the given bo and perform any necessary synchronization such as + * cache flushing, copying, etc, so that the GPU sees the same data as + * written by the CPU. + * + * \param The buffer object to be unmapped + */ +GBM_EXPORT void +gbm_bo_unmap(struct gbm_bo *bo) +{ + if (bo->gbm->bo_unmap) + bo->gbm->bo_unmap(bo); +} + /** Get the gbm device used to create the buffer object * * \param bo The buffer object @@ -335,6 +378,11 @@ gbm_bo_destroy(struct gbm_bo *bo) * when no longer needed. If an error occurs during allocation %NULL will be * returned and errno set. * + * Allocation may also fail due to an unsupported usage type. For instance, + * the flag \ref GBM_BO_USE_MAP may cause the allocation to fail if that + * optional functionality is not implemented. In that case, errno is set to + * ENOSYS. + * * \sa enum gbm_bo_format for the list of formats * \sa enum gbm_bo_flags for the list of usage flags */ @@ -343,6 +391,11 @@ gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { + if ((usage & GBM_BO_USE_MAP) && !gbm->bo_map) { + errno = ENOSYS; + return NULL; + } + if (width == 0 || height == 0) { errno = EINVAL; return NULL; diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h index 92d472a..036232d 100644 --- a/src/gbm/main/gbm.h +++ b/src/gbm/main/gbm.h @@ -207,6 +207,11 @@ enum gbm_bo_flags { * combinations. */ GBM_BO_USE_WRITE = (1 << 3), + /** + * Buffer can be mapped with gbm_bo_map(). Implementation of this + * functionality is not mandatory. + */ + GBM_BO_USE_MAP = (1 << 4), }; int @@ -270,6 +275,12 @@ gbm_bo_get_fd(struct gbm_bo *bo); int gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count); +void * +gbm_bo_map(struct gbm_bo *bo); + +void +gbm_bo_unmap(struct gbm_bo *bo); + 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 d7520ad..eea7d4d 100644 --- a/src/gbm/main/gbmint.h +++ b/src/gbm/main/gbmint.h @@ -70,6 +70,8 @@ struct gbm_device { void *buffer, uint32_t usage); int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data); int (*bo_get_fd)(struct gbm_bo *bo); + void *(*bo_map)(struct gbm_bo *bo); + void (*bo_unmap)(struct gbm_bo *bo); void (*bo_destroy)(struct gbm_bo *bo); struct gbm_surface *(*surface_create)(struct gbm_device *gbm, -- 1.8.3.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev