OSDN Git Service

minigbm: Make sure no mappings remain when closing a GEM handle
[android-x86/external-minigbm.git] / drv.c
diff --git a/drv.c b/drv.c
index 41bd1f1..10a6348 100644 (file)
--- a/drv.c
+++ b/drv.c
@@ -37,6 +37,9 @@ extern struct backend backend_marvell;
 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
@@ -64,8 +67,7 @@ static struct backend *drv_get_backend(int fd)
 #ifdef DRV_AMDGPU
                &backend_amdgpu,
 #endif
-               &backend_cirrus,
-               &backend_evdi,
+               &backend_cirrus,   &backend_evdi,
 #ifdef DRV_EXYNOS
                &backend_exynos,
 #endif
@@ -80,6 +82,9 @@ static struct backend *drv_get_backend(int fd)
                &backend_mediatek,
 #endif
                &backend_nouveau,
+#ifdef DRV_RADEON
+               &backend_radeon,
+#endif
 #ifdef DRV_ROCKCHIP
                &backend_rockchip,
 #endif
@@ -90,11 +95,10 @@ static struct backend *drv_get_backend(int fd)
 #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];
@@ -109,7 +113,7 @@ struct driver *drv_create(int fd)
        struct driver *drv;
        int ret;
 
-       drv = (struct driver *) calloc(1, sizeof(*drv));
+       drv = (struct driver *)calloc(1, sizeof(*drv));
 
        if (!drv)
                return NULL;
@@ -134,8 +138,8 @@ struct driver *drv_create(int fd)
        /* 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;
 
@@ -183,14 +187,12 @@ int drv_get_fd(struct driver *drv)
        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;
 
@@ -202,20 +204,19 @@ struct combination *drv_get_combination(struct driver *drv, uint32_t format,
        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;
@@ -224,6 +225,7 @@ struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height,
        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) {
@@ -234,14 +236,14 @@ struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height,
        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;
@@ -263,10 +265,8 @@ struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height,
        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;
@@ -277,13 +277,12 @@ struct bo *drv_bo_create_with_modifiers(struct driver *drv,
                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);
@@ -300,11 +299,11 @@ struct bo *drv_bo_create_with_modifiers(struct driver *drv,
        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);
@@ -312,13 +311,24 @@ void drv_bo_destroy(struct bo *bo)
        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);
 }
@@ -329,7 +339,7 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
        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;
@@ -351,30 +361,32 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
        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);
@@ -385,18 +397,17 @@ void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width,
        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)
@@ -457,11 +468,9 @@ int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
        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)
@@ -484,7 +493,7 @@ uint32_t drv_bo_get_plane_stride(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];
 }
 
@@ -493,10 +502,10 @@ uint32_t drv_bo_get_format(struct bo *bo)
        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;
 }
@@ -553,6 +562,7 @@ size_t drv_num_planes_from_format(uint32_t 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:
@@ -563,14 +573,7 @@ size_t drv_num_planes_from_format(uint32_t format)
        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;