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) + /* DBG("Outbuf Region New: %d %d %d %d", x, y, w, h); */ + + RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h); + + if ((ob->rotation == 0) && (ob->depth == 32)) { - if (!(img = ob->priv.onebuf)) - { - int bpl = 0; - int bw = 0, bh = 0; - void *data; + Eina_Rectangle *rect; - 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); - - 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; - - return img; - } - else - { 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,14 +381,16 @@ 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) { @@ -456,116 +398,69 @@ evas_outbuf_flush(Outbuf *ob) 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; + int x = 0, y = 0, w = 0, h = 0; - /* get number of buffer regions */ - n = eina_array_count_get(&ob->priv.onebuf_regions); - if (n == 0) return; + if (!(rect = img->extended_info)) continue; - /* allocate rectangles */ - if (!(rects = alloca(n * sizeof(Eina_Rectangle)))) return; + x = rect->x; y = rect->y; w = rect->w; h = rect->h; - /* loop the buffer regions and assign to rects */ - EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it) - rects[i] = *rect; - - /* 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 - { - /* 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) + else if (ob->rotation == 90) { - 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; - } - - eina_rectangle_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); - - i++; + 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; } - /* TODO: unmap the buffer ?? */ - /* evas_swapper_buffer_unmap(ob->priv.swapper); */ + /* 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; + } - /* force a buffer swap */ - _evas_outbuf_buffer_swap(ob, rects, n); + eina_rectangle_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); + + i++; } + + /* force a buffer swap */ + _evas_outbuf_buffer_swap(ob, rects, n); }