gbm: Explicitly disallow a planar dumb BO
[mesa.git] / src / gbm / backends / dri / gbm_dri.c
index 9c3a51b2b9de8e0eda133f151eccb7b07d5e0418..3faa19e3f19312bb7536dd54766000c0757a3b16 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <string.h>
 #include <errno.h>
 #include <limits.h>
@@ -239,11 +240,14 @@ struct dri_extension_match {
    const char *name;
    int version;
    int offset;
+   int optional;
 };
 
 static struct dri_extension_match dri_core_extensions[] = {
    { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) },
    { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) },
+   { __DRI2_FENCE, 1, offsetof(struct gbm_dri_device, fence), 1 },
+   { __DRI2_INTEROP, 1, offsetof(struct gbm_dri_device, interop), 1 },
    { NULL, 0, 0 }
 };
 
@@ -279,7 +283,7 @@ dri_bind_extensions(struct gbm_dri_device *dri,
 
    for (j = 0; matches[j].name; j++) {
       field = ((char *) dri + matches[j].offset);
-      if (*(const __DRIextension **) field == NULL) {
+      if ((*(const __DRIextension **) field == NULL) && !matches[j].optional) {
          ret = -1;
       }
    }
@@ -360,8 +364,8 @@ dri_open_driver(struct gbm_dri_device *dri)
       return NULL;
    }
 
-   if (asprintf(&get_extensions_name, "%s_%s",
-                __DRI_DRIVER_GET_EXTENSIONS, dri->base.driver_name) != -1) {
+   get_extensions_name = loader_get_extensions_name(dri->base.driver_name);
+   if (get_extensions_name) {
       const __DRIextension **(*get_extensions)(void);
 
       get_extensions = dlsym(dri->driver, get_extensions_name);
@@ -437,19 +441,19 @@ dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
       return ret;
    };
 
-   dri->extensions = gbm_dri_screen_extensions;
+   dri->loader_extensions = gbm_dri_screen_extensions;
 
    if (dri->dri2 == NULL)
       return -1;
 
    if (dri->dri2->base.version >= 4) {
       dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd,
-                                                dri->extensions,
+                                                dri->loader_extensions,
                                                 dri->driver_extensions,
                                                 &dri->driver_configs, dri);
    } else {
       dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd,
-                                               dri->extensions,
+                                               dri->loader_extensions,
                                                &dri->driver_configs, dri);
    }
    if (dri->screen == NULL)
@@ -487,17 +491,17 @@ dri_screen_create_swrast(struct gbm_dri_device *dri)
       return ret;
    }
 
-   dri->extensions = gbm_dri_screen_extensions;
+   dri->loader_extensions = gbm_dri_screen_extensions;
 
    if (dri->swrast == NULL)
       return -1;
 
    if (dri->swrast->base.version >= 4) {
-      dri->screen = dri->swrast->createNewScreen2(0, dri->extensions,
+      dri->screen = dri->swrast->createNewScreen2(0, dri->loader_extensions,
                                                   dri->driver_extensions,
                                                   &dri->driver_configs, dri);
    } else {
-      dri->screen = dri->swrast->createNewScreen(0, dri->extensions,
+      dri->screen = dri->swrast->createNewScreen(0, dri->loader_extensions,
                                                  &dri->driver_configs, dri);
    }
    if (dri->screen == NULL)
@@ -514,7 +518,7 @@ dri_screen_create(struct gbm_dri_device *dri)
 {
    char *driver_name;
 
-   driver_name = loader_get_driver_for_fd(dri->base.base.fd, 0);
+   driver_name = loader_get_driver_for_fd(dri->base.base.fd);
    if (!driver_name)
       return -1;
 
@@ -589,7 +593,8 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo)
    if (bo->image == NULL)
       return -1;
 
-   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd);
+   if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd))
+      return -1;
 
    return fd;
 }
@@ -691,6 +696,7 @@ gbm_dri_bo_import(struct gbm_device *gbm,
          gbm_format = GBM_FORMAT_YUYV;
          break;
       default:
+         dri->image->destroyImage(image);
          return NULL;
       }
       break;
@@ -711,6 +717,7 @@ gbm_dri_bo_import(struct gbm_device *gbm,
       gbm_format = gbm_dri_to_gbm_format(dri_format);
       if (gbm_format == 0) {
          errno = EINVAL;
+         dri->image->destroyImage(image);
          return NULL;
       }
       break;
@@ -755,8 +762,10 @@ gbm_dri_bo_import(struct gbm_device *gbm,
 
 
    bo = calloc(1, sizeof *bo);
-   if (bo == NULL)
+   if (bo == NULL) {
+      dri->image->destroyImage(image);
       return NULL;
+   }
 
    bo->image = image;
 
@@ -767,6 +776,7 @@ gbm_dri_bo_import(struct gbm_device *gbm,
    if (dri->image->base.version >= 2 &&
        !dri->image->validateUsage(bo->image, dri_use)) {
       errno = EINVAL;
+      dri->image->destroyImage(bo->image);
       free(bo);
       return NULL;
    }
@@ -786,6 +796,31 @@ gbm_dri_bo_import(struct gbm_device *gbm,
    return &bo->base.base;
 }
 
+static bool
+is_planar_format(uint32_t format)
+{
+   switch (format) {
+   case GBM_FORMAT_NV12:
+   case GBM_FORMAT_NV21:
+   case GBM_FORMAT_NV16:
+   case GBM_FORMAT_NV61:
+   case GBM_FORMAT_YUV410:
+   case GBM_FORMAT_YVU410:
+   case GBM_FORMAT_YUV411:
+   case GBM_FORMAT_YVU411:
+   case GBM_FORMAT_YUV420:
+   case GBM_FORMAT_YVU420:
+   case GBM_FORMAT_YUV422:
+   case GBM_FORMAT_YVU422:
+   case GBM_FORMAT_YUV444:
+   case GBM_FORMAT_YVU444:
+      return true;
+   default:
+      return false;
+   }
+
+}
+
 static struct gbm_bo *
 create_dumb(struct gbm_device *gbm,
                   uint32_t width, uint32_t height,
@@ -807,6 +842,11 @@ create_dumb(struct gbm_device *gbm,
       return NULL;
    }
 
+   if (is_planar_format(format)) {
+      errno = EINVAL;
+      return NULL;
+   }
+
    bo = calloc(1, sizeof *bo);
    if (bo == NULL)
       return NULL;
@@ -947,7 +987,7 @@ gbm_dri_bo_map(struct gbm_bo *_bo,
       return *map_data;
    }
 
-   if (!dri->image || dri->image->base.version < 12) {
+   if (!dri->image || dri->image->base.version < 12 || !dri->image->mapImage) {
       errno = ENOSYS;
       return NULL;
    }
@@ -978,7 +1018,8 @@ gbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data)
       return;
    }
 
-   if (!dri->context || !dri->image || dri->image->base.version < 12)
+   if (!dri->context || !dri->image ||
+       dri->image->base.version < 12 || !dri->image->unmapImage)
       return;
 
    dri->image->unmapImage(dri->context, bo->image, map_data);