uterm: enable DRM helpers with UTERM_VIDEO_DUMB
[platform/upstream/kmscon.git] / src / uterm_video.h
1 /*
2  * uterm - Linux User-Space Terminal
3  *
4  * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /* Internal definitions */
27
28 #ifndef UTERM_VIDEO_H
29 #define UTERM_VIDEO_H
30
31 #include <inttypes.h>
32 #include <limits.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35 #include "eloop.h"
36 #include "shl_hook.h"
37 #include "uterm.h"
38
39 /* backend-operations */
40
41 struct mode_ops {
42         int (*init) (struct uterm_mode *mode);
43         void (*destroy) (struct uterm_mode *mode);
44         const char *(*get_name) (const struct uterm_mode *mode);
45         unsigned int (*get_width) (const struct uterm_mode *mode);
46         unsigned int (*get_height) (const struct uterm_mode *mode);
47 };
48
49 struct display_ops {
50         int (*init) (struct uterm_display *display);
51         void (*destroy) (struct uterm_display *display);
52         int (*activate) (struct uterm_display *disp, struct uterm_mode *mode);
53         void (*deactivate) (struct uterm_display *disp);
54         int (*set_dpms) (struct uterm_display *disp, int state);
55         int (*use) (struct uterm_display *disp);
56         int (*swap) (struct uterm_display *disp);
57         int (*blit) (struct uterm_display *disp,
58                      const struct uterm_video_buffer *buf,
59                      unsigned int x, unsigned int y);
60         int (*blend) (struct uterm_display *disp,
61                       const struct uterm_video_buffer *buf,
62                       unsigned int x, unsigned int y,
63                       uint8_t fr, uint8_t fg, uint8_t fb,
64                       uint8_t br, uint8_t bg, uint8_t bb);
65         int (*blendv) (struct uterm_display *disp,
66                        const struct uterm_video_blend_req *req, size_t num);
67         int (*fake_blendv) (struct uterm_display *disp,
68                             const struct uterm_video_blend_req *req,
69                             size_t num);
70         int (*fill) (struct uterm_display *disp,
71                      uint8_t r, uint8_t g, uint8_t b, unsigned int x,
72                      unsigned int y, unsigned int width, unsigned int height);
73 };
74
75 struct video_ops {
76         int (*init) (struct uterm_video *video, const char *node);
77         void (*destroy) (struct uterm_video *video);
78         void (*segfault) (struct uterm_video *video);
79         int (*use) (struct uterm_video *video);
80         int (*poll) (struct uterm_video *video);
81         void (*sleep) (struct uterm_video *video);
82         int (*wake_up) (struct uterm_video *video);
83 };
84
85 #define VIDEO_CALL(func, els, ...) (func ? func(__VA_ARGS__) : els)
86
87 /* drm */
88
89 #ifdef BUILD_ENABLE_VIDEO_DRM
90
91 #include <EGL/egl.h>
92 #include <EGL/eglext.h>
93 #include <gbm.h>
94 #include <GLES2/gl2.h>
95 #include <GLES2/gl2ext.h>
96 #include <xf86drm.h>
97 #include <xf86drmMode.h>
98 #include "static_gl.h"
99
100 struct drm_mode {
101         drmModeModeInfo info;
102 };
103
104 struct drm_rb {
105         struct gbm_bo *bo;
106         uint32_t fb;
107         EGLImageKHR image;
108         GLuint rb;
109 };
110
111 struct drm_display {
112         uint32_t conn_id;
113         int crtc_id;
114         drmModeCrtc *saved_crtc;
115
116         int current_rb;
117         struct drm_rb rb[2];
118         GLuint fb;
119 };
120
121 struct drm_video {
122         int fd;
123         struct ev_fd *efd;
124         struct gbm_device *gbm;
125         EGLDisplay *disp;
126         EGLContext *ctx;
127
128         unsigned int sinit;
129         bool supports_rowlen;
130         GLuint tex;
131
132         struct gl_shader *fill_shader;
133         GLuint uni_fill_proj;
134
135         struct gl_shader *blend_shader;
136         GLuint uni_blend_proj;
137         GLuint uni_blend_tex;
138         GLuint uni_blend_fgcol;
139         GLuint uni_blend_bgcol;
140
141         struct gl_shader *blit_shader;
142         GLuint uni_blit_proj;
143         GLuint uni_blit_tex;
144 };
145
146 static const bool drm_available = true;
147 extern const struct mode_ops drm_mode_ops;
148 extern const struct display_ops drm_display_ops;
149 extern const struct video_ops drm_video_ops;
150
151 #else /* !BUILD_ENABLE_VIDEO_DRM */
152
153 struct drm_mode {
154         int unused;
155 };
156
157 struct drm_display {
158         int unused;
159 };
160
161 struct drm_video {
162         int unused;
163 };
164
165 static const bool drm_available = false;
166 static const struct mode_ops drm_mode_ops;
167 static const struct display_ops drm_display_ops;
168 static const struct video_ops drm_video_ops;
169
170 #endif /* BUILD_ENABLE_VIDEO_DRM */
171
172 /* dumb drm */
173
174 #ifdef BUILD_ENABLE_VIDEO_DUMB
175
176 #include <xf86drm.h>
177 #include <xf86drmMode.h>
178
179 struct dumb_mode {
180         drmModeModeInfo info;
181 };
182
183 struct dumb_rb {
184         uint32_t fb;
185         uint32_t handle;
186         uint32_t stride;
187         uint64_t size;
188
189         void *map;
190 };
191
192 struct dumb_display {
193         uint32_t conn_id;
194         int crtc_id;
195         drmModeCrtc *saved_crtc;
196
197         int current_rb;
198         struct dumb_rb rb[2];
199 };
200
201 struct dumb_video {
202         int fd;
203         struct ev_fd *efd;
204 };
205
206 static const bool dumb_available = true;
207 extern const struct mode_ops dumb_mode_ops;
208 extern const struct display_ops dumb_display_ops;
209 extern const struct video_ops dumb_video_ops;
210
211 #else /* !BUILD_ENABLE_VIDEO_DUMB */
212
213 struct dumb_mode {
214         int unused;
215 };
216
217 struct dumb_display {
218         int unused;
219 };
220
221 struct dumb_video {
222         int unused;
223 };
224
225 static const bool dumb_available = false;
226 static const struct mode_ops dumb_mode_ops;
227 static const struct display_ops dumb_display_ops;
228 static const struct video_ops dumb_video_ops;
229
230 #endif /* BUILD_ENABLE_VIDEO_DUMB */
231
232 /* fbdev */
233
234 #ifdef BUILD_ENABLE_VIDEO_FBDEV
235
236 #include <linux/fb.h>
237
238 struct fbdev_mode {
239         unsigned int width;
240         unsigned int height;
241 };
242
243 struct fbdev_display {
244         char *node;
245         int fd;
246         bool pending_intro;
247
248         struct fb_fix_screeninfo finfo;
249         struct fb_var_screeninfo vinfo;
250         unsigned int rate;
251
252         unsigned int bufid;
253         size_t xres;
254         size_t yres;
255         size_t len;
256         uint8_t *map;
257         unsigned int stride;
258
259         bool xrgb32;
260         unsigned int Bpp;
261         unsigned int off_r;
262         unsigned int off_g;
263         unsigned int off_b;
264         unsigned int len_r;
265         unsigned int len_g;
266         unsigned int len_b;
267         int_fast32_t dither_r;
268         int_fast32_t dither_g;
269         int_fast32_t dither_b;
270 };
271
272 struct fbdev_video {
273         int unused;
274 };
275
276 static const bool fbdev_available = true;
277 extern const struct mode_ops fbdev_mode_ops;
278 extern const struct display_ops fbdev_display_ops;
279 extern const struct video_ops fbdev_video_ops;
280
281 #else /* !BUILD_ENABLE_VIDEO_FBDEV */
282
283 struct fbdev_mode {
284         int unused;
285 };
286
287 struct fbdev_display {
288         int unused;
289 };
290
291 struct fbdev_video {
292         int unused;
293 };
294
295 static const bool fbdev_available = false;
296 static const struct mode_ops fbdev_mode_ops;
297 static const struct display_ops fbdev_display_ops;
298 static const struct video_ops fbdev_video_ops;
299
300 #endif /* BUILD_ENABLE_VIDEO_FBDEV */
301
302 /* uterm_screen */
303
304 struct uterm_screen {
305         unsigned long ref;
306         struct uterm_display *disp;
307 };
308
309 /* uterm_mode */
310
311 struct uterm_mode {
312         unsigned long ref;
313         struct uterm_mode *next;
314
315         const struct mode_ops *ops;
316         union {
317                 struct drm_mode drm;
318                 struct dumb_mode dumb;
319                 struct fbdev_mode fbdev;
320         };
321 };
322
323 int mode_new(struct uterm_mode **out, const struct mode_ops *ops);
324
325 /* uterm_display */
326
327 #define DISPLAY_ONLINE          0x01
328 #define DISPLAY_VSYNC           0x02
329 #define DISPLAY_AVAILABLE       0x04
330 #define DISPLAY_OPEN            0x08
331 #define DISPLAY_DBUF            0x10
332 #define DISPLAY_DITHERING       0x20
333
334 struct uterm_display {
335         unsigned long ref;
336         unsigned int flags;
337         struct uterm_display *next;
338         struct uterm_video *video;
339
340         struct shl_hook *hook;
341         struct uterm_mode *modes;
342         struct uterm_mode *default_mode;
343         struct uterm_mode *current_mode;
344         int dpms;
345
346         bool vblank_scheduled;
347         struct itimerspec vblank_spec;
348         struct ev_timer *vblank_timer;
349
350         const struct display_ops *ops;
351         union {
352                 struct drm_display drm;
353                 struct dumb_display dumb;
354                 struct fbdev_display fbdev;
355         };
356 };
357
358 int display_new(struct uterm_display **out, const struct display_ops *ops,
359                 struct uterm_video *video);
360 void display_set_vblank_timer(struct uterm_display *disp,
361                               unsigned int msecs);
362 int display_schedule_vblank_timer(struct uterm_display *disp);
363
364 #define DISPLAY_CB(disp, act) shl_hook_call((disp)->hook, (disp), \
365                 &(struct uterm_display_event){ \
366                         .action = (act), \
367                 })
368
369 static inline bool display_is_conn(const struct uterm_display *disp)
370 {
371         return disp->video;
372 }
373
374 static inline bool display_is_online(const struct uterm_display *disp)
375 {
376         return display_is_conn(disp) && (disp->flags & DISPLAY_ONLINE);
377 }
378
379 /* uterm_video */
380
381 #define VIDEO_AWAKE             0x01
382 #define VIDEO_HOTPLUG           0x02
383
384 struct uterm_video {
385         unsigned long ref;
386         unsigned int flags;
387         struct ev_eloop *eloop;
388
389         struct uterm_display *displays;
390         struct shl_hook *hook;
391
392         const struct video_ops *ops;
393         union {
394                 struct drm_video drm;
395                 struct dumb_video dumb;
396                 struct fbdev_video fbdev;
397         };
398 };
399
400 static inline bool video_is_awake(const struct uterm_video *video)
401 {
402         return video->flags & VIDEO_AWAKE;
403 }
404
405 static inline bool video_need_hotplug(const struct uterm_video *video)
406 {
407         return video->flags & VIDEO_HOTPLUG;
408 }
409
410 #define VIDEO_CB(vid, disp, act) shl_hook_call((vid)->hook, (vid), \
411                 &(struct uterm_video_hotplug){ \
412                         .display = (disp), \
413                         .action = (act), \
414                 })
415
416 static inline int video_do_use(struct uterm_video *video)
417 {
418         return VIDEO_CALL(video->ops->use, -EOPNOTSUPP, video);
419 }
420
421 #if defined(BUILD_ENABLE_VIDEO_DRM) || defined(BUILD_ENABLE_VIDEO_DUMB)
422
423 static inline char *video_drm_get_id(int fd)
424 {
425         if (fd < 0)
426                 return NULL;
427
428         return drmGetBusid(fd);
429 }
430
431 static inline void video_drm_free_id(char *id)
432 {
433         if (!id)
434                 return;
435
436         drmFreeBusid(id);
437 }
438
439 static inline char *video_drm_get_name(int fd)
440 {
441         drmVersionPtr v;
442         char *name;
443
444         if (fd < 0)
445                 return NULL;
446
447         v = drmGetVersion(fd);
448         if (!v)
449                 return NULL;
450
451         name = malloc(v->name_len + 1);
452         if (name) {
453                 memcpy(name, v->name, v->name_len);
454                 name[v->name_len] = 0;
455         }
456
457         drmFreeVersion(v);
458         return name;
459 }
460
461 static inline void video_drm_free_name(char *name)
462 {
463         if (!name)
464                 return;
465
466         free(name);
467 }
468
469 #else
470
471 static inline char *video_drm_get_id(int fd)
472 {
473         return NULL;
474 }
475
476 static inline void video_drm_free_id(char *id)
477 {
478 }
479
480 static inline char *video_drm_get_name(int fd)
481 {
482         return NULL;
483 }
484
485 static inline void video_drm_free_name(char *name)
486 {
487 }
488
489 #endif
490
491 #endif /* UTERM_VIDEO_H */