evas-drm: Ddd support for setting vsync with env variable.
authorChris Michael <cp.michael@samsung.com>
Fri, 28 Feb 2014 12:38:33 +0000 (12:38 +0000)
committerChris Michael <cp.michael@samsung.com>
Fri, 28 Feb 2014 13:13:17 +0000 (13:13 +0000)
@feature: Add support for EVAS_DRM_VSYNC environment variable to
@feature: Add support for marking a Framebuffer as dirty.
@bugfix: Fix color mask values for evas conversion functions.
@bugfix: Start with using the Backbuffer for drawing.
@bugfix: Fix previous Slowness with evas_cache image data.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/modules/evas/engines/drm/evas_outbuf.c

index b4941f9..54d15ac 100644 (file)
@@ -4,79 +4,65 @@
 #endif
 
 /* FIXME: We NEED to get the color map from the VT and use that for the mask */
-#define RED_MASK 0x00ff0000
-#define GREEN_MASK 0x0000ff00
-#define BLUE_MASK 0x000000ff
+#define RED_MASK 0xff0000
+#define GREEN_MASK 0x00ff00
+#define BLUE_MASK 0x0000ff
 
 static Eina_Bool 
-_evas_outbuf_buffer_new(Outbuf *ob, Buffer *buffer)
+_evas_outbuf_buffer_new(Outbuf *ob, Buffer *buff)
 {
-   /* check for valid outbuf */
-   if (!ob) return EINA_FALSE;
+   buff->w = ob->w;
+   buff->h = ob->h;
 
-   buffer->w = ob->w;
-   buffer->h = ob->h;
-
-   /* sadly we cannot create buffers to be JUST the size of the canvas.
-    * drmModeSetCrtc will barf with ENOSPC if we try that :( so we have to 
-    * allocate framebuffer objects to be the whole size of the display mode */
-
-   /* if (ob->priv.mode.hdisplay > buffer->w) */
-   /*   buffer->w = ob->priv.mode.hdisplay; */
-   /* if (ob->priv.mode.vdisplay > buffer->h) */
-   /*   buffer->h = ob->priv.mode.vdisplay; */
-
-   /* create a drm fb for this buffer */
-   if (!evas_drm_framebuffer_create(ob->priv.fd, buffer, ob->depth))
-     {
-        CRI("Could not create drm framebuffer");
-        return EINA_FALSE;
-     }
-
-   evas_drm_outbuf_framebuffer_set(ob, buffer);
+   /* create a dumb framebuffer */
+   if (!evas_drm_framebuffer_create(ob->priv.fd, buff, ob->depth))
+     return EINA_FALSE;
 
    return EINA_TRUE;
 }
 
-static void *
-_evas_outbuf_buffer_map(Outbuf *ob, int *w, int *h)
-{
-   if (w) *w = ob->w;
-   if (h) *h = ob->h;
-   return ob->priv.buffer[ob->priv.curr].data;
-}
-
 static void 
 _evas_outbuf_buffer_put(Outbuf *ob, Buffer *buffer, Eina_Rectangle *rects, unsigned int count)
 {
    /* validate input params */
    if ((!ob) || (!buffer)) return;
 
-   if (!buffer->data)
+#ifdef DRM_MODE_FEATURE_DIRTYFB
+   drmModeClip *clip;
+   unsigned int i = 0;
+   int ret;
+
+   clip = alloca(count * sizeof(drmModeClip));
+   for (i = 0; i < count; i++)
      {
-        CRI("Current Buffer Has No Data !!");
-        /* TODO: call function to mmap buffer data */
-        /* if (!_evas_outbuf_buffer_new(ob, buffer)); */
-        return;
+        clip[i].x1 = rects[i].x;
+        clip[i].y1 = rects[i].y;
+        clip[i].x2 = rects[i].w;
+        clip[i].y2 = rects[i].h;
      }
 
-   if (ob->priv.sent != buffer)
+   /* DBG("Marking FB Dirty: %d", buffer->fb); */
+   ret = drmModeDirtyFB(ob->priv.fd, buffer->fb, clip, count);
+   if (ret)
      {
-        /* DBG("Send New Buffer: %d", buffer->fb); */
-        /* if (!buffer->valid) evas_drm_outbuf_framebuffer_set(ob, buffer); */
-        if (!evas_drm_framebuffer_send(ob, buffer, rects, count))
-          ERR("Could not send buffer");
+        if (ret == -EINVAL)
+          ERR("Could not set FB Dirty: %m");
      }
+#endif
 }
 
 static void 
 _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
 {
-   /* check for valid output buffer */
-   if (!ob) return;
+   Buffer *buff;
 
-   _evas_outbuf_buffer_put(ob, &(ob->priv.buffer[ob->priv.curr]), 
-                           rects, count);
+   buff = &(ob->priv.buffer[ob->priv.curr]);
+
+   /* mark the fb as dirty */
+   _evas_outbuf_buffer_put(ob, buff, rects, count);
+
+   /* send this buffer to the crtc */
+   evas_drm_framebuffer_send(ob, buff);
 }
 
 Outbuf *
@@ -86,23 +72,24 @@ evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
    char *num;
    int i = 0;
 
-   /* try to allocate space for our outbuf structure */
-   if (!(ob = calloc(1, sizeof(Outbuf))))
-     return NULL;
+   /* try to allocate space for outbuf */
+   if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
 
-   /* set some default outbuf properties */
+   /* set properties of outbuf */
    ob->w = w;
    ob->h = h;
-   ob->rotation = info->info.rotation;
    ob->depth = info->info.depth;
+   ob->rotation = info->info.rotation;
    ob->destination_alpha = info->info.destination_alpha;
+   ob->vsync = info->info.vsync;
 
-   /* set drm file descriptor */
+   /* set drm card fd */
    ob->priv.fd = info->info.fd;
 
    /* try to setup the drm card for this outbuf */
    if (!evas_drm_outbuf_setup(ob))
      {
+        ERR("Could not setup output");
         free(ob);
         return NULL;
      }
@@ -119,20 +106,23 @@ evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
         else if (ob->priv.num > 3) ob->priv.num = 3;
      }
 
-   /* with the connector and crtc set, we can now create buffers !! :) */
+   /* check for vsync override */
+   if ((num = getenv("EVAS_DRM_VSYNC")))
+     ob->vsync = atoi(num);
+
+   /* try to create buffers */
    for (; i < ob->priv.num; i++)
      {
         if (!_evas_outbuf_buffer_new(ob, &(ob->priv.buffer[i])))
-          {
-             CRI("Failed to create buffer");
-             break;
-          }
+          break;
      }
 
-   /* set array step size for regions */
-   eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
+   /* set the front buffer to be the one on the crtc */
+   evas_drm_outbuf_framebuffer_set(ob, &(ob->priv.buffer[0]));
+
+   /* set back buffer as first one to draw into */
+   ob->priv.curr = (ob->priv.num - 1);
 
-   /* return the allocated outbuf structure */
    return ob;
 }
 
@@ -141,13 +131,11 @@ evas_outbuf_free(Outbuf *ob)
 {
    int i = 0;
 
-   /* destroy the buffers */
+   /* destroy the old buffers */
    for (; i < ob->priv.num; i++)
      evas_drm_framebuffer_destroy(ob->priv.fd, &(ob->priv.buffer[i]));
 
-   eina_array_flush(&ob->priv.onebuf_regions);
-
-   /* free the allocated outbuf structure */
+   /* free allocate space for outbuf */
    free(ob);
 }
 
@@ -222,69 +210,18 @@ evas_outbuf_buffer_state_get(Outbuf *ob)
 RGBA_Image *
 evas_outbuf_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;
+   RGBA_Image *img = NULL;
 
-   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))
-          {
-             int bpl = 0;
-             int bw = 0, bh = 0;
-             void *data;
-
-             data = _evas_outbuf_buffer_map(ob, &bw, &bh);
-             bpl = (bw * sizeof(int));
-
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               img = (RGBA_Image *)evas_cache2_image_data(evas_common_image_cache2_get(),
-                                                          bpl / sizeof(int), bh, 
-                                                          data, 
-                                                          ob->destination_alpha, 
-                                                          EVAS_COLORSPACE_ARGB8888);
-             else
-#endif
-               img = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
-                                                         bpl / sizeof(int), bh, 
-                                                         data, 
-                                                         ob->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);
+   /* DBG("Outbuf Region New: %d %d %d %d", x, y, w, h); */
 
-             eina_rectangle_free(rect);
-
-             return NULL;
-          }
-
-        /* clip the region to the onebuf region */
-        if (cx) *cx = x;
-        if (cy) *cy = y;
-        if (cw) *cw = w;
-        if (ch) *ch = h;
+   RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
 
-        return img;
-     }
-   else
+   if ((ob->rotation == 0) && (ob->depth == 32))
      {
+        Eina_Rectangle *rect;
+
         if (!(rect = eina_rectangle_new(x, y, w, h)))
           return NULL;
 
@@ -301,8 +238,7 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i
              return NULL;
           }
 
-        img->cache_entry.flags.alpha = ob->destination_alpha;
-//        img->cache_entry.flags.alpha |= ob->destination_alpha;
+        img->cache_entry.flags.alpha |= ob->destination_alpha ? 1 : 0;
 
 #ifdef EVAS_CSERVE2
         if (evas_cserve2_use_get())
@@ -313,18 +249,17 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i
 
         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;
+        /* add this cached image data to pending writes */
+        ob->priv.pending_writes = 
+          eina_list_append(ob->priv.pending_writes, img);
      }
 
-   return NULL;
+   return img;
 }
 
 void 
@@ -334,8 +269,8 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
    Eina_Rectangle rect = {0, 0, 0, 0}, pr;
    DATA32 *src;
    DATA8 *dst;
-   int depth = 32, bpp = 0, bpl = 0, wid = 0;
-   int ww = 0, hh = 0;
+   Buffer *buff;
+   int bpp = 0, bpl = 0;
    int rx = 0, ry = 0;
 
    /* check for valid output buffer */
@@ -344,17 +279,24 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
    /* check for pending writes */
    if (!ob->priv.pending_writes) return;
 
+   /* check for valid source data */
+   if (!(src = update->image.data)) return;
+
+   /* check for valid desination data */
+   buff = &(ob->priv.buffer[ob->priv.curr]);
+   if (!(dst = buff->data)) return;
+
    if ((ob->rotation == 0) || (ob->rotation == 180))
      {
         func = 
-          evas_common_convert_func_get(0, w, h, depth, 
+          evas_common_convert_func_get(0, w, h, ob->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, 
+          evas_common_convert_func_get(0, h, w, ob->depth, 
                                        RED_MASK, GREEN_MASK, BLUE_MASK,
                                        PAL_MODE_NONE, ob->rotation);
      }
@@ -396,27 +338,23 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
         rect.h = w;
      }
 
-   /* check for valid update image data */
-   if (!(src = update->image.data)) return;
-
-   bpp = depth / 8;
+   bpp = (ob->depth / 8);
    if (bpp <= 0) return;
 
-   /* check for valid desination data */
-   if (!(dst = _evas_outbuf_buffer_map(ob, &ww, &hh))) return;
-
-   bpl = (ww * sizeof(int));
+   bpl = buff->stride;
 
    if (ob->rotation == 0)
      {
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
-        dst += (bpl * rect.y) + (rect.x + bpp);
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
+                           0, 0, buff->w, buff->h);
+        dst += (bpl * rect.y) + (rect.x * bpp);
         w -= rx;
      }
    else if (ob->rotation == 180)
      {
         pr = rect;
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
+                           0, 0, buff->w, buff->h);
         rx = pr.w - rect.w;
         ry = pr.h - rect.h;
         src += (update->cache_entry.w * ry) + rx;
@@ -425,7 +363,8 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
    else if (ob->rotation == 90)
      {
         pr = rect;
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
+                           0, 0, buff->w, buff->h);
         rx = pr.w - rect.w; ry = pr.h - rect.h;
         src += ry;
         w -= ry;
@@ -433,7 +372,8 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
    else if (ob->rotation == 270)
      {
         pr = rect;
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
+                           0, 0, buff->w, buff->h);
         rx = pr.w - rect.w; ry = pr.h - rect.h;
         src += (update->cache_entry.w * rx);
         w -= ry;
@@ -441,131 +381,86 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
 
    if ((rect.w <= 0) || (rect.h <= 0)) return;
 
-   wid = bpl / bpp;
-
-   dst += (bpl * rect.y) + (rect.x * bpp);
-
-   func(src, dst, (update->cache_entry.w - w), (wid - rect.w),
+   func(src, dst, (update->cache_entry.w - w), ((bpl / bpp) - rect.w),
         rect.w, rect.h, x + rx, y + ry, NULL);
 }
 
 void 
+evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update)
+{
+   evas_cache_image_drop(&update->cache_entry);
+}
+
+void 
 evas_outbuf_flush(Outbuf *ob)
 {
    Eina_Rectangle *rects;
    RGBA_Image *img;
    unsigned int n = 0, i = 0;
 
-   /* check for valid output buffer */
-   if (!ob) return;
+   /* get number of pending writes */
+   n = eina_list_count(ob->priv.pending_writes);
+   if (n == 0) return;
 
-   /* check for pending writes */
-   if (!ob->priv.pending_writes)
+   /* 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;
-        Eina_Array_Iterator it;
-
-        /* get number of buffer regions */
-        n = eina_array_count_get(&ob->priv.onebuf_regions);
-        if (n == 0) return;
+        int x = 0, y = 0, w = 0, h = 0;
 
-        /* allocate rectangles */
-        if (!(rects = alloca(n * sizeof(Eina_Rectangle)))) return;
+        if (!(rect = img->extended_info)) continue;
 
-        /* loop the buffer regions and assign to rects */
-        EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
-          rects[i] = *rect;
+        x = rect->x; y = rect->y; w = rect->w; h = rect->h;
 
-        /* TODO: unmap the buffer ?? */
-        /* evas_swapper_buffer_unmap(ob->priv.swapper); */
-
-        /* force a buffer swap */
-        _evas_outbuf_buffer_swap(ob, rects, n);
-
-        /* clean array */
-        eina_array_clean(&ob->priv.onebuf_regions);
-
-        img = ob->priv.onebuf;
-        ob->priv.onebuf = NULL;
-        if (img)
+        /* based on rotation, set rectangle position */
+        if (ob->rotation == 0)
           {
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               evas_cache2_image_close(&img->cache_entry);
-             else
-#endif
-               evas_cache_image_drop(&img->cache_entry);
+             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;
           }
-     }
-   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)
+        /* 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))
           {
-             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;
-
-             /* 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;
-               }
+             rects[i].w = h;
+             rects[i].h = w;
+          }
 
-             eina_rectangle_free(rect);
+        eina_rectangle_free(rect);
 
 #ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               evas_cache2_image_close(&img->cache_entry);
-             else
+        if (evas_cserve2_use_get())
+          evas_cache2_image_close(&img->cache_entry);
+        else
 #endif
-               evas_cache_image_drop(&img->cache_entry);
-
-             i++;
-          }
-
-        /* TODO: unmap the buffer ?? */
-        /* evas_swapper_buffer_unmap(ob->priv.swapper); */
+          evas_cache_image_drop(&img->cache_entry);
 
-        /* force a buffer swap */
-        _evas_outbuf_buffer_swap(ob, rects, n);
+        i++;
      }
+
+   /* force a buffer swap */
+   _evas_outbuf_buffer_swap(ob, rects, n);
 }