VIGS: Automatically update VRAM when setting new root surface
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 27 Jun 2013 14:24:28 +0000 (18:24 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 27 Jun 2013 14:24:28 +0000 (18:24 +0400)
When we set new root surface (for example, as part of pageflip) we
should check if that surface is GPU dirty and if it is - update VRAM.
If we don't do this we might flip stuff without QEMU display
being updated

drivers/gpu/drm/vigs/vigs_comm.c
drivers/gpu/drm/vigs/vigs_comm.h
drivers/gpu/drm/vigs/vigs_crtc.c

index 967ac3d8f30f2b58cf4982d563c2085352bad6c6..cc5685b6dbd0b5bbaf7c2e4f7731b3eb4ca1def9 100644 (file)
@@ -4,31 +4,21 @@
 #include "vigs_regs.h"
 #include <drm/vigs_drm.h>
 
-static int vigs_comm_prepare(struct vigs_comm *comm,
-                             vigsp_cmd cmd,
-                             unsigned long request_size,
-                             unsigned long response_size,
-                             void **request,
-                             void **response)
+static int vigs_comm_alloc(struct vigs_comm *comm,
+                           unsigned long size,
+                           void **ptr)
 {
     int ret;
-    void *ptr;
-    struct vigsp_cmd_batch_header *batch_header;
-    struct vigsp_cmd_request_header *request_header;
-    unsigned long total_size = sizeof(*batch_header) +
-                               sizeof(*request_header) +
-                               request_size +
-                               sizeof(struct vigsp_cmd_response_header) +
-                               response_size;
 
-    if (!comm->execbuffer || (vigs_gem_size(&comm->execbuffer->gem) < total_size)) {
+    if (!comm->execbuffer ||
+        (vigs_gem_size(&comm->execbuffer->gem) < size)) {
         if (comm->execbuffer) {
             drm_gem_object_unreference_unlocked(&comm->execbuffer->gem.base);
             comm->execbuffer = NULL;
         }
 
         ret = vigs_execbuffer_create(comm->vigs_dev,
-                                     total_size,
+                                     size,
                                      true,
                                      &comm->execbuffer);
 
@@ -53,9 +43,36 @@ static int vigs_comm_prepare(struct vigs_comm *comm,
         }
     }
 
-    ptr = comm->execbuffer->gem.kptr;
+    *ptr = comm->execbuffer->gem.kptr;
+
+    memset(*ptr, 0, vigs_gem_size(&comm->execbuffer->gem));
+
+    return 0;
+}
+
+static int vigs_comm_prepare(struct vigs_comm *comm,
+                             vigsp_cmd cmd,
+                             unsigned long request_size,
+                             unsigned long response_size,
+                             void **request,
+                             void **response)
+{
+    int ret;
+    void *ptr;
+    struct vigsp_cmd_batch_header *batch_header;
+    struct vigsp_cmd_request_header *request_header;
 
-    memset(ptr, 0, vigs_gem_size(&comm->execbuffer->gem));
+    ret = vigs_comm_alloc(comm,
+                          sizeof(*batch_header) +
+                          sizeof(*request_header) +
+                          request_size +
+                          sizeof(struct vigsp_cmd_response_header) +
+                          response_size,
+                          &ptr);
+
+    if (ret != 0) {
+        return ret;
+    }
 
     batch_header = ptr;
     request_header = (struct vigsp_cmd_request_header*)(batch_header + 1);
@@ -89,9 +106,16 @@ static int vigs_comm_exec_internal(struct vigs_comm *comm)
     struct vigsp_cmd_batch_header *batch_header = comm->execbuffer->gem.kptr;
     struct vigsp_cmd_request_header *request_header =
         (struct vigsp_cmd_request_header*)(batch_header + 1);
-    struct vigsp_cmd_response_header *response_header =
-        (struct vigsp_cmd_response_header*)((u8*)(request_header + 1) +
-                                            request_header->size);
+    struct vigsp_cmd_response_header *response_header;
+    vigsp_u32 i;
+
+    for (i = 0; i < batch_header->num_requests; ++i) {
+        request_header =
+            (struct vigsp_cmd_request_header*)((uint8_t*)(request_header + 1) +
+                                               request_header->size);
+    }
+
+    response_header = (struct vigsp_cmd_response_header*)request_header;
 
     vigs_comm_exec_locked(comm, comm->execbuffer);
 
@@ -302,25 +326,63 @@ int vigs_comm_destroy_surface(struct vigs_comm *comm, vigsp_surface_id id)
 
 int vigs_comm_set_root_surface(struct vigs_comm *comm,
                                vigsp_surface_id id,
-                               vigsp_offset offset)
+                               vigsp_offset offset,
+                               bool update_vram)
 {
     int ret;
-    struct vigsp_cmd_set_root_surface_request *request;
+    struct vigsp_cmd_batch_header *batch_header;
+    struct vigsp_cmd_request_header *update_vram_header = NULL;
+    struct vigsp_cmd_update_vram_request *update_vram_request = NULL;
+    struct vigsp_cmd_request_header *set_root_surface_header;
+    struct vigsp_cmd_set_root_surface_request *set_root_surface_request;
+    void *ptr;
 
     DRM_DEBUG_DRIVER("id = %u, offset = %u\n", id, offset);
 
     mutex_lock(&comm->mutex);
 
-    ret = vigs_comm_prepare(comm,
-                            vigsp_cmd_set_root_surface,
-                            sizeof(*request),
-                            0,
-                            (void**)&request,
-                            NULL);
+    ret = vigs_comm_alloc(comm,
+                          sizeof(*batch_header) +
+                          (update_vram ? sizeof(*update_vram_header) +
+                                         sizeof(*update_vram_request)
+                                       : 0) +
+                          sizeof(*set_root_surface_header) +
+                          sizeof(*set_root_surface_request) +
+                          sizeof(struct vigsp_cmd_response_header),
+                          &ptr);
 
     if (ret == 0) {
-        request->id = id;
-        request->offset = offset;
+        batch_header = ptr;
+        ptr = batch_header + 1;
+
+        if (update_vram) {
+            update_vram_header = ptr;
+            ptr = update_vram_header + 1;
+            update_vram_request = ptr;
+            ptr = update_vram_request + 1;
+        }
+
+        set_root_surface_header = ptr;
+        ptr = set_root_surface_header + 1;
+        set_root_surface_request = ptr;
+
+        if (update_vram) {
+            batch_header->num_requests = 2;
+
+            update_vram_header->cmd = vigsp_cmd_update_vram;
+            update_vram_header->size = sizeof(*update_vram_request);
+
+            update_vram_request->sfc_id = id;
+            update_vram_request->offset = offset;
+        } else {
+            batch_header->num_requests = 1;
+        }
+
+        set_root_surface_header->cmd = vigsp_cmd_set_root_surface;
+        set_root_surface_header->size = sizeof(*set_root_surface_request);
+
+        set_root_surface_request->id = id;
+        set_root_surface_request->offset = offset;
 
         ret = vigs_comm_exec_internal(comm);
     }
index 5372696fb3e0f78fcb5b6d79885477216a1fa0e9..f88aac751e19b0111931dc79963ad981e5209206 100644 (file)
@@ -51,7 +51,8 @@ int vigs_comm_destroy_surface(struct vigs_comm *comm, vigsp_surface_id id);
 
 int vigs_comm_set_root_surface(struct vigs_comm *comm,
                                vigsp_surface_id id,
-                               vigsp_offset offset);
+                               vigsp_offset offset,
+                               bool update_vram);
 
 int vigs_comm_update_vram(struct vigs_comm *comm,
                           vigsp_surface_id id,
index 581f6870934d8deaa81aa7be4199e07dd25d6411..8c985d07132c2b054c166092028a06a5441d749b 100644 (file)
@@ -40,9 +40,14 @@ static int vigs_crtc_update(struct drm_crtc *crtc,
         return ret;
     }
 
+    vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+
     ret = vigs_comm_set_root_surface(vigs_dev->comm,
                                      vigs_fb->fb_sfc->id,
-                                     vigs_gem_offset(&vigs_fb->fb_sfc->gem));
+                                     vigs_gem_offset(&vigs_fb->fb_sfc->gem),
+                                     vigs_fb->fb_sfc->is_gpu_dirty);
+
+    vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
 
     if (ret != 0) {
         vigs_framebuffer_unpin(vigs_fb);
@@ -173,7 +178,7 @@ static void vigs_crtc_disable(struct drm_crtc *crtc)
         return;
     }
 
-    vigs_comm_set_root_surface(vigs_dev->comm, 0, 0);
+    vigs_comm_set_root_surface(vigs_dev->comm, 0, 0, false);
 
     vigs_framebuffer_unpin(fb_to_vigs_fb(crtc->fb));
 }