Add initial swap buffer code.
authorChristopher Michael <cp.michael@samsung.com>
Thu, 24 Jan 2013 09:16:42 +0000 (09:16 +0000)
committerChristopher Michael <cpmichael1@comcast.net>
Thu, 24 Jan 2013 09:16:42 +0000 (09:16 +0000)
Signed-off-by: Christopher Michael <cp.michael@samsung.com>
SVN revision: 83245

src/modules/evas/engines/wayland_shm/evas_swapbuf.c [new file with mode: 0644]

diff --git a/src/modules/evas/engines/wayland_shm/evas_swapbuf.c b/src/modules/evas/engines/wayland_shm/evas_swapbuf.c
new file mode 100644 (file)
index 0000000..ed68fdf
--- /dev/null
@@ -0,0 +1,451 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+//#include <sys/mman.h>
+
+#ifdef EVAS_CSERVE2
+# include "evas_cs2_private.h"
+#endif
+
+#include "evas_common.h"
+#include "evas_macros.h"
+#include "evas_engine.h"
+#include "evas_swapbuf.h"
+#include "evas_swapper.h"
+
+#define RED_MASK 0x00ff0000
+#define GREEN_MASK 0x0000ff00
+#define BLUE_MASK 0xff000000
+
+/* local function prototypes */
+
+Outbuf *
+evas_swapbuf_setup(int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *wl_shm, struct wl_surface *wl_surface)
+{
+   Outbuf *ob = NULL;
+
+   /* try to allocate a new Outbuf */
+   if (!(ob = calloc(1, sizeof(Outbuf)))) 
+     return NULL;
+
+   /* set some properties */
+   ob->w = w;
+   ob->h = h;
+   ob->rotation = rotation;
+   ob->depth = depth;
+   ob->priv.destination_alpha = alpha;
+   ob->priv.wl.shm = wl_shm;
+   ob->priv.wl.surface = wl_surface;
+
+   if ((ob->rotation == 0) || (ob->rotation == 180))
+     {
+        ob->priv.swapper = 
+          evas_swapper_setup(w, h, depth, alpha, ob->priv.wl.shm, 
+                             ob->priv.wl.surface);
+     }
+   else if ((ob->rotation == 90) || (ob->rotation == 270))
+     {
+        ob->priv.swapper = 
+          evas_swapper_setup(h, w, depth, alpha, ob->priv.wl.shm, 
+                             ob->priv.wl.surface);
+     }
+
+   /* check that a swapper was created */
+   if (!ob->priv.swapper)
+     {
+        /* free the Outbuf structure allocation */
+        free(ob);
+
+        return NULL;
+     }
+
+   /* set step size of regions array */
+   eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
+
+   /* return allocated Outbuf */
+   return ob;
+}
+
+void 
+evas_swapbuf_free(Outbuf *ob)
+{
+   /* check for valid output buffer */
+   if (!ob) return;
+
+   /* flush the output buffer */
+   evas_swapbuf_flush(ob);
+   evas_swapbuf_idle_flush(ob);
+   eina_array_flush(&ob->priv.onebuf_regions);
+
+   /* destroy the wayland shm pool */
+   /* _evas_swapbuf_pool_destroy(ob); */
+
+   /* free the allocated structure */
+   free(ob);
+}
+
+void 
+evas_swapbuf_reconfigure(Outbuf *ob, int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha)
+{
+   /* check for valid output buffer */
+   if (!ob) return;
+
+   /* check that something was actually changed */
+   if ((ob->w == w) && (ob->h == h) && (ob->rotation == rotation) && 
+       (ob->depth == depth) && (ob->priv.destination_alpha == alpha))
+     return;
+
+   /* set some properties */
+   ob->w = w;
+   ob->h = h;
+   ob->rotation = rotation;
+   ob->depth = depth;
+   ob->priv.destination_alpha = alpha;
+
+   /* check for valid swapper */
+   if (ob->priv.swapper)
+     {
+        /* free existing swapper */
+        evas_swapper_free(ob->priv.swapper);
+     }
+
+   /* create new swapper */
+   if ((ob->rotation == 0) || (ob->rotation == 180))
+     {
+        ob->priv.swapper = 
+          evas_swapper_setup(w, h, depth, alpha, ob->priv.wl.shm, 
+                             ob->priv.wl.surface);
+     }
+   else if ((ob->rotation == 90) || (ob->rotation == 270))
+     {
+        ob->priv.swapper = 
+          evas_swapper_setup(h, w, depth, alpha, ob->priv.wl.shm, 
+                             ob->priv.wl.surface);
+     }
+}
+
+RGBA_Image *
+evas_swapbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
+{
+   RGBA_Image *img;
+   Eina_Rectangle *rect;
+
+   RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
+   if ((w <= 0) || (h <= 0)) return NULL;
+
+   if (ob->rotation == 0)
+     {
+        if (!(img = ob->priv.onebuf))
+          {
+             void *data;
+
+             data = evas_swapper_buffer_map(ob->priv.swapper);
+
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               img = (RGBA_Image *)evas_cache2_image_data(evas_common_image_cache2_get(),
+                                                          ob->w, ob->h, data, 
+                                                          ob->priv.destination_alpha, 
+                                                          EVAS_COLORSPACE_ARGB8888);
+             else
+#endif
+               img = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
+                                                         ob->w, ob->h, data, 
+                                                         ob->priv.destination_alpha, 
+                                                         EVAS_COLORSPACE_ARGB8888);
+
+             ob->priv.onebuf = img;
+             if (!img) return NULL;
+          }
+
+        if (!(rect = eina_rectangle_new(x, y, w, h)))
+          return NULL;
+
+        if (!eina_array_push(&ob->priv.onebuf_regions, rect))
+          {
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+
+             free(rect);
+
+             return NULL;
+          }
+
+        /* clip the region to the onebuf region */
+        if (cx) *cx = x;
+        if (cy) *cy = y;
+     }
+   else
+     {
+        if (!(rect = eina_rectangle_new(x, y, w, h)))
+          return NULL;
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          img = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get());
+        else
+#endif
+          img = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
+
+        if (!img)
+          {
+             free(rect);
+             return NULL;
+          }
+
+        img->cache_entry.flags.alpha |= ob->priv.destination_alpha;
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_surface_alloc(&img->cache_entry, w, h);
+        else
+#endif
+          evas_cache_image_surface_alloc(&img->cache_entry, w, h);
+
+        img->extended_info = rect;
+
+        ob->priv.pending_writes = 
+          eina_list_append(ob->priv.pending_writes, img);
+
+        if (cx) *cx = 0;
+        if (cy) *cy = 0;
+     }
+
+   if (cw) *cw = w;
+   if (ch) *ch = h;
+
+   return img;
+}
+
+void 
+evas_swapbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
+{
+   Gfx_Func_Convert func = NULL;
+   Eina_Rectangle rect = {0, 0, 0, 0};
+   DATA32 *src;
+   DATA8 *dst;
+   int depth = 32, bpp = 0, bpl = 0, wid = 0;
+
+   /* check for valid output buffer */
+   if (!ob) return;
+
+   /* check for pending writes */
+   if (!ob->priv.pending_writes) return;
+
+   if ((ob->rotation == 0) || (ob->rotation == 180))
+     {
+        func = 
+          evas_common_convert_func_get(0, w, h, depth, 
+                                       RED_MASK, GREEN_MASK, BLUE_MASK,
+                                       PAL_MODE_NONE, ob->rotation);
+     }
+   else if ((ob->rotation == 90) || (ob->rotation == 270))
+     {
+        func = 
+          evas_common_convert_func_get(0, h, w, depth, 
+                                       RED_MASK, GREEN_MASK, BLUE_MASK,
+                                       PAL_MODE_NONE, ob->rotation);
+     }
+
+   /* make sure we have a valid convert function */
+   if (!func) return;
+
+   /* based on rotation, set rectangle position */
+   if (ob->rotation == 0)
+     {
+        rect.x = x;
+        rect.y = y;
+     }
+   else if (ob->rotation == 90)
+     {
+        rect.x = y;
+        rect.y = (ob->w - x - w);
+     }
+   else if (ob->rotation == 180)
+     {
+        rect.x = (ob->w - x - w);
+        rect.y = (ob->h - y - h);
+     }
+   else if (ob->rotation == 270)
+     {
+        rect.x = (ob->h - y - h);
+        rect.y = x;
+     }
+
+   /* based on rotation, set rectangle size */
+   if ((ob->rotation == 0) || (ob->rotation == 180))
+     {
+        rect.w = w;
+        rect.h = h;
+     }
+   else if ((ob->rotation == 90) || (ob->rotation == 270))
+     {
+        rect.w = h;
+        rect.h = w;
+     }
+
+   /* check for valid update image data */
+   if (!(src = update->image.data)) return;
+
+   /* check for valid desination data */
+   if (!(dst = evas_swapper_buffer_map(ob->priv.swapper))) return;
+
+   bpp = depth / 8;
+   if (bpp <= 0) return;
+
+   bpl = (ob->w * sizeof(int));
+   wid = bpl / bpp;
+
+   dst += (bpl * rect.y) + (rect.x * bpp);
+
+   func(src, dst, (update->cache_entry.w - w), (wid - rect.w), 
+        rect.w, rect.h, x, y, NULL);
+}
+
+void 
+evas_swapbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
+{
+   /* NB: nothing to do, they are cleaned up on flush */
+}
+
+void 
+evas_swapbuf_flush(Outbuf *ob)
+{
+   Eina_Rectangle *rects;
+   RGBA_Image *img;
+   unsigned int n = 0, i = 0;
+
+   /* check for valid output buffer */
+   if (!ob) return;
+
+   /* check for pending writes */
+   if (!ob->priv.pending_writes)
+     {
+        Eina_Rectangle *rect;
+        Eina_Array_Iterator it;
+
+        /* get number of buffer regions */
+        n = eina_array_count_get(&ob->priv.onebuf_regions);
+        if (n == 0) return;
+
+        /* allocate rectangles */
+        if (!(rects = alloca(n * sizeof(Eina_Rectangle)))) return;
+
+        /* loop the buffer regions and assign to rects */
+        EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
+          rects[i] = *rect;
+
+        /* unmap the buffer */
+        evas_swapper_buffer_unmap(ob->priv.swapper);
+
+        /* force a buffer swap */
+        evas_swapper_swap(ob->priv.swapper, rects, n);
+
+        /* clean array */
+        eina_array_clean(&ob->priv.onebuf_regions);
+
+        img = ob->priv.onebuf;
+        ob->priv.onebuf = NULL;
+        if (img)
+          {
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+          }
+     }
+   else
+     {
+        /* get number of pending writes */
+        n = eina_list_count(ob->priv.pending_writes);
+        if (n == 0) return;
+
+        /* allocate rectangles */
+        if (!(rects = alloca(n * sizeof(Eina_Rectangle)))) return;
+
+        /* loop the pending writes */
+        EINA_LIST_FREE(ob->priv.pending_writes, img)
+          {
+             Eina_Rectangle *rect;
+             int x = 0, y = 0, w = 0, h = 0;
+
+             if (!(rect = img->extended_info)) continue;
+
+             x = rect->x; y = rect->y; w = rect->w; h = rect->h;
+             rects[i] = *rect;
+
+             /* based on rotation, set rectangle position */
+             if (ob->rotation == 0)
+               {
+                  rects[i].x = x;
+                  rects[i].y = y;
+               }
+             else if (ob->rotation == 90)
+               {
+                  rects[i].x = y;
+                  rects[i].y = (ob->w - x - w);
+               }
+             else if (ob->rotation == 180)
+               {
+                  rects[i].x = (ob->w - x - w);
+                  rects[i].y = (ob->h - y - h);
+               }
+             else if (ob->rotation == 270)
+               {
+                  rects[i].x = (ob->h - y - h);
+                  rects[i].y = x;
+               }
+
+             /* based on rotation, set rectangle size */
+             if ((ob->rotation == 0) || (ob->rotation == 180))
+               {
+                  rects[i].w = w;
+                  rects[i].h = h;
+               }
+             else if ((ob->rotation == 90) || (ob->rotation == 270))
+               {
+                  rects[i].w = h;
+                  rects[i].h = w;
+               }
+
+             free(rect);
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+          }
+
+        /* unmap the buffer */
+        evas_swapper_buffer_unmap(ob->priv.swapper);
+
+        /* force a buffer swap */
+        evas_swapper_swap(ob->priv.swapper, rects, n);
+     }
+}
+
+void 
+evas_swapbuf_idle_flush(Outbuf *ob EINA_UNUSED)
+{
+
+}
+
+int 
+evas_swapbuf_state_get(Outbuf *ob)
+{
+   int mode = 0;
+
+   if (!ob->priv.swapper) return MODE_FULL;
+   mode = evas_swapper_buffer_state_get(ob->priv.swapper);
+   return mode;
+}
+
+/* local functions */