summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2017-11-02 12:18:19 -0400
committerChristopher Michael <cp.michael@samsung.com>2019-02-25 13:17:47 -0500
commit46aae64b3404d2cb24ee2d7735804d5a2c145a22 (patch)
treefe95571e3a633d1fe3dbb052304267e9769ec6e8
parentb532cc850f642a1f1e7862d7eadf5ee756733e05 (diff)
downloadefl-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.h7
-rw-r--r--src/modules/evas/engines/drm/evas_engine.c18
-rw-r--r--src/modules/evas/engines/drm/evas_engine.h28
-rw-r--r--src/modules/evas/engines/drm/evas_outbuf.c245
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;
}