aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2014-02-28 12:38:33 +0000
committerChris Michael <cp.michael@samsung.com>2014-02-28 12:52:03 +0000
commit909427eec7d18aa7b13e3fdf380277b6a7b80c9e (patch)
tree6a0c3f55664076f6c2f8d60d69e231556f040189
parentevas-drm: Add vsync/non-vsync support to evas_drm code (diff)
downloadefl-devs/devilhorns/evas_drm.tar.gz
evas-drm: Ddd support for setting vsync with env variable.devs/devilhorns/evas_drm
@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>
-rw-r--r--src/modules/evas/engines/drm/evas_outbuf.c391
1 files changed, 143 insertions, 248 deletions
diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c
index b4941f9a76..54d15ac971 100644
--- a/src/modules/evas/engines/drm/evas_outbuf.c
+++ b/src/modules/evas/engines/drm/evas_outbuf.c
@@ -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);
}