android: nv50/ir: Add nv50_ir_prog_info_out serialize and deserialize
[mesa.git] / src / gallium / winsys / sw / dri / dri_sw_winsys.c
index 1bca827bd65f7d6bc80a4f114074336ade2ec411..f9ff6d25d730138c2dfc19d9354461d1607c6664 100644 (file)
  *
  **************************************************************************/
 
+#ifdef HAVE_SYS_SHM_H
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#ifdef __FreeBSD__
+/* sys/ipc.h -> sys/_types.h -> machine/param.h
+ * - defines ALIGN which clashes with our ALIGN
+ */
+#undef ALIGN
+#endif
+#endif
+
 #include "pipe/p_compiler.h"
 #include "pipe/p_format.h"
+#include "pipe/p_state.h"
 #include "util/u_inlines.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
-#include "state_tracker/sw_winsys.h"
+#include "frontend/sw_winsys.h"
 #include "dri_sw_winsys.h"
 
 
@@ -44,47 +56,74 @@ struct dri_sw_displaytarget
    unsigned height;
    unsigned stride;
 
+   unsigned map_flags;
+   int shmid;
    void *data;
    void *mapped;
+   const void *front_private;
 };
 
 struct dri_sw_winsys
 {
    struct sw_winsys base;
 
-   struct drisw_loader_funcs *lf;
+   const struct drisw_loader_funcs *lf;
 };
 
-static INLINE struct dri_sw_displaytarget *
+static inline struct dri_sw_displaytarget *
 dri_sw_displaytarget( struct sw_displaytarget *dt )
 {
    return (struct dri_sw_displaytarget *)dt;
 }
 
-static INLINE struct dri_sw_winsys *
+static inline struct dri_sw_winsys *
 dri_sw_winsys( struct sw_winsys *ws )
 {
    return (struct dri_sw_winsys *)ws;
 }
 
 
-static boolean
+static bool
 dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
                                           unsigned tex_usage,
                                           enum pipe_format format )
 {
    /* TODO: check visuals or other sensible thing here */
-   return TRUE;
+   return true;
 }
 
+#ifdef HAVE_SYS_SHM_H
+static char *
+alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)
+{
+   char *addr;
+
+   /* 0600 = user read+write */
+   dri_sw_dt->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
+   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;
+}
+#endif
+
 static struct sw_displaytarget *
 dri_sw_displaytarget_create(struct sw_winsys *winsys,
                             unsigned tex_usage,
                             enum pipe_format format,
                             unsigned width, unsigned height,
                             unsigned alignment,
+                            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;
 
@@ -95,6 +134,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
    dri_sw_dt->format = format;
    dri_sw_dt->width = width;
    dri_sw_dt->height = height;
+   dri_sw_dt->front_private = front_private;
 
    format_stride = util_format_get_stride(format, width);
    dri_sw_dt->stride = align(format_stride, alignment);
@@ -102,7 +142,16 @@ 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;
+
+#ifdef HAVE_SYS_SHM_H
+   if (ws->lf->put_image_shm)
+      dri_sw_dt->data = alloc_shm(dri_sw_dt, size);
+#endif
+
+   if(!dri_sw_dt->data)
+      dri_sw_dt->data = align_malloc(size, alignment);
+
    if(!dri_sw_dt->data)
       goto no_data;
 
@@ -121,8 +170,13 @@ dri_sw_displaytarget_destroy(struct sw_winsys *ws,
 {
    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
 
-   if (dri_sw_dt->data) {
-      FREE(dri_sw_dt->data);
+   if (dri_sw_dt->shmid >= 0) {
+#ifdef HAVE_SYS_SHM_H
+      shmdt(dri_sw_dt->data);
+      shmctl(dri_sw_dt->shmid, IPC_RMID, 0);
+#endif
+   } else {
+      align_free(dri_sw_dt->data);
    }
 
    FREE(dri_sw_dt);
@@ -135,6 +189,12 @@ dri_sw_displaytarget_map(struct sw_winsys *ws,
 {
    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
    dri_sw_dt->mapped = dri_sw_dt->data;
+
+   if (dri_sw_dt->front_private && (flags & PIPE_TRANSFER_READ)) {
+      struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
+      dri_sw_ws->lf->get_image((void *)dri_sw_dt->front_private, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride, dri_sw_dt->data);
+   }
+   dri_sw_dt->map_flags = flags;
    return dri_sw_dt->mapped;
 }
 
@@ -143,6 +203,11 @@ dri_sw_displaytarget_unmap(struct sw_winsys *ws,
                            struct sw_displaytarget *dt)
 {
    struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
+   if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_TRANSFER_WRITE)) {
+      struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
+      dri_sw_ws->lf->put_image2((void *)dri_sw_dt->front_private, dri_sw_dt->data, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride);
+   }
+   dri_sw_dt->map_flags = 0;
    dri_sw_dt->mapped = NULL;
 }
 
@@ -156,37 +221,71 @@ dri_sw_displaytarget_from_handle(struct sw_winsys *winsys,
    return NULL;
 }
 
-static boolean
+static bool
 dri_sw_displaytarget_get_handle(struct sw_winsys *winsys,
                                 struct sw_displaytarget *dt,
                                 struct winsys_handle *whandle)
 {
-   assert(0);
-   return FALSE;
+   struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
+
+   if (whandle->type == WINSYS_HANDLE_TYPE_SHMID) {
+      if (dri_sw_dt->shmid < 0)
+         return false;
+      whandle->handle = dri_sw_dt->shmid;
+      return true;
+   }
+
+   return false;
 }
 
 static void
 dri_sw_displaytarget_display(struct sw_winsys *ws,
                              struct sw_displaytarget *dt,
-                             void *context_private)
+                             void *context_private,
+                             struct pipe_box *box)
 {
    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;
+   unsigned offset_x = 0;
+   char *data = dri_sw_dt->data;
+   bool is_shm = dri_sw_dt->shmid != -1;
    /* Set the width to 'stride / cpp'.
     *
     * PutImage correctly clips to the width of the dst drawable.
     */
-   width = dri_sw_dt->stride / util_format_get_blocksize(dri_sw_dt->format);
+   if (box) {
+      offset = dri_sw_dt->stride * box->y;
+      offset_x = box->x * blsize;
+      data += offset;
+      /* don't add x offset for shm, the put_image_shm will deal with it */
+      if (!is_shm)
+         data += offset_x;
+      x = box->x;
+      y = box->y;
+      width = box->width;
+      height = box->height;
+   } else {
+      width = dri_sw_dt->stride / blsize;
+      height = dri_sw_dt->height;
+   }
 
-   height = dri_sw_dt->height;
+   if (is_shm) {
+      dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, offset, offset_x,
+                                   x, y, width, height, dri_sw_dt->stride);
+      return;
+   }
 
-   dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
+   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
 dri_destroy_sw_winsys(struct sw_winsys *winsys)
 {
@@ -194,7 +293,7 @@ dri_destroy_sw_winsys(struct sw_winsys *winsys)
 }
 
 struct sw_winsys *
-dri_create_sw_winsys(struct drisw_loader_funcs *lf)
+dri_create_sw_winsys(const struct drisw_loader_funcs *lf)
 {
    struct dri_sw_winsys *ws;