drisw: use shared memory when possible
authorMarc-André Lureau <marcandre.lureau@gmail.com>
Wed, 10 Jun 2015 15:45:11 +0000 (17:45 +0200)
committerDave Airlie <airlied@redhat.com>
Tue, 29 May 2018 23:11:54 +0000 (09:11 +1000)
If drisw_loader_funcs implements put_image_shm, allocates display
target data with shared memory and display with put_image_shm().

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
src/gallium/winsys/sw/dri/dri_sw_winsys.c

index 00849985d6b99d47875556d75585255eb44a5bca..b36a53e960cc99115724ef00374f8a9c80c7a459 100644 (file)
@@ -26,6 +26,9 @@
  *
  **************************************************************************/
 
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
 #include "pipe/p_compiler.h"
 #include "pipe/p_format.h"
 #include "util/u_inlines.h"
@@ -45,6 +48,7 @@ struct dri_sw_displaytarget
    unsigned stride;
 
    unsigned map_flags;
+   int shmid;
    void *data;
    void *mapped;
    const void *front_private;
@@ -79,6 +83,25 @@ dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
    return TRUE;
 }
 
+static char *
+alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)
+{
+   char *addr;
+
+   dri_sw_dt->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
+   if (dri_sw_dt->shmid < 0)
+      return NULL;
+
+   addr = (char *) shmat(dri_sw_dt->shmid, 0, 0);
+   /* mark the segment immediately for deletion to avoid leaks */
+   shmctl(dri_sw_dt->shmid, IPC_RMID, 0);
+
+   if (addr == (char *) -1)
+      return NULL;
+
+   return addr;
+}
+
 static struct sw_displaytarget *
 dri_sw_displaytarget_create(struct sw_winsys *winsys,
                             unsigned tex_usage,
@@ -88,6 +111,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
                             const void *front_private,
                             unsigned *stride)
 {
+   struct dri_sw_winsys *ws = dri_sw_winsys(winsys);
    struct dri_sw_displaytarget *dri_sw_dt;
    unsigned nblocksy, size, format_stride;
 
@@ -106,7 +130,13 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
    nblocksy = util_format_get_nblocksy(format, height);
    size = dri_sw_dt->stride * nblocksy;
 
-   dri_sw_dt->data = align_malloc(size, alignment);
+   dri_sw_dt->shmid = -1;
+   if (ws->lf->put_image_shm)
+      dri_sw_dt->data = alloc_shm(dri_sw_dt, size);
+
+   if(!dri_sw_dt->data)
+      dri_sw_dt->data = align_malloc(size, alignment);
+
    if(!dri_sw_dt->data)
       goto no_data;
 
@@ -125,7 +155,12 @@ dri_sw_displaytarget_destroy(struct sw_winsys *ws,
 {
    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
 
-   align_free(dri_sw_dt->data);
+   if (dri_sw_dt->shmid >= 0) {
+      shmdt(dri_sw_dt->data);
+      shmctl(dri_sw_dt->shmid, IPC_RMID, 0);
+   } else {
+      align_free(dri_sw_dt->data);
+   }
 
    FREE(dri_sw_dt);
 }
@@ -187,25 +222,38 @@ dri_sw_displaytarget_display(struct sw_winsys *ws,
    struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
    struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private;
-   unsigned width, height;
+   unsigned width, height, x = 0, y = 0;
    unsigned blsize = util_format_get_blocksize(dri_sw_dt->format);
+   unsigned offset = 0;
+   void *data = dri_sw_dt->data;
 
    /* Set the width to 'stride / cpp'.
     *
     * PutImage correctly clips to the width of the dst drawable.
     */
-   width = dri_sw_dt->stride / blsize;
-
-   height = dri_sw_dt->height;
-
    if (box) {
-       void *data;
-       data = (char *)dri_sw_dt->data + (dri_sw_dt->stride * box->y) + box->x * blsize;
-       dri_sw_ws->lf->put_image2(dri_drawable, data,
-                                 box->x, box->y, box->width, box->height, dri_sw_dt->stride);
+      offset = (dri_sw_dt->stride * box->y) + box->x * blsize;
+      data += offset;
+      x = box->x;
+      y = box->y;
+      width = box->width;
+      height = box->height;
    } else {
-       dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
+      width = dri_sw_dt->stride / blsize;
+      height = dri_sw_dt->height;
    }
+
+   if (dri_sw_dt->shmid != -1) {
+      dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, offset,
+                                   x, y, width, height, dri_sw_dt->stride);
+      return;
+   }
+
+   if (box)
+      dri_sw_ws->lf->put_image2(dri_drawable, data,
+                                x, y, width, height, dri_sw_dt->stride);
+   else
+      dri_sw_ws->lf->put_image(dri_drawable, data, width, height);
 }
 
 static void