summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Ecore_Drm2.am1
-rw-r--r--src/lib/ecore_drm2/Ecore_Drm2.h122
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_fb.c265
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_outputs.c14
4 files changed, 401 insertions, 1 deletions
diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am
index ab401c625f..1c328e33de 100644
--- a/src/Makefile_Ecore_Drm2.am
+++ b/src/Makefile_Ecore_Drm2.am
@@ -9,6 +9,7 @@ dist_installed_ecoredrm2mainheaders_DATA = \
9 lib/ecore_drm2/Ecore_Drm2.h 9 lib/ecore_drm2/Ecore_Drm2.h
10 10
11lib_ecore_drm2_libecore_drm2_la_SOURCES = \ 11lib_ecore_drm2_libecore_drm2_la_SOURCES = \
12lib/ecore_drm2/ecore_drm2_fb.c \
12lib/ecore_drm2/ecore_drm2_outputs.c \ 13lib/ecore_drm2/ecore_drm2_outputs.c \
13lib/ecore_drm2/ecore_drm2_device.c \ 14lib/ecore_drm2/ecore_drm2_device.c \
14lib/ecore_drm2/ecore_drm2.c \ 15lib/ecore_drm2/ecore_drm2.c \
diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h
index 0bed771489..f1ce291651 100644
--- a/src/lib/ecore_drm2/Ecore_Drm2.h
+++ b/src/lib/ecore_drm2/Ecore_Drm2.h
@@ -2,7 +2,6 @@
2# define _ECORE_DRM2_H 2# define _ECORE_DRM2_H
3 3
4# include <Ecore.h> 4# include <Ecore.h>
5# include <Elput.h>
6 5
7# ifdef EAPI 6# ifdef EAPI
8# undef EAPI 7# undef EAPI
@@ -67,6 +66,7 @@ EAPI extern int ECORE_DRM2_EVENT_OUTPUT_CHANGED;
67 * @li @ref Ecore_Drm2_Init_Group 66 * @li @ref Ecore_Drm2_Init_Group
68 * @li @ref Ecore_Drm2_Device_Group 67 * @li @ref Ecore_Drm2_Device_Group
69 * @li @ref Ecore_Drm2_Output_Group 68 * @li @ref Ecore_Drm2_Output_Group
69 * @li @ref Ecore_Drm2_Fb_Group
70 */ 70 */
71 71
72/** 72/**
@@ -302,6 +302,126 @@ EAPI void ecore_drm2_output_geometry_get(Ecore_Drm2_Output *output, int *x, int
302 */ 302 */
303EAPI unsigned int ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output); 303EAPI unsigned int ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output);
304 304
305/**
306 * Return the next Ecore_Drm2_Fb to be used on a given output
307 *
308 * @param output
309 *
310 * @return The next Ecore_Drm2_Fb which is scheduled to to be flipped, or NULL otherwise
311 *
312 * @ingroup Ecore_Drm2_Output_Group
313 * @since 1.18
314 */
315EAPI Ecore_Drm2_Fb *ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output);
316
317/**
318 * Set the next Ecore_Drm2_Fb to be used on a given output
319 *
320 * @param output
321 * @param fb
322 *
323 * @ingroup Ecore_Drm2_Output_Group
324 * @since 1.18
325 */
326EAPI void ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb);
327
328/**
329 * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions
330 *
331 * Functions that deal with setup of framebuffers
332 */
333
334/**
335 * Create a new framebuffer object
336 *
337 * @param fd
338 * @param width
339 * @param height
340 * @param depth
341 * @param bpp
342 * @param format
343 *
344 * @return A newly create framebuffer object, or NULL on failure
345 *
346 * @ingroup Ecore_Drm2_Fb_Group
347 * @since 1.18
348 */
349EAPI Ecore_Drm2_Fb *ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format);
350
351EAPI Ecore_Drm2_Fb *ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride);
352
353/**
354 * Destroy a framebuffer object
355 *
356 * @param fb
357 *
358 * @ingroup Ecore_Drm2_Fb_Group
359 * @since 1.18
360 */
361EAPI void ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb);
362
363/**
364 * Get a framebuffer's mmap'd data
365 *
366 * @param fb
367 *
368 * @return The mmap'd area of the framebuffer or NULL on failure
369 *
370 * @ingroup Ecore_Drm2_Fb_Group
371 * @since 1.18
372 */
373EAPI void *ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb);
374
375/**
376 * Get a framebuffer's size
377 *
378 * @param fb
379 *
380 * @return size of the framebuffers' mmap'd data or 0 on failure
381 *
382 * @ingroup Ecore_Drm2_Fb_Group
383 * @since 1.18
384 */
385EAPI unsigned int ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb);
386
387/**
388 * Get a framebuffer's stride
389 *
390 * @param fb
391 *
392 * @return stride of the framebuffer or 0 on failure
393 *
394 * @ingroup Ecore_Drm2_Fb_Group
395 * @since 1.18
396 */
397EAPI unsigned int ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb);
398
399/**
400 * Mark regions of a framebuffer as dirty
401 *
402 * @param fb
403 * @param rects
404 * @param count
405 *
406 * @ingroup Ecore_Drm2_Fb_Group
407 * @since 1.18
408 */
409EAPI void ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count);
410
411/**
412 * Schedule a pageflip to the given Ecore_Drm2_Fb
413 *
414 * @param fb
415 * @param output
416 * @param data
417 *
418 * @return The result of drmModePageFlip function call
419 *
420 * @ingroup Ecore_Drm2_Fb_Group
421 * @since 1.18
422 */
423EAPI int ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output, void *data);
424
305# endif 425# endif
306 426
307#endif 427#endif
diff --git a/src/lib/ecore_drm2/ecore_drm2_fb.c b/src/lib/ecore_drm2/ecore_drm2_fb.c
new file mode 100644
index 0000000000..9032c122be
--- /dev/null
+++ b/src/lib/ecore_drm2/ecore_drm2_fb.c
@@ -0,0 +1,265 @@
1#include "ecore_drm2_private.h"
2
3static Eina_Bool
4_fb2_create(Ecore_Drm2_Fb *fb)
5{
6 struct drm_mode_fb_cmd2 cmd;
7 uint32_t hdls[4], pitches[4], offsets[4];
8 uint64_t modifiers[4];
9
10 hdls[0] = fb->hdl;
11 pitches[0] = fb->stride;
12 offsets[0] = 0;
13 modifiers[0] = 0;
14
15 memset(&cmd, 0, sizeof(struct drm_mode_fb_cmd2));
16 cmd.fb_id = 0;
17 cmd.width = fb->w;
18 cmd.height = fb->h;
19 cmd.pixel_format = fb->format;
20 cmd.flags = 0;
21 memcpy(cmd.handles, hdls, 4 * sizeof(hdls[0]));
22 memcpy(cmd.pitches, pitches, 4 * sizeof(pitches[0]));
23 memcpy(cmd.offsets, offsets, 4 * sizeof(offsets[0]));
24 memcpy(cmd.modifier, modifiers, 4 * sizeof(modifiers[0]));
25
26 if (drmIoctl(fb->fd, DRM_IOCTL_MODE_ADDFB2, &cmd))
27 return EINA_FALSE;
28
29 fb->id = cmd.fb_id;
30
31 return EINA_TRUE;
32}
33
34EAPI Ecore_Drm2_Fb *
35ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format)
36{
37 Ecore_Drm2_Fb *fb;
38 struct drm_mode_create_dumb carg;
39 struct drm_mode_destroy_dumb darg;
40 struct drm_mode_map_dumb marg;
41 int ret;
42
43 EINA_SAFETY_ON_TRUE_RETURN_VAL((fd < 0), NULL);
44
45 fb = calloc(1, sizeof(Ecore_Drm2_Fb));
46 if (!fb) return NULL;
47
48 fb->fd = fd;
49 fb->w = width;
50 fb->h = height;
51 fb->bpp = bpp;
52 fb->depth = depth;
53 fb->format = format;
54
55 memset(&carg, 0, sizeof(struct drm_mode_create_dumb));
56 carg.bpp = bpp;
57 carg.width = width;
58 carg.height = height;
59
60 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg);
61 if (ret) goto err;
62
63 fb->hdl = carg.handle;
64 fb->size = carg.size;
65 fb->stride = carg.pitch;
66
67 if (!_fb2_create(fb))
68 {
69 ret =
70 drmModeAddFB(fd, width, height, depth, bpp,
71 fb->stride, fb->hdl, &fb->id);
72 if (ret)
73 {
74 ERR("Could not add framebuffer: %m");
75 goto add_err;
76 }
77 }
78
79 memset(&marg, 0, sizeof(struct drm_mode_map_dumb));
80 marg.handle = fb->hdl;
81 ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
82 if (ret)
83 {
84 ERR("Could not map framebuffer: %m");
85 goto map_err;
86 }
87
88 fb->mmap = mmap(NULL, fb->size, PROT_WRITE, MAP_SHARED, fd, marg.offset);
89 if (fb->mmap == MAP_FAILED)
90 {
91 ERR("Could not mmap framebuffer memory: %m");
92 goto map_err;
93 }
94
95 return fb;
96
97map_err:
98 drmModeRmFB(fd, fb->id);
99add_err:
100 memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
101 darg.handle = fb->hdl;
102 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
103err:
104 free(fb);
105 return NULL;
106}
107
108EAPI Ecore_Drm2_Fb *
109ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride)
110{
111 Ecore_Drm2_Fb *fb;
112
113 EINA_SAFETY_ON_TRUE_RETURN_VAL((fd < 0), NULL);
114
115 fb = calloc(1, sizeof(Ecore_Drm2_Fb));
116 if (!fb) return NULL;
117
118 fb->gbm = EINA_TRUE;
119
120 fb->fd = fd;
121 fb->w = width;
122 fb->h = height;
123 fb->bpp = bpp;
124 fb->depth = depth;
125 fb->format = format;
126 fb->stride = stride;
127 fb->size = fb->stride * fb->h;
128 fb->hdl = handle;
129
130 if (!_fb2_create(fb))
131 {
132 int ret;
133
134 ret =
135 drmModeAddFB(fd, width, height, depth, bpp,
136 fb->stride, fb->hdl, &fb->id);
137 if (ret)
138 {
139 ERR("Could not add framebuffer: %m");
140 goto err;
141 }
142 }
143
144 return fb;
145
146err:
147 free(fb);
148 return NULL;
149}
150
151EAPI void
152ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb)
153{
154 EINA_SAFETY_ON_NULL_RETURN(fb);
155
156 if (fb->id) drmModeRmFB(fb->fd, fb->id);
157
158 if (!fb->gbm)
159 {
160 struct drm_mode_destroy_dumb darg;
161
162 if (fb->mmap) munmap(fb->mmap, fb->size);
163
164 memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
165 darg.handle = fb->hdl;
166 drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
167 }
168
169 free(fb);
170}
171
172EAPI void *
173ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb)
174{
175 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
176 return fb->mmap;
177}
178
179EAPI unsigned int
180ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb)
181{
182 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
183 return fb->size;
184}
185
186EAPI unsigned int
187ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb)
188{
189 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
190 return fb->stride;
191}
192
193EAPI void
194ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count)
195{
196 EINA_SAFETY_ON_NULL_RETURN(fb);
197 EINA_SAFETY_ON_NULL_RETURN(rects);
198
199#ifdef DRM_MODE_FEATURE_DIRTYFB
200 drmModeClip *clip;
201 unsigned int i = 0;
202 int ret;
203
204 clip = alloca(count * sizeof(drmModeClip));
205 for (i = 0; i < count; i++)
206 {
207 clip[i].x1 = rects[i].x;
208 clip[i].y1 = rects[i].y;
209 clip[i].x2 = rects[i].w;
210 clip[i].y2 = rects[i].h;
211 }
212
213 ret = drmModeDirtyFB(fb->fd, fb->id, clip, count);
214 if ((ret) && (ret == -EINVAL))
215 WRN("Could not mark framebuffer as dirty: %m");
216#endif
217}
218
219EAPI int
220ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output, void *data)
221{
222 int ret = 0;
223
224 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, -1);
225 EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1);
226 EINA_SAFETY_ON_NULL_RETURN_VAL(output->current_mode, -1);
227
228 if (output->next)
229 WRN("Fb reused too soon, tearing may be visible");
230
231 if ((!output->current) ||
232 (output->current->stride != fb->stride))
233 {
234 ret =
235 drmModeSetCrtc(fb->fd, output->crtc_id, fb->id,
236 output->x, output->y, &output->conn_id, 1,
237 &output->current_mode->info);
238 if (ret)
239 {
240 ERR("Failed to set Mode %dx%d for Output %s: %m",
241 output->current_mode->width, output->current_mode->height,
242 output->name);
243 return ret;
244 }
245
246 output->current = fb;
247 output->next = NULL;
248
249 return 0;
250 }
251
252 ret =
253 drmModePageFlip(fb->fd, output->crtc_id, fb->id,
254 DRM_MODE_PAGE_FLIP_EVENT, data);
255 if (ret < 0)
256 {
257 DBG("Pageflip Failed for Crtc %u on Connector %u: %m",
258 output->crtc_id, output->conn_id);
259 output->next = fb;
260 return ret;
261 }
262
263 output->current = fb;
264 return 0;
265}
diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c
index d7f1c39f03..6443ecaf1a 100644
--- a/src/lib/ecore_drm2/ecore_drm2_outputs.c
+++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c
@@ -884,3 +884,17 @@ ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output)
884 EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0); 884 EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0);
885 return output->crtc_id; 885 return output->crtc_id;
886} 886}
887
888EAPI Ecore_Drm2_Fb *
889ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output)
890{
891 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
892 return output->next;
893}
894
895EAPI void
896ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb)
897{
898 EINA_SAFETY_ON_NULL_RETURN(output);
899 output->next = fb;
900}