VIGS: Add DRM_IOCTL_SURFACE_CONVERT 59/146259/1
authorVladislav Andresov <v.andresov@partner.samsung.com>
Wed, 16 Aug 2017 11:55:24 +0000 (14:55 +0300)
committerVasiliy Ulyanov <v.ulyanov@samsung.com>
Fri, 25 Aug 2017 11:23:55 +0000 (14:23 +0300)
This ioctl adds support of hardware surface convertion. Only y-invert
operation has been implemented so far.

Change-Id: Icf06dc84fd995eaa43c7990778d67e558c2c0274
Signed-off-by: Vladislav Andresov <v.andresov@partner.samsung.com>
Signed-off-by: Vasiliy Ulyanov <v.ulyanov@samsung.com>
drivers/gpu/drm/vigs/vigs_driver.c
drivers/gpu/drm/vigs/vigs_execbuffer.c
drivers/gpu/drm/vigs/vigs_protocol.h
drivers/gpu/drm/vigs/vigs_surface.c
drivers/gpu/drm/vigs/vigs_surface.h
include/drm/vigs_drm.h

index 24a8fc6..f0211cc 100644 (file)
@@ -60,6 +60,8 @@ static struct drm_ioctl_desc vigs_drm_ioctls[] =
                       DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
     DRM_IOCTL_DEF_DRV(VIGS_SURFACE_END_ACCESS, vigs_surface_end_access_ioctl,
                       DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_CONVERT, vigs_surface_convert_ioctl,
+                      DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
     DRM_IOCTL_DEF_DRV(VIGS_CREATE_FENCE, vigs_fence_create_ioctl,
                       DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
     DRM_IOCTL_DEF_DRV(VIGS_FENCE_WAIT, vigs_fence_wait_ioctl,
index e619950..d9c4c07 100644 (file)
@@ -14,6 +14,7 @@ union vigs_request
     struct vigsp_cmd_copy_request *copy;
     struct vigsp_cmd_solid_fill_request *solid_fill;
     struct vigsp_cmd_ga_copy_request *ga_copy;
+    struct vigsp_cmd_convert_request *convert;
     void *data;
 };
 
@@ -152,6 +153,9 @@ int vigs_execbuffer_validate_buffers(struct vigs_execbuffer *execbuffer,
         case vigsp_cmd_ga_copy:
             *num_buffers += 2;
             break;
+        case vigsp_cmd_convert:
+            *num_buffers += 2;
+            break;
         default:
             break;
         }
@@ -288,6 +292,36 @@ int vigs_execbuffer_validate_buffers(struct vigs_execbuffer *execbuffer,
             ++*num_buffers;
 
             break;
+        case vigsp_cmd_convert:
+            ret = vigs_execbuffer_validate_buffer(vigs_dev,
+                                                  &(*buffers)[*num_buffers],
+                                                  list,
+                                                  request.convert->src_id,
+                                                  request_header->cmd,
+                                                  0,
+                                                  request.data);
+
+            if (ret != 0) {
+                goto fail2;
+            }
+
+            ++*num_buffers;
+
+            ret = vigs_execbuffer_validate_buffer(vigs_dev,
+                                                  &(*buffers)[*num_buffers],
+                                                  list,
+                                                  request.convert->dst_id,
+                                                  request_header->cmd,
+                                                  1,
+                                                  request.data);
+
+            if (ret != 0) {
+                goto fail2;
+            }
+
+            ++*num_buffers;
+
+            break;
         default:
             break;
         }
@@ -385,6 +419,11 @@ void vigs_execbuffer_process_buffers(struct vigs_execbuffer *execbuffer,
                 }
             }
             break;
+        case vigsp_cmd_convert:
+            if (buffers[i].which && vigs_gem_in_vram(&sfc->gem)) {
+                sfc->is_gpu_dirty = true;
+            }
+            break;
         default:
             break;
         }
index 1115c9a..c69d4c0 100644 (file)
@@ -52,7 +52,8 @@ typedef enum
     vigsp_cmd_copy = 0x8,
     vigsp_cmd_solid_fill = 0x9,
     vigsp_cmd_set_plane = 0xA,
-    vigsp_cmd_ga_copy = 0xB
+    vigsp_cmd_ga_copy = 0xB,
+    vigsp_cmd_convert = 0xC
     /*
      * @}
      */
@@ -375,6 +376,28 @@ struct vigsp_cmd_ga_copy_request
  * @}
  */
 
+/*
+ * cmd_convert
+ *
+ * Convert surface 'src_id' to
+ * surface 'dst_id'.
+ *
+ * @{
+ */
+
+struct vigsp_cmd_convert_request
+{
+    vigsp_surface_id src_id;
+    vigsp_u32 src_format;
+    vigsp_surface_id dst_id;
+    vigsp_u32 dst_format;
+    vigsp_bool y_invert;
+};
+
+/*
+ * @}
+ */
+
 #pragma pack()
 
 #endif
index b5ec2f4..4eb91d8 100644 (file)
@@ -2,6 +2,8 @@
 #include "vigs_device.h"
 #include "vigs_comm.h"
 #include "vigs_mman.h"
+#include "vigs_execbuffer.h"
+#include "vigs_file.h"
 #include <drm/vigs_drm.h>
 
 /*
@@ -470,3 +472,141 @@ int vigs_surface_end_access_ioctl(struct drm_device *drm_dev,
                                 &vigs_surface_end_access,
                                 args);
 }
+
+int vigs_surface_convert_ioctl(struct drm_device *drm_dev,
+                               void *data,
+                               struct drm_file *file_priv)
+{
+    struct vigs_device *vigs_dev = drm_dev->dev_private;
+    struct vigs_file *vigs_file = file_priv->driver_priv;
+    struct drm_vigs_surface_convert *args = data;
+    struct drm_gem_object *gem;
+    struct vigs_gem_object *vigs_gem;
+    struct vigs_surface *src_sfc = NULL, *dst_sfc = NULL;
+    struct vigsp_cmd_batch_header *batch_header;
+    struct vigsp_cmd_request_header *convert_request_header;
+    struct vigsp_cmd_convert_request *convert_request;
+    int ret;
+
+    /*
+     * Currently we support only y-invert operation. Format conversion still
+     * needs to be implemented.
+     */
+    if (args->src_format != args->dst_format) {
+        ret = -EINVAL;
+        goto out;
+    }
+
+    /* src_sfc */
+    gem = drm_gem_object_lookup(drm_dev, file_priv, args->src_handle);
+
+    if (gem == NULL) {
+        ret = -ENOENT;
+        goto out;
+    }
+
+    vigs_gem = gem_to_vigs_gem(gem);
+
+    if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+        drm_gem_object_unreference_unlocked(gem);
+        ret = -ENOENT;
+        goto out;
+    }
+
+    src_sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    /* dst_sfc */
+    gem = drm_gem_object_lookup(drm_dev, file_priv, args->dst_handle);
+
+    if (gem == NULL) {
+        ret = -ENOENT;
+        goto out;
+    }
+
+    vigs_gem = gem_to_vigs_gem(gem);
+
+    if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+        drm_gem_object_unreference_unlocked(gem);
+        ret = -ENOENT;
+        goto out;
+    }
+
+    dst_sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    vigs_gem_reserve(&src_sfc->gem);
+
+    if (vigs_gem_in_vram(&src_sfc->gem) &&
+        vigs_surface_need_gpu_update(src_sfc)) {
+        vigs_comm_update_gpu(vigs_dev->comm,
+                             src_sfc->id,
+                             src_sfc->width,
+                             src_sfc->height,
+                             vigs_gem_offset(&src_sfc->gem));
+        src_sfc->is_gpu_dirty = false;
+    }
+
+    vigs_gem_unreserve(&src_sfc->gem);
+
+    mutex_lock(&vigs_file->mutex);
+
+    if (vigs_file->execbuffer == NULL) {
+        ret = vigs_execbuffer_create(vigs_dev,
+                                     4096,
+                                     true,
+                                     &vigs_file->execbuffer);
+
+        if (ret != 0) {
+            DRM_ERROR("unable to create execbuffer\n");
+
+            goto out_unlock;
+        }
+
+        vigs_gem_reserve(&vigs_file->execbuffer->gem);
+
+        ret = vigs_gem_kmap(&vigs_file->execbuffer->gem);
+
+        vigs_gem_unreserve(&vigs_file->execbuffer->gem);
+
+        if (ret != 0) {
+            DRM_ERROR("unable to kmap execbuffer\n");
+
+            drm_gem_object_unreference_unlocked(&vigs_file->execbuffer->gem.base);
+            vigs_file->execbuffer = NULL;
+
+            goto out_unlock;
+        }
+    }
+
+    batch_header = vigs_file->execbuffer->gem.kptr;
+    convert_request_header = (struct vigsp_cmd_request_header *)(batch_header + 1);
+    convert_request = (struct vigsp_cmd_convert_request *)(convert_request_header + 1);
+
+    batch_header->fence_seq = 0;
+    batch_header->size = sizeof(*convert_request_header) +
+                         sizeof(*convert_request);
+
+    convert_request_header->cmd = vigsp_cmd_convert;
+    convert_request_header->size = sizeof(*convert_request);
+
+    convert_request->src_id = src_sfc->id;
+    convert_request->src_format = args->src_format;
+    convert_request->dst_id = dst_sfc->id;
+    convert_request->dst_format = args->dst_format;
+    convert_request->y_invert = args->y_invert;
+
+    ret = vigs_comm_exec_checked(vigs_dev->comm, vigs_file->execbuffer);
+
+out_unlock:
+    mutex_unlock(&vigs_file->mutex);
+
+out:
+    if (src_sfc) {
+        drm_gem_object_unreference_unlocked(&src_sfc->gem.base);
+    }
+
+    if (dst_sfc) {
+        drm_gem_object_unreference_unlocked(&dst_sfc->gem.base);
+    }
+
+    return ret;
+}
index 1d89e3b..bd1707c 100644 (file)
@@ -121,6 +121,10 @@ int vigs_surface_end_access_ioctl(struct drm_device *drm_dev,
                                   void *data,
                                   struct drm_file *file_priv);
 
+int vigs_surface_convert_ioctl(struct drm_device *drm_dev,
+                               void *data,
+                               struct drm_file *file_priv);
+
 /*
  * @}
  */
index 9ae8245..f418fef 100644 (file)
@@ -97,6 +97,15 @@ struct drm_vigs_surface_end_access
     int sync;
 };
 
+struct drm_vigs_surface_convert
+{
+    uint32_t src_handle;
+    uint32_t src_format;
+    uint32_t dst_handle;
+    uint32_t dst_format;
+    int y_invert;
+};
+
 struct drm_vigs_create_fence
 {
     int send;
@@ -176,6 +185,8 @@ struct drm_vigs_dp_open_surface
 #define DRM_VIGS_DP_CREATE_SURFACE 0x20
 #define DRM_VIGS_DP_OPEN_SURFACE 0x21
 
+#define DRM_VIGS_SURFACE_CONVERT 0x22
+
 #define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \
             DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version)
 #define DRM_IOCTL_VIGS_CREATE_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
@@ -196,6 +207,8 @@ struct drm_vigs_dp_open_surface
             DRM_VIGS_SURFACE_START_ACCESS, struct drm_vigs_surface_start_access)
 #define DRM_IOCTL_VIGS_SURFACE_END_ACCESS DRM_IOW(DRM_COMMAND_BASE + \
             DRM_VIGS_SURFACE_END_ACCESS, struct drm_vigs_surface_end_access)
+#define DRM_IOCTL_VIGS_SURFACE_CONVERT DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_CONVERT, struct drm_vigs_surface_convert)
 #define DRM_IOCTL_VIGS_CREATE_FENCE DRM_IOWR(DRM_COMMAND_BASE + \
             DRM_VIGS_CREATE_FENCE, struct drm_vigs_create_fence)
 #define DRM_IOCTL_VIGS_FENCE_WAIT DRM_IOW(DRM_COMMAND_BASE + \