summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2015-06-05 10:01:46 -0400
committerChris Michael <cp.michael@samsung.com>2015-06-05 10:01:46 -0400
commite3a16aeacd82eb9d5dce14f08abd26a964fcb792 (patch)
treef546e33d7c3e8c3599cea8584b7c3d1844522a35
parent3f4c569341ab501b188f49c273bb961e0f1b75ee (diff)
parent939d221ff119f82fc30674d8c293b6b8a18a4db1 (diff)
Merge branch 'devs/devilhorns/gl_drm'
This merges a refactored evas gl_drm engine which actually functions now :)
-rw-r--r--src/Makefile_Evas.am3
-rw-r--r--src/lib/ecore_drm/ecore_drm_fb.c6
-rw-r--r--src/lib/ecore_drm/ecore_drm_output.c3
-rw-r--r--src/lib/ecore_evas/ecore_evas_module.c2
-rw-r--r--src/modules/ecore_evas/engines/drm/ecore_evas_drm.c53
-rw-r--r--src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h33
-rw-r--r--src/modules/evas/engines/gl_drm/evas_drm.c347
-rw-r--r--src/modules/evas/engines/gl_drm/evas_drm_main.c636
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.c749
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.h204
-rw-r--r--src/modules/evas/engines/gl_drm/evas_outbuf.c702
11 files changed, 1229 insertions, 1509 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index e5b771d8da..de4626ba62 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -1199,8 +1199,7 @@ endif
1199if BUILD_ENGINE_GL_DRM 1199if BUILD_ENGINE_GL_DRM
1200dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h 1200dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
1201GL_DRM_SOURCES = \ 1201GL_DRM_SOURCES = \
1202modules/evas/engines/gl_drm/evas_drm.c \ 1202modules/evas/engines/gl_drm/evas_outbuf.c \
1203modules/evas/engines/gl_drm/evas_drm_main.c \
1204modules/evas/engines/gl_drm/evas_engine.c \ 1203modules/evas/engines/gl_drm/evas_engine.c \
1205modules/evas/engines/gl_drm/evas_engine.h \ 1204modules/evas/engines/gl_drm/evas_engine.h \
1206modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h 1205modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
diff --git a/src/lib/ecore_drm/ecore_drm_fb.c b/src/lib/ecore_drm/ecore_drm_fb.c
index 18ba8ad5d3..69c6107617 100644
--- a/src/lib/ecore_drm/ecore_drm_fb.c
+++ b/src/lib/ecore_drm/ecore_drm_fb.c
@@ -141,8 +141,8 @@ EAPI void
141ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count) 141ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count)
142{ 142{
143 EINA_SAFETY_ON_NULL_RETURN(fb); 143 EINA_SAFETY_ON_NULL_RETURN(fb);
144 EINA_SAFETY_ON_NULL_RETURN(rects); 144
145 EINA_SAFETY_ON_TRUE_RETURN(!count); 145 if ((!rects) || (!count)) return;
146 146
147#ifdef DRM_MODE_FEATURE_DIRTYFB 147#ifdef DRM_MODE_FEATURE_DIRTYFB
148 drmModeClip *clip; 148 drmModeClip *clip;
@@ -238,8 +238,6 @@ ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb
238 EINA_LIST_FOREACH(dev->outputs, l, output) 238 EINA_LIST_FOREACH(dev->outputs, l, output)
239 if (output->enabled) cb->count++; 239 if (output->enabled) cb->count++;
240 240
241 /* cb->count = eina_list_count(dev->outputs); */
242
243 EINA_LIST_FOREACH(dev->outputs, l, output) 241 EINA_LIST_FOREACH(dev->outputs, l, output)
244 { 242 {
245 if ((!output->enabled) || (!output->current_mode)) continue; 243 if ((!output->enabled) || (!output->current_mode)) continue;
diff --git a/src/lib/ecore_drm/ecore_drm_output.c b/src/lib/ecore_drm/ecore_drm_output.c
index d6573f3a3d..892c20fde8 100644
--- a/src/lib/ecore_drm/ecore_drm_output.c
+++ b/src/lib/ecore_drm/ecore_drm_output.c
@@ -710,7 +710,6 @@ next:
710 { 710 {
711 disconnects &= ~(1 << output->conn_id); 711 disconnects &= ~(1 << output->conn_id);
712 _ecore_drm_output_event_send(output, EINA_FALSE); 712 _ecore_drm_output_event_send(output, EINA_FALSE);
713 ecore_drm_output_free(output);
714 } 713 }
715 } 714 }
716 } 715 }
@@ -763,6 +762,7 @@ _ecore_drm_output_render_disable(Ecore_Drm_Output *output)
763 EINA_SAFETY_ON_NULL_RETURN(output); 762 EINA_SAFETY_ON_NULL_RETURN(output);
764 763
765 output->need_repaint = EINA_FALSE; 764 output->need_repaint = EINA_FALSE;
765 if (!output->enabled) return;
766 ecore_drm_output_cursor_size_set(output, 0, 0, 0); 766 ecore_drm_output_cursor_size_set(output, 0, 0, 0);
767 ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_OFF); 767 ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_OFF);
768} 768}
@@ -951,6 +951,7 @@ EAPI void
951ecore_drm_output_cursor_size_set(Ecore_Drm_Output *output, int handle, int w, int h) 951ecore_drm_output_cursor_size_set(Ecore_Drm_Output *output, int handle, int w, int h)
952{ 952{
953 EINA_SAFETY_ON_NULL_RETURN(output); 953 EINA_SAFETY_ON_NULL_RETURN(output);
954 if (!output->enabled) return;
954 drmModeSetCursor(output->dev->drm.fd, output->crtc_id, handle, w, h); 955 drmModeSetCursor(output->dev->drm.fd, output->crtc_id, handle, w, h);
955} 956}
956 957
diff --git a/src/lib/ecore_evas/ecore_evas_module.c b/src/lib/ecore_evas/ecore_evas_module.c
index 6cb9cd1934..59fb6010cb 100644
--- a/src/lib/ecore_evas/ecore_evas_module.c
+++ b/src/lib/ecore_evas/ecore_evas_module.c
@@ -263,7 +263,7 @@ _ecore_evas_available_engines_get(void)
263 ADDENG("drm"); 263 ADDENG("drm");
264#endif 264#endif
265#ifdef BUILD_ECORE_EVAS_GL_DRM 265#ifdef BUILD_ECORE_EVAS_GL_DRM
266 ADDENG("opengl_drm"); 266 ADDENG("gl_drm");
267#endif 267#endif
268 } 268 }
269 } 269 }
diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
index 01c230b47c..682cbe8351 100644
--- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
+++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
@@ -322,11 +322,6 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED,
322 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, 322 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
323 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); 323 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
324 324
325 evas_event_feed_mouse_in(ee->evas,
326 (unsigned int)((unsigned long long)
327 (ecore_time_get() * 1000.0) &
328 0xffffffff), NULL);
329
330 return ee; 325 return ee;
331 326
332eng_err: 327eng_err:
@@ -346,7 +341,7 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
346 Ecore_Evas_Interface_Drm *iface; 341 Ecore_Evas_Interface_Drm *iface;
347 Ecore_Evas_Engine_Drm_Data *edata; 342 Ecore_Evas_Engine_Drm_Data *edata;
348 int method; 343 int method;
349 uint32_t format = GBM_FORMAT_ARGB8888; 344 uint32_t format = GBM_FORMAT_XRGB8888;
350 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; 345 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
351 char *num; 346 char *num;
352 347
@@ -360,6 +355,12 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
360 /* try to init drm */ 355 /* try to init drm */
361 if (_ecore_evas_drm_init(device) < 1) return NULL; 356 if (_ecore_evas_drm_init(device) < 1) return NULL;
362 357
358 if (!ecore_drm_device_software_setup(dev))
359 {
360 ERR("Could not setup device for software");
361 goto soft_err;
362 }
363
363 /* try to load gl libary, gbm libary */ 364 /* try to load gl libary, gbm libary */
364 /* Typically, gbm loads the dri driver However some versions of Mesa 365 /* Typically, gbm loads the dri driver However some versions of Mesa
365 * do not have libglapi symbols linked in the driver. Because of this, 366 * do not have libglapi symbols linked in the driver. Because of this,
@@ -427,9 +428,16 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
427 evas_data_attach_set(ee->evas, ee); 428 evas_data_attach_set(ee->evas, ee);
428 evas_output_method_set(ee->evas, method); 429 evas_output_method_set(ee->evas, method);
429 430
430 /* FIXME: Support initial rotation ?? */ 431 if ((ee->rotation == 90) || (ee->rotation == 270))
431 evas_output_size_set(ee->evas, w, h); 432 {
432 evas_output_viewport_set(ee->evas, 0, 0, w, h); 433 evas_output_size_set(ee->evas, h, w);
434 evas_output_viewport_set(ee->evas, 0, 0, h, w);
435 }
436 else
437 {
438 evas_output_size_set(ee->evas, w, h);
439 evas_output_viewport_set(ee->evas, 0, 0, w, h);
440 }
433 441
434 if (ee->can_async_render) 442 if (ee->can_async_render)
435 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, 443 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
@@ -437,6 +445,8 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
437 445
438 if ((einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(ee->evas))) 446 if ((einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(ee->evas)))
439 { 447 {
448 Ecore_Drm_Output *output;
449
440 einfo->info.depth = 32; 450 einfo->info.depth = 32;
441 einfo->info.destination_alpha = ee->alpha; 451 einfo->info.destination_alpha = ee->alpha;
442 einfo->info.rotation = ee->rotation; 452 einfo->info.rotation = ee->rotation;
@@ -444,24 +454,22 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
444 if ((num = getenv("EVAS_DRM_VSYNC"))) 454 if ((num = getenv("EVAS_DRM_VSYNC")))
445 { 455 {
446 if (!atoi(num)) 456 if (!atoi(num))
447 einfo->vsync = EINA_FALSE; 457 einfo->info.vsync = EINA_FALSE;
448 else 458 else
449 einfo->vsync = EINA_TRUE; 459 einfo->info.vsync = EINA_TRUE;
450 } 460 }
451 else 461 else
452 einfo->vsync = EINA_TRUE; 462 einfo->info.vsync = EINA_TRUE;
453 463
454 einfo->info.fd = ecore_drm_device_fd_get(dev);
455 einfo->info.dev = dev; 464 einfo->info.dev = dev;
456 einfo->info.format = format; 465 einfo->info.format = format;
457 einfo->info.flags = flags; 466 einfo->info.flags = flags;
458 467
459 if (einfo->info.fd) 468 if ((output = ecore_drm_device_output_find(dev, x, y)))
460 einfo->info.gbm = gbm_create_device(einfo->info.fd);
461 if (einfo->info.gbm)
462 { 469 {
463 einfo->info.surface = 470 einfo->info.conn_id = ecore_drm_output_connector_id_get(output);
464 gbm_surface_create(einfo->info.gbm, w, h, format, flags); 471 einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output);
472 einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output);
465 } 473 }
466 474
467 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) 475 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
@@ -476,7 +484,7 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
476 goto eng_err; 484 goto eng_err;
477 } 485 }
478 486
479 ee->prop.window = einfo->info.output; 487 ee->prop.window = einfo->info.buffer_id;
480 488
481 _ecore_evas_register(ee); 489 _ecore_evas_register(ee);
482 ecore_evas_input_event_register(ee); 490 ecore_evas_input_event_register(ee);
@@ -488,18 +496,13 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS
488 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, 496 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
489 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); 497 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
490 498
491 evas_event_feed_mouse_in(ee->evas,
492 (unsigned int)((unsigned long long)
493 (ecore_time_get() * 1000.0) &
494 0xffffffff), NULL);
495
496 return ee; 499 return ee;
497 500
498eng_err: 501eng_err:
499 ecore_evas_free(ee); 502 ecore_evas_free(ee);
503soft_err:
500ee_err: 504ee_err:
501 _ecore_evas_drm_shutdown(); 505 _ecore_evas_drm_shutdown();
502
503 return NULL; 506 return NULL;
504} 507}
505#endif 508#endif
diff --git a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
index 92069b61e0..17fe8cbabc 100644
--- a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
+++ b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
@@ -1,44 +1,43 @@
1#ifndef _EVAS_ENGINE_GL_DRM_H 1#ifndef _EVAS_ENGINE_GL_DRM_H
2# define _EVAS_ENGINE_GL_DRM_H 2# define _EVAS_ENGINE_GL_DRM_H
3 3
4# include <gbm.h>
5# include <Ecore_Drm.h> 4# include <Ecore_Drm.h>
5# include <gbm.h>
6 6
7typedef struct _Evas_Engine_Info_GL_Drm Evas_Engine_Info_GL_Drm; 7typedef struct _Evas_Engine_Info_GL_Drm Evas_Engine_Info_GL_Drm;
8 8
9struct _Evas_Engine_Info_GL_Drm 9struct _Evas_Engine_Info_GL_Drm
10{ 10{
11 /* PRIVATE - don't mess with this baby or evas will poke its tongue out 11 /* PRIVATE - don't mess with this baby or evas will poke its tongue out */
12 * at you and make nasty noises */ 12 /* at you and make nasty noises */
13 Evas_Engine_Info magic; 13 Evas_Engine_Info magic;
14 14
15 /* engine specific data & parameters it needs to set up */ 15 struct
16 struct
17 { 16 {
18 struct gbm_device *gbm; 17 struct gbm_device *gbm;
19 struct gbm_surface *surface; 18 struct gbm_surface *surface;
20 uint32_t format; 19
21 uint32_t flags; 20 unsigned int rotation, depth;
22 int depth, screen, rotation; 21 unsigned int crtc_id, conn_id, buffer_id;
23 unsigned char destination_alpha : 1; 22 unsigned int format, flags;
24 int fd; 23
25 int output, plane;
26 Ecore_Drm_Device *dev; 24 Ecore_Drm_Device *dev;
25
26 Eina_Bool destination_alpha : 1;
27 Eina_Bool vsync : 1;
28 Eina_Bool indirect : 1;
29 unsigned char swap_mode : 4;
27 } info; 30 } info;
28 31
29 struct 32 struct
30 { 33 {
31 void (*pre_swap) (void *data, Evas *evas); 34 void (*pre_swap)(void *data, Evas *evas);
32 void (*post_swap) (void *data, Evas *evas); 35 void (*post_swap)(void *data, Evas *evas);
33 void *data; 36 void *data;
34 } callback; 37 } callback;
35 38
36 /* non-blocking or blocking mode */ 39 /* non-blocking or blocking mode */
37 Evas_Engine_Render_Mode render_mode; 40 Evas_Engine_Render_Mode render_mode;
38
39 unsigned char vsync : 1;
40 unsigned char indirect : 1;
41 unsigned char swap_mode : 4;
42}; 41};
43 42
44#endif 43#endif
diff --git a/src/modules/evas/engines/gl_drm/evas_drm.c b/src/modules/evas/engines/gl_drm/evas_drm.c
deleted file mode 100644
index c049fb9629..0000000000
--- a/src/modules/evas/engines/gl_drm/evas_drm.c
+++ /dev/null
@@ -1,347 +0,0 @@
1#include "evas_engine.h"
2#include <sys/mman.h>
3
4static void
5_evas_drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
6{
7 Buffer *buffer = data;
8 struct gbm_device *gbm = gbm_bo_get_device(bo);
9
10 if (buffer->fb)
11 drmModeRmFB(gbm_device_get_fd(gbm), buffer->fb);
12}
13
14static unsigned int
15_evas_drm_crtc_buffer_get(int fd, int crtc_id)
16{
17 drmModeCrtc *crtc;
18 unsigned int id;
19
20 if (!(crtc = drmModeGetCrtc(fd, crtc_id))) return 0;
21 id = crtc->buffer_id;
22 drmModeFreeCrtc(crtc);
23 return id;
24}
25
26static void
27_evas_drm_outbuf_page_flip(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED, void *data)
28{
29 Outbuf *ob;
30 Buffer *buff;
31
32 /* get the output buffer from data */
33 if (!(ob = data)) return;
34
35 buff = &(ob->priv.buffer[ob->priv.curr]);
36 gbm_surface_release_buffer(ob->surface, buff->bo);
37
38 ob->priv.pending_flip = EINA_FALSE;
39 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
40}
41
42static Eina_Bool
43_evas_drm_outbuf_planes_setup(Outbuf *ob, drmModePlaneResPtr pres)
44{
45 drmModePlanePtr dplane;
46 Plane *oplane;
47 unsigned int p = 0;
48 unsigned int f = 0;
49
50 for (p = 0; p < pres->count_planes; p++)
51 {
52 /* try to get this plane */
53 if (!(dplane = drmModeGetPlane(ob->priv.fd, pres->planes[p])))
54 continue;
55
56 /* try to allocate space for our plane */
57 if (!(oplane =
58 malloc(sizeof(Plane) +
59 ((sizeof(unsigned int)) * dplane->count_formats))))
60 {
61 drmModeFreePlane(dplane);
62 continue;
63 }
64
65 oplane->crtcs = dplane->possible_crtcs;
66 oplane->id = dplane->plane_id;
67 oplane->num_formats = dplane->count_formats;
68 memcpy(oplane->formats, dplane->formats,
69 dplane->count_formats * sizeof(dplane->formats[0]));
70
71 DBG("Plane %d, %d %d", p, dplane->x, dplane->y);
72 DBG("\tFB: %d", dplane->fb_id);
73 DBG("\tCrtc: %d, %d %d", dplane->crtc_id,
74 dplane->crtc_x, dplane->crtc_y);
75
76 DBG("\tSupported Formats");
77 for (f = 0; f < dplane->count_formats; f++)
78 {
79 DBG("\t\t%C%C%C%C", (dplane->formats[f] & 0xFF),
80 ((dplane->formats[f] >> 8) & 0xFF),
81 ((dplane->formats[f] >> 16) & 0xFF),
82 ((dplane->formats[f] >> 24) & 0xFF));
83 }
84
85 /* free this plane */
86 drmModeFreePlane(dplane);
87
88 /* append this plane */
89 ob->priv.planes = eina_list_append(ob->priv.planes, oplane);
90 }
91
92 if (eina_list_count(ob->priv.planes) < 1) return EINA_FALSE;
93 return EINA_TRUE;
94}
95
96Eina_Bool
97evas_drm_gbm_init(Evas_Engine_Info_GL_Drm *info, int w, int h)
98{
99 if (!info) return EINA_FALSE;
100 if (info->info.fd < 0) return EINA_FALSE;
101
102 if (!(info->info.gbm = gbm_create_device(info->info.fd)))
103 return EINA_FALSE;
104
105 if (!(info->info.surface =
106 gbm_surface_create(info->info.gbm, w, h,
107 info->info.format, info->info.flags)))
108 {
109 gbm_device_destroy(info->info.gbm);
110 info->info.gbm = NULL;
111 return EINA_FALSE;
112 }
113
114 return EINA_TRUE;
115}
116
117Eina_Bool
118evas_drm_gbm_shutdown(Evas_Engine_Info_GL_Drm *info)
119{
120 if (!info) return EINA_TRUE;
121
122 if (info->info.surface)
123 {
124 gbm_surface_destroy(info->info.surface);
125 info->info.surface = NULL;
126 }
127 if (info->info.gbm)
128 {
129 gbm_device_destroy(info->info.gbm);
130 info->info.gbm = NULL;
131 }
132
133 return EINA_TRUE;
134}
135
136Eina_Bool
137evas_drm_outbuf_setup(Outbuf *ob)
138{
139 drmModeRes *res;
140 drmModeConnector *conn;
141 drmModePlaneResPtr pres;
142 drmModeEncoder *enc;
143 drmModeModeInfo crtc_mode;
144 int i = 0;
145
146 /* check for valid Output buffer */
147 if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE;
148
149 /* setup drmHandleEvent context */
150 memset(&ob->priv.ctx, 0, sizeof(ob->priv.ctx));
151 ob->priv.ctx.version = DRM_EVENT_CONTEXT_VERSION;
152 ob->priv.ctx.page_flip_handler = _evas_drm_outbuf_page_flip;
153
154 /* try to get drm resources */
155 if (!(res = drmModeGetResources(ob->priv.fd)))
156 {
157 CRI("Could not get drm resources: %m");
158 return EINA_FALSE;
159 }
160
161 /* loop the connectors */
162 for (; i < res->count_connectors; ++i)
163 {
164 int crtc_id = -1;
165 int m = 0;
166
167 /* try to get this connector */
168 if (!(conn = drmModeGetConnector(ob->priv.fd, res->connectors[i])))
169 {
170 WRN("Could not get drm connector %d: %m", i);
171 continue;
172 }
173
174 /* make sure this connector is actually connected */
175 if (conn->connection != DRM_MODE_CONNECTED)
176 {
177 /* free connector resources */
178 drmModeFreeConnector(conn);
179 continue;
180 }
181
182 /* make sure it has modes */
183 if (conn->count_modes == 0)
184 {
185 /* free connector resources */
186 drmModeFreeConnector(conn);
187 continue;
188 }
189
190 /* record the connector id */
191 ob->priv.conn = conn->connector_id;
192
193 if ((enc = drmModeGetEncoder(ob->priv.fd, conn->encoder_id)))
194 {
195 drmModeCrtc *crtc;
196
197 if ((crtc = drmModeGetCrtc(ob->priv.fd, enc->crtc_id)))
198 {
199 crtc_id = enc->crtc_id;
200 if (crtc->mode_valid) crtc_mode = crtc->mode;
201 drmModeFreeCrtc(crtc);
202 }
203
204 drmModeFreeEncoder(enc);
205 }
206
207 /* record the crtc id */
208 ob->priv.crtc = crtc_id;
209
210 /* get the current framebuffer */
211 ob->priv.fb = _evas_drm_crtc_buffer_get(ob->priv.fd, crtc_id);
212
213 memset(&ob->priv.mode, 0, sizeof(ob->priv.mode));
214
215 for (m = 0; m < conn->count_modes; m++)
216 {
217 DBG("Output Available Mode: %d: %d %d %d", ob->priv.conn,
218 conn->modes[m].hdisplay, conn->modes[m].vdisplay,
219 conn->modes[m].vrefresh);
220 if (!memcmp(&crtc_mode, &conn->modes[m], sizeof(crtc_mode)))
221 {
222 /* record the current mode */
223 memcpy(&ob->priv.mode, &conn->modes[m], sizeof(ob->priv.mode));
224 break;
225 }
226
227 }
228
229 if ((!ob->priv.mode.hdisplay) && (crtc_mode.clock != 0))
230 memcpy(&ob->priv.mode, &crtc_mode, sizeof(ob->priv.mode));
231
232 DBG("Output Current Mode: %d: %d %d", ob->priv.conn,
233 ob->priv.mode.hdisplay, ob->priv.mode.vdisplay);
234
235 if ((ob->priv.mode.hdisplay != conn->modes[0].hdisplay) ||
236 (ob->priv.mode.vdisplay != conn->modes[0].vdisplay))
237 {
238 /* set new crtc mode */
239 drmModeSetCrtc(ob->priv.fd, ob->priv.crtc, ob->priv.fb, 0, 0,
240 &ob->priv.conn, 1, &ob->priv.mode);
241 }
242
243 /* free connector resources */
244 drmModeFreeConnector(conn);
245
246 break;
247 }
248
249 /* get any plane resource from the card */
250 pres = drmModeGetPlaneResources(ob->priv.fd);
251
252 /* if we have at least one plane, set it up */
253 if (pres->count_planes > 0)
254 {
255 if (!_evas_drm_outbuf_planes_setup(ob, pres))
256 WRN("Could not setup hardware planes");
257 }
258
259 /* free plane resources */
260 drmModeFreePlaneResources(pres);
261
262 /* free drm resources */
263 drmModeFreeResources(res);
264
265 return EINA_TRUE;
266}
267
268void
269evas_drm_outbuf_framebuffer_set(Outbuf *ob, Buffer *buffer)
270{
271 int ret;
272 uint32_t handles[4], pitches[4], offsets[4];
273 uint32_t width, height;
274 uint32_t format;
275
276 /* validate params */
277 if ((!ob) || (!buffer)) return;
278
279 if (buffer->valid) return;
280
281 width = gbm_bo_get_width(buffer->bo);
282 height = gbm_bo_get_height(buffer->bo);
283 buffer->stride = gbm_bo_get_stride(buffer->bo);
284 buffer->handle = gbm_bo_get_handle(buffer->bo).u32;
285 buffer->size = buffer->stride * height;
286 format = gbm_bo_get_format(buffer->bo);
287
288 handles[0] = buffer->handle;
289 pitches[0] = buffer->stride;
290 offsets[0] = 0;
291
292 ret = drmModeAddFB2(ob->priv.fd, width, height, format, handles,
293 pitches, offsets, &(buffer->fb), 0);
294 if (ret)
295 {
296 ret = drmModeAddFB(ob->priv.fd, width, height, 24, 32,
297 buffer->stride, buffer->handle, &(buffer->fb));
298 }
299 if (ret) ERR("Failed to AddFB: %m");
300
301 ret = drmModeSetCrtc(ob->priv.fd, ob->priv.crtc, buffer->fb, 0, 0,
302 &ob->priv.conn, 1, &ob->priv.mode);
303 if (ret) ERR("Failed to set crtc: %m");
304
305 gbm_bo_set_user_data(buffer->bo, buffer, _evas_drm_fb_destroy_callback);
306
307 buffer->valid = EINA_TRUE;
308}
309
310Eina_Bool
311evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer)
312{
313 /* check for valid Output buffer */
314 if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE;
315
316 /* check for valid buffer */
317 if (!buffer) return EINA_FALSE;
318
319 if (ob->vsync)
320 {
321 if (drmModePageFlip(ob->priv.fd, ob->priv.crtc,
322 buffer->fb, DRM_MODE_PAGE_FLIP_EVENT, ob) < 0)
323 {
324 ERR("Cannot flip crtc for connector %u: %m", ob->priv.conn);
325 return EINA_FALSE;
326 }
327
328 ob->priv.pending_flip = EINA_TRUE;
329
330 while (ob->priv.pending_flip)
331 drmHandleEvent(ob->priv.fd, &ob->priv.ctx);
332 }
333 else
334 {
335 /* NB: We don't actually need to do this if we are not vsync
336 * because we are drawing directly to the buffer anyway.
337 * If we enable the sending of buffer to crtc, it causes vsync */
338
339 /* send this buffer to the crtc */
340 /* evas_drm_outbuf_framebuffer_set(ob, buffer); */
341
342 /* increment buffer we are using */
343 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
344 }
345
346 return EINA_TRUE;
347}
diff --git a/src/modules/evas/engines/gl_drm/evas_drm_main.c b/src/modules/evas/engines/gl_drm/evas_drm_main.c
deleted file mode 100644
index 9918673974..0000000000
--- a/src/modules/evas/engines/gl_drm/evas_drm_main.c
+++ /dev/null
@@ -1,636 +0,0 @@
1#include "evas_engine.h"
2
3/* local variables */
4static Outbuf *_evas_gl_drm_window = NULL;
5static EGLContext context = EGL_NO_CONTEXT;
6static int win_count = 0;
7
8/* local function prototypes */
9static void _outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count);
10static void _outbuf_flush_famebuffer(Outbuf *ob);
11
12/* local functions */
13static void
14_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects EINA_UNUSED, unsigned int count EINA_UNUSED)
15{
16 Buffer *buff;
17
18 buff = &(ob->priv.buffer[ob->priv.curr]);
19
20 buff->bo = gbm_surface_lock_front_buffer(ob->surface);
21
22 /* if this buffer is not valid, we need to set it */
23 if (!buff->valid) evas_drm_outbuf_framebuffer_set(ob, buff);
24
25 /* send this buffer to the crtc */
26 evas_drm_framebuffer_send(ob, buff);
27}
28
29static void
30_outbuf_flush_famebuffer(Outbuf *ob)
31{
32 Eina_Rectangle *rects = NULL;
33 unsigned int n = 0;
34 //TODO: add region flush routine for SwapBuffersWithDamage
35
36 /* force a buffer swap */
37 _outbuf_buffer_swap(ob, rects, n);
38}
39
40Outbuf *
41eng_window_new(Evas_Engine_Info_GL_Drm *info, Evas *e, struct gbm_device *gbm, struct gbm_surface *surface, int screen, int depth, int w, int h, int indirect EINA_UNUSED, int alpha, int rot, Render_Engine_Swap_Mode swap_mode)
42{
43 Outbuf *gw;
44 int context_attrs[3];
45 int config_attrs[40];
46 int major_version, minor_version;
47 int num_config, n = 0;
48 const GLubyte *vendor, *renderer, *version, *glslversion;
49 Eina_Bool blacklist = EINA_FALSE;
50 char *num;
51
52 /* try to allocate space for outbuf */
53 gw = calloc(1, sizeof(Outbuf));
54 if (!gw) return NULL;
55
56 /* set properties of outbuf */
57 win_count++;
58 gw->gbm = gbm;
59 gw->surface = surface;
60 gw->screen = screen;
61 gw->depth = depth;
62 gw->w = w;
63 gw->h = h;
64 gw->alpha = alpha;
65 gw->rot = rot;
66 gw->swap_mode = swap_mode;
67 gw->info = info;
68 gw->evas = e;
69
70 /* setup drm outbuf */
71 /* set drm card fd */
72 gw->priv.fd = info->info.fd;
73 /* try to setup the drm card for this outbuf */
74 if (!evas_drm_outbuf_setup(gw))
75 {
76 ERR("Could not setup drm outbuf");
77 free(gw);
78 return NULL;
79 }
80
81 if (gw->w < gw->priv.mode.hdisplay) gw->w = gw->priv.mode.hdisplay;
82 if (gw->h < gw->priv.mode.vdisplay) gw->h = gw->priv.mode.vdisplay;
83
84 info->info.output = gw->priv.fb;
85 // TODO: change vsync for drm egl
86 //gw->vsync = info->vsync;
87
88 gw->priv.num = NUM_BUFFERS;
89 /* check for buffer override */
90 // TODO: change for gbm_bo related drm buffer number.
91 if ((num = getenv("EVAS_GL_DRM_BUFFERS")))
92 {
93 gw->priv.num = atoi(num);
94
95 /* cap maximum # of buffers */
96 if (gw->priv.num <= 0) gw->priv.num = 1;
97 else if (gw->priv.num > 3) gw->priv.num = 3;
98 }
99 /* end drm outbuf setup */
100
101 /* setup gbm egl surface */
102 context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
103 context_attrs[1] = 2;
104 context_attrs[2] = EGL_NONE;
105
106 config_attrs[n++] = EGL_SURFACE_TYPE;
107 config_attrs[n++] = EGL_WINDOW_BIT;
108 config_attrs[n++] = EGL_RED_SIZE;
109 config_attrs[n++] = 1;
110 config_attrs[n++] = EGL_GREEN_SIZE;
111 config_attrs[n++] = 1;
112 config_attrs[n++] = EGL_BLUE_SIZE;
113 config_attrs[n++] = 1;
114 config_attrs[n++] = EGL_ALPHA_SIZE;
115 if (gw->alpha) config_attrs[n++] = 1;
116 else config_attrs[n++] = 0;
117 config_attrs[n++] = EGL_RENDERABLE_TYPE;
118 config_attrs[n++] = EGL_OPENGL_ES2_BIT;
119 config_attrs[n++] = EGL_NONE;
120
121#ifdef GL_DRM_DBG
122 DBG("GBM DEVICE: %x", (unsigned int)gbm);
123#endif
124
125 gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)(gw->gbm));
126 if (gw->egl_disp == EGL_NO_DISPLAY)
127 {
128 ERR("eglGetDisplay() fail. code=%#x", eglGetError());
129 eng_window_free(gw);
130 return NULL;
131 }
132 if (!eglInitialize(gw->egl_disp, &major_version, &minor_version))
133 {
134 ERR("eglInitialize() fail. code=%#x", eglGetError());
135 eng_window_free(gw);
136 return NULL;
137 }
138 eglBindAPI(EGL_OPENGL_ES_API);
139 if (eglGetError() != EGL_SUCCESS)
140 {
141 ERR("eglBindAPI() fail. code=%#x", eglGetError());
142 eng_window_free(gw);
143 return NULL;
144 }
145
146 num_config = 0;
147 if (!eglChooseConfig(gw->egl_disp, config_attrs, &gw->egl_config,
148 1, &num_config) || (num_config != 1))
149 {
150 ERR("eglChooseConfig() fail. code=%#x", eglGetError());
151 eng_window_free(gw);
152 return NULL;
153 }
154
155 gw->egl_surface[0] =
156 eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
157 (EGLNativeWindowType)gw->surface, NULL);
158 if (gw->egl_surface[0] == EGL_NO_SURFACE)
159 {
160 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
161 gw->surface, eglGetError());
162 eng_window_free(gw);
163 return NULL;
164 }
165
166 gw->egl_context[0] =
167 eglCreateContext(gw->egl_disp, gw->egl_config, context, context_attrs);
168 if (gw->egl_context[0] == EGL_NO_CONTEXT)
169 {
170 ERR("eglCreateContext() fail. code=%#x", eglGetError());
171 eng_window_free(gw);
172 return NULL;
173 }
174
175 if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
176
177 if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
178 gw->egl_surface[0], gw->egl_context[0]) == EGL_FALSE)
179 {
180 ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
181 eng_window_free(gw);
182 return NULL;
183 }
184
185 vendor = glGetString(GL_VENDOR);
186 renderer = glGetString(GL_RENDERER);
187 version = glGetString(GL_VERSION);
188 glslversion = glGetString(GL_SHADING_LANGUAGE_VERSION);
189 if (!vendor) vendor = (unsigned char *)"-UNKNOWN-";
190 if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
191 if (!version) version = (unsigned char *)"-UNKNOWN-";
192 if (!glslversion) glslversion = (unsigned char *)"-UNKNOWN-";
193 if (getenv("EVAS_GL_INFO"))
194 {
195 fprintf(stderr, "vendor : %s\n", vendor);
196 fprintf(stderr, "renderer: %s\n", renderer);
197 fprintf(stderr, "version : %s\n", version);
198 fprintf(stderr, "glsl ver: %s\n", glslversion);
199 }
200
201 if (strstr((const char *)vendor, "Mesa Project"))
202 {
203 if (strstr((const char *)renderer, "Software Rasterizer"))
204 blacklist = EINA_TRUE;
205 }
206 if (strstr((const char *)renderer, "softpipe"))
207 blacklist = EINA_TRUE;
208 if (strstr((const char *)renderer, "llvmpipe"))
209 blacklist = EINA_TRUE;
210 if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
211 {
212 ERR("OpenGL Driver blacklisted:");
213 ERR("Vendor: %s", (const char *)vendor);
214 ERR("Renderer: %s", (const char *)renderer);
215 ERR("Version: %s", (const char *)version);
216 eng_window_free(gw);
217 return NULL;
218 }
219
220 gw->gl_context = glsym_evas_gl_common_context_new();
221 if (!gw->gl_context)
222 {
223 eng_window_free(gw);
224 return NULL;
225 }
226
227#ifdef GL_GLES
228 gw->gl_context->egldisp = gw->egl_disp;
229 gw->gl_context->eglctxt = gw->egl_context[0];
230#endif
231
232 eng_window_use(gw);
233 glsym_evas_gl_common_context_resize(gw->gl_context, w, h, rot);
234
235 gw->surf = EINA_TRUE;
236
237 return gw;
238}
239
240void
241eng_window_free(Outbuf *gw)
242{
243 int ref = 0;
244
245 win_count--;
246 eng_window_use(gw);
247
248 if (gw == _evas_gl_drm_window) _evas_gl_drm_window = NULL;
249
250 if (gw->gl_context)
251 {
252 ref = gw->gl_context->references - 1;
253 glsym_evas_gl_common_context_free(gw->gl_context);
254 }
255
256 eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
257
258 if (gw->egl_context[0] != context)
259 eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
260
261 if (gw->egl_surface[0] != EGL_NO_SURFACE)
262 eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
263
264//TODO: consider gbm_surface destroy or not.
265#if 0
266 if (gw->surface)
267 {
268 gbm_surface_destroy(gw->surface);
269 gw->info->info.surface = NULL;
270 }
271#endif
272
273 if (ref == 0)
274 {
275 if (context) eglDestroyContext(gw->egl_disp, context);
276 eglTerminate(gw->egl_disp);
277 eglReleaseThread();
278 context = EGL_NO_CONTEXT;
279 }
280 free(gw);
281}
282
283Eina_Bool
284eng_window_make_current(void *data, void *doit)
285{
286 Outbuf *gw;
287
288 if (!(gw = data)) return EINA_FALSE;
289
290 if (doit)
291 {
292 if (!eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
293 gw->egl_surface[0], gw->egl_context[0]))
294 return EINA_FALSE;
295 }
296 else
297 {
298 if (!eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
299 EGL_NO_SURFACE, EGL_NO_CONTEXT))
300 return EINA_FALSE;
301 }
302
303 return EINA_TRUE;
304}
305
306void
307eng_window_use(Outbuf *gw)
308{
309 Eina_Bool force = EINA_FALSE;
310
311 glsym_evas_gl_preload_render_lock(eng_window_make_current, gw);
312
313 if (_evas_gl_drm_window)
314 {
315 if (eglGetCurrentContext() != _evas_gl_drm_window->egl_context[0])
316 force = EINA_TRUE;
317 }
318
319 if ((_evas_gl_drm_window != gw) || (force))
320 {
321 if (_evas_gl_drm_window)
322 {
323 glsym_evas_gl_common_context_use(_evas_gl_drm_window->gl_context);
324 glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
325 }
326
327 _evas_gl_drm_window = gw;
328
329 if (gw)
330 {
331 if (gw->egl_surface[0] != EGL_NO_SURFACE)
332 {
333 if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
334 gw->egl_surface[0],
335 gw->egl_context[0]) == EGL_FALSE)
336 ERR("eglMakeCurrent() failed!");
337 }
338 }
339 }
340
341 if (gw) glsym_evas_gl_common_context_use(gw->gl_context);
342}
343
344void
345eng_window_unsurf(Outbuf *gw)
346{
347 if (!gw->surf) return;
348 if (!getenv("EVAS_GL_WIN_RESURF")) return;
349 if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw);
350
351 if (_evas_gl_drm_window)
352 glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
353 if (_evas_gl_drm_window == gw)
354 {
355 eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
356 EGL_NO_SURFACE, EGL_NO_CONTEXT);
357 if (gw->egl_surface[0] != EGL_NO_SURFACE)
358 eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
359 gw->egl_surface[0] = EGL_NO_SURFACE;
360
361 _evas_gl_drm_window = NULL;
362 }
363
364 gw->surf = EINA_FALSE;
365}
366
367void
368eng_window_resurf(Outbuf *gw)
369{
370 if (gw->surf) return;
371 if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", gw);
372
373 gw->egl_surface[0] =
374 eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
375 (EGLNativeWindowType)gw->surface, NULL);
376
377 if (gw->egl_surface[0] == EGL_NO_SURFACE)
378 {
379 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
380 gw->surface, eglGetError());
381 return;
382 }
383
384 if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0], gw->egl_surface[0],
385 gw->egl_context[0]) == EGL_FALSE)
386 ERR("eglMakeCurrent() failed!");
387
388 gw->surf = EINA_TRUE;
389}
390
391Context_3D *
392eng_gl_context_new(Outbuf *gw)
393{
394 Context_3D *ctx;
395 int context_attrs[3] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
396
397 if (!gw) return NULL;
398
399 ctx = calloc(1, sizeof(Context_3D));
400 if (!ctx) return NULL;
401
402 ctx->context = eglCreateContext(gw->egl_disp, gw->egl_config,
403 gw->egl_context[0], context_attrs);
404
405 if (!ctx->context)
406 {
407 ERR("EGL context creation failed.");
408 goto error;
409 }
410
411 ctx->display = gw->egl_disp;
412 ctx->surface = gw->egl_surface[0];
413
414 return ctx;
415
416error:
417 free(ctx);
418 return NULL;
419}
420
421void
422eng_gl_context_free(Context_3D *ctx)
423{
424 eglDestroyContext(ctx->display, ctx->context);
425 free(ctx);
426}
427
428void
429eng_gl_context_use(Context_3D *ctx)
430{
431 if (eglMakeCurrent(ctx->display, ctx->surface,
432 ctx->surface, ctx->context) == EGL_FALSE)
433 ERR("eglMakeCurrent() failed.");
434}
435
436void
437eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EINA_UNUSED)
438{
439 ob->w = w;
440 ob->h = h;
441 ob->rot = rot;
442 eng_window_use(ob);
443 glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot);
444
445 //TODO: need drm gbm surface destroy & re-create.?
446}
447
448int
449eng_outbuf_get_rot(Outbuf *ob)
450{
451 return ob->rot;
452}
453
454Render_Engine_Swap_Mode
455eng_outbuf_swap_mode(Outbuf *ob)
456{
457 if (ob->swap_mode == MODE_AUTO && extn_have_buffer_age)
458 {
459 Render_Engine_Swap_Mode swap_mode;
460
461 EGLint age = 0;
462
463 if (!eglQuerySurface(ob->egl_disp, ob->egl_surface[0],
464 EGL_BUFFER_AGE_EXT, &age))
465 age = 0;
466
467 if (age == 1) swap_mode = MODE_COPY;
468 else if (age == 2) swap_mode = MODE_DOUBLE;
469 else if (age == 3) swap_mode = MODE_TRIPLE;
470 else if (age == 4) swap_mode = MODE_QUADRUPLE;
471 else swap_mode = MODE_FULL;
472 if ((int)age != ob->prev_age) swap_mode = MODE_FULL;
473 ob->prev_age = age;
474
475 return swap_mode;
476 }
477
478 return ob->swap_mode;
479}
480
481Eina_Bool
482eng_outbuf_region_first_rect(Outbuf *ob)
483{
484 ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
485
486 glsym_evas_gl_preload_render_lock(eng_preload_make_current, ob);
487 eng_window_use(ob);
488 if (!_re_wincheck(ob)) return EINA_TRUE;
489
490 glsym_evas_gl_common_context_resize(ob->gl_context, ob->w, ob->h, ob->rot);
491 glsym_evas_gl_common_context_flush(ob->gl_context);
492 glsym_evas_gl_common_context_newframe(ob->gl_context);
493
494 return EINA_FALSE;
495}
496
497void *
498eng_outbuf_new_region_for_update(Outbuf *ob, int x, int y, int w, int h, int *cx EINA_UNUSED, int *cy EINA_UNUSED, int *cw EINA_UNUSED, int *ch EINA_UNUSED)
499{
500 if ((w == ob->w) && (h == ob->h))
501 ob->gl_context->master_clip.enabled = EINA_FALSE;
502 else
503 {
504 ob->gl_context->master_clip.enabled = EINA_TRUE;
505 ob->gl_context->master_clip.x = x;
506 ob->gl_context->master_clip.y = y;
507 ob->gl_context->master_clip.w = w;
508 ob->gl_context->master_clip.h = h;
509 }
510 return ob->gl_context->def_surface;
511}
512
513void
514eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
515{
516 /* Is it really necessary to flush per region ? Shouldn't we be able to
517 still do that for the full canvas when doing partial update */
518 if (!_re_wincheck(ob)) return;
519 ob->draw.drew = EINA_TRUE;
520 glsym_evas_gl_common_context_flush(ob->gl_context);
521}
522
523void
524eng_outbuf_push_free_region_for_update(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
525{
526 /* Nothing to do here as we don't really create an image per area */
527}
528
529void
530eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
531{
532 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
533
534 if (!_re_wincheck(ob)) goto end;
535 if (!ob->draw.drew) goto end;
536
537 ob->draw.drew = EINA_FALSE;
538 eng_window_use(ob);
539 glsym_evas_gl_common_context_done(ob->gl_context);
540
541 if (!ob->vsync)
542 {
543 if (ob->info->vsync) eglSwapInterval(ob->egl_disp, 1);
544 else eglSwapInterval(ob->egl_disp, 0);
545 ob->vsync = 1;
546 }
547
548 if (ob->info->callback.pre_swap)
549 ob->info->callback.pre_swap(ob->info->callback.data, ob->evas);
550
551// TODO: Check eglSwapBuffersWithDamage for gl_drm and apply
552#if 0
553 if ((glsym_eglSwapBuffersWithDamage) && (ob->swap_mode != MODE_FULL))
554
555 {
556 EGLint num = 0, *result = NULL, i = 0;
557 Tilebuf_Rect *r;
558
559 // if partial swaps can be done use re->rects
560 num = eina_inlist_count(EINA_INLIST_GET(rects));
561 if (num > 0)
562 {
563 result = alloca(sizeof(EGLint) * 4 * num);
564 EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
565 {
566 int gw, gh;
567
568 gw = ob->gl_context->w;
569 gh = ob->gl_context->h;
570 switch (ob->rot)
571 {
572 case 0:
573 result[i + 0] = r->x;
574 result[i + 1] = gh - (r->y + r->h);
575 result[i + 2] = r->w;
576 result[i + 3] = r->h;
577 break;
578 case 90:
579 result[i + 0] = r->y;
580 result[i + 1] = r->x;
581 result[i + 2] = r->h;
582 result[i + 3] = r->w;
583 break;
584 case 180:
585 result[i + 0] = gw - (r->x + r->w);
586 result[i + 1] = r->y;
587 result[i + 2] = r->w;
588 result[i + 3] = r->h;
589 break;
590 case 270:
591 result[i + 0] = gh - (r->y + r->h);
592 result[i + 1] = gw - (r->x + r->w);
593 result[i + 2] = r->h;
594 result[i + 3] = r->w;
595 break;
596 default:
597 result[i + 0] = r->x;
598 result[i + 1] = gh - (r->y + r->h);
599 result[i + 2] = r->w;
600 result[i + 3] = r->h;
601 break;
602 }
603 i += 4;
604 }
605 glsym_eglSwapBuffersWithDamage(ob->egl_disp, ob->egl_surface[0],
606 result, num);
607 }
608 }
609 else
610#endif
611 eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]);
612
613 if (ob->info->callback.post_swap)
614 ob->info->callback.post_swap(ob->info->callback.data, ob->evas);
615
616 //Flush GL Surface data to Framebuffer
617 _outbuf_flush_famebuffer(ob);
618
619 ob->frame_cnt++;
620
621 end:
622 //TODO: Need render unlock after drm page flip?
623 glsym_evas_gl_preload_render_unlock(eng_preload_make_current, ob);
624}
625
626Evas_Engine_GL_Context *
627eng_outbuf_gl_context_get(Outbuf *ob)
628{
629 return ob->gl_context;
630}
631
632void *
633eng_outbuf_egl_display_get(Outbuf *ob)
634{
635 return ob->egl_disp;
636}
diff --git a/src/modules/evas/engines/gl_drm/evas_engine.c b/src/modules/evas/engines/gl_drm/evas_engine.c
index 0049819de2..ceddf5c537 100644
--- a/src/modules/evas/engines/gl_drm/evas_engine.c
+++ b/src/modules/evas/engines/gl_drm/evas_engine.c
@@ -1,5 +1,6 @@
1#include "evas_common_private.h" /* Also includes international specific stuff */ 1#include "config.h"
2#include "evas_engine.h" 2#include "evas_engine.h"
3#include <wayland-client.h>
3 4
4#ifdef HAVE_DLSYM 5#ifdef HAVE_DLSYM
5# include <dlfcn.h> /* dlopen,dlclose,etc */ 6# include <dlfcn.h> /* dlopen,dlclose,etc */
@@ -20,10 +21,37 @@
20# define EGL_NATIVE_PIXMAP_KHR 0x30b0 21# define EGL_NATIVE_PIXMAP_KHR 0x30b0
21#endif 22#endif
22 23
23#include <wayland-client.h>
24/* external variables */ 24/* external variables */
25int _evas_engine_gl_drm_log_dom = -1; 25int _evas_engine_gl_drm_log_dom = -1;
26int extn_have_buffer_age = 1; 26int _extn_have_buffer_age = 1;
27
28/* local variables */
29static Eina_Bool initted = EINA_FALSE;
30static int gl_wins = 0;
31
32/* local structures */
33typedef struct _Render_Engine Render_Engine;
34struct _Render_Engine
35{
36 Render_Engine_GL_Generic generic;
37};
38
39typedef struct _Native Native;
40struct _Native
41{
42 Evas_Native_Surface ns;
43 struct wl_buffer *wl_buf;
44 void *egl_surface;
45};
46
47/* local function prototype types */
48typedef void (*_eng_fn)(void);
49typedef _eng_fn (*glsym_func_eng_fn)();
50typedef void (*glsym_func_void)();
51typedef void *(*glsym_func_void_ptr)();
52typedef int (*glsym_func_int)();
53typedef unsigned int (*glsym_func_uint)();
54typedef const char *(*glsym_func_const_char_ptr)();
27 55
28/* external dynamic loaded Evas_GL function pointers */ 56/* external dynamic loaded Evas_GL function pointers */
29Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL; 57Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL;
@@ -36,6 +64,7 @@ Evas_GL_Common_Context_Call glsym_evas_gl_common_image_all_unload = NULL;
36Evas_GL_Preload glsym_evas_gl_preload_init = NULL; 64Evas_GL_Preload glsym_evas_gl_preload_init = NULL;
37Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL; 65Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL;
38EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL; 66EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL;
67EVGL_Current_Native_Context_Get_Call glsym_evgl_current_native_context_get = NULL;
39Evas_Gl_Symbols glsym_evas_gl_symbols = NULL; 68Evas_Gl_Symbols glsym_evas_gl_symbols = NULL;
40 69
41Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL; 70Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL;
@@ -50,29 +79,7 @@ Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL;
50Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL; 79Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
51Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL; 80Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;
52 81
53/* local structures */ 82glsym_func_void_ptr glsym_evas_gl_common_current_context_get = NULL;
54typedef struct _Render_Engine Render_Engine;
55struct _Render_Engine
56{
57 Render_Engine_GL_Generic generic;
58};
59
60typedef struct _Native Native;
61struct _Native
62{
63 Evas_Native_Surface ns;
64 struct wl_buffer *wl_buf;
65 void *egl_surface;
66};
67
68/* local function prototype types */
69typedef void (*_eng_fn) (void);
70typedef _eng_fn (*glsym_func_eng_fn) ();
71typedef void (*glsym_func_void) ();
72typedef void *(*glsym_func_void_ptr) ();
73typedef int (*glsym_func_int) ();
74typedef unsigned int (*glsym_func_uint) ();
75typedef const char *(*glsym_func_const_char_ptr) ();
76 83
77/* dynamic loaded local egl function pointers */ 84/* dynamic loaded local egl function pointers */
78_eng_fn (*glsym_eglGetProcAddress)(const char *a) = NULL; 85_eng_fn (*glsym_eglGetProcAddress)(const char *a) = NULL;
@@ -99,19 +106,6 @@ static const char *evgl_eng_string_get(void *data);
99static void *evgl_eng_proc_address_get(const char *name); 106static void *evgl_eng_proc_address_get(const char *name);
100static int evgl_eng_rotation_angle_get(void *data); 107static int evgl_eng_rotation_angle_get(void *data);
101 108
102static void _re_winfree(Render_Engine *re);
103
104/* local variables */
105static Eina_Bool initted = EINA_FALSE;
106static int gl_wins = 0;
107
108/* local inline functions */
109static inline Outbuf *
110eng_get_ob(Render_Engine *re)
111{
112 return re->generic.software.ob;
113}
114
115/* function tables - filled in later (func and parent func) */ 109/* function tables - filled in later (func and parent func) */
116static Evas_Func func, pfunc; 110static Evas_Func func, pfunc;
117static const EVGL_Interface evgl_funcs = 111static const EVGL_Interface evgl_funcs =
@@ -136,6 +130,13 @@ static const EVGL_Interface evgl_funcs =
136 NULL, // native_win_surface_config_get 130 NULL, // native_win_surface_config_get
137}; 131};
138 132
133/* local inline functions */
134static inline Outbuf *
135eng_get_ob(Render_Engine *re)
136{
137 return re->generic.software.ob;
138}
139
139/* local functions */ 140/* local functions */
140static void 141static void
141gl_symbols(void) 142gl_symbols(void)
@@ -169,7 +170,9 @@ gl_symbols(void)
169 LINK2GENERIC(evas_gl_preload_init); 170 LINK2GENERIC(evas_gl_preload_init);
170 LINK2GENERIC(evas_gl_preload_shutdown); 171 LINK2GENERIC(evas_gl_preload_shutdown);
171 LINK2GENERIC(evgl_engine_shutdown); 172 LINK2GENERIC(evgl_engine_shutdown);
173 LINK2GENERIC(evgl_current_native_context_get);
172 LINK2GENERIC(evas_gl_symbols); 174 LINK2GENERIC(evas_gl_symbols);
175 LINK2GENERIC(evas_gl_common_current_context_get);
173 176
174#define FINDSYM(dst, sym, typ) \ 177#define FINDSYM(dst, sym, typ) \
175 if (glsym_eglGetProcAddress) { \ 178 if (glsym_eglGetProcAddress) { \
@@ -215,36 +218,38 @@ static void
215gl_extn_veto(Render_Engine *re) 218gl_extn_veto(Render_Engine *re)
216{ 219{
217 const char *str = NULL; 220 const char *str = NULL;
218 str = eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS); 221
222 str = eglQueryString(eng_get_ob(re)->egl.disp, EGL_EXTENSIONS);
219 if (str) 223 if (str)
220 { 224 {
221 const char *s; 225 const char *s = NULL;
222 if (getenv("EVAS_GL_INFO")) 226
223 printf("EGL EXTN:\n%s\n", str); 227 if (getenv("EVAS_GL_INFO")) printf("EGL EXTN:\n%s\n", str);
228
224 // Disable Partial Rendering 229 // Disable Partial Rendering
225 if ((s = getenv("EVAS_GL_PARTIAL_DISABLE")) && atoi(s)) 230 s = getenv("EVAS_GL_PARTIAL_DISABLE");
231 if ((s) && (atoi(s)))
226 { 232 {
227 extn_have_buffer_age = 0; 233 _extn_have_buffer_age = 0;
228 glsym_eglSwapBuffersWithDamage = NULL; 234 glsym_eglSwapBuffersWithDamage = NULL;
229 } 235 }
230 if (!strstr(str, "EGL_EXT_buffer_age")) 236 if (!strstr(str, "EGL_EXT_buffer_age")) _extn_have_buffer_age = 0;
231 extn_have_buffer_age = 0;
232 if (!strstr(str, "EGL_EXT_swap_buffers_with_damage")) 237 if (!strstr(str, "EGL_EXT_swap_buffers_with_damage"))
233 glsym_eglSwapBuffersWithDamage = NULL; 238 glsym_eglSwapBuffersWithDamage = NULL;
234 } 239 }
235 else 240 else
236 { 241 {
237 if (getenv("EVAS_GL_INFO")) 242 if (getenv("EVAS_GL_INFO")) printf("NO EGL EXTN!\n");
238 printf("NO EGL EXTN!\n"); 243 _extn_have_buffer_age = 0;
239 extn_have_buffer_age = 0;
240 } 244 }
241} 245}
242 246
243static void * 247static void *
244evgl_eng_display_get(void *data) 248evgl_eng_display_get(void *data)
245{ 249{
246 Render_Engine *re = (Render_Engine *)data; 250 Render_Engine *re;
247 251
252 re = (Render_Engine *)data;
248 if (!re) 253 if (!re)
249 { 254 {
250 ERR("Invalid Render Engine Data!"); 255 ERR("Invalid Render Engine Data!");
@@ -252,7 +257,7 @@ evgl_eng_display_get(void *data)
252 } 257 }
253 258
254 if (eng_get_ob(re)) 259 if (eng_get_ob(re))
255 return (void*)eng_get_ob(re)->egl_disp; 260 return (void *)eng_get_ob(re)->egl.disp;
256 else 261 else
257 return NULL; 262 return NULL;
258} 263}
@@ -260,8 +265,9 @@ evgl_eng_display_get(void *data)
260static void * 265static void *
261evgl_eng_evas_surface_get(void *data) 266evgl_eng_evas_surface_get(void *data)
262{ 267{
263 Render_Engine *re = (Render_Engine *)data; 268 Render_Engine *re;
264 269
270 re = (Render_Engine *)data;
265 if (!re) 271 if (!re)
266 { 272 {
267 ERR("Invalid Render Engine Data!"); 273 ERR("Invalid Render Engine Data!");
@@ -269,7 +275,7 @@ evgl_eng_evas_surface_get(void *data)
269 } 275 }
270 276
271 if (eng_get_ob(re)) 277 if (eng_get_ob(re))
272 return (void*)eng_get_ob(re)->egl_surface[0]; 278 return (void *)eng_get_ob(re)->egl.surface[0];
273 else 279 else
274 return NULL; 280 return NULL;
275} 281}
@@ -277,19 +283,20 @@ evgl_eng_evas_surface_get(void *data)
277static int 283static int
278evgl_eng_make_current(void *data, void *surface, void *context, int flush) 284evgl_eng_make_current(void *data, void *surface, void *context, int flush)
279{ 285{
280 Render_Engine *re = (Render_Engine *)data; 286 Render_Engine *re;
281 EGLContext ctx; 287 EGLContext ctx;
282 EGLSurface sfc; 288 EGLSurface sfc;
283 EGLDisplay dpy; 289 EGLDisplay dpy;
284 int ret = 0; 290 int ret = 0;
285 291
292 re = (Render_Engine *)data;
286 if (!re) 293 if (!re)
287 { 294 {
288 ERR("Invalid Render Engine Data!"); 295 ERR("Invalid Render Engine Data!");
289 return 0; 296 return 0;
290 } 297 }
291 298
292 dpy = eng_get_ob(re)->egl_disp; 299 dpy = eng_get_ob(re)->egl.disp;
293 ctx = (EGLContext)context; 300 ctx = (EGLContext)context;
294 sfc = (EGLSurface)surface; 301 sfc = (EGLSurface)surface;
295 302
@@ -302,6 +309,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
302 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError()); 309 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
303 return 0; 310 return 0;
304 } 311 }
312
305 return 1; 313 return 1;
306 } 314 }
307 315
@@ -309,7 +317,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
309 (eglGetCurrentSurface(EGL_READ) != sfc) || 317 (eglGetCurrentSurface(EGL_READ) != sfc) ||
310 (eglGetCurrentSurface(EGL_DRAW) != sfc) ) 318 (eglGetCurrentSurface(EGL_DRAW) != sfc) )
311 { 319 {
312 if (flush) eng_window_use(NULL); 320 if (flush) evas_outbuf_use(NULL);
313 321
314 ret = eglMakeCurrent(dpy, sfc, sfc, ctx); 322 ret = eglMakeCurrent(dpy, sfc, sfc, ctx);
315 if (!ret) 323 if (!ret)
@@ -325,10 +333,11 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
325static void * 333static void *
326evgl_eng_native_window_create(void *data) 334evgl_eng_native_window_create(void *data)
327{ 335{
328 Render_Engine *re = (Render_Engine *)data; 336 Render_Engine *re;
329 struct gbm_surface *surface; 337 struct gbm_surface *surface;
330 Evas_Engine_Info_GL_Drm *info; 338 Evas_Engine_Info_GL_Drm *info;
331 339
340 re = (Render_Engine *)data;
332 if (!re) 341 if (!re)
333 { 342 {
334 ERR("Invalid Render Engine Data!"); 343 ERR("Invalid Render Engine Data!");
@@ -345,9 +354,12 @@ evgl_eng_native_window_create(void *data)
345 surface = gbm_surface_create(info->info.gbm, 1, 1, info->info.format, 354 surface = gbm_surface_create(info->info.gbm, 1, 1, info->info.format,
346 info->info.flags); 355 info->info.flags);
347 if (!surface) 356 if (!surface)
348 ERR("Could not create gl drm window: %m"); 357 {
358 ERR("Could not create gl drm window: %m");
359 return NULL;
360 }
349 361
350 return (void*)surface; 362 return (void *)surface;
351} 363}
352 364
353static int 365static int
@@ -367,16 +379,20 @@ evgl_eng_native_window_destroy(void *data, void *native_window)
367 return 0; 379 return 0;
368 } 380 }
369 381
370 gbm_surface_destroy((struct gbm_surface*)native_window); 382 gbm_surface_destroy((struct gbm_surface *)native_window);
383
384 native_window = NULL;
385
371 return 1; 386 return 1;
372} 387}
373 388
374static void * 389static void *
375evgl_eng_window_surface_create(void *data, void *native_window) 390evgl_eng_window_surface_create(void *data, void *native_window)
376{ 391{
377 Render_Engine *re = (Render_Engine *)data; 392 Render_Engine *re;
378 EGLSurface surface = EGL_NO_SURFACE; 393 EGLSurface surface = EGL_NO_SURFACE;
379 394
395 re = (Render_Engine *)data;
380 if (!re) 396 if (!re)
381 { 397 {
382 ERR("Invalid Render Engine Data!"); 398 ERR("Invalid Render Engine Data!");
@@ -384,8 +400,8 @@ evgl_eng_window_surface_create(void *data, void *native_window)
384 } 400 }
385 401
386 // Create resource surface for EGL 402 // Create resource surface for EGL
387 surface = eglCreateWindowSurface(eng_get_ob(re)->egl_disp, 403 surface = eglCreateWindowSurface(eng_get_ob(re)->egl.disp,
388 eng_get_ob(re)->egl_config, 404 eng_get_ob(re)->egl.config,
389 (EGLNativeWindowType)native_window, 405 (EGLNativeWindowType)native_window,
390 NULL); 406 NULL);
391 if (!surface) 407 if (!surface)
@@ -394,15 +410,16 @@ evgl_eng_window_surface_create(void *data, void *native_window)
394 return NULL; 410 return NULL;
395 } 411 }
396 412
397 return (void*)surface; 413 return (void *)surface;
398} 414}
399 415
400static int 416static int
401evgl_eng_window_surface_destroy(void *data, void *surface) 417evgl_eng_window_surface_destroy(void *data, void *surface)
402{ 418{
403 Render_Engine *re = (Render_Engine *)data; 419 Render_Engine *re;
404 EGLBoolean ret = EGL_FALSE; 420 EGLBoolean ret = EGL_FALSE;
405 421
422 re = (Render_Engine *)data;
406 if (!re) 423 if (!re)
407 { 424 {
408 ERR("Invalid Render Engine Data!"); 425 ERR("Invalid Render Engine Data!");
@@ -415,7 +432,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
415 return 0; 432 return 0;
416 } 433 }
417 434
418 ret = eglDestroySurface(eng_get_ob(re)->egl_disp, (EGLSurface)surface); 435 ret = eglDestroySurface(eng_get_ob(re)->egl.disp, (EGLSurface)surface);
419 if (ret == EGL_TRUE) return 1; 436 if (ret == EGL_TRUE) return 1;
420 437
421 return 0; 438 return 0;
@@ -424,10 +441,11 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
424static void * 441static void *
425evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version version) 442evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version version)
426{ 443{
427 Render_Engine *re = (Render_Engine *)data; 444 Render_Engine *re;
428 EGLContext context = EGL_NO_CONTEXT; 445 EGLContext context = EGL_NO_CONTEXT;
429 int context_attrs[3]; 446 int context_attrs[3];
430 447
448 re = (Render_Engine *)data;
431 if (!re) 449 if (!re)
432 { 450 {
433 ERR("Invalid Render Engine Data!"); 451 ERR("Invalid Render Engine Data!");
@@ -447,41 +465,43 @@ evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version ver
447 // Share context already assumes that it's sharing with evas' context 465 // Share context already assumes that it's sharing with evas' context
448 if (share_ctx) 466 if (share_ctx)
449 { 467 {
450 context = eglCreateContext(eng_get_ob(re)->egl_disp, 468 context = eglCreateContext(eng_get_ob(re)->egl.disp,
451 eng_get_ob(re)->egl_config, 469 eng_get_ob(re)->egl.config,
452 (EGLContext)share_ctx, 470 (EGLContext)share_ctx,
453 context_attrs); 471 context_attrs);
454 } 472 }
455 else 473 else
456 { 474 {
457 context = eglCreateContext(eng_get_ob(re)->egl_disp, 475 context = eglCreateContext(eng_get_ob(re)->egl.disp,
458 eng_get_ob(re)->egl_config, 476 eng_get_ob(re)->egl.config,
459 eng_get_ob(re)->egl_context[0], // Evas' GL Context 477 eng_get_ob(re)->egl.context[0], // Evas' GL Context
460 context_attrs); 478 context_attrs);
461 } 479 }
462 480
463 if (!context) 481 if (!context)
464 { 482 {
465 ERR("Engine Context Creations Failed. Error: %#x.", eglGetError()); 483 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
466 return NULL; 484 return NULL;
467 } 485 }
468 486
469 return (void*)context; 487 return (void *)context;
470} 488}
471 489
472static int 490static int
473evgl_eng_context_destroy(void *data, void *context) 491evgl_eng_context_destroy(void *data, void *context)
474{ 492{
475 Render_Engine *re = (Render_Engine *)data; 493 Render_Engine *re;
476 EGLBoolean ret = EGL_FALSE; 494 EGLBoolean ret = EGL_FALSE;
477 495
496 re = (Render_Engine *)data;
478 if ((!re) || (!context)) 497 if ((!re) || (!context))
479 { 498 {
480 ERR("Invalid Render Input Data. Engine: %p, Context: %p", data, context); 499 ERR("Invalid Render Input Data. Engine: %p, Context: %p",
500 data, context);
481 return 0; 501 return 0;
482 } 502 }
483 503
484 ret = eglDestroyContext(eng_get_ob(re)->egl_disp, (EGLContext)context); 504 ret = eglDestroyContext(eng_get_ob(re)->egl.disp, (EGLContext)context);
485 if (ret == EGL_TRUE) return 1; 505 if (ret == EGL_TRUE) return 1;
486 506
487 return 0; 507 return 0;
@@ -490,15 +510,16 @@ evgl_eng_context_destroy(void *data, void *context)
490static const char * 510static const char *
491evgl_eng_string_get(void *data) 511evgl_eng_string_get(void *data)
492{ 512{
493 Render_Engine *re = (Render_Engine *)data; 513 Render_Engine *re;
494 514
515 re = (Render_Engine *)data;
495 if (!re) 516 if (!re)
496 { 517 {
497 ERR("Invalid Render Engine Data!"); 518 ERR("Invalid Render Engine Data!");
498 return NULL; 519 return NULL;
499 } 520 }
500 521
501 return eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS); 522 return eglQueryString(eng_get_ob(re)->egl.disp, EGL_EXTENSIONS);
502} 523}
503 524
504static void * 525static void *
@@ -511,8 +532,9 @@ evgl_eng_proc_address_get(const char *name)
511static int 532static int
512evgl_eng_rotation_angle_get(void *data) 533evgl_eng_rotation_angle_get(void *data)
513{ 534{
514 Render_Engine *re = (Render_Engine *)data; 535 Render_Engine *re;
515 536
537 re = (Render_Engine *)data;
516 if (!re) 538 if (!re)
517 { 539 {
518 ERR("Invalid Render Engine Data!"); 540 ERR("Invalid Render Engine Data!");
@@ -528,13 +550,177 @@ evgl_eng_rotation_angle_get(void *data)
528 } 550 }
529} 551}
530 552
553static Eina_Bool
554eng_preload_make_current(void *data, void *doit)
555{
556 Outbuf *ob;
557
558 ob = (Outbuf *)data;
559 if (!ob) return EINA_FALSE;
560
561 if (doit)
562 {
563 if (!eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
564 ob->egl.surface[0], ob->egl.context[0]))
565 return EINA_FALSE;
566 }
567 else
568 {
569 if (!eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
570 EGL_NO_SURFACE, EGL_NO_CONTEXT))
571 return EINA_FALSE;
572 }
573
574 return EINA_TRUE;
575}
576
531static void 577static void
532_re_winfree(Render_Engine *re) 578_re_winfree(Render_Engine *re)
533{ 579{
534 if (!re) return; 580 if (!re) return;
535 if (!eng_get_ob(re)->surf) return; 581 if (!eng_get_ob(re)->surf) return;
536 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re)); 582 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
537 eng_window_unsurf(eng_get_ob(re)); 583 evas_outbuf_unsurf(eng_get_ob(re));
584}
585
586static void
587_native_cb_bind(void *data EINA_UNUSED, void *image)
588{
589 Evas_GL_Image *img;
590 Native *n;
591
592 if (!(img = image)) return;
593 if (!(n = img->native.data)) return;
594
595 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
596 {
597 if (n->egl_surface)
598 {
599 if (glsym_glEGLImageTargetTexture2DOES)
600 {
601 glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, n->egl_surface);
602 if (eglGetError() != EGL_SUCCESS)
603 ERR("glEGLImageTargetTexture2DOES() failed.");
604 }
605 else
606 ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
607 }
608 }
609 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
610 glBindTexture(GL_TEXTURE_2D, n->ns.data.opengl.texture_id);
611
612 /* TODO: NATIVE_SURFACE_TBM and NATIVE_SURFACE_EVASGL */
613}
614
615static void
616_native_cb_unbind(void *data EINA_UNUSED, void *image)
617{
618 Evas_GL_Image *img;
619 Native *n;
620
621 if (!(img = image)) return;
622 if (!(n = img->native.data)) return;
623
624 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
625 {
626 //glBindTexture(GL_TEXTURE_2D, 0); //really need?
627 }
628 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
629 glBindTexture(GL_TEXTURE_2D, 0);
630
631 /* TODO: NATIVE_SURFACE_TBM and NATIVE_SURFACE_EVASGL */
632}
633
634static void
635_native_cb_free(void *data, void *image)
636{
637 Render_Engine *re;
638 Outbuf *ob;
639 Evas_GL_Image *img;
640 Native *n;
641 uint32_t texid;
642 void *wlid;
643
644 if (!(re = (Render_Engine *)data)) return;
645 if (!(img = image)) return;
646 if (!(n = img->native.data)) return;
647 if (!(ob = eng_get_ob(re))) return;
648
649 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
650 {
651 wlid = (void*)n->wl_buf;
652 eina_hash_del(ob->gl_context->shared->native_wl_hash, &wlid, img);
653 if (n->egl_surface)
654 {
655 if (glsym_eglDestroyImage)
656 {
657 glsym_eglDestroyImage(ob->egl.disp, n->egl_surface);
658 if (eglGetError() != EGL_SUCCESS)
659 ERR("eglDestroyImage() failed.");
660 }
661 else
662 ERR("Try eglDestroyImage on EGL with no support");
663 }
664 }
665 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
666 {
667 texid = n->ns.data.opengl.texture_id;
668 eina_hash_del(ob->gl_context->shared->native_tex_hash, &texid, img);
669 }
670
671 img->native.data = NULL;
672 img->native.func.data = NULL;
673 img->native.func.bind = NULL;
674 img->native.func.unbind = NULL;
675 img->native.func.free = NULL;
676
677 free(n);
678}
679
680static Eina_Bool
681eng_gbm_init(Evas_Engine_Info_GL_Drm *info, int w, int h)
682{
683 Ecore_Drm_Device *dev;
684
685 if (!info) return EINA_FALSE;
686 if (!(dev = info->info.dev)) return EINA_FALSE;
687
688 if (!(info->info.gbm = gbm_create_device(dev->drm.fd)))
689 {
690 ERR("Coult not create gbm device: %m");
691 return EINA_FALSE;
692 }
693
694 if (!(info->info.surface =
695 gbm_surface_create(info->info.gbm, w, h,
696 info->info.format, info->info.flags)))
697 {
698 ERR("Could not create gbm surface: %m");
699 gbm_device_destroy(info->info.gbm);
700 info->info.gbm = NULL;
701 return EINA_FALSE;
702 }
703
704 return EINA_TRUE;
705}
706
707static Eina_Bool
708eng_gbm_shutdown(Evas_Engine_Info_GL_Drm *info)
709{
710 if (!info) return EINA_TRUE;
711
712 if (info->info.surface)
713 {
714 gbm_surface_destroy(info->info.surface);
715 info->info.surface = NULL;
716 }
717 if (info->info.gbm)
718 {
719 gbm_device_destroy(info->info.gbm);
720 info->info.gbm = NULL;
721 }
722
723 return EINA_TRUE;
538} 724}
539 725
540/* engine specific override functions */ 726/* engine specific override functions */
@@ -563,21 +749,22 @@ eng_info_free(Evas *eo_e EINA_UNUSED, void *in)
563} 749}
564 750
565static int 751static int
566eng_setup(Evas *eo_e, void *in) 752eng_setup(Evas *evas, void *in)
567{ 753{
568 Evas_Engine_Info_GL_Drm *info = NULL; 754 Evas_Engine_Info_GL_Drm *info;
569 Evas_Public_Data *epd = NULL; 755 Evas_Public_Data *epd;
570 Render_Engine *re = NULL; 756 Render_Engine *re;
571 Render_Engine_Swap_Mode swap_mode = MODE_FULL; 757 Render_Engine_Swap_Mode swap_mode = MODE_FULL;
572 const char *s; 758 const char *s = NULL;
573 759
574 /* try to cast to our engine info structure */ 760 /* try to cast to our engine info structure */
575 if (!(info = (Evas_Engine_Info_GL_Drm *)in)) return 0; 761 if (!(info = (Evas_Engine_Info_GL_Drm *)in)) return 0;
576 762
577 /* try to get the evas public data */ 763 /* try to get the evas public data */
578 if (!(epd = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS))) return 0; 764 if (!(epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS))) return 0;
579 765
580 if ((s = getenv("EVAS_GL_SWAP_MODE"))) 766 s = getenv("EVAS_GL_SWAP_MODE");
767 if (s)
581 { 768 {
582 if ((!strcasecmp(s, "full")) || (!strcasecmp(s, "f"))) 769 if ((!strcasecmp(s, "full")) || (!strcasecmp(s, "f")))
583 swap_mode = MODE_FULL; 770 swap_mode = MODE_FULL;
@@ -594,11 +781,10 @@ eng_setup(Evas *eo_e, void *in)
594 swap_mode = MODE_QUADRUPLE; 781 swap_mode = MODE_QUADRUPLE;
595 } 782 }
596 783
597 /* check for existing engine output */ 784 if (!(re = epd->engine.data.output))
598 if (!epd->engine.data.output)
599 { 785 {
600 Outbuf *ob; 786 Outbuf *ob;
601 Render_Engine_Merge_Mode merge_mode = MERGE_FULL; 787 Render_Engine_Merge_Mode merge_mode = MERGE_BOUNDING;
602 788
603 if (!initted) 789 if (!initted)
604 { 790 {
@@ -606,64 +792,55 @@ eng_setup(Evas *eo_e, void *in)
606 glsym_evas_gl_preload_init(); 792 glsym_evas_gl_preload_init();
607 } 793 }
608 794
609 if (!(info->info.gbm) || !(info->info.surface)) 795 if (!(re = calloc(1, sizeof(Render_Engine)))) return 0;
610 return 0;
611
612#ifdef GL_DRM_DBG
613 DBG("FD: %d, GBM_DEVICE: 0x%x, GBM_SURFACE: 0x%x",
614 info->info.fd, (unsigned int)info->info.gbm,
615 (unsigned int)info->info.surface);
616#endif
617 796
618 re = calloc(1, sizeof(Render_Engine)); 797 if (!eng_gbm_init(info, epd->output.w, epd->output.h))
619 if (!re) return 0; 798 {
799 free(re);
800 return 0;
801 }
620 802
621 /* try to create new outbuf */ 803 /* try to create new outbuf */
622 ob = eng_window_new(info, eo_e, info->info.gbm, info->info.surface, 804 ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode);
623 info->info.screen,info->info.depth,
624 epd->output.w, epd->output.h, info->indirect,
625 info->info.destination_alpha,
626 info->info.rotation, swap_mode);
627 if (!ob) 805 if (!ob)
628 { 806 {
629 /* shutdown destroy gbm surface & shutdown gbm device */ 807 eng_gbm_shutdown(info);
630 evas_drm_gbm_shutdown(info);
631 free(re); 808 free(re);
632 return 0; 809 return 0;
633 } 810 }
634 811
812 ob->evas = evas;
813
635 if (!evas_render_engine_gl_generic_init(&re->generic, ob, 814 if (!evas_render_engine_gl_generic_init(&re->generic, ob,
636 eng_outbuf_swap_mode, 815 evas_outbuf_buffer_state_get,
637 eng_outbuf_get_rot, 816 evas_outbuf_rot_get,
638 eng_outbuf_reconfigure, 817 evas_outbuf_reconfigure,
639 eng_outbuf_region_first_rect, 818 evas_outbuf_update_region_first_rect,
640 eng_outbuf_new_region_for_update, 819 evas_outbuf_update_region_new,
641 eng_outbuf_push_updated_region, 820 evas_outbuf_update_region_push,
642 eng_outbuf_push_free_region_for_update, 821 evas_outbuf_update_region_free,
643 NULL, 822 NULL,
644 eng_outbuf_flush, 823 evas_outbuf_flush,
645 eng_window_free, 824 evas_outbuf_free,
646 eng_window_use, 825 evas_outbuf_use,
647 eng_outbuf_gl_context_get, 826 evas_outbuf_gl_context_get,
648 eng_outbuf_egl_display_get, 827 evas_outbuf_egl_display_get,
649 eng_gl_context_new, 828 evas_outbuf_gl_context_new,
650 eng_gl_context_use, 829 evas_outbuf_gl_context_use,
651 &evgl_funcs, 830 &evgl_funcs, ob->w, ob->h))
652 epd->output.w, epd->output.h))
653 { 831 {
832 eng_gbm_shutdown(info);
654 /* free outbuf */ 833 /* free outbuf */
655 eng_window_free(ob); 834 evas_outbuf_free(ob);
656 /* shutdown destroy gbm surface & shutdown gbm device */
657 evas_drm_gbm_shutdown(info);
658 free(re); 835 free(re);
659 return 0; 836 return 0;
660 } 837 }
661 838
662 /* tell the engine to use this render_engine for output */
663 epd->engine.data.output = re; 839 epd->engine.data.output = re;
664 gl_wins++; 840 gl_wins++;
665 841
666 if ((s = getenv("EVAS_GL_PARTIAL_MERGE"))) 842 s = getenv("EVAS_GL_PARTIAL_MERGE");
843 if (s)
667 { 844 {
668 if ((!strcmp(s, "bounding")) || (!strcmp(s, "b"))) 845 if ((!strcmp(s, "bounding")) || (!strcmp(s, "b")))
669 merge_mode = MERGE_BOUNDING; 846 merge_mode = MERGE_BOUNDING;
@@ -681,83 +858,52 @@ eng_setup(Evas *eo_e, void *in)
681 } 858 }
682 else 859 else
683 { 860 {
684 re = epd->engine.data.output;
685
686 if (eng_get_ob(re) && _re_wincheck(eng_get_ob(re))) 861 if (eng_get_ob(re) && _re_wincheck(eng_get_ob(re)))
687 { 862 {
688 if ((eng_get_ob(re)->info->info.gbm != eng_get_ob(re)->gbm) || 863 if ((info->info.gbm != eng_get_ob(re)->gbm) ||
689 (eng_get_ob(re)->info->info.surface != eng_get_ob(re)->surface) || 864 (info->info.surface != eng_get_ob(re)->surface) ||
690 (eng_get_ob(re)->info->info.screen != eng_get_ob(re)->screen) || 865 (info->info.depth != eng_get_ob(re)->depth) ||
691 (eng_get_ob(re)->info->info.depth != eng_get_ob(re)->depth) || 866 (info->info.destination_alpha != eng_get_ob(re)->destination_alpha))
692 (eng_get_ob(re)->info->info.destination_alpha != eng_get_ob(re)->alpha))
693 { 867 {
694 Outbuf *ob; 868 Outbuf *ob, *ob_old;
695
696 eng_get_ob(re)->gl_context->references++;
697 gl_wins--;
698 869
699 ob = eng_window_new(info, eo_e, 870 ob_old = re->generic.software.ob;
700 eng_get_ob(re)->info->info.gbm,
701 eng_get_ob(re)->info->info.surface,
702 eng_get_ob(re)->info->info.screen,
703 eng_get_ob(re)->info->info.depth,
704 epd->output.w, epd->output.h,
705 eng_get_ob(re)->info->indirect,
706 eng_get_ob(re)->info->info.destination_alpha,
707 eng_get_ob(re)->info->info.rotation,
708 swap_mode);
709
710 eng_window_free(eng_get_ob(re));
711 re->generic.software.ob = NULL; 871 re->generic.software.ob = NULL;
872 gl_wins--;
712 873
713 eng_window_use(ob); 874 ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode);
714 if (ob) 875 if (!ob)
715 { 876 {
716 evas_render_engine_software_generic_update(&re->generic.software, ob, 877 if (ob_old) evas_outbuf_free(ob_old);
717 epd->output.w, epd->output.h); 878 free(re);
718 879 return 0;
719 gl_wins++;
720 eng_get_ob(re)->gl_context->references--;
721 } 880 }
722 }
723 else if ((eng_get_ob(re)->w != epd->output.w) ||
724 (eng_get_ob(re)->h != epd->output.h) ||
725 (eng_get_ob(re)->info->info.rotation != eng_get_ob(re)->rot))
726 {
727 Outbuf *ob;
728 881
729 eng_get_ob(re)->gl_context->references++; 882 evas_outbuf_use(ob);
730 gl_wins--; 883 if (ob_old) evas_outbuf_free(ob_old);
731
732 eng_window_free(eng_get_ob(re));
733 re->generic.software.ob = NULL;
734 evas_drm_gbm_shutdown(eng_get_ob(re)->info);
735 if (!evas_drm_gbm_init(info, epd->output.w, epd->output.h))
736 return 0;
737
738#ifdef GL_DRM_DBG
739 DBG("FD: %d, GBM_DEVICE: 0x%x, GBM_SURFACE: 0x%x",
740 info->info.fd, (unsigned int)info->info.gbm,
741 (unsigned int)info->info.surface);
742#endif
743 884
744 ob = eng_window_new(info, eo_e, info->info.gbm, 885 ob->evas = evas;
745 info->info.surface, info->info.screen,
746 info->info.depth,
747 epd->output.w, epd->output.h,
748 info->indirect,
749 info->info.destination_alpha,
750 info->info.rotation, swap_mode);
751 886
752 eng_window_use(ob); 887 evas_render_engine_software_generic_update(&re->generic.software, ob,
753 if (ob) 888 epd->output.w, epd->output.h);
754 {
755 evas_render_engine_software_generic_update(&re->generic.software, ob,
756 epd->output.w, epd->output.h);
757 889
758 gl_wins++; 890 gl_wins++;
759 eng_get_ob(re)->gl_context->references--; 891 }
760 } 892 else if ((eng_get_ob(re)->w != epd->output.w) ||
893 (eng_get_ob(re)->h != epd->output.h) ||
894 (info->info.rotation != eng_get_ob(re)->rotation))
895 {
896 evas_outbuf_reconfigure(eng_get_ob(re),
897 epd->output.w, epd->output.h,
898 info->info.rotation,
899 info->info.depth);
900 if (re->generic.software.tb)
901 evas_common_tilebuf_free(re->generic.software.tb);
902 re->generic.software.tb =
903 evas_common_tilebuf_new(epd->output.w, epd->output.h);
904 if (re->generic.software.tb)
905 evas_common_tilebuf_set_tile_size(re->generic.software.tb,
906 TILESIZE, TILESIZE);
761 } 907 }
762 } 908 }
763 } 909 }
@@ -772,15 +918,16 @@ eng_setup(Evas *eo_e, void *in)
772 { 918 {
773 if (eng_get_ob(re)) 919 if (eng_get_ob(re))
774 { 920 {
775 eng_window_free(eng_get_ob(re)); 921 evas_outbuf_free(eng_get_ob(re));
776 gl_wins--; 922 gl_wins--;
777 evas_drm_gbm_shutdown(info); 923 eng_gbm_shutdown(info);
778 } 924 }
779 free(re); 925 free(re);
780 return 0; 926 return 0;
781 } 927 }
782 928
783 evas_render_engine_software_generic_tile_strict_set(&re->generic.software, EINA_TRUE); 929 if (re->generic.software.tb)
930 evas_render_engine_software_generic_tile_strict_set(&re->generic.software, EINA_TRUE);
784 931
785 if (!epd->engine.data.context) 932 if (!epd->engine.data.context)
786 { 933 {
@@ -788,7 +935,7 @@ eng_setup(Evas *eo_e, void *in)
788 epd->engine.func->context_new(epd->engine.data.output); 935 epd->engine.func->context_new(epd->engine.data.output);
789 } 936 }
790 937
791 eng_window_use(eng_get_ob(re)); 938 evas_outbuf_use(eng_get_ob(re));
792 939
793 return 1; 940 return 1;
794} 941}
@@ -799,22 +946,22 @@ eng_output_free(void *data)
799 Render_Engine *re; 946 Render_Engine *re;
800 947
801 re = (Render_Engine *)data; 948 re = (Render_Engine *)data;
802
803 if (re) 949 if (re)
804 { 950 {
805 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re)); 951 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
806 952
807 if (gl_wins == 1) glsym_evgl_engine_shutdown(re); 953 if (gl_wins == 1) glsym_evgl_engine_shutdown(re);
808 954
809 evas_drm_gbm_shutdown(eng_get_ob(re)->info); 955 eng_gbm_shutdown(eng_get_ob(re)->info);
810 956
811 //evas_render_engine_software_generic_clean() frees ob. 957 /* NB: evas_render_engine_software_generic_clean() frees ob */
812 evas_render_engine_software_generic_clean(&re->generic.software); 958 evas_render_engine_software_generic_clean(&re->generic.software);
813 959
814 gl_wins--; 960 gl_wins--;
815 961
816 free(re); 962 free(re);
817 } 963 }
964
818 if ((initted == EINA_TRUE) && (gl_wins == 0)) 965 if ((initted == EINA_TRUE) && (gl_wins == 0))
819 { 966 {
820 glsym_evas_gl_preload_shutdown(); 967 glsym_evas_gl_preload_shutdown();
@@ -823,35 +970,15 @@ eng_output_free(void *data)
823 } 970 }
824} 971}
825 972
826Eina_Bool
827eng_preload_make_current(void *data, void *doit)
828{
829 Outbuf *ob = data;
830 if (!ob) return EINA_FALSE;
831
832 if (doit)
833 {
834 if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0],
835 ob->egl_surface[0], ob->egl_context[0]))
836 return EINA_FALSE;
837 }
838 else
839 {
840 if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE,
841 EGL_NO_SURFACE, EGL_NO_CONTEXT))
842 return EINA_FALSE;
843 }
844 return EINA_TRUE;
845}
846
847static Eina_Bool 973static Eina_Bool
848eng_canvas_alpha_get(void *data, void *info EINA_UNUSED) 974eng_canvas_alpha_get(void *data, void *info EINA_UNUSED)
849{ 975{
850 Render_Engine *re; 976 Render_Engine *re;
851 977
852 if (!(re = (Render_Engine *)data)) return EINA_FALSE; 978 re = (Render_Engine *)data;
979 if (!re) return EINA_FALSE;
853 980
854 return re->generic.software.ob->alpha; 981 return eng_get_ob(re)->destination_alpha;
855} 982}
856 983
857static void 984static void
@@ -859,7 +986,8 @@ eng_output_dump(void *data)
859{ 986{
860 Render_Engine *re; 987 Render_Engine *re;
861 988
862 if (!(re = (Render_Engine *)data)) return; 989 re = (Render_Engine *)data;
990 if (!re) return;
863 991
864 evas_common_image_image_all_unload(); 992 evas_common_image_image_all_unload();
865 evas_common_font_font_all_unload(); 993 evas_common_font_font_all_unload();
@@ -867,101 +995,6 @@ eng_output_dump(void *data)
867 _re_winfree(re); 995 _re_winfree(re);
868} 996}
869 997
870static void
871_native_cb_bind(void *data EINA_UNUSED, void *image)
872{
873 Evas_GL_Image *img;
874 Native *n;
875
876 if (!(img = image)) return;
877 if (!(n = img->native.data)) return;
878
879 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
880 {
881 if (n->egl_surface)
882 {
883 if (glsym_glEGLImageTargetTexture2DOES)
884 {
885 glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, n->egl_surface);
886 if (eglGetError() != EGL_SUCCESS)
887 ERR("glEGLImageTargetTexture2DOES() failed.");
888 }
889 else
890 ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
891 }
892 }
893 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
894 {
895 glBindTexture(GL_TEXTURE_2D, n->ns.data.opengl.texture_id);
896 }
897}
898
899static void
900_native_cb_unbind(void *data EINA_UNUSED, void *image)
901{
902 Evas_GL_Image *img;
903 Native *n;
904
905 if (!(img = image)) return;
906 if (!(n = img->native.data)) return;
907
908 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
909 {
910 //glBindTexture(GL_TEXTURE_2D, 0); //really need?
911 }
912 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
913 {
914 glBindTexture(GL_TEXTURE_2D, 0);
915 }
916}
917
918static void
919_native_cb_free(void *data, void *image)
920{
921 Render_Engine *re;
922 Outbuf *ob;
923 Evas_GL_Image *img;
924 Native *n;
925 uint32_t texid;
926 void *wlid;
927
928 if (!(re = (Render_Engine *)data)) return;
929 if (!(img = image)) return;
930 if (!(n = img->native.data)) return;
931 if (!(ob = eng_get_ob(re))) return;
932
933 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
934 {
935 wlid = (void*)n->wl_buf;
936 eina_hash_del(ob->gl_context->shared->native_wl_hash, &wlid, img);
937 if (n->egl_surface)
938 {
939 if (glsym_eglDestroyImage)
940 {
941 glsym_eglDestroyImage(eng_get_ob(re)->egl_disp,
942 n->egl_surface);
943 if (eglGetError() != EGL_SUCCESS)
944 ERR("eglDestroyImage() failed.");
945 }
946 else
947 ERR("Try eglDestroyImage on EGL with no support");
948 }
949 }
950 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
951 {
952 texid = n->ns.data.opengl.texture_id;
953 eina_hash_del(ob->gl_context->shared->native_tex_hash, &texid, img);
954 }
955
956 img->native.data = NULL;
957 img->native.func.data = NULL;
958 img->native.func.bind = NULL;
959 img->native.func.unbind = NULL;
960 img->native.func.free = NULL;
961
962 free(n);
963}
964
965static void * 998static void *
966eng_image_native_set(void *data, void *image, void *native) 999eng_image_native_set(void *data, void *image, void *native)
967{ 1000{
@@ -972,11 +1005,13 @@ eng_image_native_set(void *data, void *image, void *native)
972 Evas_GL_Image *img, *img2; 1005 Evas_GL_Image *img, *img2;
973 unsigned int tex = 0, fbo = 0; 1006 unsigned int tex = 0, fbo = 0;
974 uint32_t texid; 1007 uint32_t texid;
975 void *wlid; 1008 void *wlid, *wl_buf = NULL;
976 void *wl_buf = NULL; 1009
1010 re = (Render_Engine *)data;
1011 if (!re) return NULL;
977 1012
978 if (!(re = (Render_Engine *)data)) return NULL; 1013 ob = eng_get_ob(re);
979 if (!(ob = eng_get_ob(re))) return NULL; 1014 if (!ob) return NULL;
980 1015
981 ns = native; 1016 ns = native;
982 1017
@@ -1027,7 +1062,7 @@ eng_image_native_set(void *data, void *image, void *native)
1027 1062
1028 if ((!ns) && (!img->native.data)) return img; 1063 if ((!ns) && (!img->native.data)) return img;
1029 1064
1030 eng_window_use(ob); 1065 evas_outbuf_use(ob);
1031 1066
1032 if (img->native.data) 1067 if (img->native.data)
1033 { 1068 {
@@ -1085,8 +1120,10 @@ eng_image_native_set(void *data, void *image, void *native)
1085 EGLint attribs[3]; 1120 EGLint attribs[3];
1086 int format, yinvert = 1; 1121 int format, yinvert = 1;
1087 1122
1088 glsym_eglQueryWaylandBufferWL(ob->egl_disp, wl_buf, EGL_TEXTURE_FORMAT, &format); 1123 glsym_eglQueryWaylandBufferWL(ob->egl.disp, wl_buf,
1089 if ((format != EGL_TEXTURE_RGB) && (format != EGL_TEXTURE_RGBA)) 1124 EGL_TEXTURE_FORMAT, &format);
1125 if ((format != EGL_TEXTURE_RGB) &&
1126 (format != EGL_TEXTURE_RGBA))
1090 { 1127 {
1091 ERR("eglQueryWaylandBufferWL() %d format is not supported ", format); 1128 ERR("eglQueryWaylandBufferWL() %d format is not supported ", format);
1092 glsym_evas_gl_common_image_free(img); 1129 glsym_evas_gl_common_image_free(img);
@@ -1099,20 +1136,23 @@ eng_image_native_set(void *data, void *image, void *native)
1099 attribs[2] = EGL_NONE; 1136 attribs[2] = EGL_NONE;
1100 1137
1101 memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface)); 1138 memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
1102 glsym_eglQueryWaylandBufferWL(ob->egl_disp, wl_buf, EGL_WAYLAND_Y_INVERTED_WL, &yinvert); 1139 glsym_eglQueryWaylandBufferWL(ob->egl.disp, wl_buf,
1103 eina_hash_add(ob->gl_context->shared->native_wl_hash, &wlid, img); 1140 EGL_WAYLAND_Y_INVERTED_WL,
1141 &yinvert);
1142 eina_hash_add(ob->gl_context->shared->native_wl_hash,
1143 &wlid, img);
1104 1144
1105 n->wl_buf = wl_buf; 1145 n->wl_buf = wl_buf;
1106 if (glsym_eglCreateImage) 1146 if (glsym_eglCreateImage)
1107 n->egl_surface = glsym_eglCreateImage(ob->egl_disp, 1147 n->egl_surface = glsym_eglCreateImage(ob->egl.disp,
1108 NULL, 1148 NULL,
1109 EGL_WAYLAND_BUFFER_WL, 1149 EGL_WAYLAND_BUFFER_WL,
1110 wl_buf, 1150 wl_buf, attribs);
1111 attribs);
1112 else 1151 else
1113 { 1152 {
1114 ERR("Try eglCreateImage on EGL with no support"); 1153 ERR("Try eglCreateImage on EGL with no support");
1115 eina_hash_del(ob->gl_context->shared->native_wl_hash, &wlid, img); 1154 eina_hash_del(ob->gl_context->shared->native_wl_hash,
1155 &wlid, img);
1116 glsym_evas_gl_common_image_free(img); 1156 glsym_evas_gl_common_image_free(img);
1117 free(n); 1157 free(n);
1118 return NULL; 1158 return NULL;
@@ -1121,7 +1161,8 @@ eng_image_native_set(void *data, void *image, void *native)
1121 if (!n->egl_surface) 1161 if (!n->egl_surface)
1122 { 1162 {
1123 ERR("eglCreatePixmapSurface() for %p failed", wl_buf); 1163 ERR("eglCreatePixmapSurface() for %p failed", wl_buf);
1124 eina_hash_del(ob->gl_context->shared->native_wl_hash, &wlid, img); 1164 eina_hash_del(ob->gl_context->shared->native_wl_hash,
1165 &wlid, img);
1125 glsym_evas_gl_common_image_free(img); 1166 glsym_evas_gl_common_image_free(img);
1126 free(n); 1167 free(n);
1127 return NULL; 1168 return NULL;
@@ -1151,7 +1192,8 @@ eng_image_native_set(void *data, void *image, void *native)
1151 if ((n = calloc(1, sizeof(Native)))) 1192 if ((n = calloc(1, sizeof(Native))))
1152 { 1193 {
1153 memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface)); 1194 memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
1154 eina_hash_add(ob->gl_context->shared->native_tex_hash, &texid, img); 1195 eina_hash_add(ob->gl_context->shared->native_tex_hash,
1196 &texid, img);
1155 1197
1156 n->egl_surface = 0; 1198 n->egl_surface = 0;
1157 1199
@@ -1170,9 +1212,25 @@ eng_image_native_set(void *data, void *image, void *native)
1170 } 1212 }
1171 } 1213 }
1172 1214
1215 /* TODO: NATIVE_SURFACE_TBM and NATIVE_SURFACE_EVASGL */
1216
1173 return img; 1217 return img;
1174} 1218}
1175 1219
1220static void *
1221eng_gl_current_context_get(void *data EINA_UNUSED)
1222{
1223 EVGL_Context *ctx;
1224 EVGLNative_Context context;
1225
1226 ctx = glsym_evas_gl_common_current_context_get();
1227 if (!ctx) return NULL;
1228
1229 context = glsym_evgl_current_native_context_get(ctx);
1230 if (eglGetCurrentContext() == context) return ctx;
1231
1232 return NULL;
1233}
1176 1234
1177/* module api functions */ 1235/* module api functions */
1178static int 1236static int
@@ -1202,22 +1260,24 @@ module_open(Evas_Module *em)
1202 func = pfunc; 1260 func = pfunc;
1203 1261
1204 /* now to override methods */ 1262 /* now to override methods */
1205#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_) 1263 EVAS_API_OVERRIDE(info, &func, eng_);
1206 ORD(info); 1264 EVAS_API_OVERRIDE(info_free, &func, eng_);
1207 ORD(info_free); 1265 EVAS_API_OVERRIDE(setup, &func, eng_);
1208 ORD(setup); 1266 EVAS_API_OVERRIDE(canvas_alpha_get, &func, eng_);
1209 ORD(canvas_alpha_get); 1267 EVAS_API_OVERRIDE(output_free, &func, eng_);
1210 ORD(output_free); 1268 EVAS_API_OVERRIDE(output_dump, &func, eng_);
1211 ORD(output_dump); 1269 EVAS_API_OVERRIDE(image_native_set, &func, eng_);
1212 ORD(image_native_set); 1270 EVAS_API_OVERRIDE(gl_current_context_get, &func, eng_);
1213 1271
1214 /* Mesa's EGL driver loads wayland egl by default. (called by eglGetProcaddr() ) 1272 /* Mesa's EGL driver loads wayland egl by default. (called by eglGetProcaddr() )
1215 * implicit env set (EGL_PLATFORM=drm) prevent that. */ 1273 * implicit env set (EGL_PLATFORM=drm) prevent that. */
1216 setenv("EGL_PLATFORM", "drm", 1); 1274 setenv("EGL_PLATFORM", "drm", 1);
1275
1217 gl_symbols(); 1276 gl_symbols();
1218 1277
1219 /* now advertise out own api */ 1278 /* now advertise out own api */
1220 em->functions = (void *)(&func); 1279 em->functions = (void *)(&func);
1280
1221 return 1; 1281 return 1;
1222} 1282}
1223 1283
@@ -1226,6 +1286,7 @@ module_close(Evas_Module *em EINA_UNUSED)
1226{ 1286{
1227 /* unregister the eina log domain for this engine */ 1287 /* unregister the eina log domain for this engine */
1228 eina_log_domain_unregister(_evas_engine_gl_drm_log_dom); 1288 eina_log_domain_unregister(_evas_engine_gl_drm_log_dom);
1289 _evas_engine_gl_drm_log_dom = -1;
1229} 1290}
1230 1291
1231static Evas_Module_Api evas_modapi = 1292static Evas_Module_Api evas_modapi =
diff --git a/src/modules/evas/engines/gl_drm/evas_engine.h b/src/modules/evas/engines/gl_drm/evas_engine.h
index b97b0476fe..28928932e7 100644
--- a/src/modules/evas/engines/gl_drm/evas_engine.h
+++ b/src/modules/evas/engines/gl_drm/evas_engine.h
@@ -1,47 +1,22 @@
1#ifndef EVAS_ENGINE_H 1#ifndef EVAS_ENGINE_H
2# define EVAS_ENGINE_H 2# define EVAS_ENGINE_H
3 3
4#include "config.h" 4# include "evas_common_private.h"
5#include "evas_common_private.h" 5# include "evas_macros.h"
6#include "evas_private.h" 6# include "evas_private.h"
7#include "Evas.h" 7# include "Evas.h"
8#include "Evas_Engine_GL_Drm.h" 8# include "Evas_Engine_GL_Drm.h"
9#include "evas_macros.h" 9
10 10# define GL_GLEXT_PROTOTYPES
11#define GL_GLEXT_PROTOTYPES 11# include <EGL/egl.h>
12#include <EGL/egl.h> 12# include <EGL/eglext.h>
13#include <EGL/eglext.h> 13# include <EGL/eglmesaext.h>
14#include <EGL/eglmesaext.h> 14# include <GLES2/gl2.h>
15#include <GLES2/gl2.h> 15# include <GLES2/gl2ext.h>
16#include <GLES2/gl2ext.h> 16# include "../gl_generic/Evas_Engine_GL_Generic.h"
17#include "../gl_generic/Evas_Engine_GL_Generic.h"
18
19#include <xf86drm.h>
20#include <xf86drmMode.h>
21#include <drm_fourcc.h>
22
23#include <signal.h>
24#include <sys/ioctl.h>
25#include <sys/types.h>
26#include <unistd.h>
27#include <fcntl.h>
28
29extern int extn_have_buffer_age;
30extern int _evas_engine_gl_drm_log_dom;
31 17
32extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new; 18extern int _evas_engine_gl_drm_log_dom;
33extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush; 19extern int _extn_have_buffer_age;
34extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free;
35extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use;
36extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe;
37extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done;
38extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize;
39extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump;
40extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock;
41extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
42
43/* define this to enable debug for the gl_drm engine */
44/* #define GL_DRM_DBG 0 */
45 20
46# ifdef ERR 21# ifdef ERR
47# undef ERR 22# undef ERR
@@ -68,124 +43,89 @@ extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
68# endif 43# endif
69# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_gl_drm_log_dom, __VA_ARGS__) 44# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_gl_drm_log_dom, __VA_ARGS__)
70 45
71# define NUM_BUFFERS 2 46extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new;
72 47extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush;
73typedef struct _Buffer Buffer; 48extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free;
74typedef struct _Plane Plane; 49extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use;
50extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe;
51extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done;
52extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize;
53extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump;
54extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock;
55extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
75 56
76struct _Buffer 57struct _Context_3D
77{ 58{
78 int stride; 59 EGLDisplay display;
79 int size; 60 EGLContext context;
80 int handle; 61 EGLSurface surface;
81 unsigned int fb;
82 struct gbm_bo *bo; //used for hardware framebuffers
83 Eina_Bool valid : 1;
84}; 62};
85 63
86struct _Plane 64struct _Outbuf
87{ 65{
88 unsigned int id; 66 Evas_Engine_Info_GL_Drm *info;
89 unsigned int crtcs; 67 Evas_Engine_GL_Context *gl_context;
90 68
91 struct 69 Evas *evas; // used for pre_swap, post_swap
92 {
93 unsigned int x, y;
94 unsigned int w, h;
95 } src, dst;
96 70
97 unsigned int num_formats; 71 int w, h;
98 unsigned int formats[]; 72 unsigned int rotation, depth;
99}; 73 Render_Engine_Swap_Mode swap_mode;
100 74
101struct _Outbuf
102{
103 EGLContext egl_context[1];
104 EGLSurface egl_surface[1];
105 EGLConfig egl_config;
106 EGLDisplay egl_disp;
107 struct gbm_device *gbm; 75 struct gbm_device *gbm;
108 struct gbm_surface *surface; 76 struct gbm_surface *surface;
109 Evas *evas;
110 uint32_t format;
111 uint32_t flags;
112 Evas_Engine_GL_Context *gl_context;
113 Evas_Engine_Info_GL_Drm *info;
114 Render_Engine_Swap_Mode swap_mode;
115 int w, h;
116 int depth, rot, screen, alpha;
117 int prev_age;
118 int frame_cnt;
119 int vsync;
120 Eina_Bool lost_back : 1;
121 Eina_Bool surf : 1;
122 77
123 struct 78 struct
124 { 79 {
125 Eina_Bool drew : 1; 80 EGLContext context[1];
126 } draw; 81 EGLSurface surface[1];
82 EGLConfig config;
83 EGLDisplay disp;
84 } egl;
127 85
128 struct 86 struct
129 { 87 {
130 int fd; 88 int prev_age, frame_cnt;
131 unsigned int conn, crtc, fb; 89 int curr, last, num;
132 Buffer buffer[NUM_BUFFERS]; 90 struct gbm_bo *bo[4];
133 int curr, num;
134 drmModeModeInfo mode;
135 drmEventContext ctx;
136 Eina_List *pending_writes; 91 Eina_List *pending_writes;
137 Eina_List *planes;
138 Eina_Bool pending_flip : 1;
139 } priv; 92 } priv;
140};
141 93
142struct _Context_3D 94 Eina_Bool destination_alpha : 1;
143{ 95 Eina_Bool vsync : 1;
144 EGLDisplay display; 96 Eina_Bool lost_back : 1;
145 EGLContext context; 97 Eina_Bool surf : 1;
146 EGLSurface surface; 98 Eina_Bool drew : 1;
147}; 99};
148 100
149Outbuf *eng_window_new(Evas_Engine_Info_GL_Drm *info, Evas *e, struct gbm_device *gbm, struct gbm_surface *surface, int screen, int depth, int w, int h, int indirect, int alpha, int rot, Render_Engine_Swap_Mode swap_mode); 101Outbuf *evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_Mode swap_mode);
150void eng_window_free(Outbuf *gw); 102void evas_outbuf_free(Outbuf *ob);
151void eng_window_use(Outbuf *gw); 103void evas_outbuf_use(Outbuf *ob);
152void eng_window_unsurf(Outbuf *gw); 104void evas_outbuf_resurf(Outbuf *ob);
153void eng_window_resurf(Outbuf *gw); 105void evas_outbuf_unsurf(Outbuf *ob);
154 106void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
155void eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth); 107Render_Engine_Swap_Mode evas_outbuf_buffer_state_get(Outbuf *ob);
156int eng_outbuf_get_rot(Outbuf *ob); 108int evas_outbuf_rot_get(Outbuf *ob);
157Render_Engine_Swap_Mode eng_outbuf_swap_mode(Outbuf *ob); 109Eina_Bool evas_outbuf_update_region_first_rect(Outbuf *ob);
158Eina_Bool eng_outbuf_region_first_rect(Outbuf *ob); 110void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
159void *eng_outbuf_new_region_for_update(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); 111void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
160void eng_outbuf_push_free_region_for_update(Outbuf *ob, RGBA_Image *update); 112void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
161void eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); 113void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
162void eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); 114Evas_Engine_GL_Context* evas_outbuf_gl_context_get(Outbuf *ob);
163Evas_Engine_GL_Context* eng_outbuf_gl_context_get(Outbuf *ob); 115void *evas_outbuf_egl_display_get(Outbuf *ob);
164void *eng_outbuf_egl_display_get(Outbuf *ob); 116Context_3D *evas_outbuf_gl_context_new(Outbuf *ob);
165 117void evas_outbuf_gl_context_use(Context_3D *ctx);
166void eng_gl_context_free(Context_3D *context);
167void eng_gl_context_use(Context_3D *context);
168
169Eina_Bool eng_preload_make_current(void *data, void *doit);
170
171Context_3D *eng_gl_context_new(Outbuf *win);
172 118
173static inline Eina_Bool 119static inline Eina_Bool
174_re_wincheck(Outbuf *ob) 120_re_wincheck(Outbuf *ob)
175{ 121{
176 if (ob->surf) return EINA_TRUE; 122 if (ob->surf) return EINA_TRUE;
177 eng_window_resurf(ob); 123 evas_outbuf_resurf(ob);
178 ob->lost_back = 1; 124 ob->lost_back = 1;
179 if (!ob->surf) 125 if (!ob->surf) ERR("GL engine can't re-create window surface!");
180 {
181 ERR("GL engine can't re-create window surface!");
182 }
183 return EINA_FALSE; 126 return EINA_FALSE;
184} 127}
185 128
186Eina_Bool evas_drm_gbm_init(Evas_Engine_Info_GL_Drm *info, int w, int h); 129extern unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c);
187Eina_Bool evas_drm_gbm_shutdown(Evas_Engine_Info_GL_Drm *info); 130
188Eina_Bool evas_drm_outbuf_setup(Outbuf *ob);
189void evas_drm_outbuf_framebuffer_set(Outbuf *ob, Buffer *buffer);
190Eina_Bool evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer);
191#endif 131#endif
diff --git a/src/modules/evas/engines/gl_drm/evas_outbuf.c b/src/modules/evas/engines/gl_drm/evas_outbuf.c
new file mode 100644
index 0000000000..6a9d7b8ded
--- /dev/null
+++ b/src/modules/evas/engines/gl_drm/evas_outbuf.c
@@ -0,0 +1,702 @@
1#include "evas_engine.h"
2
3/* local variables */
4static Outbuf *_evas_gl_drm_window = NULL;
5static EGLContext context = EGL_NO_CONTEXT;
6static int win_count = 0;
7
8static void
9_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data)
10{
11 Ecore_Drm_Fb *fb;
12
13 fb = data;
14 if (fb)
15 {
16 struct gbm_device *gbm;
17
18 gbm = gbm_bo_get_device(bo);
19 drmModeRmFB(gbm_device_get_fd(gbm), fb->id);
20 free(fb);
21 }
22}
23
24static Ecore_Drm_Fb *
25_evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo)
26{
27 int ret;
28 Ecore_Drm_Fb *fb;
29 uint32_t format;
30 uint32_t handles[4], pitches[4], offsets[4];
31
32 fb = gbm_bo_get_user_data(bo);
33 if (fb) return fb;
34
35 if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL;
36
37 format = gbm_bo_get_format(bo);
38
39 fb->w = gbm_bo_get_width(bo);
40 fb->h = gbm_bo_get_height(bo);
41 fb->hdl = gbm_bo_get_handle(bo).u32;
42 fb->stride = gbm_bo_get_stride(bo);
43 fb->size = fb->stride * fb->h;
44
45 handles[0] = fb->hdl;
46 pitches[0] = fb->stride;
47 offsets[0] = 0;
48
49 ret = drmModeAddFB2(dev->drm.fd, fb->w, fb->h, format,
50 handles, pitches, offsets, &(fb->id), 0);
51 if (ret)
52 ret = drmModeAddFB(dev->drm.fd, fb->w, fb->h, 24, 32,
53 fb->stride, fb->hdl, &(fb->id));
54
55 if (ret) ERR("FAILED TO ADD FB: %m");
56
57 gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy);
58
59 return fb;
60}
61
62static void
63_evas_outbuf_cb_pageflip(void *data)
64{
65 Outbuf *ob;
66 Ecore_Drm_Fb *fb;
67 struct gbm_bo *bo;
68
69 if (!(ob = data)) return;
70
71 bo = ob->priv.bo[ob->priv.curr];
72
73 fb = _evas_outbuf_fb_get(ob->info->info.dev, bo);
74 if (fb) fb->pending_flip = EINA_FALSE;
75
76 gbm_surface_release_buffer(ob->surface, bo);
77
78 ob->priv.last = ob->priv.curr;
79 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
80}
81
82static void
83_evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
84{
85 Ecore_Drm_Fb *fb;
86
87 ob->priv.bo[ob->priv.curr] = gbm_surface_lock_front_buffer(ob->surface);
88
89 fb = _evas_outbuf_fb_get(ob->info->info.dev, ob->priv.bo[ob->priv.curr]);
90 if (fb)
91 {
92 ecore_drm_fb_dirty(fb, rects, count);
93 ecore_drm_fb_set(ob->info->info.dev, fb);
94 ecore_drm_fb_send(ob->info->info.dev, fb, _evas_outbuf_cb_pageflip, ob);
95 }
96}
97
98static Eina_Bool
99_evas_outbuf_make_current(void *data, void *doit)
100{
101 Outbuf *ob;
102
103 if (!(ob = data)) return EINA_FALSE;
104
105 if (doit)
106 {
107 if (!eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
108 ob->egl.surface[0], ob->egl.context[0]))
109 return EINA_FALSE;
110 }
111 else
112 {
113 if (!eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
114 EGL_NO_SURFACE, EGL_NO_CONTEXT))
115 return EINA_FALSE;
116 }
117
118 return EINA_TRUE;
119}
120
121static Eina_Bool
122_evas_outbuf_egl_setup(Outbuf *ob)
123{
124 int ctx_attr[3];
125 int cfg_attr[40];
126 int maj = 0, min = 0;
127 int ncfg = 0, n = 0;
128 const GLubyte *vendor, *renderer, *version, *glslversion;
129 Eina_Bool blacklist = EINA_FALSE;
130
131 /* setup gbm egl surface */
132 ctx_attr[0] = EGL_CONTEXT_CLIENT_VERSION;
133 ctx_attr[1] = 2;
134 ctx_attr[2] = EGL_NONE;
135
136 cfg_attr[n++] = EGL_SURFACE_TYPE;
137 cfg_attr[n++] = EGL_WINDOW_BIT;
138 cfg_attr[n++] = EGL_RED_SIZE;
139 cfg_attr[n++] = 1;
140 cfg_attr[n++] = EGL_GREEN_SIZE;
141 cfg_attr[n++] = 1;
142 cfg_attr[n++] = EGL_BLUE_SIZE;
143 cfg_attr[n++] = 1;
144 cfg_attr[n++] = EGL_ALPHA_SIZE;
145 if (ob->destination_alpha) cfg_attr[n++] = 1;
146 else cfg_attr[n++] = 0;
147 cfg_attr[n++] = EGL_RENDERABLE_TYPE;
148 cfg_attr[n++] = EGL_OPENGL_ES2_BIT;
149 cfg_attr[n++] = EGL_NONE;
150
151 ob->egl.disp = eglGetDisplay((EGLNativeDisplayType)(ob->gbm));
152 if (ob->egl.disp == EGL_NO_DISPLAY)
153 {
154 ERR("eglGetDisplay() fail. code=%#x", eglGetError());
155 return EINA_FALSE;
156 }
157
158 if (!eglInitialize(ob->egl.disp, &maj, &min))
159 {
160 ERR("eglInitialize() fail. code=%#x", eglGetError());
161 return EINA_FALSE;
162 }
163
164 eglBindAPI(EGL_OPENGL_ES_API);
165 if (eglGetError() != EGL_SUCCESS)
166 {
167 ERR("eglBindAPI() fail. code=%#x", eglGetError());
168 return EINA_FALSE;
169 }
170
171 if (!eglChooseConfig(ob->egl.disp, cfg_attr, &ob->egl.config,
172 1, &ncfg) || (ncfg != 1))
173 {
174 ERR("eglChooseConfig() fail. code=%#x", eglGetError());
175 return EINA_FALSE;
176 }
177
178 ob->egl.surface[0] =
179 eglCreateWindowSurface(ob->egl.disp, ob->egl.config,
180 (EGLNativeWindowType)ob->surface, NULL);
181 if (ob->egl.surface[0] == EGL_NO_SURFACE)
182 {
183 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
184 ob->surface, eglGetError());
185 return EINA_FALSE;
186 }
187
188 ob->egl.context[0] =
189 eglCreateContext(ob->egl.disp, ob->egl.config, context, ctx_attr);
190 if (ob->egl.context[0] == EGL_NO_CONTEXT)
191 {
192 ERR("eglCreateContext() fail. code=%#x", eglGetError());
193 return EINA_FALSE;
194 }
195
196 if (context == EGL_NO_CONTEXT) context = ob->egl.context[0];
197
198 if (eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
199 ob->egl.surface[0], ob->egl.context[0]) == EGL_FALSE)
200 {
201 ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
202 return EINA_FALSE;
203 }
204
205 vendor = glGetString(GL_VENDOR);
206 renderer = glGetString(GL_RENDERER);
207 version = glGetString(GL_VERSION);
208 glslversion = glGetString(GL_SHADING_LANGUAGE_VERSION);
209 if (!vendor) vendor = (unsigned char *)"-UNKNOWN-";
210 if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
211 if (!version) version = (unsigned char *)"-UNKNOWN-";
212 if (!glslversion) glslversion = (unsigned char *)"-UNKNOWN-";
213 if (getenv("EVAS_GL_INFO"))
214 {
215 fprintf(stderr, "vendor : %s\n", vendor);
216 fprintf(stderr, "renderer: %s\n", renderer);
217 fprintf(stderr, "version : %s\n", version);
218 fprintf(stderr, "glsl ver: %s\n", glslversion);
219 }
220
221 if (strstr((const char *)vendor, "Mesa Project"))
222 {
223 if (strstr((const char *)renderer, "Software Rasterizer"))
224 blacklist = EINA_TRUE;
225 }
226 if (strstr((const char *)renderer, "softpipe"))
227 blacklist = EINA_TRUE;
228 if (strstr((const char *)renderer, "llvmpipe"))
229 blacklist = EINA_TRUE;
230
231 if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
232 {
233 ERR("OpenGL Driver blacklisted:");
234 ERR("Vendor: %s", (const char *)vendor);
235 ERR("Renderer: %s", (const char *)renderer);
236 ERR("Version: %s", (const char *)version);
237 return EINA_FALSE;
238 }
239
240 /* eng_gl_symbols(); */
241
242 ob->gl_context = glsym_evas_gl_common_context_new();
243 if (!ob->gl_context) return EINA_FALSE;
244
245#ifdef GL_GLES
246 ob->gl_context->egldisp = ob->egl.disp;
247 ob->gl_context->eglctxt = ob->egl.context[0];
248#endif
249
250 evas_outbuf_use(ob);
251 glsym_evas_gl_common_context_resize(ob->gl_context,
252 ob->w, ob->h, ob->rotation);
253
254 ob->surf = EINA_TRUE;
255
256 return EINA_TRUE;
257}
258
259Outbuf *
260evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_Mode swap_mode)
261{
262 Outbuf *ob;
263 char *num;
264
265 /* try to allocate space for outbuf */
266 if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
267
268 win_count++;
269
270 ob->w = w;
271 ob->h = h;
272 ob->info = info;
273 ob->depth = info->info.depth;
274 ob->rotation = info->info.rotation;
275 ob->destination_alpha = info->info.destination_alpha;
276 /* ob->vsync = info->info.vsync; */
277 ob->gbm = info->info.gbm;
278 ob->surface = info->info.surface;
279 ob->swap_mode = swap_mode;
280 ob->priv.num = 2;
281
282 if ((num = getenv("EVAS_GL_DRM_BUFFERS")))
283 {
284 ob->priv.num = atoi(num);
285 if (ob->priv.num <= 0) ob->priv.num = 1;
286 else if (ob->priv.num > 4) ob->priv.num = 4;
287 }
288
289 if ((num = getenv("EVAS_GL_DRM_VSYNC")))
290 ob->vsync = atoi(num);
291
292 if (!_evas_outbuf_egl_setup(ob))
293 {
294 evas_outbuf_free(ob);
295 return NULL;
296 }
297
298 return ob;
299}
300
301void
302evas_outbuf_free(Outbuf *ob)
303{
304 int ref = 0;
305
306 win_count--;
307 evas_outbuf_use(ob);
308
309 if (ob == _evas_gl_drm_window) _evas_gl_drm_window = NULL;
310
311 if (ob->gl_context)
312 {
313 ref = ob->gl_context->references - 1;
314 glsym_evas_gl_common_context_free(ob->gl_context);
315 }
316
317 eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
318
319 if (ob->egl.context[0] != context)
320 eglDestroyContext(ob->egl.disp, ob->egl.context[0]);
321
322 if (ob->egl.surface[0] != EGL_NO_SURFACE)
323 eglDestroySurface(ob->egl.disp, ob->egl.surface[0]);
324
325//#if 0
326 if (ob->surface)
327 {
328 gbm_surface_destroy(ob->surface);
329 ob->info->info.surface = NULL;
330 }
331//#endif
332
333 if (ref == 0)
334 {
335 if (context) eglDestroyContext(ob->egl.disp, context);
336 eglTerminate(ob->egl.disp);
337 eglReleaseThread();
338 context = EGL_NO_CONTEXT;
339 }
340
341 free(ob);
342}
343
344void
345evas_outbuf_use(Outbuf *ob)
346{
347 Eina_Bool force = EINA_FALSE;
348
349 glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob);
350
351 if (_evas_gl_drm_window)
352 {
353 if (eglGetCurrentContext() != _evas_gl_drm_window->egl.context[0])
354 force = EINA_TRUE;
355 }
356
357 if ((_evas_gl_drm_window != ob) || (force))
358 {
359 if (_evas_gl_drm_window)
360 {
361 glsym_evas_gl_common_context_use(_evas_gl_drm_window->gl_context);
362 glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
363 }
364
365 _evas_gl_drm_window = ob;
366
367 if (ob)
368 {
369 if (ob->egl.surface[0] != EGL_NO_SURFACE)
370 {
371 if (eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
372 ob->egl.surface[0],
373 ob->egl.context[0]) == EGL_FALSE)
374 ERR("eglMakeCurrent() failed!");
375 }
376 }
377 }
378
379 if (ob) glsym_evas_gl_common_context_use(ob->gl_context);
380}
381
382void
383evas_outbuf_resurf(Outbuf *ob)
384{
385 if (ob->surf) return;
386 if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", ob);
387
388 ob->egl.surface[0] =
389 eglCreateWindowSurface(ob->egl.disp, ob->egl.config,
390 (EGLNativeWindowType)ob->surface, NULL);
391
392 if (ob->egl.surface[0] == EGL_NO_SURFACE)
393 {
394 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
395 ob->surface, eglGetError());
396 return;
397 }
398
399 if (eglMakeCurrent(ob->egl.disp, ob->egl.surface[0], ob->egl.surface[0],
400 ob->egl.context[0]) == EGL_FALSE)
401 ERR("eglMakeCurrent() failed!");
402
403 ob->surf = EINA_TRUE;
404}
405
406void
407evas_outbuf_unsurf(Outbuf *ob)
408{
409 if (!ob->surf) return;
410 if (!getenv("EVAS_GL_WIN_RESURF")) return;
411 if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", ob);
412
413 if (_evas_gl_drm_window)
414 glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
415 if (_evas_gl_drm_window == ob)
416 {
417 eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
418 EGL_NO_SURFACE, EGL_NO_CONTEXT);
419 if (ob->egl.surface[0] != EGL_NO_SURFACE)
420 eglDestroySurface(ob->egl.disp, ob->egl.surface[0]);
421 ob->egl.surface[0] = EGL_NO_SURFACE;
422
423 _evas_gl_drm_window = NULL;
424 }
425
426 ob->surf = EINA_FALSE;
427}
428
429void
430evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth)
431{
432 /* if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth; */
433
434 /* check for changes */
435 /* if ((ob->w == w) && (ob->h == h) && */
436 /* (ob->destination_alpha == ob->info->info.destination_alpha) && */
437 /* ((int)ob->rotation == rot) && (ob->depth == depth)) */
438 /* return; */
439
440 ob->w = w;
441 ob->h = h;
442 ob->depth = depth;
443 ob->rotation = rot;
444 evas_outbuf_use(ob);
445 glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot);
446
447 //TODO: need drm gbm surface destroy & re-create.?
448}
449
450Render_Engine_Swap_Mode
451evas_outbuf_buffer_state_get(Outbuf *ob)
452{
453 /* check for valid output buffer */
454 if (!ob) return MODE_FULL;
455
456 if (ob->swap_mode == MODE_AUTO && _extn_have_buffer_age)
457 {
458 Render_Engine_Swap_Mode swap_mode;
459 EGLint age = 0;
460
461 if (!eglQuerySurface(ob->egl.disp, ob->egl.surface[0],
462 EGL_BUFFER_AGE_EXT, &age))
463 age = 0;
464
465 if (age == 1) swap_mode = MODE_COPY;
466 else if (age == 2) swap_mode = MODE_DOUBLE;
467 else if (age == 3) swap_mode = MODE_TRIPLE;
468 else if (age == 4) swap_mode = MODE_QUADRUPLE;
469 else swap_mode = MODE_FULL;
470 if ((int)age != ob->priv.prev_age) swap_mode = MODE_FULL;
471 ob->priv.prev_age = age;
472
473 return swap_mode;
474 }
475 else
476 {
477 int delta;
478
479 delta = (ob->priv.last - ob->priv.curr +
480 (ob->priv.last > ob->priv.last ?
481 0 : ob->priv.num)) % ob->priv.num;
482
483 /* This is the number of frame since last frame */
484 switch (delta)
485 {
486 case 0:
487 return MODE_COPY;
488 case 1:
489 return MODE_DOUBLE;
490 case 2:
491 return MODE_TRIPLE;
492 case 3:
493 return MODE_QUADRUPLE;
494 default:
495 return MODE_FULL;
496 }
497 }
498
499 return ob->swap_mode;
500}
501
502int
503evas_outbuf_rot_get(Outbuf *ob)
504{
505 return ob->rotation;
506}
507
508Eina_Bool
509evas_outbuf_update_region_first_rect(Outbuf *ob)
510{
511 ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
512
513 glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob);
514 evas_outbuf_use(ob);
515
516 if (!_re_wincheck(ob)) return EINA_TRUE;
517
518 glsym_evas_gl_common_context_resize(ob->gl_context, ob->w, ob->h, ob->rotation);
519 glsym_evas_gl_common_context_flush(ob->gl_context);
520 glsym_evas_gl_common_context_newframe(ob->gl_context);
521
522 return EINA_FALSE;
523}
524
525void *
526evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx EINA_UNUSED, int *cy EINA_UNUSED, int *cw EINA_UNUSED, int *ch EINA_UNUSED)
527{
528 if ((w == ob->w) && (h == ob->h))
529 ob->gl_context->master_clip.enabled = EINA_FALSE;
530 else
531 {
532 ob->gl_context->master_clip.enabled = EINA_TRUE;
533 ob->gl_context->master_clip.x = x;
534 ob->gl_context->master_clip.y = y;
535 ob->gl_context->master_clip.w = w;
536 ob->gl_context->master_clip.h = h;
537 }
538
539 return ob->gl_context->def_surface;
540}
541
542void
543evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
544{
545 /* Is it really necessary to flush per region ? Shouldn't we be able to
546 still do that for the full canvas when doing partial update */
547 if (!_re_wincheck(ob)) return;
548 ob->drew = EINA_TRUE;
549 glsym_evas_gl_common_context_flush(ob->gl_context);
550}
551
552void
553evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
554{
555 /* Nothing to do here as we don't really create an image per area */
556}
557
558void
559evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
560{
561 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
562
563 if (!_re_wincheck(ob)) goto end;
564 if (!ob->drew) goto end;
565
566 ob->drew = EINA_FALSE;
567 evas_outbuf_use(ob);
568 glsym_evas_gl_common_context_done(ob->gl_context);
569
570 if (!ob->vsync)
571 {
572 if (ob->info->info.vsync) eglSwapInterval(ob->egl.disp, 1);
573 else eglSwapInterval(ob->egl.disp, 0);
574 ob->vsync = 1;
575 }
576
577 if (ob->info->callback.pre_swap)
578 ob->info->callback.pre_swap(ob->info->callback.data, ob->evas);
579
580// TODO: Check eglSwapBuffersWithDamage for gl_drm and apply
581//#if 0
582 if ((glsym_eglSwapBuffersWithDamage) && (ob->swap_mode != MODE_FULL))
583 {
584 EGLint num = 0, *result = NULL, i = 0;
585 Tilebuf_Rect *r;
586
587 // if partial swaps can be done use re->rects
588 num = eina_inlist_count(EINA_INLIST_GET(rects));
589 if (num > 0)
590 {
591 result = alloca(sizeof(EGLint) * 4 * num);
592 EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
593 {
594 int gw, gh;
595
596 gw = ob->gl_context->w;
597 gh = ob->gl_context->h;
598 switch (ob->rotation)