summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/ecore_drm/Ecore_Drm.h4
-rw-r--r--src/lib/ecore_drm/ecore_drm_device.c132
-rw-r--r--src/lib/ecore_drm/ecore_drm_fb.c102
-rw-r--r--src/lib/ecore_drm/ecore_drm_private.h1
-rw-r--r--src/modules/evas/engines/drm/evas_outbuf.c31
5 files changed, 116 insertions, 154 deletions
diff --git a/src/lib/ecore_drm/Ecore_Drm.h b/src/lib/ecore_drm/Ecore_Drm.h
index 0366899..8d2787b 100644
--- a/src/lib/ecore_drm/Ecore_Drm.h
+++ b/src/lib/ecore_drm/Ecore_Drm.h
@@ -671,10 +671,12 @@ EAPI void ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned i
671 * @param dev The Ecore_Drm_Device to use 671 * @param dev The Ecore_Drm_Device to use
672 * @param fb The Ecore_Drm_Fb to make the current framebuffer 672 * @param fb The Ecore_Drm_Fb to make the current framebuffer
673 * 673 *
674 * @deprecated just call ecore_drm_fb_send() instead.
675 *
674 * @ingroup Ecore_Drm_Fb_Group 676 * @ingroup Ecore_Drm_Fb_Group
675 * @since 1.14 677 * @since 1.14
676 */ 678 */
677EAPI void ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb); 679EINA_DEPRECATED EAPI void ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb);
678 680
679/** 681/**
680 * Send an Ecore_Drm_Fb to the Ecore_Drm_Device 682 * Send an Ecore_Drm_Fb to the Ecore_Drm_Device
diff --git a/src/lib/ecore_drm/ecore_drm_device.c b/src/lib/ecore_drm/ecore_drm_device.c
index cca3332..756a5fc 100644
--- a/src/lib/ecore_drm/ecore_drm_device.c
+++ b/src/lib/ecore_drm/ecore_drm_device.c
@@ -10,93 +10,86 @@
10 ((x) >= (xx)) && ((y) >= (yy))) 10 ((x) >= (xx)) && ((y) >= (yy)))
11 11
12static Eina_List *drm_devices; 12static Eina_List *drm_devices;
13static int flip_count = 0; 13static int ticking = 0;
14 14
15static void 15static void
16_ecore_drm_device_cb_page_flip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) 16_ecore_drm_tick_schedule(Ecore_Drm_Device *dev)
17{ 17{
18 Ecore_Drm_Pageflip_Callback *cb; 18 drmVBlank vbl;
19
20 /* DBG("Drm Page Flip Event"); */
21
22 if (!(cb = data)) return;
23
24 flip_count++;
25 if (flip_count < cb->count) return;
26 19
27 cb->dev->current = cb->dev->next; 20 if (!ticking) return;
28 cb->dev->next = NULL;
29 21
30 flip_count = 0; 22 vbl.request.type = (DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT);
31 if (cb->func) cb->func(cb->data); 23 vbl.request.sequence = 1;
32 /* free(cb); */ 24 vbl.request.signal = (unsigned long)dev;
25 drmWaitVBlank(dev->drm.fd, &vbl);
26}
33 27
34 /* Ecore_Drm_Output *output; */ 28static void
29_ecore_drm_tick_begin(void *data)
30{
31 ticking = 1;
32 _ecore_drm_tick_schedule(data);
33}
35 34
36 /* DBG("Drm Page Flip Event"); */ 35static void
36_ecore_drm_tick_end(void *data EINA_UNUSED)
37{
38 ticking = 0;
39}
37 40
38 /* if (!(output = data)) return; */ 41static void
42_ecore_drm_tick_source_set(Ecore_Drm_Device *dev)
43{
44 ecore_animator_custom_source_tick_begin_callback_set
45 (_ecore_drm_tick_begin, dev);
46 ecore_animator_custom_source_tick_end_callback_set
47 (_ecore_drm_tick_end, dev);
48 ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
49}
39 50
40 /* if (output->pending_flip) */ 51static void
41 /* { */ 52_ecore_drm_device_cb_page_flip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data)
42 /* if (output->dev->current) */ 53{
43 /* ecore_drm_output_fb_release(output, output->dev->current); */ 54 Ecore_Drm_Output *output = data;
44 /* output->dev->current = output->dev->next; */ 55 Ecore_Drm_Fb *next;
45 /* output->dev->next = NULL; */
46 /* } */
47 56
48 /* output->pending_flip = EINA_FALSE; */ 57 if (output->pending_destroy)
49 /* if (output->pending_destroy) */ 58 {
50 /* { */ 59 ecore_drm_output_free(output);
51 /* output->pending_destroy = EINA_FALSE; */ 60 return;
52 /* ecore_drm_output_free(output); */ 61 }
53 /* } */ 62 /* We were unable to queue a page on the last flip attempt, so we'll
54 /* else if (!output->pending_vblank) */ 63 * try again now. */
55 /* ecore_drm_output_repaint(output); */ 64 next = output->next;
65 if (next)
66 {
67 output->next = NULL;
68 ecore_drm_fb_send(output->dev, next, NULL, NULL);
69 }
56} 70}
57 71
58static void 72static void
59_ecore_drm_device_cb_vblank(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) 73_ecore_drm_device_cb_vblank(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data)
60{ 74{
61 Ecore_Drm_Sprite *sprite; 75 ecore_animator_custom_tick();
62 Ecore_Drm_Output *output; 76 if (ticking) _ecore_drm_tick_schedule(data);
63
64 /* DBG("Drm VBlank Event"); */
65
66 if (!(sprite = data)) return;
67
68 output = sprite->output;
69 output->pending_vblank = EINA_FALSE;
70
71 ecore_drm_output_fb_release(output, sprite->current_fb);
72 sprite->current_fb = sprite->next_fb;
73 sprite->next_fb = NULL;
74
75 if (!output->pending_flip) _ecore_drm_output_frame_finish(output);
76} 77}
77 78
78#if 0 79static Eina_Bool
79static Eina_Bool 80_cb_drm_event_handle(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
80_ecore_drm_device_cb_idle(void *data)
81{ 81{
82 Ecore_Drm_Device *dev; 82 Ecore_Drm_Device *dev = data;
83 Ecore_Drm_Output *output; 83 int err;
84 Eina_List *l;
85
86 if (!(dev = data)) return ECORE_CALLBACK_CANCEL;
87 84
88 if (!dev->active) return ECORE_CALLBACK_RENEW; 85 err = drmHandleEvent(dev->drm.fd, &dev->drm_ctx);
89 86 if (err)
90 EINA_LIST_FOREACH(dev->outputs, l, output)
91 { 87 {
92 if ((!output->enabled) || (!output->need_repaint)) continue; 88 ERR("drmHandleEvent failed to read an event");
93 if (output->repaint_scheduled) continue; 89 return EINA_FALSE;
94 _ecore_drm_output_repaint_start(output);
95 } 90 }
96 91 return EINA_TRUE;
97 return ECORE_CALLBACK_RENEW;
98} 92}
99#endif
100 93
101static void 94static void
102_ecore_drm_device_cb_output_event(const char *device EINA_UNUSED, Eeze_Udev_Event event EINA_UNUSED, void *data, Eeze_Udev_Watch *watch EINA_UNUSED) 95_ecore_drm_device_cb_output_event(const char *device EINA_UNUSED, Eeze_Udev_Event event EINA_UNUSED, void *data, Eeze_Udev_Watch *watch EINA_UNUSED)
@@ -379,6 +372,10 @@ ecore_drm_device_open(Ecore_Drm_Device *dev)
379 eeze_udev_watch_add(EEZE_UDEV_TYPE_DRM, events, 372 eeze_udev_watch_add(EEZE_UDEV_TYPE_DRM, events,
380 _ecore_drm_device_cb_output_event, dev); 373 _ecore_drm_device_cb_output_event, dev);
381 374
375 dev->drm.hdlr =
376 ecore_main_fd_handler_add(dev->drm.fd, ECORE_FD_READ,
377 _cb_drm_event_handle, dev, NULL, NULL);
378
382 /* dev->drm.idler = */ 379 /* dev->drm.idler = */
383 /* ecore_idle_enterer_add(_ecore_drm_device_cb_idle, dev); */ 380 /* ecore_idle_enterer_add(_ecore_drm_device_cb_idle, dev); */
384 381
@@ -546,6 +543,7 @@ ecore_drm_device_software_setup(Ecore_Drm_Device *dev)
546 DBG("\tSize: %d", dev->dumb[i]->size); 543 DBG("\tSize: %d", dev->dumb[i]->size);
547 DBG("\tW: %d\tH: %d", dev->dumb[i]->w, dev->dumb[i]->h); 544 DBG("\tW: %d\tH: %d", dev->dumb[i]->w, dev->dumb[i]->h);
548 } 545 }
546 _ecore_drm_tick_source_set(dev);
549 547
550 return EINA_TRUE; 548 return EINA_TRUE;
551 549
diff --git a/src/lib/ecore_drm/ecore_drm_fb.c b/src/lib/ecore_drm/ecore_drm_fb.c
index 234b06f..8b7ca52 100644
--- a/src/lib/ecore_drm/ecore_drm_fb.c
+++ b/src/lib/ecore_drm/ecore_drm_fb.c
@@ -167,7 +167,15 @@ ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count)
167} 167}
168 168
169EAPI void 169EAPI void
170ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb) 170ecore_drm_fb_set(Ecore_Drm_Device *dev EINA_UNUSED, Ecore_Drm_Fb *fb EINA_UNUSED)
171{
172 /* ecore_drm_fb_set no longer has any functionality distinct from
173 * ecore_drm_fb_send so it is reduced to NO-OP to prevent messing up state
174 */
175}
176
177EAPI void
178ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func EINA_UNUSED, void *data EINA_UNUSED)
171{ 179{
172 Ecore_Drm_Output *output; 180 Ecore_Drm_Output *output;
173 Eina_List *l; 181 Eina_List *l;
@@ -185,88 +193,58 @@ ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb)
185 } 193 }
186 } 194 }
187 195
188 if (!dev->next) dev->next = fb; 196 if (!dev->outputs) return;
189 if (!dev->next) return;
190 197
191 EINA_LIST_FOREACH(dev->outputs, l, output) 198 EINA_LIST_FOREACH(dev->outputs, l, output)
192 { 199 {
193 int x = 0, y = 0;
194
195 if ((!output->enabled) || (!output->current_mode)) continue; 200 if ((!output->enabled) || (!output->current_mode)) continue;
196 201
197 if (!output->cloned) 202 if (output->next) WRN("fb reused too soon, tearing may be visible");
198 {
199 x = output->x;
200 y = output->y;
201 }
202 203
203 if ((!dev->current) || 204 /* If we changed display parameters or haven't displayed anything
204 (dev->current->stride != dev->next->stride)) 205 * yet we need to do a SetCrtc
206 */
207 if ((!output->current) ||
208 (output->current->stride != fb->stride))
205 { 209 {
206 if (drmModeSetCrtc(dev->drm.fd, output->crtc_id, dev->next->id, 210 int x = 0, y = 0;
211
212 if (!output->cloned)
213 {
214 x = output->x;
215 y = output->y;
216 }
217 if (drmModeSetCrtc(dev->drm.fd, output->crtc_id, fb->id,
207 x, y, &output->conn_id, 1, 218 x, y, &output->conn_id, 1,
208 &output->current_mode->info)) 219 &output->current_mode->info))
209 { 220 {
210 ERR("Failed to set Mode %dx%d for Output %s: %m", 221 ERR("Failed to set Mode %dx%d for Output %s: %m",
211 output->current_mode->width, output->current_mode->height, 222 output->current_mode->width, output->current_mode->height,
212 output->name); 223 output->name);
224 continue;
213 } 225 }
226 output->current = fb;
227 output->next = NULL;
214 228
215 /* TODO: set dpms on ?? */ 229 /* TODO: set dpms on ?? */
230 continue;
216 } 231 }
217 }
218}
219
220EAPI void
221ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data)
222{
223 Ecore_Drm_Output *output;
224 Eina_List *l;
225 Ecore_Drm_Pageflip_Callback *cb;
226
227 EINA_SAFETY_ON_NULL_RETURN(dev);
228 EINA_SAFETY_ON_NULL_RETURN(fb);
229 EINA_SAFETY_ON_NULL_RETURN(func);
230
231 if (eina_list_count(dev->outputs) < 1) return;
232
233 if (fb->pending_flip) return;
234
235 if (!(cb = calloc(1, sizeof(Ecore_Drm_Pageflip_Callback))))
236 return;
237
238 cb->dev = dev;
239 cb->func = func;
240 cb->data = data;
241
242 EINA_LIST_FOREACH(dev->outputs, l, output)
243 if (output->enabled) cb->count++;
244
245 EINA_LIST_FOREACH(dev->outputs, l, output)
246 {
247 if ((!output->enabled) || (!output->current_mode)) continue;
248 232
233 /* The normal case: We do a flip which waits for vblank and
234 * posts an event.
235 */
249 if (drmModePageFlip(dev->drm.fd, output->crtc_id, fb->id, 236 if (drmModePageFlip(dev->drm.fd, output->crtc_id, fb->id,
250 DRM_MODE_PAGE_FLIP_EVENT, cb) < 0) 237 DRM_MODE_PAGE_FLIP_EVENT, output) < 0)
251 { 238 {
252 ERR("Cannot flip crtc %u for connector %u: %m", 239 /* Failure to flip - likely there's already a flip
240 * queued, and we can't cancel, so just store this
241 * fb for later and it'll be queued in the flip
242 * handler */
243 DBG("flip crtc %u for connector %u failed, re-queued",
253 output->crtc_id, output->conn_id); 244 output->crtc_id, output->conn_id);
245 output->next = fb;
254 continue; 246 continue;
255 } 247 }
256 248 output->current = fb;
257 fb->pending_flip = EINA_TRUE;
258 }
259
260 while (fb->pending_flip)
261 {
262 int ret = 0;
263
264 ret = drmHandleEvent(dev->drm.fd, &dev->drm_ctx);
265 if (ret < 0)
266 {
267 ERR("drmHandleEvent Failed");
268 free(cb);
269 break;
270 }
271 } 249 }
272} 250}
diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h
index de78d6d..4271a7e 100644
--- a/src/lib/ecore_drm/ecore_drm_private.h
+++ b/src/lib/ecore_drm/ecore_drm_private.h
@@ -150,6 +150,7 @@ struct _Ecore_Drm_Output
150 } edid; 150 } edid;
151 151
152 Ecore_Drm_Backlight *backlight; 152 Ecore_Drm_Backlight *backlight;
153 Ecore_Drm_Fb *current, *next;
153 154
154 Eina_Bool primary : 1; 155 Eina_Bool primary : 1;
155 Eina_Bool connected : 1; 156 Eina_Bool connected : 1;
diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c
index 11d3dc6..64b3ba9 100644
--- a/src/modules/evas/engines/drm/evas_outbuf.c
+++ b/src/modules/evas/engines/drm/evas_outbuf.c
@@ -8,23 +8,6 @@
8#define GREEN_MASK 0x00ff00 8#define GREEN_MASK 0x00ff00
9#define BLUE_MASK 0x0000ff 9#define BLUE_MASK 0x0000ff
10 10
11static void
12_evas_outbuf_cb_pageflip(void *data)
13{
14 Outbuf *ob;
15 Ecore_Drm_Fb *fb;
16
17 if (!(ob = data)) return;
18
19 /* DBG("Outbuf Pagelip Done"); */
20
21 if ((fb = ob->priv.buffer[ob->priv.curr]))
22 fb->pending_flip = EINA_FALSE;
23
24 ob->priv.last = ob->priv.curr;
25 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
26}
27
28static void 11static void
29_evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) 12_evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
30{ 13{
@@ -35,11 +18,11 @@ _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
35 /* mark the fb as dirty */ 18 /* mark the fb as dirty */
36 ecore_drm_fb_dirty(buff, rects, count); 19 ecore_drm_fb_dirty(buff, rects, count);
37 20
38 /* if this buffer is not valid, we need to set it */
39 ecore_drm_fb_set(ob->info->info.dev, buff);
40
41 /* send this buffer to the crtc */ 21 /* send this buffer to the crtc */
42 ecore_drm_fb_send(ob->info->info.dev, buff, _evas_outbuf_cb_pageflip, ob); 22 ecore_drm_fb_send(ob->info->info.dev, buff, NULL, NULL);
23
24 ob->priv.last = ob->priv.curr;
25 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
43} 26}
44 27
45Outbuf * 28Outbuf *
@@ -62,8 +45,8 @@ evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
62 ob->destination_alpha = info->info.destination_alpha; 45 ob->destination_alpha = info->info.destination_alpha;
63 ob->vsync = info->info.vsync; 46 ob->vsync = info->info.vsync;
64 47
65 /* default to double-buffer */ 48 /* we must triple-buffer to prevent problems with the page flip handler */
66 ob->priv.num = 2; 49 ob->priv.num = 3;
67 50
68 /* check for buffer override */ 51 /* check for buffer override */
69 if ((num = getenv("EVAS_DRM_BUFFERS"))) 52 if ((num = getenv("EVAS_DRM_BUFFERS")))
@@ -98,7 +81,7 @@ evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
98 } 81 }
99 82
100 /* set the front buffer to be the one on the crtc */ 83 /* set the front buffer to be the one on the crtc */
101 ecore_drm_fb_set(info->info.dev, ob->priv.buffer[0]); 84 ecore_drm_fb_send(info->info.dev, ob->priv.buffer[0], NULL, NULL);
102 85
103 return ob; 86 return ob;
104} 87}