#ifdef DRV_ROCKCHIP
extern const struct backend backend_rockchip;
#endif
+#ifdef DRV_SYNAPTICS
+extern const struct backend backend_synaptics;
+#endif
#ifdef DRV_TEGRA
extern const struct backend backend_tegra;
#endif
#ifdef DRV_ROCKCHIP
&backend_rockchip,
#endif
+#ifdef DRV_SYNAPTICS
+ &backend_synaptics,
+#endif
#ifdef DRV_TEGRA
&backend_tegra,
#endif
#ifdef DRV_VC4
&backend_vc4,
#endif
- &backend_vgem, &backend_virtio_gpu,
+ &backend_vgem, &backend_virtio_gpu,
};
- for (i = 0; i < ARRAY_SIZE(backend_list); i++)
- if (!strcmp(drm_version->name, backend_list[i]->name)) {
+ for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
+ const struct backend *b = backend_list[i];
+ // Exactly one of the main create functions must be defined.
+ assert((b->bo_create != NULL) ^ (b->bo_create_from_metadata != NULL));
+ // Either both or neither must be implemented.
+ assert((b->bo_compute_metadata != NULL) == (b->bo_create_from_metadata != NULL));
+ // Both can't be defined, but it's okay for neither to be (i.e. only bo_create).
+ assert((b->bo_create_with_modifiers == NULL) ||
+ (b->bo_create_from_metadata == NULL));
+
+ if (!strcmp(drm_version->name, b->name)) {
drmFreeVersion(drm_version);
- return backend_list[i];
+ return b;
}
+ }
drmFreeVersion(drm_version);
return NULL;
}
struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
- uint64_t use_flags)
+ uint64_t use_flags, bool is_test_buffer)
{
struct bo *bo;
bo->meta.format = format;
bo->meta.use_flags = use_flags;
bo->meta.num_planes = drv_num_planes_from_format(format);
+ bo->is_test_buffer = is_test_buffer;
if (!bo->meta.num_planes) {
free(bo);
int ret;
size_t plane;
struct bo *bo;
+ bool is_test_alloc;
- bo = drv_bo_new(drv, width, height, format, use_flags);
+ is_test_alloc = use_flags & BO_USE_TEST_ALLOC;
+ use_flags &= ~BO_USE_TEST_ALLOC;
+
+ bo = drv_bo_new(drv, width, height, format, use_flags, is_test_alloc);
if (!bo)
return NULL;
- ret = drv->backend->bo_create(bo, width, height, format, use_flags);
+ ret = -EINVAL;
+ if (drv->backend->bo_compute_metadata) {
+ ret = drv->backend->bo_compute_metadata(bo, width, height, format, use_flags, NULL,
+ 0);
+ if (!is_test_alloc && ret == 0)
+ ret = drv->backend->bo_create_from_metadata(bo);
+ } else if (!is_test_alloc) {
+ ret = drv->backend->bo_create(bo, width, height, format, use_flags);
+ }
if (ret) {
free(bo);
size_t plane;
struct bo *bo;
- if (!drv->backend->bo_create_with_modifiers) {
+ if (!drv->backend->bo_create_with_modifiers && !drv->backend->bo_compute_metadata) {
errno = ENOENT;
return NULL;
}
- bo = drv_bo_new(drv, width, height, format, BO_USE_NONE);
+ bo = drv_bo_new(drv, width, height, format, BO_USE_NONE, false);
if (!bo)
return NULL;
- ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count);
+ ret = -EINVAL;
+ if (drv->backend->bo_compute_metadata) {
+ ret = drv->backend->bo_compute_metadata(bo, width, height, format, BO_USE_NONE,
+ modifiers, count);
+ if (ret == 0)
+ ret = drv->backend->bo_create_from_metadata(bo);
+ } else {
+ ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers,
+ count);
+ }
if (ret) {
free(bo);
uintptr_t total = 0;
struct driver *drv = bo->drv;
- pthread_mutex_lock(&drv->driver_lock);
+ if (!bo->is_test_buffer) {
+ pthread_mutex_lock(&drv->driver_lock);
- for (plane = 0; plane < bo->meta.num_planes; plane++)
- drv_decrement_reference_count(drv, bo, plane);
+ for (plane = 0; plane < bo->meta.num_planes; plane++)
+ drv_decrement_reference_count(drv, bo, plane);
- for (plane = 0; plane < bo->meta.num_planes; plane++)
- total += drv_get_reference_count(drv, bo, plane);
+ for (plane = 0; plane < bo->meta.num_planes; plane++)
+ total += drv_get_reference_count(drv, bo, plane);
- pthread_mutex_unlock(&drv->driver_lock);
+ pthread_mutex_unlock(&drv->driver_lock);
- if (total == 0) {
- ret = drv_mapping_destroy(bo);
- assert(ret == 0);
- bo->drv->backend->bo_destroy(bo);
+ if (total == 0) {
+ ret = drv_mapping_destroy(bo);
+ assert(ret == 0);
+ bo->drv->backend->bo_destroy(bo);
+ }
}
free(bo);
struct bo *bo;
off_t seek_end;
- bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags);
+ bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags, false);
if (!bo)
return NULL;
/* No CPU access for protected buffers. */
assert(!(bo->meta.use_flags & BO_USE_PROTECTED));
+ if (bo->is_test_buffer) {
+ return MAP_FAILED;
+ }
+
memset(&mapping, 0, sizeof(mapping));
mapping.rect = *rect;
mapping.refcount = 1;
return ret;
}
+int drv_bo_flush(struct bo *bo, struct mapping *mapping)
+{
+ int ret = 0;
+
+ assert(mapping);
+ assert(mapping->vma);
+ assert(mapping->refcount > 0);
+ assert(mapping->vma->refcount > 0);
+
+ if (bo->drv->backend->bo_flush)
+ ret = bo->drv->backend->bo_flush(bo, mapping);
+
+ return ret;
+}
+
int drv_bo_flush_or_unmap(struct bo *bo, struct mapping *mapping)
{
int ret = 0;
int ret, fd;
assert(plane < bo->meta.num_planes);
+ if (bo->is_test_buffer) {
+ return -EINVAL;
+ }
+
ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
// Older DRM implementations blocked DRM_RDWR, but gave a read/write mapping anyways
return bo->meta.format;
}
+size_t drv_bo_get_total_size(struct bo *bo)
+{
+ return bo->meta.total_size;
+}
+
uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
{
if (drv->backend->resolve_format)
uint32_t count = 0;
size_t plane, p;
+ if (bo->is_test_buffer) {
+ return 0;
+ }
+
for (plane = 0; plane < bo->meta.num_planes; plane++) {
for (p = 0; p < plane; p++)
if (bo->handles[p].u32 == bo->handles[plane].u32)
#endif
va_end(args);
}
+
+int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
+ uint32_t offsets[DRV_MAX_PLANES])
+{
+ for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
+ strides[plane] = bo->meta.strides[plane];
+ offsets[plane] = bo->meta.offsets[plane];
+ }
+
+ if (bo->drv->backend->resource_info)
+ return bo->drv->backend->resource_info(bo, strides, offsets);
+
+ return 0;
+}