1 #include "ecore_drm2_private.h"
2 
3 static int _ecore_drm2_init_count = 0;
4 static void *drm_lib = NULL;
5 
6 int _ecore_drm2_log_dom = -1;
7 
8 int (*sym_drmHandleEvent)(int fd, drmEventContext *evctx) = NULL;
9 void *(*sym_drmGetVersion)(int fd) = NULL;
10 void (*sym_drmFreeVersion)(void *drmver) = NULL;
11 void *(*sym_drmModeGetProperty)(int fd, uint32_t propertyId) = NULL;
12 void (*sym_drmModeFreeProperty)(drmModePropertyPtr ptr) = NULL;
13 void *(*sym_drmModeGetPropertyBlob)(int fd, uint32_t blob_id) = NULL;
14 void (*sym_drmModeFreePropertyBlob)(drmModePropertyBlobPtr ptr) = NULL;
15 int (*sym_drmModeDestroyPropertyBlob)(int fd, uint32_t id) = NULL;
16 int (*sym_drmIoctl)(int fd, unsigned long request, void *arg) = NULL;
17 void *(*sym_drmModeObjectGetProperties)(int fd, uint32_t object_id, uint32_t object_type) = NULL;
18 void (*sym_drmModeFreeObjectProperties)(drmModeObjectPropertiesPtr ptr) = NULL;
19 int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id) = NULL;
20 void *(*sym_drmModeAtomicAlloc)(void) = NULL;
21 void (*sym_drmModeAtomicFree)(drmModeAtomicReqPtr req) = NULL;
22 int (*sym_drmModeAtomicAddProperty)(drmModeAtomicReqPtr req, uint32_t object_id, uint32_t property_id, uint64_t value) = NULL;
23 int (*sym_drmModeAtomicCommit)(int fd, drmModeAtomicReqPtr req, uint32_t flags, void *user_data) = NULL;
24 void (*sym_drmModeAtomicSetCursor)(drmModeAtomicReqPtr req, int cursor) = NULL;
25 int (*sym_drmModeAtomicMerge)(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment);
26 void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id) = NULL;
27 void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr) = NULL;
28 void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId) = NULL;
29 void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr) = NULL;
30 int (*sym_drmModeSetCrtc)(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode) = NULL;
31 void *(*sym_drmModeGetResources)(int fd) = NULL;
32 void (*sym_drmModeFreeResources)(drmModeResPtr ptr) = NULL;
33 void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId) = NULL;
34 void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr) = NULL;
35 int (*sym_drmModeConnectorSetProperty)(int fd, uint32_t connector_id, uint32_t property_id, uint64_t value) = NULL;
36 int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value) = NULL;
37 int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value) = NULL;
38 void *(*sym_drmModeGetPlaneResources)(int fd) = NULL;
39 void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr) = NULL;
40 void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id) = NULL;
41 void (*sym_drmModeFreePlane)(drmModePlanePtr ptr) = NULL;
42 int (*sym_drmModeAddFB)(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id) = NULL;
43 int (*sym_drmModeAddFB2)(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, uint32_t bo_handles[4], uint32_t pitches[4], uint32_t offsets[4], uint32_t *buf_id, uint32_t flags) = NULL;
44 int (*sym_drmModeRmFB)(int fd, uint32_t bufferId) = NULL;
45 int (*sym_drmModePageFlip)(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data) = NULL;
46 int (*sym_drmModeDirtyFB)(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips) = NULL;
47 int (*sym_drmModeCrtcSetGamma)(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue) = NULL;
48 int (*sym_drmPrimeFDToHandle)(int fd, int prime_fd, uint32_t *handle) = NULL;
49 int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl) = NULL;
50 
51 EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
52 EAPI int ECORE_DRM2_EVENT_ACTIVATE = -1;
53 
54 static Eina_Bool
_ecore_drm2_link(void)55 _ecore_drm2_link(void)
56 {
57    int i, fail;
58    const char *drm_libs[] =
59      {
60         "libdrm.so.2",
61         "libdrm.so.1",
62         "libdrm.so.0",
63         "libdrm.so",
64         NULL,
65      };
66 
67 #define SYM(lib, xx)                         \
68    do {                                      \
69       sym_ ## xx = dlsym(lib, #xx);          \
70       if (!(sym_ ## xx)) {                   \
71          fail = 1;                           \
72       }                                      \
73    } while (0)
74 
75    if (drm_lib) return EINA_TRUE;
76 
77    for (i = 0; drm_libs[i]; i++)
78      {
79         drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY);
80         if (!drm_lib) continue;
81 
82         fail = 0;
83 
84         SYM(drm_lib, drmIoctl);
85         /* SYM(drm_lib, drmClose); */
86         SYM(drm_lib, drmWaitVBlank);
87         SYM(drm_lib, drmHandleEvent);
88         SYM(drm_lib, drmGetVersion);
89         SYM(drm_lib, drmFreeVersion);
90         SYM(drm_lib, drmModeGetProperty);
91         SYM(drm_lib, drmModeFreeProperty);
92         SYM(drm_lib, drmModeGetPropertyBlob);
93         SYM(drm_lib, drmModeFreePropertyBlob);
94         SYM(drm_lib, drmModeDestroyPropertyBlob);
95         SYM(drm_lib, drmModeObjectGetProperties);
96         SYM(drm_lib, drmModeFreeObjectProperties);
97         SYM(drm_lib, drmModeCreatePropertyBlob);
98         SYM(drm_lib, drmModeAtomicAlloc);
99         SYM(drm_lib, drmModeAtomicFree);
100         SYM(drm_lib, drmModeAtomicAddProperty);
101         SYM(drm_lib, drmModeAtomicCommit);
102         SYM(drm_lib, drmModeAtomicSetCursor);
103         SYM(drm_lib, drmModeAtomicMerge);
104         SYM(drm_lib, drmModeGetEncoder);
105         SYM(drm_lib, drmModeFreeEncoder);
106         SYM(drm_lib, drmModeGetCrtc);
107         SYM(drm_lib, drmModeFreeCrtc);
108         SYM(drm_lib, drmModeSetCrtc);
109         SYM(drm_lib, drmModeGetResources);
110         SYM(drm_lib, drmModeFreeResources);
111         SYM(drm_lib, drmModeGetConnector);
112         SYM(drm_lib, drmModeFreeConnector);
113         SYM(drm_lib, drmModeConnectorSetProperty);
114         SYM(drm_lib, drmGetCap);
115         SYM(drm_lib, drmSetClientCap);
116         SYM(drm_lib, drmModeGetPlaneResources);
117         SYM(drm_lib, drmModeFreePlaneResources);
118         SYM(drm_lib, drmModeGetPlane);
119         SYM(drm_lib, drmModeFreePlane);
120         SYM(drm_lib, drmModeAddFB);
121         SYM(drm_lib, drmModeAddFB2);
122         SYM(drm_lib, drmModeRmFB);
123         SYM(drm_lib, drmModePageFlip);
124         SYM(drm_lib, drmModeDirtyFB);
125         SYM(drm_lib, drmModeCrtcSetGamma);
126         SYM(drm_lib, drmPrimeFDToHandle);
127 
128         if (fail)
129           {
130              dlclose(drm_lib);
131              drm_lib = NULL;
132           }
133         else
134           break;
135      }
136 
137    if (!drm_lib) return EINA_FALSE;
138    return EINA_TRUE;
139 }
140 
141 EAPI int
ecore_drm2_init(void)142 ecore_drm2_init(void)
143 {
144    if (++_ecore_drm2_init_count != 1) return _ecore_drm2_init_count;
145 
146    if (!eina_init()) goto eina_err;
147 
148    if (!ecore_init())
149      {
150         EINA_LOG_ERR("Could not initialize Ecore library");
151         goto ecore_err;
152      }
153 
154    if (!eeze_init())
155      {
156         EINA_LOG_ERR("Could not initialize Eeze library");
157         goto eeze_err;
158      }
159 
160    if (!elput_init())
161      {
162         EINA_LOG_ERR("Could not initialize Elput library");
163         goto elput_err;
164      }
165 
166    _ecore_drm2_log_dom =
167      eina_log_domain_register("ecore_drm2", ECORE_DRM2_DEFAULT_LOG_COLOR);
168    if (!_ecore_drm2_log_dom)
169      {
170         EINA_LOG_ERR("Could not create logging domain for Ecore_Drm2");
171         goto log_err;
172      }
173 
174    ECORE_DRM2_EVENT_OUTPUT_CHANGED = ecore_event_type_new();
175    ECORE_DRM2_EVENT_ACTIVATE = ecore_event_type_new();
176 
177    if (!_ecore_drm2_link()) goto link_err;
178 
179    return _ecore_drm2_init_count;
180 
181 link_err:
182    eina_log_domain_unregister(_ecore_drm2_log_dom);
183    _ecore_drm2_log_dom = -1;
184 log_err:
185    elput_shutdown();
186 elput_err:
187    eeze_shutdown();
188 eeze_err:
189    ecore_shutdown();
190 ecore_err:
191    eina_shutdown();
192 eina_err:
193    return --_ecore_drm2_init_count;
194 }
195 
196 EAPI int
ecore_drm2_shutdown(void)197 ecore_drm2_shutdown(void)
198 {
199    if (_ecore_drm2_init_count < 1)
200      {
201         ERR("Ecore_Drm2 shutdown called without init");
202         return 0;
203      }
204 
205    if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count;
206 
207    ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
208    ECORE_DRM2_EVENT_ACTIVATE = -1;
209 
210    eina_log_domain_unregister(_ecore_drm2_log_dom);
211    _ecore_drm2_log_dom = -1;
212 
213    elput_shutdown();
214    eeze_shutdown();
215    ecore_shutdown();
216    eina_shutdown();
217 
218    return _ecore_drm2_init_count;
219 }
220 
221 EAPI int
ecore_drm2_event_handle(Ecore_Drm2_Device * dev,Ecore_Drm2_Context * drmctx)222 ecore_drm2_event_handle(Ecore_Drm2_Device *dev, Ecore_Drm2_Context *drmctx)
223 {
224    drmEventContext ctx;
225 
226    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, -1);
227 
228    memset(&ctx, 0, sizeof(ctx));
229    ctx.version = 2;
230    ctx.page_flip_handler = drmctx->page_flip_handler;
231    ctx.vblank_handler = drmctx->vblank_handler;
232 
233    return sym_drmHandleEvent(dev->fd, &ctx);
234 }
235