extern struct backend backend_mediatek;
#endif
extern struct backend backend_nouveau;
+#ifdef DRV_RADEON
+extern struct backend backend_radeon;
+#endif
#ifdef DRV_ROCKCHIP
extern struct backend backend_rockchip;
#endif
#ifdef DRV_AMDGPU
&backend_amdgpu,
#endif
- &backend_cirrus,
- &backend_evdi,
+ &backend_cirrus, &backend_evdi,
#ifdef DRV_EXYNOS
&backend_exynos,
#endif
&backend_mediatek,
#endif
&backend_nouveau,
+#ifdef DRV_RADEON
+ &backend_radeon,
+#endif
#ifdef DRV_ROCKCHIP
&backend_rockchip,
#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++)
+ for (i = 0; i < ARRAY_SIZE(backend_list); i++)
if (!strcmp(drm_version->name, backend_list[i]->name)) {
drmFreeVersion(drm_version);
return backend_list[i];
struct driver *drv;
int ret;
- drv = (struct driver *) calloc(1, sizeof(*drv));
+ drv = (struct driver *)calloc(1, sizeof(*drv));
if (!drv)
return NULL;
/* Start with a power of 2 number of allocations. */
drv->backend->combos.allocations = 2;
drv->backend->combos.size = 0;
- drv->backend->combos.data = calloc(drv->backend->combos.allocations,
- sizeof(struct combination));
+ drv->backend->combos.data =
+ calloc(drv->backend->combos.allocations, sizeof(struct combination));
if (!drv->backend->combos.data)
goto free_map_table;
return drv->fd;
}
-const char *
-drv_get_name(struct driver *drv)
+const char *drv_get_name(struct driver *drv)
{
return drv->backend->name;
}
-struct combination *drv_get_combination(struct driver *drv, uint32_t format,
- uint64_t usage)
+struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t usage)
{
struct combination *curr, *best;
for (i = 0; i < drv->backend->combos.size; i++) {
curr = &drv->backend->combos.data[i];
if ((format == curr->format) && usage == (curr->usage & usage))
- if (!best ||
- best->metadata.priority < curr->metadata.priority)
+ if (!best || best->metadata.priority < curr->metadata.priority)
best = curr;
}
return best;
}
-struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height,
- uint32_t format)
+struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t flags)
{
struct bo *bo;
- bo = (struct bo *) calloc(1, sizeof(*bo));
+ bo = (struct bo *)calloc(1, sizeof(*bo));
if (!bo)
return NULL;
bo->width = width;
bo->height = height;
bo->format = format;
+ bo->flags = flags;
bo->num_planes = drv_num_planes_from_format(format);
if (!bo->num_planes) {
return bo;
}
-struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height,
- uint32_t format, uint64_t flags)
+struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t flags)
{
int ret;
size_t plane;
struct bo *bo;
- bo = drv_bo_new(drv, width, height, format);
+ bo = drv_bo_new(drv, width, height, format, flags);
if (!bo)
return NULL;
return bo;
}
-struct bo *drv_bo_create_with_modifiers(struct driver *drv,
- uint32_t width, uint32_t height,
- uint32_t format,
- const uint64_t *modifiers, uint32_t count)
+struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
+ uint32_t format, const uint64_t *modifiers, uint32_t count)
{
int ret;
size_t plane;
return NULL;
}
- bo = drv_bo_new(drv, width, height, format);
+ bo = drv_bo_new(drv, width, height, format, BO_USE_NONE);
if (!bo)
return NULL;
- ret = drv->backend->bo_create_with_modifiers(bo, width, height,
- format, modifiers, count);
+ ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count);
if (ret) {
free(bo);
return bo;
}
-
void drv_bo_destroy(struct bo *bo)
{
size_t plane;
uintptr_t total = 0;
+ size_t map_count = 0;
struct driver *drv = bo->drv;
pthread_mutex_lock(&drv->driver_lock);
for (plane = 0; plane < bo->num_planes; plane++)
drv_decrement_reference_count(drv, bo, plane);
- for (plane = 0; plane < bo->num_planes; plane++)
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ void *ptr;
+
total += drv_get_reference_count(drv, bo, plane);
+ map_count += !drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr);
+ }
pthread_mutex_unlock(&drv->driver_lock);
- if (total == 0)
+ if (total == 0) {
+ /*
+ * If we leak a reference to the GEM handle being freed here in the mapping table,
+ * we risk using the mapping table entry later for a completely different BO that
+ * gets the same handle. (See b/38250067.)
+ */
+ assert(!map_count);
bo->drv->backend->bo_destroy(bo);
+ }
free(bo);
}
size_t plane;
struct bo *bo;
- bo = drv_bo_new(drv, data->width, data->height, data->format);
+ bo = drv_bo_new(drv, data->width, data->height, data->format, data->flags);
if (!bo)
return NULL;
return bo;
}
-void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width,
- uint32_t height, uint32_t flags, struct map_info **map_data,
- size_t plane)
+void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+ uint32_t flags, struct map_info **map_data, size_t plane)
{
void *ptr;
uint8_t *addr;
size_t offset;
struct map_info *data;
+ int prot;
assert(width > 0);
assert(height > 0);
assert(x + width <= drv_bo_get_width(bo));
assert(y + height <= drv_bo_get_height(bo));
+ assert(BO_TRANSFER_READ_WRITE & flags);
pthread_mutex_lock(&bo->drv->driver_lock);
if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) {
- data = (struct map_info *) ptr;
+ data = (struct map_info *)ptr;
data->refcount++;
goto success;
}
data = calloc(1, sizeof(*data));
- addr = bo->drv->backend->bo_map(bo, data, plane);
+ prot = BO_TRANSFER_WRITE & flags ? PROT_WRITE | PROT_READ : PROT_READ;
+ addr = bo->drv->backend->bo_map(bo, data, plane, prot);
if (addr == MAP_FAILED) {
*map_data = NULL;
free(data);
data->refcount = 1;
data->addr = addr;
data->handle = bo->handles[plane].u32;
- drmHashInsert(bo->drv->map_table, bo->handles[plane].u32,
- (void *) data);
+ drmHashInsert(bo->drv->map_table, bo->handles[plane].u32, (void *)data);
success:
*map_data = data;
offset = drv_bo_get_plane_stride(bo, plane) * y;
offset += drv_stride_from_format(bo->format, x, plane);
- addr = (uint8_t *) data->addr;
+ addr = (uint8_t *)data->addr;
addr += drv_bo_get_plane_offset(bo, plane) + offset;
pthread_mutex_unlock(&bo->drv->driver_lock);
- return (void *) addr;
+ return (void *)addr;
}
int drv_bo_unmap(struct bo *bo, struct map_info *data)
int ret, fd;
assert(plane < bo->num_planes);
- ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32,
- DRM_CLOEXEC | DRM_RDWR, &fd);
+ ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
return (ret) ? ret : fd;
-
}
uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane)
uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane)
{
- assert(plane < bo->num_planes);
+ assert(plane < bo->num_planes);
return bo->format_modifiers[plane];
}
return bo->format;
}
-uint32_t drv_resolve_format(struct driver *drv, uint32_t format)
+uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t usage)
{
if (drv->backend->resolve_format)
- return drv->backend->resolve_format(format);
+ return drv->backend->resolve_format(format, usage);
return format;
}
case DRM_FORMAT_YVYU:
return 1;
case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
return 2;
case DRM_FORMAT_YVU420:
case DRM_FORMAT_YVU420_ANDROID:
return 0;
}
-uint32_t
-drv_bytes_per_pixel(uint32_t format, size_t plane)
-{
- return DIV_ROUND_UP(drv_bpp_from_format(format, plane), 8);
-}
-
-uint32_t drv_size_from_format(uint32_t format, uint32_t stride,
- uint32_t height, size_t plane)
+uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane)
{
assert(plane < drv_num_planes_from_format(format));
uint32_t vertical_subsampling;