chiark / gitweb /
build-sys: unbundle unifont
[elogind.git] / src / libsystemd-terminal / grdev.h
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 /*
23  * Graphics Devices
24  * The grdev layer provides generic access to graphics devices. The device
25  * types are hidden in the implementation and exported in a generic way. The
26  * grdev_session object forms the base layer. It loads, configures and prepares
27  * any graphics devices associated with that session. Each session is totally
28  * independent of other sessions and can be controlled separately.
29  * The target devices on a session are called display. A display always
30  * corresponds to a real display regardless how many pipes are needed to drive
31  * that display. That is, an exported display might internally be created out
32  * of arbitrary combinations of target pipes. However, this is meant as
33  * implementation detail and API users must never assume details below the
34  * display-level. That is, a display is the most low-level object exported.
35  * Therefore, pipe-configuration and any low-level modesetting is hidden from
36  * the public API. It is provided by the implementation, and it is the
37  * implementation that decides how pipes are driven.
38  *
39  * The API users are free to ignore specific displays or combine them to create
40  * larger screens. This often requires user-configuration so is dictated by
41  * policy. The underlying pipe-configuration might be affected by these
42  * high-level policies, but is never directly controlled by those. That means,
43  * depending on the displays you use, it might affect how underlying resources
44  * are assigned. However, users can never directly apply policies to the pipes,
45  * but only to displays. In case specific hardware needs quirks on the pipe
46  * level, we support that via hwdb, not via public user configuration.
47  *
48  * Right now, displays are limited to rgb32 memory-mapped framebuffers on the
49  * primary plane. However, the grdev implementation can be easily extended to
50  * allow more powerful access (including hardware-acceleration for 2D and 3D
51  * compositing). So far, this wasn't needed so it is not exposed.
52  */
53
54 #pragma once
55
56 #include <drm_fourcc.h>
57 #include <inttypes.h>
58 #include <libudev.h>
59 #include <stdbool.h>
60 #include <stdlib.h>
61 #include <systemd/sd-bus.h>
62 #include <systemd/sd-event.h>
63 #include "util.h"
64
65 typedef struct grdev_fb                 grdev_fb;
66 typedef struct grdev_display_target     grdev_display_target;
67 typedef struct grdev_display            grdev_display;
68
69 typedef struct grdev_event              grdev_event;
70 typedef struct grdev_session            grdev_session;
71 typedef struct grdev_context            grdev_context;
72
73 enum {
74         /* clockwise rotation; we treat this is abelian group Z4 with ADD */
75         GRDEV_ROTATE_0                  = 0,
76         GRDEV_ROTATE_90                 = 1,
77         GRDEV_ROTATE_180                = 2,
78         GRDEV_ROTATE_270                = 3,
79 };
80
81 enum {
82         /* flip states; we treat this as abelian group V4 with XOR */
83         GRDEV_FLIP_NONE                 = 0x0,
84         GRDEV_FLIP_HORIZONTAL           = 0x1,
85         GRDEV_FLIP_VERTICAL             = 0x2,
86 };
87
88 /*
89  * Displays
90  */
91
92 struct grdev_fb {
93         uint32_t width;
94         uint32_t height;
95         uint32_t format;
96         int32_t strides[4];
97         void *maps[4];
98
99         union {
100                 void *ptr;
101                 uint64_t u64;
102         } data;
103
104         void (*free_fn) (void *ptr);
105 };
106
107 struct grdev_display_target {
108         uint32_t x;
109         uint32_t y;
110         uint32_t width;
111         uint32_t height;
112         unsigned int rotate;
113         unsigned int flip;
114         grdev_fb *front;
115         grdev_fb *back;
116 };
117
118 void grdev_display_set_userdata(grdev_display *display, void *userdata);
119 void *grdev_display_get_userdata(grdev_display *display);
120
121 const char *grdev_display_get_name(grdev_display *display);
122 uint32_t grdev_display_get_width(grdev_display *display);
123 uint32_t grdev_display_get_height(grdev_display *display);
124
125 bool grdev_display_is_enabled(grdev_display *display);
126 void grdev_display_enable(grdev_display *display);
127 void grdev_display_disable(grdev_display *display);
128
129 const grdev_display_target *grdev_display_next_target(grdev_display *display, const grdev_display_target *prev);
130 void grdev_display_flip_target(grdev_display *display, const grdev_display_target *target);
131
132 #define GRDEV_DISPLAY_FOREACH_TARGET(_display, _t)                      \
133         for ((_t) = grdev_display_next_target((_display), NULL);        \
134              (_t);                                                      \
135              (_t) = grdev_display_next_target((_display), (_t)))
136
137 /*
138  * Events
139  */
140
141 enum {
142         GRDEV_EVENT_DISPLAY_ADD,
143         GRDEV_EVENT_DISPLAY_REMOVE,
144         GRDEV_EVENT_DISPLAY_CHANGE,
145         GRDEV_EVENT_DISPLAY_FRAME,
146 };
147
148 typedef void (*grdev_event_fn) (grdev_session *session, void *userdata, grdev_event *ev);
149
150 struct grdev_event {
151         unsigned int type;
152         union {
153                 struct {
154                         grdev_display *display;
155                 } display_add, display_remove, display_change;
156
157                 struct {
158                         grdev_display *display;
159                 } display_frame;
160         };
161 };
162
163 /*
164  * Sessions
165  */
166
167 enum {
168         GRDEV_SESSION_CUSTOM                    = (1 << 0),
169         GRDEV_SESSION_MANAGED                   = (1 << 1),
170 };
171
172 int grdev_session_new(grdev_session **out,
173                       grdev_context *context,
174                       unsigned int flags,
175                       const char *name,
176                       grdev_event_fn event_fn,
177                       void *userdata);
178 grdev_session *grdev_session_free(grdev_session *session);
179
180 DEFINE_TRIVIAL_CLEANUP_FUNC(grdev_session*, grdev_session_free);
181
182 bool grdev_session_is_enabled(grdev_session *session);
183 void grdev_session_enable(grdev_session *session);
184 void grdev_session_disable(grdev_session *session);
185
186 void grdev_session_commit(grdev_session *session);
187 void grdev_session_restore(grdev_session *session);
188
189 void grdev_session_add_drm(grdev_session *session, struct udev_device *ud);
190 void grdev_session_remove_drm(grdev_session *session, struct udev_device *ud);
191 void grdev_session_hotplug_drm(grdev_session *session, struct udev_device *ud);
192
193 /*
194  * Contexts
195  */
196
197 int grdev_context_new(grdev_context **out, sd_event *event, sd_bus *sysbus);
198 grdev_context *grdev_context_ref(grdev_context *context);
199 grdev_context *grdev_context_unref(grdev_context *context);
200
201 DEFINE_TRIVIAL_CLEANUP_FUNC(grdev_context*, grdev_context_unref);