OSDN Git Service

Fix potential uninitialized read
[android-x86/external-minigbm.git] / helpers.c
index 6c26e54..592981d 100644 (file)
--- a/helpers.c
+++ b/helpers.c
 #include "helpers.h"
 #include "util.h"
 
-static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane)
-{
-
-       if (plane != 0) {
-               switch (format) {
-               case DRM_FORMAT_YVU420:
-               case DRM_FORMAT_YVU420_ANDROID:
-                       stride = DIV_ROUND_UP(stride, 2);
-                       break;
-               }
-       }
-
-       return stride;
-}
-
-static uint32_t bpp_from_format(uint32_t format, size_t plane)
+struct planar_layout {
+       size_t num_planes;
+       int horizontal_subsampling[DRV_MAX_PLANES];
+       int vertical_subsampling[DRV_MAX_PLANES];
+       int bytes_per_pixel[DRV_MAX_PLANES];
+};
+
+// clang-format off
+
+static const struct planar_layout packed_1bpp_layout = {
+       .num_planes = 1,
+       .horizontal_subsampling = { 1 },
+       .vertical_subsampling = { 1 },
+       .bytes_per_pixel = { 1 }
+};
+
+static const struct planar_layout packed_2bpp_layout = {
+       .num_planes = 1,
+       .horizontal_subsampling = { 1 },
+       .vertical_subsampling = { 1 },
+       .bytes_per_pixel = { 2 }
+};
+
+static const struct planar_layout packed_3bpp_layout = {
+       .num_planes = 1,
+       .horizontal_subsampling = { 1 },
+       .vertical_subsampling = { 1 },
+       .bytes_per_pixel = { 3 }
+};
+
+static const struct planar_layout packed_4bpp_layout = {
+       .num_planes = 1,
+       .horizontal_subsampling = { 1 },
+       .vertical_subsampling = { 1 },
+       .bytes_per_pixel = { 4 }
+};
+
+static const struct planar_layout biplanar_yuv_420_layout = {
+       .num_planes = 2,
+       .horizontal_subsampling = { 1, 2 },
+       .vertical_subsampling = { 1, 2 },
+       .bytes_per_pixel = { 1, 2 }
+};
+
+static const struct planar_layout triplanar_yuv_420_layout = {
+       .num_planes = 3,
+       .horizontal_subsampling = { 1, 2, 2 },
+       .vertical_subsampling = { 1, 2, 2 },
+       .bytes_per_pixel = { 1, 1, 1 }
+};
+
+// clang-format on
+
+static const struct planar_layout *layout_from_format(uint32_t format)
 {
-       assert(plane < drv_num_planes_from_format(format));
-
        switch (format) {
        case DRM_FORMAT_BGR233:
        case DRM_FORMAT_C8:
        case DRM_FORMAT_R8:
        case DRM_FORMAT_RGB332:
+               return &packed_1bpp_layout;
+
        case DRM_FORMAT_YVU420:
        case DRM_FORMAT_YVU420_ANDROID:
-               return 8;
+               return &triplanar_yuv_420_layout;
 
        case DRM_FORMAT_NV12:
        case DRM_FORMAT_NV21:
-               return (plane == 0) ? 8 : 4;
+               return &biplanar_yuv_420_layout;
 
        case DRM_FORMAT_ABGR1555:
        case DRM_FORMAT_ABGR4444:
@@ -74,11 +112,11 @@ static uint32_t bpp_from_format(uint32_t format, size_t plane)
        case DRM_FORMAT_XRGB4444:
        case DRM_FORMAT_YUYV:
        case DRM_FORMAT_YVYU:
-               return 16;
+               return &packed_2bpp_layout;
 
        case DRM_FORMAT_BGR888:
        case DRM_FORMAT_RGB888:
-               return 24;
+               return &packed_3bpp_layout;
 
        case DRM_FORMAT_ABGR2101010:
        case DRM_FORMAT_ABGR8888:
@@ -97,17 +135,44 @@ static uint32_t bpp_from_format(uint32_t format, size_t plane)
        case DRM_FORMAT_XBGR8888:
        case DRM_FORMAT_XRGB2101010:
        case DRM_FORMAT_XRGB8888:
-               return 32;
+               return &packed_4bpp_layout;
+
+       default:
+               drv_log("UNKNOWN FORMAT %d\n", format);
+               return NULL;
        }
+}
 
-       fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
-       return 0;
+size_t drv_num_planes_from_format(uint32_t format)
+{
+       const struct planar_layout *layout = layout_from_format(format);
+
+       /*
+        * drv_bo_new calls this function early to query number of planes and
+        * considers 0 planes to mean unknown format, so we have to support
+        * that.  All other layout_from_format() queries can assume that the
+        * format is supported and that the return value is non-NULL.
+        */
+
+       return layout ? layout->num_planes : 0;
 }
 
-uint32_t drv_bo_get_stride_in_pixels(struct bo *bo)
+uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane)
 {
-       uint32_t bytes_per_pixel = DIV_ROUND_UP(bpp_from_format(bo->format, 0), 8);
-       return DIV_ROUND_UP(bo->strides[0], bytes_per_pixel);
+       const struct planar_layout *layout = layout_from_format(format);
+
+       assert(plane < layout->num_planes);
+
+       return DIV_ROUND_UP(height, layout->vertical_subsampling[plane]);
+}
+
+uint32_t drv_bytes_per_pixel_from_format(uint32_t format, size_t plane)
+{
+       const struct planar_layout *layout = layout_from_format(format);
+
+       assert(plane < layout->num_planes);
+
+       return layout->bytes_per_pixel[plane];
 }
 
 /*
@@ -115,7 +180,11 @@ uint32_t drv_bo_get_stride_in_pixels(struct bo *bo)
  */
 uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane)
 {
-       uint32_t stride = DIV_ROUND_UP(width * bpp_from_format(format, plane), 8);
+       const struct planar_layout *layout = layout_from_format(format);
+       assert(plane < layout->num_planes);
+
+       uint32_t plane_width = DIV_ROUND_UP(width, layout->horizontal_subsampling[plane]);
+       uint32_t stride = plane_width * layout->bytes_per_pixel[plane];
 
        /*
         * The stride of Android YV12 buffers is required to be aligned to 16 bytes
@@ -129,20 +198,21 @@ uint32_t drv_stride_from_format(uint32_t format, uint32_t width, 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;
+       return stride * drv_height_from_format(format, height, plane);
+}
 
-       switch (format) {
-       case DRM_FORMAT_NV12:
-       case DRM_FORMAT_YVU420:
-       case DRM_FORMAT_YVU420_ANDROID:
-               vertical_subsampling = (plane == 0) ? 1 : 2;
-               break;
-       default:
-               vertical_subsampling = 1;
+static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane)
+{
+       if (plane != 0) {
+               switch (format) {
+               case DRM_FORMAT_YVU420:
+               case DRM_FORMAT_YVU420_ANDROID:
+                       stride = DIV_ROUND_UP(stride, 2);
+                       break;
+               }
        }
 
-       return stride * DIV_ROUND_UP(height, vertical_subsampling);
+       return stride;
 }
 
 /*
@@ -206,12 +276,12 @@ int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t
        memset(&create_dumb, 0, sizeof(create_dumb));
        create_dumb.height = aligned_height;
        create_dumb.width = aligned_width;
-       create_dumb.bpp = bpp_from_format(format, 0);
+       create_dumb.bpp = layout_from_format(format)->bytes_per_pixel[0] * 8;
        create_dumb.flags = 0;
 
        ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
        if (ret) {
-               fprintf(stderr, "drv: DRM_IOCTL_MODE_CREATE_DUMB failed\n");
+               drv_log("DRM_IOCTL_MODE_CREATE_DUMB failed (%d, %d)\n", bo->drv->fd, errno);
                return ret;
        }
 
@@ -234,8 +304,7 @@ int drv_dumb_bo_destroy(struct bo *bo)
 
        ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
        if (ret) {
-               fprintf(stderr, "drv: DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n",
-                       bo->handles[0].u32);
+               drv_log("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handles[0].u32);
                return ret;
        }
 
@@ -261,7 +330,7 @@ int drv_gem_bo_destroy(struct bo *bo)
 
                ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
                if (ret) {
-                       fprintf(stderr, "drv: DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
+                       drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
                                bo->handles[plane].u32, ret);
                        error = ret;
                }
@@ -283,8 +352,7 @@ int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data)
                ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle);
 
                if (ret) {
-                       fprintf(stderr, "drv: DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n",
-                               prime_handle.fd);
+                       drv_log("DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n", prime_handle.fd);
 
                        /*
                         * Need to call GEM close on planes that were opened,
@@ -320,7 +388,7 @@ void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map
 
        ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
        if (ret) {
-               fprintf(stderr, "drv: DRM_IOCTL_MODE_MAP_DUMB failed \n");
+               drv_log("DRM_IOCTL_MODE_MAP_DUMB failed\n");
                return MAP_FAILED;
        }
 
@@ -361,7 +429,7 @@ int drv_mapping_destroy(struct bo *bo)
                        if (!--mapping->vma->refcount) {
                                ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
                                if (ret) {
-                                       fprintf(stderr, "drv: munmap failed");
+                                       drv_log("munmap failed\n");
                                        return ret;
                                }
 
@@ -452,7 +520,8 @@ void drv_modify_combination(struct driver *drv, uint32_t format, struct format_m
 struct drv_array *drv_query_kms(struct driver *drv)
 {
        struct drv_array *kms_items;
-       uint64_t plane_type, use_flag;
+       uint64_t plane_type = UINT64_MAX;
+        uint64_t use_flag;
        uint32_t i, j, k;
 
        drmModePlanePtr plane;