1 #include "ecore_drm2_private.h"
2
3 #ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
4 # define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
5 #endif
6
7 #ifndef DRM_CAP_DUMB_PREFER_SHADOW
8 # define DRM_CAP_DUMB_PREFER_SHADOW 0x4
9 #endif
10
11 #include <sys/utsname.h>
12
13 Eina_Bool _ecore_drm2_use_atomic = EINA_TRUE;
14
15 static Eina_Bool
_cb_session_active(void * data,int type EINA_UNUSED,void * event)16 _cb_session_active(void *data, int type EINA_UNUSED, void *event)
17 {
18 Eina_List *l;
19 Ecore_Drm2_Device *device;
20 Ecore_Drm2_Output *output;
21 Elput_Event_Session_Active *ev;
22 Ecore_Drm2_Event_Activate *ea;
23
24 ev = event;
25 device = data;
26
27 if (ev->active)
28 EINA_LIST_FOREACH(device->outputs, l, output)
29 ecore_drm2_output_dpms_set(output, DRM_MODE_DPMS_ON);
30
31 ea = calloc(1, sizeof(Ecore_Drm2_Event_Activate));
32 if (!ea) return ECORE_CALLBACK_RENEW;
33
34 ea->active = ev->active;
35
36 ecore_event_add(ECORE_DRM2_EVENT_ACTIVATE, ea, NULL, NULL);
37
38 return ECORE_CALLBACK_RENEW;
39 }
40
41 static Eina_Bool
_cb_device_change(void * data,int type EINA_UNUSED,void * event)42 _cb_device_change(void *data, int type EINA_UNUSED, void *event)
43 {
44 Elput_Event_Device_Change *ev = event;
45 Ecore_Drm2_Device *device = data;
46
47 if (ev->type == ELPUT_DEVICE_ADDED)
48 {
49 Eina_List *l;
50 Ecore_Drm2_Output *output;
51 Eina_Stringshare *name;
52
53 name = elput_device_output_name_get(ev->device);
54 if (!name)
55 {
56 output = eina_list_data_get(device->outputs);
57 if (output)
58 ecore_drm2_device_calibrate(device,
59 output->w, output->h);
60 }
61 else
62 {
63 EINA_LIST_FOREACH(device->outputs, l, output)
64 {
65 if (eina_streq(output->name, name))
66 {
67 ecore_drm2_device_calibrate(device,
68 output->w, output->h);
69 break;
70 }
71 }
72 }
73 }
74
75 return ECORE_CALLBACK_RENEW;
76 }
77
78 static Eina_Bool
_drm2_device_modeset_capable(int fd)79 _drm2_device_modeset_capable(int fd)
80 {
81 int ret = EINA_TRUE;
82 drmModeRes *res;
83
84 res = sym_drmModeGetResources(fd);
85 if (!res)
86 return EINA_FALSE;
87
88 if (res->count_crtcs <= 0 ||
89 res->count_connectors <= 0 ||
90 res->count_encoders <= 0)
91 ret = EINA_FALSE;
92
93 sym_drmModeFreeResources(res);
94
95 return ret;
96 }
97
98 static const char *
_drm2_device_find(Elput_Manager * em,const char * seat)99 _drm2_device_find(Elput_Manager *em, const char *seat)
100 {
101 Eina_List *devs, *l;
102 const char *dev, *ret = NULL, *chosen_dev = NULL, *d = NULL;
103 Eina_Bool found = EINA_FALSE;
104 Eina_Bool modeset;
105 int fd;
106
107 EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
108
109 d = getenv("ECORE_DRM2_CARD");
110 if (d)
111 devs = eeze_udev_find_by_subsystem_sysname("drm", d);
112 else
113 devs = eeze_udev_find_by_subsystem_sysname("drm", "card[0-9]*");
114
115 if (!devs) return NULL;
116
117 EINA_LIST_FOREACH(devs, l, dev)
118 {
119 const char *dpath, *dseat, *dparent;
120
121 dpath = eeze_udev_syspath_get_devpath(dev);
122 if (!dpath) continue;
123
124 dseat = eeze_udev_syspath_get_property(dev, "ID_SEAT");
125 if (!dseat) dseat = eina_stringshare_add("seat0");
126
127 if (strcmp(seat, dseat))
128 goto cont;
129
130 fd = elput_manager_open(em, dpath, -1);
131 if (fd < 0)
132 goto cont;
133 modeset = _drm2_device_modeset_capable(fd);
134 elput_manager_close(em, fd);
135 if (!modeset)
136 goto cont;
137
138 chosen_dev = dev;
139
140 dparent = eeze_udev_syspath_get_parent_filtered(dev, "pci", NULL);
141 if (dparent)
142 {
143 const char *id;
144
145 id = eeze_udev_syspath_get_sysattr(dparent, "boot_vga");
146 if (id)
147 {
148 if (!strcmp(id, "1")) found = EINA_TRUE;
149 eina_stringshare_del(id);
150 }
151
152 eina_stringshare_del(dparent);
153 }
154
155 cont:
156 eina_stringshare_del(dpath);
157 eina_stringshare_del(dseat);
158 if (found) break;
159 }
160
161 if (chosen_dev)
162 ret = eeze_udev_syspath_get_devpath(chosen_dev);
163
164 EINA_LIST_FREE(devs, dev)
165 eina_stringshare_del(dev);
166
167 return ret;
168 }
169
170 # if 0
171 static Eina_Bool
172 _drm2_atomic_usable(int fd)
173 {
174 drmVersion *drmver;
175 Eina_Bool ret = EINA_FALSE;
176
177 drmver = sym_drmGetVersion(fd);
178 if (!drmver) return EINA_FALSE;
179
180 /* detect driver */
181 if ((!strcmp(drmver->name, "i915")) &&
182 (!strcmp(drmver->desc, "Intel Graphics")))
183 {
184 FILE *fp;
185
186 /* detect kernel version
187 * NB: In order for atomic modesetting to work properly for Intel,
188 * we need to be using a kernel >= 4.8.0 */
189
190 fp = fopen("/proc/sys/kernel/osrelease", "rb");
191 if (fp)
192 {
193 char buff[512];
194 int maj = 0, min = 0;
195
196 if (fgets(buff, sizeof(buff), fp))
197 {
198 if (sscanf(buff, "%i.%i.%*s", &maj, &min) == 2)
199 {
200 if ((maj >= 4) && (min >= 8))
201 ret = EINA_TRUE;
202 }
203 }
204 fclose(fp);
205 }
206 }
207
208 sym_drmFreeVersion(drmver);
209
210 return ret;
211 }
212 # endif
213
214 static void
_drm2_atomic_state_crtc_fill(Ecore_Drm2_Crtc_State * cstate,int fd)215 _drm2_atomic_state_crtc_fill(Ecore_Drm2_Crtc_State *cstate, int fd)
216 {
217 drmModeObjectPropertiesPtr oprops;
218 unsigned int i = 0;
219
220 DBG("Atomic State Crtc Fill");
221
222 oprops =
223 sym_drmModeObjectGetProperties(fd, cstate->obj_id, DRM_MODE_OBJECT_CRTC);
224 if (!oprops) return;
225
226 DBG("\tCrtc %d", cstate->obj_id);
227
228 for (i = 0; i < oprops->count_props; i++)
229 {
230 drmModePropertyPtr prop;
231
232 prop = sym_drmModeGetProperty(fd, oprops->props[i]);
233 if (!prop) continue;
234
235 DBG("\t\tProperty: %s %d", prop->name, i);
236
237 if (!strcmp(prop->name, "MODE_ID"))
238 {
239 drmModePropertyBlobPtr bp;
240
241 cstate->mode.id = prop->prop_id;
242 cstate->mode.value = oprops->prop_values[i];
243 DBG("\t\t\tValue: %d", cstate->mode.value);
244
245 if (!cstate->mode.value)
246 {
247 cstate->mode.len = 0;
248 goto cont;
249 }
250
251 bp = sym_drmModeGetPropertyBlob(fd, cstate->mode.value);
252 if (!bp) goto cont;
253
254 if ((!cstate->mode.data) ||
255 memcmp(cstate->mode.data, bp->data, bp->length) != 0)
256 {
257 cstate->mode.data =
258 eina_memdup(bp->data, bp->length, 1);
259 }
260
261 cstate->mode.len = bp->length;
262
263 if (cstate->mode.value != 0)
264 sym_drmModeCreatePropertyBlob(fd, bp->data, bp->length,
265 &cstate->mode.value);
266
267 sym_drmModeFreePropertyBlob(bp);
268 }
269 else if (!strcmp(prop->name, "ACTIVE"))
270 {
271 cstate->active.id = prop->prop_id;
272 cstate->active.value = oprops->prop_values[i];
273 DBG("\t\t\tValue: %lu", (long)cstate->active.value);
274 }
275 else if (!strcmp(prop->name, "BACKGROUND_COLOR"))
276 {
277 cstate->background.id = prop->prop_id;
278 cstate->background.value = oprops->prop_values[i];
279 }
280 cont:
281 sym_drmModeFreeProperty(prop);
282 }
283
284 sym_drmModeFreeObjectProperties(oprops);
285 }
286
287 static void
_drm2_atomic_state_conn_fill(Ecore_Drm2_Connector_State * cstate,int fd)288 _drm2_atomic_state_conn_fill(Ecore_Drm2_Connector_State *cstate, int fd)
289 {
290 drmModeObjectPropertiesPtr oprops;
291 unsigned int i = 0;
292
293 DBG("Atomic State Connector Fill");
294
295 oprops =
296 sym_drmModeObjectGetProperties(fd, cstate->obj_id, DRM_MODE_OBJECT_CONNECTOR);
297 if (!oprops) return;
298
299 DBG("\tConnector: %d", cstate->obj_id);
300
301 for (i = 0; i < oprops->count_props; i++)
302 {
303 drmModePropertyPtr prop;
304
305 prop = sym_drmModeGetProperty(fd, oprops->props[i]);
306 if (!prop) continue;
307
308 DBG("\t\tProperty: %s", prop->name);
309
310 if (!strcmp(prop->name, "CRTC_ID"))
311 {
312 cstate->crtc.id = prop->prop_id;
313 cstate->crtc.value = oprops->prop_values[i];
314 DBG("\t\t\tValue: %lu", (long)cstate->crtc.value);
315 }
316 else if (!strcmp(prop->name, "DPMS"))
317 {
318 cstate->dpms.id = prop->prop_id;
319 cstate->dpms.value = oprops->prop_values[i];
320 DBG("\t\t\tValue: %lu", (long)cstate->dpms.value);
321 }
322 else if (!strcmp(prop->name, "EDID"))
323 {
324 drmModePropertyBlobPtr bp;
325
326 cstate->edid.id = oprops->prop_values[i];
327 if (!cstate->edid.id)
328 {
329 cstate->edid.len = 0;
330 goto cont;
331 }
332
333 bp = sym_drmModeGetPropertyBlob(fd, cstate->edid.id);
334 if (!bp) goto cont;
335
336 if ((!cstate->edid.data) ||
337 memcmp(cstate->edid.data, bp->data, bp->length) != 0)
338 {
339 cstate->edid.data =
340 eina_memdup(bp->data, bp->length, 1);
341 }
342
343 cstate->edid.len = bp->length;
344
345 if (cstate->edid.id != 0)
346 sym_drmModeCreatePropertyBlob(fd, bp->data, bp->length,
347 &cstate->edid.id);
348
349 sym_drmModeFreePropertyBlob(bp);
350 }
351 else if (!strcmp(prop->name, "aspect ratio"))
352 {
353 cstate->aspect.id = prop->prop_id;
354 cstate->aspect.value = oprops->prop_values[i];
355 DBG("\t\t\tValue: %lu", (long)cstate->aspect.value);
356 }
357 else if (!strcmp(prop->name, "scaling mode"))
358 {
359 cstate->scaling.id = prop->prop_id;
360 cstate->scaling.value = oprops->prop_values[i];
361 DBG("\t\t\tValue: %lu", (long)cstate->scaling.value);
362 }
363
364 cont:
365 sym_drmModeFreeProperty(prop);
366 }
367
368 sym_drmModeFreeObjectProperties(oprops);
369 }
370
371 static void
_drm2_atomic_state_plane_fill(Ecore_Drm2_Plane_State * pstate,int fd)372 _drm2_atomic_state_plane_fill(Ecore_Drm2_Plane_State *pstate, int fd)
373 {
374 drmModeObjectPropertiesPtr oprops;
375 unsigned int i = 0;
376 int k = 0;
377
378 DBG("Atomic State Plane Fill");
379
380 oprops =
381 sym_drmModeObjectGetProperties(fd, pstate->obj_id, DRM_MODE_OBJECT_PLANE);
382 if (!oprops) return;
383
384 DBG("\tPlane: %d", pstate->obj_id);
385
386 for (i = 0; i < oprops->count_props; i++)
387 {
388 drmModePropertyPtr prop;
389
390 prop = sym_drmModeGetProperty(fd, oprops->props[i]);
391 if (!prop) continue;
392
393 DBG("\t\tProperty: %s", prop->name);
394
395 if (!strcmp(prop->name, "CRTC_ID"))
396 {
397 pstate->cid.id = prop->prop_id;
398 pstate->cid.value = oprops->prop_values[i];
399 DBG("\t\t\tValue: %lu", (long)pstate->cid.value);
400 }
401 else if (!strcmp(prop->name, "FB_ID"))
402 {
403 pstate->fid.id = prop->prop_id;
404 pstate->fid.value = oprops->prop_values[i];
405 DBG("\t\t\tValue: %lu", (long)pstate->fid.value);
406 }
407 else if (!strcmp(prop->name, "CRTC_X"))
408 {
409 pstate->cx.id = prop->prop_id;
410 pstate->cx.value = oprops->prop_values[i];
411 }
412 else if (!strcmp(prop->name, "CRTC_Y"))
413 {
414 pstate->cy.id = prop->prop_id;
415 pstate->cy.value = oprops->prop_values[i];
416 }
417 else if (!strcmp(prop->name, "CRTC_W"))
418 {
419 pstate->cw.id = prop->prop_id;
420 pstate->cw.value = oprops->prop_values[i];
421 }
422 else if (!strcmp(prop->name, "CRTC_H"))
423 {
424 pstate->ch.id = prop->prop_id;
425 pstate->ch.value = oprops->prop_values[i];
426 }
427 else if (!strcmp(prop->name, "SRC_X"))
428 {
429 pstate->sx.id = prop->prop_id;
430 pstate->sx.value = oprops->prop_values[i];
431 }
432 else if (!strcmp(prop->name, "SRC_Y"))
433 {
434 pstate->sy.id = prop->prop_id;
435 pstate->sy.value = oprops->prop_values[i];
436 }
437 else if (!strcmp(prop->name, "SRC_W"))
438 {
439 pstate->sw.id = prop->prop_id;
440 pstate->sw.value = oprops->prop_values[i];
441 }
442 else if (!strcmp(prop->name, "SRC_H"))
443 {
444 pstate->sh.id = prop->prop_id;
445 pstate->sh.value = oprops->prop_values[i];
446 }
447 else if (!strcmp(prop->name, "type"))
448 {
449 pstate->type.id = prop->prop_id;
450 pstate->type.value = oprops->prop_values[i];
451 switch (pstate->type.value)
452 {
453 case DRM_PLANE_TYPE_OVERLAY:
454 DBG("\t\t\tOverlay Plane");
455 break;
456 case DRM_PLANE_TYPE_PRIMARY:
457 DBG("\t\t\tPrimary Plane");
458 break;
459 case DRM_PLANE_TYPE_CURSOR:
460 DBG("\t\t\tCursor Plane");
461 break;
462 default:
463 DBG("\t\t\tValue: %lu", (long)pstate->type.value);
464 break;
465 }
466 }
467 else if (!strcmp(prop->name, "rotation"))
468 {
469 pstate->rotation.id = prop->prop_id;
470 pstate->rotation.value = oprops->prop_values[i];
471
472 for (k = 0; k < prop->count_enums; k++)
473 {
474 int r = -1;
475
476 DBG("\t\t\tRotation: %s", prop->enums[k].name);
477 if (!strcmp(prop->enums[k].name, "rotate-0"))
478 r = ECORE_DRM2_ROTATION_NORMAL;
479 else if (!strcmp(prop->enums[k].name, "rotate-90"))
480 r = ECORE_DRM2_ROTATION_90;
481 else if (!strcmp(prop->enums[k].name, "rotate-180"))
482 r = ECORE_DRM2_ROTATION_180;
483 else if (!strcmp(prop->enums[k].name, "rotate-270"))
484 r = ECORE_DRM2_ROTATION_270;
485 else if (!strcmp(prop->enums[k].name, "reflect-x"))
486 r = ECORE_DRM2_ROTATION_REFLECT_X;
487 else if (!strcmp(prop->enums[k].name, "reflect-y"))
488 r = ECORE_DRM2_ROTATION_REFLECT_Y;
489
490 if (r != -1)
491 {
492 pstate->supported_rotations |= r;
493 pstate->rotation_map[ffs(r)] =
494 1ULL << prop->enums[k].value;
495 }
496 }
497 }
498
499 sym_drmModeFreeProperty(prop);
500 }
501
502 sym_drmModeFreeObjectProperties(oprops);
503 }
504
505 static void
_drm2_atomic_state_fill(Ecore_Drm2_Atomic_State * state,int fd)506 _drm2_atomic_state_fill(Ecore_Drm2_Atomic_State *state, int fd)
507 {
508 int i = 0;
509 drmModeResPtr res;
510 drmModePlaneResPtr pres;
511
512 res = sym_drmModeGetResources(fd);
513 if (!res) return;
514
515 pres = sym_drmModeGetPlaneResources(fd);
516 if (!pres) goto err;
517
518 state->crtcs = res->count_crtcs;
519 state->crtc_states = calloc(state->crtcs, sizeof(Ecore_Drm2_Crtc_State));
520 if (state->crtc_states)
521 {
522 for (i = 0; i < state->crtcs; i++)
523 {
524 Ecore_Drm2_Crtc_State *cstate;
525
526 cstate = &state->crtc_states[i];
527 cstate->obj_id = res->crtcs[i];
528 cstate->index = i;
529
530 _drm2_atomic_state_crtc_fill(cstate, fd);
531 }
532 }
533
534 state->conns = res->count_connectors;
535 state->conn_states =
536 calloc(state->conns, sizeof(Ecore_Drm2_Connector_State));
537 if (state->conn_states)
538 {
539 for (i = 0; i < state->conns; i++)
540 {
541 Ecore_Drm2_Connector_State *cstate;
542
543 cstate = &state->conn_states[i];
544 cstate->obj_id = res->connectors[i];
545
546 _drm2_atomic_state_conn_fill(cstate, fd);
547 }
548 }
549
550 state->planes = pres->count_planes;
551 state->plane_states = calloc(state->planes, sizeof(Ecore_Drm2_Plane_State));
552 if (state->plane_states)
553 {
554 unsigned int f = 0;
555
556 for (i = 0; i < state->planes; i++)
557 {
558 drmModePlanePtr plane;
559 Ecore_Drm2_Plane_State *pstate;
560
561 plane = sym_drmModeGetPlane(fd, pres->planes[i]);
562 if (!plane) continue;
563
564 pstate = &state->plane_states[i];
565 pstate->obj_id = pres->planes[i];
566 pstate->mask = plane->possible_crtcs;
567 pstate->num_formats = plane->count_formats;
568
569 pstate->formats = calloc(plane->count_formats, sizeof(uint32_t));
570
571 for (f = 0; f < plane->count_formats; f++)
572 pstate->formats[f] = plane->formats[f];
573
574 sym_drmModeFreePlane(plane);
575
576 _drm2_atomic_state_plane_fill(pstate, fd);
577 }
578 }
579
580 sym_drmModeFreePlaneResources(pres);
581
582 err:
583 sym_drmModeFreeResources(res);
584 }
585
586 static void
_drm2_atomic_state_free(Ecore_Drm2_Atomic_State * state)587 _drm2_atomic_state_free(Ecore_Drm2_Atomic_State *state)
588 {
589 free(state->plane_states);
590 free(state->conn_states);
591 free(state->crtc_states);
592 free(state);
593 }
594
595 EAPI Ecore_Drm2_Device *
ecore_drm2_device_open(const char * seat,unsigned int tty)596 ecore_drm2_device_open(const char *seat, unsigned int tty)
597 {
598 Ecore_Drm2_Device *device;
599
600 device = calloc(1, sizeof(Ecore_Drm2_Device));
601 if (!device) return NULL;
602
603 device->em = elput_manager_connect(seat, tty);
604 if (!device->em)
605 {
606 ERR("Could not connect to input manager");
607 goto man_err;
608 }
609
610 device->path = _drm2_device_find(device->em, seat);
611 if (!device->path)
612 {
613 ERR("Could not find drm device on seat %s", seat);
614 goto path_err;
615 }
616
617 device->fd = elput_manager_open(device->em, device->path, -1);
618 if (device->fd < 0) goto path_err;
619
620 if (!elput_input_init(device->em))
621 {
622 ERR("Could not initialize Elput Input");
623 goto input_err;
624 }
625
626 DBG("Device Path: %s", device->path);
627 DBG("Device Fd: %d", device->fd);
628
629 # if 0
630 /* check that this system can do atomic */
631 _ecore_drm2_use_atomic = _drm2_atomic_usable(device->fd);
632 # endif
633
634 if (getenv("ECORE_DRM2_ATOMIC_DISABLE"))
635 _ecore_drm2_use_atomic = EINA_FALSE;
636
637 if (_ecore_drm2_use_atomic)
638 {
639 if (sym_drmSetClientCap(device->fd,
640 DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0)
641 {
642 WRN("Could not enable Universal Plane support");
643 _ecore_drm2_use_atomic = EINA_FALSE;
644 }
645 else
646 {
647 if (sym_drmSetClientCap(device->fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0)
648 {
649 WRN("Could not enable Atomic Modesetting support");
650 _ecore_drm2_use_atomic = EINA_FALSE;
651 }
652 }
653 }
654
655 if (_ecore_drm2_use_atomic)
656 {
657 device->state = calloc(1, sizeof(Ecore_Drm2_Atomic_State));
658 if (device->state)
659 _drm2_atomic_state_fill(device->state, device->fd);
660 }
661
662 device->active_hdlr =
663 ecore_event_handler_add(ELPUT_EVENT_SESSION_ACTIVE,
664 _cb_session_active, device);
665
666 device->device_change_hdlr =
667 ecore_event_handler_add(ELPUT_EVENT_DEVICE_CHANGE,
668 _cb_device_change, device);
669
670 return device;
671
672 input_err:
673 elput_manager_close(device->em, device->fd);
674 path_err:
675 elput_manager_disconnect(device->em);
676 man_err:
677 free(device);
678 return NULL;
679 }
680
681 EAPI void
ecore_drm2_device_close(Ecore_Drm2_Device * device)682 ecore_drm2_device_close(Ecore_Drm2_Device *device)
683 {
684 EINA_SAFETY_ON_NULL_RETURN(device);
685
686 elput_input_shutdown(device->em);
687 elput_manager_close(device->em, device->fd);
688 if (_ecore_drm2_use_atomic)
689 _drm2_atomic_state_free(device->state);
690
691 ecore_event_handler_del(device->active_hdlr);
692 ecore_event_handler_del(device->device_change_hdlr);
693 eina_stringshare_del(device->path);
694 free(device);
695 }
696
697 EAPI int
ecore_drm2_device_clock_id_get(Ecore_Drm2_Device * device)698 ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device)
699 {
700 uint64_t caps;
701 int ret;
702
703 EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1);
704
705 ret = sym_drmGetCap(device->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &caps);
706 if ((ret == 0) && (caps == 1))
707 return CLOCK_MONOTONIC;
708 else
709 return CLOCK_REALTIME;
710 }
711
712 EAPI void
ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device * device,int * width,int * height)713 ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height)
714 {
715 uint64_t caps;
716 int ret;
717
718 EINA_SAFETY_ON_NULL_RETURN(device);
719
720 if (width)
721 {
722 *width = 64;
723 ret = sym_drmGetCap(device->fd, DRM_CAP_CURSOR_WIDTH, &caps);
724 if (ret == 0)
725 {
726 device->cursor.width = caps;
727 *width = caps;
728 }
729 }
730 if (height)
731 {
732 *height = 64;
733 ret = sym_drmGetCap(device->fd, DRM_CAP_CURSOR_HEIGHT, &caps);
734 if (ret == 0)
735 {
736 device->cursor.height = caps;
737 *height = caps;
738 }
739 }
740 }
741
742 EAPI void
ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device * device,int * x,int * y)743 ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, int *y)
744 {
745 if (x) *x = 0;
746 if (y) *y = 0;
747
748 EINA_SAFETY_ON_NULL_RETURN(device);
749
750 elput_input_pointer_xy_get(device->em, NULL, x, y);
751 }
752
753 EAPI void
ecore_drm2_device_pointer_warp(Ecore_Drm2_Device * device,int x,int y)754 ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y)
755 {
756 EINA_SAFETY_ON_NULL_RETURN(device);
757
758 elput_input_pointer_xy_set(device->em, NULL, x, y);
759 }
760
761 EAPI Eina_Bool
ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device * device,Eina_Bool left)762 ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool left)
763 {
764 EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
765
766 return elput_input_pointer_left_handed_set(device->em, NULL, left);
767 }
768
769 EAPI Eina_Bool
ecore_drm2_device_pointer_rotation_set(Ecore_Drm2_Device * device,int rotation)770 ecore_drm2_device_pointer_rotation_set(Ecore_Drm2_Device *device, int rotation)
771 {
772 EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
773
774 return elput_input_pointer_rotation_set(device->em, rotation);
775 }
776
777 EAPI void
ecore_drm2_device_pointer_accel_speed_set(Ecore_Drm2_Device * device,double speed)778 ecore_drm2_device_pointer_accel_speed_set(Ecore_Drm2_Device *device, double speed)
779 {
780 EINA_SAFETY_ON_NULL_RETURN(device);
781
782 elput_input_pointer_accel_speed_set(device->em, NULL, speed);
783 }
784
785 EAPI void
ecore_drm2_device_pointer_accel_profile_set(Ecore_Drm2_Device * device,uint32_t profile)786 ecore_drm2_device_pointer_accel_profile_set(Ecore_Drm2_Device *device, uint32_t profile)
787 {
788 EINA_SAFETY_ON_NULL_RETURN(device);
789
790 elput_input_pointer_accel_profile_set(device->em, NULL, profile);
791 }
792
793 EAPI void
ecore_drm2_device_touch_tap_to_click_enabled_set(Ecore_Drm2_Device * device,Eina_Bool enabled)794 ecore_drm2_device_touch_tap_to_click_enabled_set(Ecore_Drm2_Device *device, Eina_Bool enabled)
795 {
796 EINA_SAFETY_ON_NULL_RETURN(device);
797
798 elput_input_touch_tap_to_click_enabled_set(device->em, NULL, enabled);
799 }
800
801 EAPI void
ecore_drm2_device_window_set(Ecore_Drm2_Device * device,unsigned int window)802 ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window)
803 {
804 EINA_SAFETY_ON_NULL_RETURN(device);
805 EINA_SAFETY_ON_NULL_RETURN(device->em);
806 elput_manager_window_set(device->em, window);
807 }
808
809 EAPI void
ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device * device,int w,int h)810 ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h)
811 {
812 EINA_SAFETY_ON_NULL_RETURN(device);
813 EINA_SAFETY_ON_NULL_RETURN(device->em);
814
815 elput_input_pointer_max_set(device->em, w, h);
816 }
817
818 EAPI void
ecore_drm2_device_keyboard_info_set(Ecore_Drm2_Device * device,void * context,void * keymap,int group)819 ecore_drm2_device_keyboard_info_set(Ecore_Drm2_Device *device, void *context, void *keymap, int group)
820 {
821 EINA_SAFETY_ON_NULL_RETURN(device);
822
823 elput_input_keyboard_info_set(device->em, context, keymap, group);
824 }
825
826 EAPI void
ecore_drm2_device_keyboard_group_set(Ecore_Drm2_Device * device,int group)827 ecore_drm2_device_keyboard_group_set(Ecore_Drm2_Device *device, int group)
828 {
829 EINA_SAFETY_ON_NULL_RETURN(device);
830
831 elput_input_keyboard_group_set(device->em, group);
832 }
833
834 EAPI unsigned int *
ecore_drm2_device_crtcs_get(Ecore_Drm2_Device * device,int * num)835 ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num)
836 {
837 EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL);
838
839 if (num) *num = device->num_crtcs;
840 return device->crtcs;
841 }
842
843 EAPI void
ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device * device,int * minw,int * minh,int * maxw,int * maxh)844 ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh)
845 {
846 if (minw) *minw = 0;
847 if (minh) *minh = 0;
848 if (maxw) *maxw = 0;
849 if (maxh) *maxh = 0;
850
851 EINA_SAFETY_ON_NULL_RETURN(device);
852
853 if (minw) *minw = device->min.width;
854 if (minh) *minh = device->min.height;
855 if (maxw) *maxw = device->max.width;
856 if (maxh) *maxh = device->max.height;
857 }
858
859 EAPI void
ecore_drm2_device_calibrate(Ecore_Drm2_Device * device,int w,int h)860 ecore_drm2_device_calibrate(Ecore_Drm2_Device *device, int w, int h)
861 {
862 EINA_SAFETY_ON_NULL_RETURN(device);
863
864 elput_input_devices_calibrate(device->em, w, h);
865 }
866
867 EAPI Eina_Bool
ecore_drm2_device_vt_set(Ecore_Drm2_Device * device,int vt)868 ecore_drm2_device_vt_set(Ecore_Drm2_Device *device, int vt)
869 {
870 EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
871
872 return elput_manager_vt_set(device->em, vt);
873 }
874
875 EAPI Eina_Bool
ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device * device)876 ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device)
877 {
878 uint64_t caps;
879 int ret;
880
881 EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
882
883 ret = sym_drmGetCap(device->fd, DRM_CAP_DUMB_PREFER_SHADOW, &caps);
884 if ((ret == 0) && (caps == 1))
885 return EINA_TRUE;
886 else
887 return EINA_FALSE;
888 }
889
890 EAPI void
ecore_drm2_device_preferred_depth_get(Ecore_Drm2_Device * device,int * depth,int * bpp)891 ecore_drm2_device_preferred_depth_get(Ecore_Drm2_Device *device, int *depth, int *bpp)
892 {
893 uint64_t caps;
894 int ret;
895
896 EINA_SAFETY_ON_NULL_RETURN(device);
897
898 ret = sym_drmGetCap(device->fd, DRM_CAP_DUMB_PREFERRED_DEPTH, &caps);
899 if (ret == 0)
900 {
901 if (depth) *depth = caps;
902 if (bpp) *bpp = caps;
903 }
904 }
905
906 EAPI int
ecore_drm2_device_fd_get(Ecore_Drm2_Device * device)907 ecore_drm2_device_fd_get(Ecore_Drm2_Device *device)
908 {
909 EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1);
910
911 return device->fd;
912 }
913
914 EAPI Eina_Bool
ecore_drm2_vblank_supported(Ecore_Drm2_Device * dev)915 ecore_drm2_vblank_supported(Ecore_Drm2_Device *dev)
916 {
917 drmVBlank tmp;
918 int ret = 0;
919
920 EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
921
922 memset(&tmp, 0, sizeof(drmVBlank));
923 tmp.request.type = DRM_VBLANK_RELATIVE;
924
925 ret = sym_drmWaitVBlank(dev->fd, &tmp);
926
927 if (ret != 0) return EINA_FALSE;
928 return EINA_TRUE;
929 }
930
931 /* prevent crashing with old apps compiled against these functions */
ecore_drm2_device_keyboard_cached_context_set()932 EAPI void ecore_drm2_device_keyboard_cached_context_set(){};
ecore_drm2_device_keyboard_cached_keymap_set()933 EAPI void ecore_drm2_device_keyboard_cached_keymap_set(){};
934