gbm: Export a per plane getter for stride
[mesa.git] / src / gbm / backends / dri / gbm_dri.c
index 3faa19e3f19312bb7536dd54766000c0757a3b16..5a98b6aba68c1dfdd7791b57773821ac32840f45 100644 (file)
@@ -599,6 +599,108 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo)
    return fd;
 }
 
+static int
+get_number_planes(struct gbm_dri_device *dri, __DRIimage *image)
+{
+   int num_planes = 0;
+
+   /* Dumb buffers are single-plane only. */
+   if (!image)
+      return 1;
+
+   dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes);
+
+   if (num_planes <= 0)
+      num_planes = 1;
+
+   return num_planes;
+}
+
+static int
+gbm_dri_bo_get_planes(struct gbm_bo *_bo)
+{
+   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
+   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
+
+   return get_number_planes(dri, bo->image);
+}
+
+static union gbm_bo_handle
+gbm_dri_bo_get_handle_for_plane(struct gbm_bo *_bo, int plane)
+{
+   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
+   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
+   union gbm_bo_handle ret;
+   ret.s32 = -1;
+
+   if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) {
+      errno = ENOSYS;
+      return ret;
+   }
+
+   if (plane >= get_number_planes(dri, bo->image)) {
+      errno = EINVAL;
+      return ret;
+   }
+
+   /* dumb BOs can only utilize non-planar formats */
+   if (!bo->image) {
+      assert(plane == 0);
+      ret.s32 = bo->handle;
+      return ret;
+   }
+
+   __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL);
+   if (image) {
+      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32);
+      dri->image->destroyImage(image);
+   } else {
+      assert(plane == 0);
+      dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32);
+   }
+
+   return ret;
+}
+
+static uint32_t
+gbm_dri_bo_get_stride(struct gbm_bo *_bo, int plane)
+{
+   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
+   struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
+   __DRIimage *image;
+   int stride = 0;
+
+   if (!dri->image || dri->image->base.version < 11 || !dri->image->fromPlanar) {
+      /* Preserve legacy behavior if plane is 0 */
+      if (plane == 0)
+         return _bo->stride;
+
+      errno = ENOSYS;
+      return 0;
+   }
+
+   if (plane >= get_number_planes(dri, bo->image)) {
+      errno = EINVAL;
+      return 0;
+   }
+
+   if (bo->image == NULL) {
+      assert(plane == 0);
+      return _bo->stride;
+   }
+
+   image = dri->image->fromPlanar(bo->image, plane, NULL);
+   if (image) {
+      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
+      dri->image->destroyImage(image);
+   } else {
+      assert(plane == 0);
+      dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
+   }
+
+   return (uint32_t)stride;
+}
+
 static void
 gbm_dri_bo_destroy(struct gbm_bo *_bo)
 {
@@ -1091,6 +1193,9 @@ dri_device_create(int fd)
    dri->base.base.is_format_supported = gbm_dri_is_format_supported;
    dri->base.base.bo_write = gbm_dri_bo_write;
    dri->base.base.bo_get_fd = gbm_dri_bo_get_fd;
+   dri->base.base.bo_get_planes = gbm_dri_bo_get_planes;
+   dri->base.base.bo_get_handle = gbm_dri_bo_get_handle_for_plane;
+   dri->base.base.bo_get_stride = gbm_dri_bo_get_stride;
    dri->base.base.bo_destroy = gbm_dri_bo_destroy;
    dri->base.base.destroy = dri_destroy;
    dri->base.base.surface_create = gbm_dri_surface_create;