diff options
author | Chris Michael <cp.michael@samsung.com> | 2017-11-02 12:18:19 -0400 |
---|---|---|
committer | Christopher Michael <cp.michael@samsung.com> | 2019-02-25 13:17:47 -0500 |
commit | 46aae64b3404d2cb24ee2d7735804d5a2c145a22 (patch) | |
tree | fe95571e3a633d1fe3dbb052304267e9769ec6e8 | |
parent | b532cc850f642a1f1e7862d7eadf5ee756733e05 (diff) | |
download | efl-46aae64b3404d2cb24ee2d7735804d5a2c145a22.tar.gz |
evas-drm: Refactor evas drm engine to work with multiple outputs
This commit refactors the evas drm engine in order to support multiple
outputs
@feature
Signed-off-by: Chris Michael <cp.michael@samsung.com>
-rw-r--r-- | src/modules/evas/engines/drm/Evas_Engine_Drm.h | 7 | ||||
-rw-r--r-- | src/modules/evas/engines/drm/evas_engine.c | 18 | ||||
-rw-r--r-- | src/modules/evas/engines/drm/evas_engine.h | 28 | ||||
-rw-r--r-- | src/modules/evas/engines/drm/evas_outbuf.c | 245 |
4 files changed, 164 insertions, 134 deletions
diff --git a/src/modules/evas/engines/drm/Evas_Engine_Drm.h b/src/modules/evas/engines/drm/Evas_Engine_Drm.h index 24d0fa41d5..778d0fc65d 100644 --- a/src/modules/evas/engines/drm/Evas_Engine_Drm.h +++ b/src/modules/evas/engines/drm/Evas_Engine_Drm.h @@ -12,10 +12,11 @@ typedef struct _Evas_Engine_Info_Drm struct { Ecore_Drm2_Device *dev; - int depth, bpp; - unsigned int format, rotation; - Ecore_Drm2_Output *output; + + int rotation, bpp; + unsigned int depth, format; + Eina_Bool alpha : 1; Eina_Bool vsync : 1; } info; diff --git a/src/modules/evas/engines/drm/evas_engine.c b/src/modules/evas/engines/drm/evas_engine.c index 63719018ec..ffafb6a11a 100644 --- a/src/modules/evas/engines/drm/evas_engine.c +++ b/src/modules/evas/engines/drm/evas_engine.c @@ -5,7 +5,7 @@ typedef struct _Render_Engine { Render_Output_Software_Generic generic; - Ecore_Drm2_Device *dev; + Evas_Engine_Info_Drm *einfo; } Render_Engine; struct scanout_handle @@ -31,8 +31,6 @@ eng_output_setup(void *engine, void *einfo, unsigned int w, unsigned int h) ob = _outbuf_setup(info, w, h); if (!ob) goto err; - re->dev = info->info.dev; - if (!evas_render_engine_software_generic_init(engine, &re->generic, ob, _outbuf_state_get, _outbuf_rotation_get, @@ -51,7 +49,7 @@ eng_output_setup(void *engine, void *einfo, unsigned int w, unsigned int h) evas_render_engine_software_generic_merge_mode_set(&re->generic); - re->generic.ob->info = einfo; + re->einfo = einfo; return re; @@ -76,7 +74,7 @@ eng_output_resize(void *engine EINA_UNUSED, void *data, int w, int h) Render_Engine *re = data; Evas_Engine_Info_Drm *info; - info = re->generic.ob->info; + info = re->einfo; if (!info) return; _outbuf_reconfigure(re->generic.ob, w, h, @@ -113,7 +111,7 @@ eng_output_free(void *engine, void *data) } static Ecore_Drm2_Fb * -drm_import_simple_dmabuf(Ecore_Drm2_Device *dev, struct dmabuf_attributes *attributes) +drm_import_simple_dmabuf(Outbuf *ob, struct dmabuf_attributes *attributes) { unsigned int stride[4] = { 0 }; int dmabuf_fd[4] = { 0 }; @@ -125,8 +123,8 @@ drm_import_simple_dmabuf(Ecore_Drm2_Device *dev, struct dmabuf_attributes *attri dmabuf_fd[i] = attributes->fd[i]; } - return ecore_drm2_fb_dmabuf_import(dev, attributes->width, - attributes->height, 32, 32, + return ecore_drm2_fb_dmabuf_import(ob->dev, attributes->width, + attributes->height, ob->depth, ob->bpp, attributes->format, stride, dmabuf_fd, attributes->n_planes); } @@ -190,7 +188,7 @@ eng_image_plane_assign(void *data, void *image, int x, int y) * sticking to this one for now */ if (n->ns.type != EVAS_NATIVE_SURFACE_WL_DMABUF) return NULL; - fb = drm_import_simple_dmabuf(re->dev, &n->ns_data.wl_surface_dmabuf.attr); + fb = drm_import_simple_dmabuf(ob, &n->ns_data.wl_surface_dmabuf.attr); if (!fb) return NULL; g = calloc(1, sizeof(struct scanout_handle)); @@ -203,7 +201,7 @@ eng_image_plane_assign(void *data, void *image, int x, int y) /* Fail or not, we're going to drop that fb and let refcounting get rid of * it later */ - plane = ecore_drm2_plane_assign(ob->priv.output, fb, x, y); + plane = ecore_drm2_plane_assign(ob->output, fb, x, y); out: ecore_drm2_fb_discard(fb); diff --git a/src/modules/evas/engines/drm/evas_engine.h b/src/modules/evas/engines/drm/evas_engine.h index ea8a6cec03..c80381f18f 100644 --- a/src/modules/evas/engines/drm/evas_engine.h +++ b/src/modules/evas/engines/drm/evas_engine.h @@ -9,8 +9,6 @@ # include <Ecore.h> # include <Ecore_Drm2.h> # include <drm_fourcc.h> -# include <xf86drm.h> -# include <xf86drmMode.h> # include "../software_generic/Evas_Engine_Software_Generic.h" @@ -53,28 +51,24 @@ typedef struct _Outbuf_Fb struct _Outbuf { Ecore_Drm2_Device *dev; - int w, h, bpp, rotation; - unsigned int depth, format; + Ecore_Drm2_Output *output; + Ecore_Drm2_Plane *plane; + + Outbuf_Fb ofb[4], *draw; - Evas_Engine_Info_Drm *info; + int num_buffers; + int w, h, rotation, bpp; + unsigned int depth, format; - struct - { - Eina_List *fb_list; - Outbuf_Fb *draw; - Ecore_Drm2_Output *output; - Ecore_Drm2_Plane *plane; - Eina_List *pending; - Eina_Rectangle *rects; - unsigned int rect_count; - int unused_duration; - } priv; + Eina_List *pending; + Eina_Rectangle *rects; + unsigned int count; Eina_Bool alpha : 1; Eina_Bool vsync : 1; }; -Outbuf *_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h); +Outbuf *_outbuf_setup(Evas_Engine_Info_Drm *einfo, int w, int h); void _outbuf_free(Outbuf *ob); int _outbuf_rotation_get(Outbuf *ob); void _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth); diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c index f53f9683db..68fd3827f4 100644 --- a/src/modules/evas/engines/drm/evas_outbuf.c +++ b/src/modules/evas/engines/drm/evas_outbuf.c @@ -5,41 +5,14 @@ #define GREEN_MASK 0x00ff00 #define BLUE_MASK 0x0000ff -#define MAX_BUFFERS 10 -#define QUEUE_TRIM_DURATION 100 - -static void -_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) -{ - /* Ecore_Drm2_Plane *plane; */ - Outbuf_Fb *ofb; - - ofb = ob->priv.draw; - if (!ofb) return; - - ecore_drm2_fb_dirty(ofb->fb, rects, count); - - if (!ob->priv.plane) - ob->priv.plane = ecore_drm2_plane_assign(ob->priv.output, ofb->fb, 0, 0); - else ecore_drm2_plane_fb_set(ob->priv.plane, ofb->fb); - - ecore_drm2_fb_flip(ofb->fb, ob->priv.output); - ofb->drawn = EINA_TRUE; - ofb->age = 0; -} - -static Outbuf_Fb * -_outbuf_fb_create(Outbuf *ob, int w, int h) +static Eina_Bool +_outbuf_fb_create(Outbuf *ob, Outbuf_Fb *ofb, int w, int h) { - Outbuf_Fb *out; + fprintf(stdout, "Evas Drm: Creating Framebuffer: %dx%d\n", w, h); - out = calloc(1, sizeof(Outbuf_Fb)); - if (!out) return NULL; - - out->fb = - ecore_drm2_fb_create(ob->dev, w, h, - ob->depth, ob->bpp, ob->format); - if (!out->fb) + ofb->fb = + ecore_drm2_fb_create(ob->dev, w, h, ob->depth, ob->bpp, ob->format); + if (!ofb->fb) { WRN("Failed To Create FB: %d %d", w, h); free(out); @@ -69,6 +42,8 @@ Outbuf * _outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) { Outbuf *ob; + char *num; + int i = 0, fw, fh; ob = calloc(1, sizeof(Outbuf)); if (!ob) return NULL; @@ -77,13 +52,43 @@ _outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) ob->h = h; ob->dev = info->info.dev; ob->alpha = info->info.alpha; - ob->rotation = info->info.rotation; ob->bpp = info->info.bpp; ob->depth = info->info.depth; ob->format = info->info.format; + ob->rotation = info->info.rotation; + ob->output = info->info.output; - ob->priv.output = info->info.output; + ob->num_buffers = 3; + num = getenv("EVAS_DRM_BUFFERS"); + if (num) + { + ob->num_buffers = atoi(num); + if (ob->num_buffers <= 0) ob->num_buffers = 3; + else if (ob->num_buffers > 4) ob->num_buffers = 4; + } + + if ((!w) || (!h)) return ob; + + if ((ob->rotation == 0) || (ob->rotation == 180)) + { + fw = w; + fh = h; + } + else if ((ob->rotation == 90) || (ob->rotation == 270)) + { + fw = h; + fh = w; + } + + for (i = 0; i < ob->num_buffers; i++) + { + if (!_outbuf_fb_create(ob, &(ob->ofb[i]), fw, fh)) + { + WRN("Failed to create framebuffer %d", i); + continue; + } + } return ob; } @@ -93,14 +98,14 @@ _outbuf_free(Outbuf *ob) { Outbuf_Fb *ofb; - while (ob->priv.pending) + while (ob->pending) { RGBA_Image *img; Eina_Rectangle *rect; - img = ob->priv.pending->data; - ob->priv.pending = - eina_list_remove_list(ob->priv.pending, ob->priv.pending); + img = ob->pending->data; + ob->pending = + eina_list_remove_list(ob->pending, ob->pending); rect = img->extended_info; @@ -109,12 +114,11 @@ _outbuf_free(Outbuf *ob) eina_rectangle_free(rect); } - /* TODO: idle flush */ - _outbuf_flush(ob, NULL, NULL, EVAS_RENDER_MODE_UNDEF); + /* TODO: idle flush */ - EINA_LIST_FREE(ob->priv.fb_list, ofb) - _outbuf_fb_destroy(ofb); + for (; i < ob->num_buffers; i++) + _outbuf_fb_destroy(&ob->ofb[i]); free(ob); } @@ -128,7 +132,7 @@ _outbuf_rotation_get(Outbuf *ob) void _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth) { - Outbuf_Fb *ofb; + int i = 0, fw, fh; unsigned int format = DRM_FORMAT_ARGB8888; switch (depth) @@ -181,10 +185,32 @@ _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth) ob->rotation = rotation; ob->priv.unused_duration = 0; - EINA_LIST_FREE(ob->priv.fb_list, ofb) - _outbuf_fb_destroy(ofb); + for (; i < ob->num_buffers; i++) + _outbuf_fb_destroy(&ob->ofb[i]); - /* TODO: idle flush */ + if ((!w) || (!h)) return; + + if ((ob->rotation == 0) || (ob->rotation == 180)) + { + fw = w; + fh = h; + } + else if ((ob->rotation == 90) || (ob->rotation == 270)) + { + fw = h; + fh = w; + } + + for (i = 0; i < ob->num_buffers; i++) + { + if (!_outbuf_fb_create(ob, &(ob->ofb[i]), fw, fh)) + { + WRN("Failed to create framebuffer %d", i); + continue; + } + } + + /* TODO: idle_flush */ } static Outbuf_Fb * @@ -194,17 +220,23 @@ _outbuf_fb_wait(Outbuf *ob) Outbuf_Fb *ofb, *best = NULL; int best_age = -1, num_required = 1, num_allocated = 0; + fprintf(stderr, "FB Wait on Output %s\n", + ecore_drm2_output_name_get(ob->output)); + /* We pick the oldest available buffer to avoid using the same two - * repeatedly and then having the third be stale when we need it - */ - EINA_LIST_FOREACH(ob->priv.fb_list, l, ofb) + * repeatedly and then having the third be stale when we need it */ + for (i = 0; i < ob->num_buffers; i++) { - num_allocated++; - if (ecore_drm2_fb_busy_get(ofb->fb)) + if (ecore_drm2_fb_busy_get(ob->ofb[i].fb)) { - num_required++; + fprintf(stderr, "\t FB %d Busy\n", i); continue; } + if (ob->ofb[i].valid && (ob->ofb[i].age > best_age)) + { + best = i; + best_age = ob->ofb[i].age; + } if (ofb->valid && (ofb->age > best_age)) { best = ofb; @@ -229,7 +261,8 @@ _outbuf_fb_wait(Outbuf *ob) best = _outbuf_fb_wait(ob); } - return best; + if (best >= 0) return &(ob->ofb[best]); + return NULL; } static Eina_Bool @@ -239,41 +272,25 @@ _outbuf_fb_assign(Outbuf *ob) Outbuf_Fb *ofb; Eina_List *l; - ob->priv.draw = _outbuf_fb_wait(ob); - if (!ob->priv.draw) - { - EINA_SAFETY_ON_TRUE_RETURN_VAL(eina_list_count(ob->priv.fb_list) >= MAX_BUFFERS, EINA_FALSE); - - if ((ob->rotation == 0) || (ob->rotation == 180)) - { - fw = ob->w; - fh = ob->h; - } - else if ((ob->rotation == 90) || (ob->rotation == 270)) - { - fw = ob->h; - fh = ob->w; - } - ob->priv.draw = _outbuf_fb_create(ob, fw, fh); - if (ob->priv.draw) - ob->priv.fb_list = eina_list_append(ob->priv.fb_list, ob->priv.draw); - } + fprintf(stderr, "FB Assign on Output %s\n", + ecore_drm2_output_name_get(ob->output)); - while (!ob->priv.draw) + ob->draw = _outbuf_fb_wait(ob); + while (!ob->draw) { - ecore_drm2_fb_release(ob->priv.output, EINA_TRUE); - ob->priv.draw = _outbuf_fb_wait(ob); + ecore_drm2_fb_release(ob->output, EINA_TRUE); + ob->draw = _outbuf_fb_wait(ob); } - EINA_LIST_FOREACH(ob->priv.fb_list, l, ofb) + for (i = 0; i < ob->num_buffers; i++) { - if ((ofb->valid) && (ofb->drawn)) + if ((ob->ofb[i].valid) && (ob->ofb[i].drawn)) { - ofb->age++; - if (ofb->age > 4) + ob->ofb[i].age++; + if (ob->ofb[i].age > 4) { - ofb->age = 0; - ofb->drawn = EINA_FALSE; + ob->ofb[i].age = 0; + ob->ofb[i].drawn = EINA_FALSE; } } } @@ -284,12 +301,13 @@ _outbuf_fb_assign(Outbuf *ob) Render_Output_Swap_Mode _outbuf_state_get(Outbuf *ob) { - int age; + int age = 0; if (!_outbuf_fb_assign(ob)) return MODE_FULL; - age = ob->priv.draw->age; - if (age > 4) return MODE_FULL; + if (ob->draw) age = ob->draw->age; + + if (age > ob->num_buffers) return MODE_FULL; else if (age == 1) return MODE_COPY; else if (age == 2) return MODE_DOUBLE; else if (age == 3) return MODE_TRIPLE; @@ -331,8 +349,8 @@ _outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int * if (ch) *ch = h; /* add this cached image data to pending writes */ - ob->priv.pending = - eina_list_append(ob->priv.pending, img); + ob->pending = + eina_list_append(ob->pending, img); return img; } @@ -344,7 +362,6 @@ _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, Eina_Rectangle rect = {0, 0, 0, 0}, pr; DATA32 *src; DATA8 *dst; - Ecore_Drm2_Fb *buff; int bpp = 0, bpl = 0; int rx = 0, ry = 0; int bw = 0, bh = 0; @@ -353,16 +370,15 @@ _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, if (!ob) return; /* check for pending writes */ - if (!ob->priv.pending) return; + if (!ob->pending) return; /* check for valid source data */ if (!(src = update->image.data)) return; /* check for valid desination data */ - if (!ob->priv.draw) return; - buff = ob->priv.draw->fb; + if (!ob->draw) return; - dst = ecore_drm2_fb_data_get(buff); + dst = ecore_drm2_fb_data_get(ob->draw->fb); if (!dst) return; if ((ob->rotation == 0) || (ob->rotation == 180)) @@ -423,7 +439,7 @@ _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, /* bpp = (ob->depth / 8); */ /* if (bpp <= 0) return; */ - bpl = ecore_drm2_fb_stride_get(buff); + bpl = ecore_drm2_fb_stride_get(ob->draw->fb); if (ob->rotation == 0) { @@ -476,19 +492,20 @@ _outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf_Rect if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; - if (ob->priv.rect_count) free(ob->priv.rects); + if (ob->count) free(ob->rects); /* get number of pending writes */ - ob->priv.rect_count = eina_list_count(ob->priv.pending); - if (ob->priv.rect_count == 0) return; + ob->count = eina_list_count(ob->pending); + if (ob->count == 0) return; /* allocate rectangles */ - ob->priv.rects = malloc(ob->priv.rect_count * sizeof(Eina_Rectangle)); - if (!ob->priv.rects) return; - r = ob->priv.rects; + ob->rects = malloc(ob->count * sizeof(Eina_Rectangle)); + if (!ob->rects) return; + + r = ob->rects; /* loop the pending writes */ - EINA_LIST_FREE(ob->priv.pending, img) + EINA_LIST_FREE(ob->pending, img) { Eina_Rectangle *rect; int x = 0, y = 0, w = 0, h = 0; @@ -540,12 +557,32 @@ _outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf_Rect } } +static void +_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) +{ + Outbuf_Fb *ofb; + + ofb = ob->draw; + if (!ofb) return; + + ecore_drm2_fb_dirty(ofb->fb, rects, count); + + if (!ob->plane) + ob->plane = ecore_drm2_plane_assign(ob->output, ofb->fb, 0, 0); + else + ecore_drm2_plane_fb_set(ob->plane, ofb->fb); + + ecore_drm2_fb_flip(ofb->fb, ob->output); + ofb->drawn = EINA_TRUE; + ofb->age = 0; +} + void _outbuf_redraws_clear(Outbuf *ob) { - if (!ob->priv.rect_count) return; + if (!ob->count) return; - _outbuf_buffer_swap(ob, ob->priv.rects, ob->priv.rect_count); - free(ob->priv.rects); - ob->priv.rect_count = 0; + _outbuf_buffer_swap(ob, ob->rects, ob->count); + free(ob->rects); + ob->count = 0; } |