dri: Make query image WIDTH and HEIGHT be version 4
[mesa.git] / src / gbm / backends / dri / gbm_dri.c
index e5ddfb6ce69ebf78074062b4fa9d3838f4367312..1831f1377897c6159b3e2e4319fa8d63fed94b68 100644 (file)
 
 #include "gbmint.h"
 
+/* For importing wl_buffer */
+#if HAVE_WAYLAND_PLATFORM
+#include "../../../egl/wayland/wayland-drm/wayland-drm.h"
+#endif
+
 static __DRIimage *
 dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
 {
@@ -294,13 +299,21 @@ gbm_dri_is_format_supported(struct gbm_device *gbm,
 static int
 gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count)
 {
-   struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
    struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
+   void *ptr;
+   int ret;
 
-   if (dri->image->base.version < 4)
+   if (bo->bo == NULL)
+      return -1;
+
+   ret = kms_bo_map(bo->bo, &ptr);
+   if (ret < 0)
       return -1;
 
-   return dri->image->write(bo->image, buf, count);
+   memcpy(ptr, buf, count);
+
+   kms_bo_unmap(bo->bo);
+   return 0;
 }
 
 static void
@@ -309,7 +322,10 @@ gbm_dri_bo_destroy(struct gbm_bo *_bo)
    struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm);
    struct gbm_dri_bo *bo = gbm_dri_bo(_bo);
 
-   dri->image->destroyImage(bo->image);
+   if (bo->image != NULL)
+      dri->image->destroyImage(bo->image);
+   if (bo->bo != NULL)
+      kms_bo_destroy(&bo->bo);
    free(bo);
 }
 
@@ -340,36 +356,80 @@ gbm_dri_to_gbm_format(uint32_t dri_format)
 }
 
 static struct gbm_bo *
-gbm_dri_bo_create_from_egl_image(struct gbm_device *gbm,
-                                 void *egl_dpy, void *egl_img,
-                                 uint32_t width, uint32_t height,
-                                 uint32_t usage)
+gbm_dri_bo_import(struct gbm_device *gbm,
+                  uint32_t type, void *buffer, uint32_t usage)
 {
    struct gbm_dri_device *dri = gbm_dri_device(gbm);
    struct gbm_dri_bo *bo;
-   int dri_format;
+   __DRIimage *image;
    unsigned dri_use = 0;
+   int dri_format, width, height, gbm_format, stride, cpp, offset;
 
-   (void) egl_dpy;
+   /* Required for query image WIDTH & HEIGHT */
+   if (dri->image->base.version < 4)
+      return NULL;
 
-   if (dri->lookup_image == NULL)
+   switch (type) {
+#if HAVE_WAYLAND_PLATFORM
+   case GBM_BO_IMPORT_WL_BUFFER:
+   {
+      struct wl_drm_buffer *wb = (struct wl_drm_buffer *) buffer;
+
+      image = wb->driver_buffer;
+      stride = wb->stride[0];
+      offset = wb->offset[0];
+      cpp = 4;
+      switch (wb->format) {
+      case WL_DRM_FORMAT_XRGB8888:
+         dri_format = __DRI_IMAGE_FORMAT_XRGB8888;
+         gbm_format = GBM_FORMAT_XRGB8888;
+         break;
+      case WL_DRM_FORMAT_ARGB8888:
+         dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
+         gbm_format = GBM_FORMAT_ARGB8888;
+         break;
+      case WL_DRM_FORMAT_YUYV:
+         dri_format = __DRI_IMAGE_FORMAT_ARGB8888;
+         gbm_format = GBM_FORMAT_YUYV;
+         break;
+      default:
+         return NULL;
+      }
+      break;
+   }
+#endif
+
+   case GBM_BO_IMPORT_EGL_IMAGE:
+   {
+      if (dri->lookup_image == NULL)
+         return NULL;
+
+      image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data);
+      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format);
+      gbm_format = gbm_dri_to_gbm_format(dri_format);
+      dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
+      offset = 0;
+      cpp = 4;
+      break;
+   }
+
+   default:
       return NULL;
+   }
+
 
    bo = calloc(1, sizeof *bo);
    if (bo == NULL)
       return NULL;
 
-   bo->base.base.gbm = gbm;
-   bo->base.base.width = width;
-   bo->base.base.height = height;
+   dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
+   dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
+
+   bo->image = dri->image->createSubImage(image,
+                                          width, height, dri_format,
+                                          offset, stride / cpp, NULL);
 
-   __DRIimage *tmp = dri->lookup_image(dri->screen, egl_img,
-                                       dri->lookup_user_data);
 
-   bo->image = dri->image->dupImage(tmp, bo);
-   if (bo->image == NULL)
-      return NULL;
-   
    if (usage & GBM_BO_USE_SCANOUT)
       dri_use |= __DRI_IMAGE_USE_SCANOUT;
    if (usage & GBM_BO_USE_CURSOR_64X64)
@@ -380,14 +440,13 @@ gbm_dri_bo_create_from_egl_image(struct gbm_device *gbm,
       return NULL;
    }
 
+   bo->base.base.gbm = gbm;
+   bo->base.base.width = width;
+   bo->base.base.height = height;
+   bo->base.base.stride = stride;
+   bo->base.base.format = gbm_format;
    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
                           &bo->base.base.handle.s32);
-   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
-                          (int *) &bo->base.base.pitch);
-   dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FORMAT,
-                         &dri_format);
-
-   bo->base.base.format = gbm_dri_to_gbm_format(dri_format);
 
    return &bo->base.base;
 }
@@ -402,9 +461,6 @@ gbm_dri_bo_create(struct gbm_device *gbm,
    int dri_format;
    unsigned dri_use = 0;
 
-   if (dri->image->base.version < 4 && (usage & GBM_BO_USE_WRITE))
-      return NULL;
-
    bo = calloc(1, sizeof *bo);
    if (bo == NULL)
       return NULL;
@@ -413,6 +469,33 @@ gbm_dri_bo_create(struct gbm_device *gbm,
    bo->base.base.width = width;
    bo->base.base.height = height;
 
+   if (usage & GBM_BO_USE_WRITE) {
+      int ret;
+      unsigned attrs[7] = {
+         KMS_WIDTH, 64,
+         KMS_HEIGHT, 64,
+         KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
+         KMS_TERMINATE_PROP_LIST,
+      };
+
+      if (!(usage & GBM_BO_USE_CURSOR_64X64))
+         return NULL;
+
+      if (dri->kms == NULL)
+         return NULL;
+
+      ret = kms_bo_create(dri->kms, attrs, &bo->bo);
+      if (ret < 0) {
+         free(bo);
+         return NULL;
+      }
+
+      kms_bo_get_prop(bo->bo, KMS_PITCH, &bo->base.base.stride);
+      kms_bo_get_prop(bo->bo, KMS_HANDLE, (unsigned*)&bo->base.base.handle);
+
+      return &bo->base.base;
+   }
+
    switch (format) {
    case GBM_FORMAT_RGB565:
       dri_format =__DRI_IMAGE_FORMAT_RGB565;
@@ -436,8 +519,9 @@ gbm_dri_bo_create(struct gbm_device *gbm,
       dri_use |= __DRI_IMAGE_USE_SCANOUT;
    if (usage & GBM_BO_USE_CURSOR_64X64)
       dri_use |= __DRI_IMAGE_USE_CURSOR;
-   if (usage & GBM_BO_USE_WRITE)
-      dri_use |= __DRI_IMAGE_USE_WRITE;
+
+   /* Gallium drivers requires shared in order to get the handle/stride */
+   dri_use |= __DRI_IMAGE_USE_SHARE;
 
    bo->image =
       dri->image->createImage(dri->screen,
@@ -450,7 +534,7 @@ gbm_dri_bo_create(struct gbm_device *gbm,
    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE,
                           &bo->base.base.handle.s32);
    dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE,
-                          (int *) &bo->base.base.pitch);
+                          (int *) &bo->base.base.stride);
 
    return &bo->base.base;
 }
@@ -506,7 +590,7 @@ dri_device_create(int fd)
 
    dri->base.base.fd = fd;
    dri->base.base.bo_create = gbm_dri_bo_create;
-   dri->base.base.bo_create_from_egl_image = gbm_dri_bo_create_from_egl_image;
+   dri->base.base.bo_import = gbm_dri_bo_import;
    dri->base.base.is_format_supported = gbm_dri_is_format_supported;
    dri->base.base.bo_write = gbm_dri_bo_write;
    dri->base.base.bo_destroy = gbm_dri_bo_destroy;
@@ -517,13 +601,21 @@ dri_device_create(int fd)
    dri->base.type = GBM_DRM_DRIVER_TYPE_DRI;
    dri->base.base.name = "drm";
 
+   kms_create(fd, &dri->kms);
+   if (dri->kms == NULL)
+      goto err_kms;
+
    ret = dri_screen_create(dri);
-   if (ret) {
-      free(dri);
-      return NULL;
-   }
+   if (ret)
+      goto err_dri;
 
    return &dri->base.base;
+
+err_dri:
+   kms_destroy(&dri->kms);
+err_kms:
+   free(dri);
+   return NULL;
 }
 
 struct gbm_backend gbm_dri_backend = {