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