VIGS: kernel now is surface dirty aware
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 6 Jun 2013 16:48:36 +0000 (20:48 +0400)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 9 Apr 2014 05:42:22 +0000 (14:42 +0900)
kernel now knows about dirty state of each surface

Change-Id: I7f801fa84f57ee9811fbd79bcb408507439acd62

drivers/gpu/drm/vigs/vigs_device.c
drivers/gpu/drm/vigs/vigs_driver.c
drivers/gpu/drm/vigs/vigs_surface.c
drivers/gpu/drm/vigs/vigs_surface.h
include/drm/vigs_drm.h

index f07f4bd..4489ccc 100644 (file)
@@ -41,12 +41,12 @@ static void vigs_device_mman_vram_to_gpu(void *user_data,
     struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
     struct vigs_surface *vigs_sfc = vigs_gem_to_vigs_surface(vigs_gem);
 
-    if (vigs_sfc->is_dirty) {
+    if (vigs_sfc->dirty_flag == vigs_dirty_vram) {
         vigs_comm_update_gpu(vigs_dev->comm,
                              vigs_sfc->id,
                              vigs_gem_offset(vigs_gem));
-        vigs_sfc->is_dirty = false;
     }
+    vigs_sfc->dirty_flag = vigs_dirty_none;
 }
 
 static void vigs_device_mman_gpu_to_vram(void *user_data,
@@ -94,8 +94,7 @@ static bool vigs_gem_is_reserved(struct list_head* gem_list,
 {
     struct vigs_gem_object *tmp;
 
-    list_for_each_entry(tmp, gem_list, list)
-    {
+    list_for_each_entry(tmp, gem_list, list) {
         if (tmp == gem) {
             return true;
         }
@@ -116,8 +115,13 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
     struct vigsp_cmd_batch_header *batch_header = data;
     struct vigsp_cmd_request_header *request_header =
         (struct vigsp_cmd_request_header*)(batch_header + 1);
-    struct vigsp_cmd_update_vram_request *update_vram_request;
-    struct vigsp_cmd_update_gpu_request *update_gpu_request;
+    union
+    {
+        struct vigsp_cmd_update_vram_request *update_vram;
+        struct vigsp_cmd_update_gpu_request *update_gpu;
+        struct vigsp_cmd_copy_request *copy;
+        struct vigsp_cmd_solid_fill_request *solid_fill;
+    } request;
     vigsp_u32 i;
     struct vigs_surface *sfc;
     int ret = 0;
@@ -144,11 +148,11 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
 
         switch (request_header->cmd) {
         case vigsp_cmd_update_vram:
-            update_vram_request =
+            request.update_vram =
                 (struct vigsp_cmd_update_vram_request*)(request_header + 1);
-            sfc = vigs_device_reference_surface_unlocked(vigs_dev, update_vram_request->sfc_id);
+            sfc = vigs_device_reference_surface_unlocked(vigs_dev, request.update_vram->sfc_id);
             if (!sfc) {
-                DRM_ERROR("Surface %u not found\n", update_vram_request->sfc_id);
+                DRM_ERROR("Surface %u not found\n", request.update_vram->sfc_id);
                 ret = -EINVAL;
                 break;
             }
@@ -159,19 +163,20 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                 list_add_tail(&sfc->gem.list, gem_list);
             }
             if (vigs_gem_in_vram(&sfc->gem)) {
-                update_vram_request->offset = vigs_gem_offset(&sfc->gem);
+                request.update_vram->offset = vigs_gem_offset(&sfc->gem);
+                sfc->dirty_flag = vigs_dirty_none;
             } else {
                 DRM_DEBUG_DRIVER("Surface %u not in VRAM, ignoring update_vram\n",
-                                 update_vram_request->sfc_id);
-                update_vram_request->sfc_id = 0;
+                                 request.update_vram->sfc_id);
+                request.update_vram->sfc_id = 0;
             }
             break;
         case vigsp_cmd_update_gpu:
-            update_gpu_request =
+            request.update_gpu =
                 (struct vigsp_cmd_update_gpu_request*)(request_header + 1);
-            sfc = vigs_device_reference_surface_unlocked(vigs_dev, update_gpu_request->sfc_id);
+            sfc = vigs_device_reference_surface_unlocked(vigs_dev, request.update_gpu->sfc_id);
             if (!sfc) {
-                DRM_ERROR("Surface %u not found\n", update_gpu_request->sfc_id);
+                DRM_ERROR("Surface %u not found\n", request.update_gpu->sfc_id);
                 ret = -EINVAL;
                 break;
             }
@@ -182,12 +187,50 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                 list_add_tail(&sfc->gem.list, gem_list);
             }
             if (vigs_gem_in_vram(&sfc->gem)) {
-                update_gpu_request->offset = vigs_gem_offset(&sfc->gem);
-                sfc->is_dirty = false;
+                request.update_gpu->offset = vigs_gem_offset(&sfc->gem);
+                sfc->dirty_flag = vigs_dirty_none;
             } else {
                 DRM_DEBUG_DRIVER("Surface %u not in VRAM, ignoring update_gpu\n",
-                                 update_gpu_request->sfc_id);
-                update_gpu_request->sfc_id = 0;
+                                 request.update_gpu->sfc_id);
+                request.update_gpu->sfc_id = 0;
+            }
+            break;
+        case vigsp_cmd_copy:
+            request.copy =
+                (struct vigsp_cmd_copy_request*)(request_header + 1);
+            sfc = vigs_device_reference_surface_unlocked(vigs_dev, request.copy->dst_id);
+            if (!sfc) {
+                DRM_ERROR("Surface %u not found\n", request.copy->dst_id);
+                ret = -EINVAL;
+                break;
+            }
+            if (vigs_gem_is_reserved(gem_list, &sfc->gem)) {
+                drm_gem_object_unreference_unlocked(&sfc->gem.base);
+            } else {
+                vigs_gem_reserve(&sfc->gem);
+                list_add_tail(&sfc->gem.list, gem_list);
+            }
+            if (vigs_gem_in_vram(&sfc->gem)) {
+                sfc->dirty_flag = vigs_dirty_gpu;
+            }
+            break;
+        case vigsp_cmd_solid_fill:
+            request.solid_fill =
+                (struct vigsp_cmd_solid_fill_request*)(request_header + 1);
+            sfc = vigs_device_reference_surface_unlocked(vigs_dev, request.solid_fill->sfc_id);
+            if (!sfc) {
+                DRM_ERROR("Surface %u not found\n", request.solid_fill->sfc_id);
+                ret = -EINVAL;
+                break;
+            }
+            if (vigs_gem_is_reserved(gem_list, &sfc->gem)) {
+                drm_gem_object_unreference_unlocked(&sfc->gem.base);
+            } else {
+                vigs_gem_reserve(&sfc->gem);
+                list_add_tail(&sfc->gem.list, gem_list);
+            }
+            if (vigs_gem_in_vram(&sfc->gem)) {
+                sfc->dirty_flag = vigs_dirty_gpu;
             }
             break;
         default:
@@ -206,8 +249,7 @@ static void vigs_device_finish_patch_commands(struct list_head* gem_list)
 {
     struct vigs_gem_object *gem, *gem_tmp;
 
-    list_for_each_entry_safe(gem, gem_tmp, gem_list, list)
-    {
+    list_for_each_entry_safe(gem, gem_tmp, gem_list, list) {
         list_del(&gem->list);
         vigs_gem_unreserve(gem);
         drm_gem_object_unreference_unlocked(&gem->base);
index 7caa837..c36abaf 100644 (file)
@@ -43,8 +43,14 @@ static struct drm_ioctl_desc vigs_drm_ioctls[] =
                                          DRM_UNLOCKED | DRM_AUTH),
     DRM_IOCTL_DEF_DRV(VIGS_EXEC, vigs_device_exec_ioctl,
                                  DRM_UNLOCKED | DRM_AUTH),
-    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_SET_DIRTY, vigs_surface_set_dirty_ioctl,
-                                              DRM_UNLOCKED | DRM_AUTH),
+    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_SET_VRAM_DIRTY, vigs_surface_set_vram_dirty_ioctl,
+                                                   DRM_UNLOCKED | DRM_AUTH),
+    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_SET_GPU_DIRTY, vigs_surface_set_gpu_dirty_ioctl,
+                                                  DRM_UNLOCKED | DRM_AUTH),
+    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_UPDATE_VRAM, vigs_surface_update_vram_ioctl,
+                                                DRM_UNLOCKED | DRM_AUTH),
+    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_UPDATE_GPU, vigs_surface_update_gpu_ioctl,
+                                               DRM_UNLOCKED | DRM_AUTH)
 };
 
 static const struct file_operations vigs_drm_driver_fops =
index b03e3b7..b3634bb 100644 (file)
@@ -35,6 +35,7 @@ int vigs_surface_create(struct vigs_device *vigs_dev,
     (*sfc)->height = height;
     (*sfc)->stride = stride;
     (*sfc)->format = format;
+    (*sfc)->dirty_flag = vigs_dirty_none;
 
     ret = vigs_gem_init(&(*sfc)->gem,
                         vigs_dev,
@@ -150,11 +151,11 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
     return 0;
 }
 
-int vigs_surface_set_dirty_ioctl(struct drm_device *drm_dev,
-                                 void *data,
-                                 struct drm_file *file_priv)
+int vigs_surface_set_vram_dirty_ioctl(struct drm_device *drm_dev,
+                                      void *data,
+                                      struct drm_file *file_priv)
 {
-    struct drm_vigs_surface_set_dirty *args = data;
+    struct drm_vigs_surface_set_vram_dirty *args = data;
     struct drm_gem_object *gem;
     struct vigs_gem_object *vigs_gem;
     struct vigs_surface *sfc;
@@ -177,7 +178,126 @@ int vigs_surface_set_dirty_ioctl(struct drm_device *drm_dev,
     vigs_gem_reserve(&sfc->gem);
 
     if (vigs_gem_in_vram(&sfc->gem)) {
-        sfc->is_dirty = true;
+        sfc->dirty_flag = vigs_dirty_vram;
+    }
+
+    vigs_gem_unreserve(&sfc->gem);
+
+    drm_gem_object_unreference_unlocked(gem);
+
+    return 0;
+}
+
+int vigs_surface_set_gpu_dirty_ioctl(struct drm_device *drm_dev,
+                                     void *data,
+                                     struct drm_file *file_priv)
+{
+    struct drm_vigs_surface_set_gpu_dirty *args = data;
+    struct drm_gem_object *gem;
+    struct vigs_gem_object *vigs_gem;
+    struct vigs_surface *sfc;
+
+    gem = drm_gem_object_lookup(drm_dev, file_priv, args->handle);
+
+    if (gem == NULL) {
+        return -ENOENT;
+    }
+
+    vigs_gem = gem_to_vigs_gem(gem);
+
+    if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+        drm_gem_object_unreference_unlocked(gem);
+        return -ENOENT;
+    }
+
+    sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    vigs_gem_reserve(&sfc->gem);
+
+    if (vigs_gem_in_vram(&sfc->gem)) {
+        sfc->dirty_flag = vigs_dirty_gpu;
+    }
+
+    vigs_gem_unreserve(&sfc->gem);
+
+    drm_gem_object_unreference_unlocked(gem);
+
+    return 0;
+}
+
+int vigs_surface_update_vram_ioctl(struct drm_device *drm_dev,
+                                   void *data,
+                                   struct drm_file *file_priv)
+{
+    struct vigs_device *vigs_dev = drm_dev->dev_private;
+    struct drm_vigs_surface_update_vram *args = data;
+    struct drm_gem_object *gem;
+    struct vigs_gem_object *vigs_gem;
+    struct vigs_surface *sfc;
+
+    gem = drm_gem_object_lookup(drm_dev, file_priv, args->handle);
+
+    if (gem == NULL) {
+        return -ENOENT;
+    }
+
+    vigs_gem = gem_to_vigs_gem(gem);
+
+    if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+        drm_gem_object_unreference_unlocked(gem);
+        return -ENOENT;
+    }
+
+    sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    vigs_gem_reserve(&sfc->gem);
+
+    if (vigs_gem_in_vram(&sfc->gem) && (sfc->dirty_flag == vigs_dirty_gpu)) {
+        vigs_comm_update_vram(vigs_dev->comm,
+                              sfc->id,
+                              vigs_gem_offset(vigs_gem));
+        sfc->dirty_flag = vigs_dirty_none;
+    }
+
+    vigs_gem_unreserve(&sfc->gem);
+
+    drm_gem_object_unreference_unlocked(gem);
+
+    return 0;
+}
+
+int vigs_surface_update_gpu_ioctl(struct drm_device *drm_dev,
+                                  void *data,
+                                  struct drm_file *file_priv)
+{
+    struct vigs_device *vigs_dev = drm_dev->dev_private;
+    struct drm_vigs_surface_update_gpu *args = data;
+    struct drm_gem_object *gem;
+    struct vigs_gem_object *vigs_gem;
+    struct vigs_surface *sfc;
+
+    gem = drm_gem_object_lookup(drm_dev, file_priv, args->handle);
+
+    if (gem == NULL) {
+        return -ENOENT;
+    }
+
+    vigs_gem = gem_to_vigs_gem(gem);
+
+    if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+        drm_gem_object_unreference_unlocked(gem);
+        return -ENOENT;
+    }
+
+    sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    vigs_gem_reserve(&sfc->gem);
+
+    if (vigs_gem_in_vram(&sfc->gem)) {
+        vigs_comm_update_gpu(vigs_dev->comm,
+                             sfc->id,
+                             vigs_gem_offset(vigs_gem));
+        sfc->dirty_flag = vigs_dirty_none;
     }
 
     vigs_gem_unreserve(&sfc->gem);
index 6a81fdc..25ad8da 100644 (file)
@@ -5,6 +5,13 @@
 #include "vigs_protocol.h"
 #include "vigs_gem.h"
 
+typedef enum
+{
+    vigs_dirty_none = 0,
+    vigs_dirty_vram = 1,
+    vigs_dirty_gpu = 2
+} vigs_dirty_flag;
+
 struct vigs_surface
 {
     /*
@@ -24,7 +31,7 @@ struct vigs_surface
      * @{
      */
 
-    bool is_dirty;
+    vigs_dirty_flag dirty_flag;
 
     /*
      * @}
@@ -56,9 +63,21 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
                             void *data,
                             struct drm_file *file_priv);
 
-int vigs_surface_set_dirty_ioctl(struct drm_device *drm_dev,
-                                 void *data,
-                                 struct drm_file *file_priv);
+int vigs_surface_set_vram_dirty_ioctl(struct drm_device *drm_dev,
+                                      void *data,
+                                      struct drm_file *file_priv);
+
+int vigs_surface_set_gpu_dirty_ioctl(struct drm_device *drm_dev,
+                                     void *data,
+                                     struct drm_file *file_priv);
+
+int vigs_surface_update_vram_ioctl(struct drm_device *drm_dev,
+                                   void *data,
+                                   struct drm_file *file_priv);
+
+int vigs_surface_update_gpu_ioctl(struct drm_device *drm_dev,
+                                  void *data,
+                                  struct drm_file *file_priv);
 
 /*
  * @}
index 10427f3..8783841 100644 (file)
@@ -8,7 +8,7 @@
 /*
  * Bump this whenever driver interface changes.
  */
-#define DRM_VIGS_DRIVER_VERSION 5
+#define DRM_VIGS_DRIVER_VERSION 6
 
 struct drm_vigs_get_protocol_version
 {
@@ -51,7 +51,22 @@ struct drm_vigs_exec
     uint32_t handle;
 };
 
-struct drm_vigs_surface_set_dirty
+struct drm_vigs_surface_set_vram_dirty
+{
+    uint32_t handle;
+};
+
+struct drm_vigs_surface_set_gpu_dirty
+{
+    uint32_t handle;
+};
+
+struct drm_vigs_surface_update_vram
+{
+    uint32_t handle;
+};
+
+struct drm_vigs_surface_update_gpu
 {
     uint32_t handle;
 };
@@ -61,7 +76,10 @@ struct drm_vigs_surface_set_dirty
 #define DRM_VIGS_CREATE_EXECBUFFER 0x02
 #define DRM_VIGS_SURFACE_INFO 0x03
 #define DRM_VIGS_EXEC 0x04
-#define DRM_VIGS_SURFACE_SET_DIRTY 0x05
+#define DRM_VIGS_SURFACE_SET_VRAM_DIRTY 0x05
+#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x06
+#define DRM_VIGS_SURFACE_UPDATE_VRAM 0x07
+#define DRM_VIGS_SURFACE_UPDATE_GPU 0x08
 
 #define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \
             DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version)
@@ -73,7 +91,13 @@ struct drm_vigs_surface_set_dirty
             DRM_VIGS_SURFACE_INFO, struct drm_vigs_surface_info)
 #define DRM_IOCTL_VIGS_EXEC DRM_IOW(DRM_COMMAND_BASE + \
             DRM_VIGS_EXEC, struct drm_vigs_exec)
-#define DRM_IOCTL_VIGS_SURFACE_SET_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
-            DRM_VIGS_SURFACE_SET_DIRTY, struct drm_vigs_surface_set_dirty)
+#define DRM_IOCTL_VIGS_SURFACE_SET_VRAM_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_SET_VRAM_DIRTY, struct drm_vigs_surface_set_vram_dirty)
+#define DRM_IOCTL_VIGS_SURFACE_SET_GPU_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_SET_GPU_DIRTY, struct drm_vigs_surface_set_gpu_dirty)
+#define DRM_IOCTL_VIGS_SURFACE_UPDATE_VRAM DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_UPDATE_VRAM, struct drm_vigs_surface_update_vram)
+#define DRM_IOCTL_VIGS_SURFACE_UPDATE_GPU DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_UPDATE_GPU, struct drm_vigs_surface_update_gpu)
 
 #endif