Line |
Branch |
Exec |
Source |
1 |
|
|
/* GATE PROJECT LICENSE: |
2 |
|
|
+----------------------------------------------------------------------------+ |
3 |
|
|
| Copyright(c) 2018-2025, Stefan Meislinger | |
4 |
|
|
| All rights reserved. | |
5 |
|
|
| | |
6 |
|
|
| Redistribution and use in source and binary forms, with or without | |
7 |
|
|
| modification, are permitted provided that the following conditions are met:| |
8 |
|
|
| | |
9 |
|
|
| 1. Redistributions of source code must retain the above copyright notice, | |
10 |
|
|
| this list of conditions and the following disclaimer. | |
11 |
|
|
| 2. Redistributions in binary form must reproduce the above copyright | |
12 |
|
|
| notice, this list of conditions and the following disclaimer in the | |
13 |
|
|
| documentation and/or other materials provided with the distribution. | |
14 |
|
|
| | |
15 |
|
|
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| |
16 |
|
|
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 |
|
|
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 |
|
|
| ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
19 |
|
|
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 |
|
|
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 |
|
|
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 |
|
|
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 |
|
|
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 |
|
|
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
25 |
|
|
| THE POSSIBILITY OF SUCH DAMAGE. | |
26 |
|
|
+----------------------------------------------------------------------------+ |
27 |
|
|
*/ |
28 |
|
|
|
29 |
|
|
#include "gate/graphics/framebuffers.h" |
30 |
|
|
#include "gate/atomics.h" |
31 |
|
|
#include "gate/results.h" |
32 |
|
|
#include "gate/times.h" |
33 |
|
|
|
34 |
|
|
#if defined(GATE_SYS_WINSTORE) |
35 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_DIRECTX |
36 |
|
|
#elif defined(GATE_SYS_WIN16) |
37 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_WIN16 |
38 |
|
|
#elif defined(GATE_SYS_WIN) |
39 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_WIN32 |
40 |
|
|
#elif defined(GATE_SYS_ANDROID) |
41 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_GL |
42 |
|
|
#elif defined(GATE_SYS_OPENBSD) || defined(GATE_SYS_BEOS) |
43 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL |
44 |
|
|
#elif defined(GATE_SYS_DARWIN) |
45 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL |
46 |
|
|
#elif defined(GATE_SYS_POSIX) |
47 |
|
|
# if defined(GATE_GRAPHICS_WAYLAND) |
48 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_WAYLAND 1 |
49 |
|
|
# else |
50 |
|
|
# if defined(HAVE_X11_HEADERS) |
51 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_XLIB 1 |
52 |
|
|
# else |
53 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL |
54 |
|
|
# endif |
55 |
|
|
# endif |
56 |
|
|
#elif defined(GATE_SYS_EFI) |
57 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_UGA |
58 |
|
|
#elif defined(GATE_SYS_DOS) |
59 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_INT10 |
60 |
|
|
#elif defined(GATE_SYS_WASM) |
61 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_WASM |
62 |
|
|
#else |
63 |
|
|
# define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL |
64 |
|
|
#endif |
65 |
|
|
|
66 |
|
|
|
67 |
|
|
|
68 |
|
|
/************************************************** |
69 |
|
|
* generic rasterimage framebuffer implementation * |
70 |
|
|
**************************************************/ |
71 |
|
|
|
72 |
|
|
typedef struct rasterfb_impl |
73 |
|
|
{ |
74 |
|
|
GATE_INTERFACE_VTBL(gate_framebuffer) const* vtbl; |
75 |
|
|
|
76 |
|
|
gate_atomic_int_t ref_counter; |
77 |
|
|
|
78 |
|
|
gate_rasterimage_t image_header; |
79 |
|
|
|
80 |
|
|
gate_uint8_t image_data[8]; |
81 |
|
|
} rasterfb_t; |
82 |
|
|
|
83 |
|
|
|
84 |
|
✗ |
static char const* rasterfb_get_interface_name(void* obj) |
85 |
|
|
{ |
86 |
|
|
GATE_UNUSED_ARG(obj); |
87 |
|
✗ |
return GATE_INTERFACE_NAME_FRAMEBUFFER; |
88 |
|
|
} |
89 |
|
✗ |
static void rasterfb_release(void* obj) |
90 |
|
|
{ |
91 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
92 |
|
✗ |
if (0 == gate_atomic_int_dec(&impl->ref_counter)) |
93 |
|
|
{ |
94 |
|
✗ |
gate_mem_clear(impl, sizeof(rasterfb_t)); |
95 |
|
✗ |
gate_mem_dealloc(impl); |
96 |
|
|
} |
97 |
|
✗ |
} |
98 |
|
✗ |
static int rasterfb_retain(void* obj) |
99 |
|
|
{ |
100 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
101 |
|
✗ |
return gate_atomic_int_inc(&impl->ref_counter); |
102 |
|
|
} |
103 |
|
|
|
104 |
|
✗ |
static gate_result_t rasterfb_get_info(void* obj, gate_framebuffer_info_t* ptr_info) |
105 |
|
|
{ |
106 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
107 |
|
✗ |
gate_result_t ret = GATE_RESULT_INVALIDARG; |
108 |
|
✗ |
if (impl && ptr_info) |
109 |
|
|
{ |
110 |
|
✗ |
ptr_info->width = gate_rasterimage_width(&impl->image_header); |
111 |
|
✗ |
ptr_info->height = gate_rasterimage_height(&impl->image_header); |
112 |
|
✗ |
ptr_info->bits_per_pixel = 32; |
113 |
|
✗ |
ptr_info->format_id = 0; |
114 |
|
✗ |
ret = GATE_RESULT_OK; |
115 |
|
|
} |
116 |
|
✗ |
return ret; |
117 |
|
|
} |
118 |
|
✗ |
static gate_result_t rasterfb_get_property(void* obj, gate_string_t const* name, gate_property_t* prop) |
119 |
|
|
{ |
120 |
|
|
GATE_UNUSED_ARG(obj); |
121 |
|
|
GATE_UNUSED_ARG(name); |
122 |
|
|
GATE_UNUSED_ARG(prop); |
123 |
|
✗ |
return GATE_RESULT_NOTSUPPORTED; |
124 |
|
|
} |
125 |
|
✗ |
static gate_result_t rasterfb_set_property(void* obj, gate_string_t const* name, gate_property_t const* prop) |
126 |
|
|
{ |
127 |
|
|
GATE_UNUSED_ARG(obj); |
128 |
|
|
GATE_UNUSED_ARG(name); |
129 |
|
|
GATE_UNUSED_ARG(prop); |
130 |
|
✗ |
return GATE_RESULT_NOTSUPPORTED; |
131 |
|
|
} |
132 |
|
|
|
133 |
|
✗ |
static gate_result_t rasterfb_update(void* obj) |
134 |
|
|
{ |
135 |
|
|
/* rasterimage framebuffer is always up-to-date */ |
136 |
|
|
GATE_UNUSED_ARG(obj); |
137 |
|
✗ |
return GATE_RESULT_OK; |
138 |
|
|
} |
139 |
|
|
|
140 |
|
✗ |
static gate_result_t rasterfb_get_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t* ptr_col) |
141 |
|
|
{ |
142 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
143 |
|
✗ |
return gate_rasterimage_get_pixel(&impl->image_header, x, y, ptr_col); |
144 |
|
|
} |
145 |
|
✗ |
static gate_result_t rasterfb_set_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t col) |
146 |
|
|
{ |
147 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
148 |
|
✗ |
return gate_rasterimage_set_pixel(&impl->image_header, x, y, &col); |
149 |
|
|
} |
150 |
|
|
|
151 |
|
✗ |
static gate_result_t rasterfb_get_image(void* obj, gate_uint32_t src_x, gate_uint32_t src_y, gate_uint32_t width, gate_uint32_t height, gate_rasterimage_t* ptr_image) |
152 |
|
|
{ |
153 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
154 |
|
✗ |
gate_result_t ret = GATE_RESULT_FAILED; |
155 |
|
✗ |
gate_uint32_t fb_width = gate_rasterimage_width(&impl->image_header); |
156 |
|
✗ |
gate_uint32_t fb_height = gate_rasterimage_height(&impl->image_header); |
157 |
|
|
|
158 |
|
✗ |
if ((src_x == 0) && (src_y == 0) && (((width == 0) && (height == 0)) || ((width == fb_width) && (height == fb_height)))) |
159 |
|
|
{ |
160 |
|
✗ |
if (gate_rasterimage_copy(ptr_image, &impl->image_header)) |
161 |
|
|
{ |
162 |
|
✗ |
ret = GATE_RESULT_OK; |
163 |
|
|
} |
164 |
|
|
} |
165 |
|
|
else |
166 |
|
|
{ |
167 |
|
|
do |
168 |
|
|
{ |
169 |
|
✗ |
if (!gate_rasterimage_create(ptr_image, GATE_IMAGE_PIXELFORMAT_BGR32, width, height, NULL)) |
170 |
|
|
{ |
171 |
|
✗ |
ret = GATE_RESULT_OUTOFMEMORY; |
172 |
|
✗ |
break; |
173 |
|
|
} |
174 |
|
✗ |
ret = gate_rasterimage_paste_image(ptr_image, &impl->image_header, 0, 0, src_x, src_y, width, height, false); |
175 |
|
✗ |
if (GATE_FAILED(ret)) |
176 |
|
|
{ |
177 |
|
✗ |
gate_rasterimage_release(ptr_image); |
178 |
|
|
} |
179 |
|
|
} while (0); |
180 |
|
|
} |
181 |
|
✗ |
return ret; |
182 |
|
|
} |
183 |
|
|
|
184 |
|
✗ |
static gate_result_t rasterfb_set_image(void* obj, gate_rasterimage_t const* ptr_image, gate_uint32_t dest_x, gate_uint32_t dest_y) |
185 |
|
|
{ |
186 |
|
✗ |
rasterfb_t* const impl = (rasterfb_t*)obj; |
187 |
|
✗ |
gate_result_t ret = GATE_RESULT_FAILED; |
188 |
|
✗ |
gate_uint32_t width = gate_rasterimage_width(ptr_image); |
189 |
|
✗ |
gate_uint32_t height = gate_rasterimage_height(ptr_image); |
190 |
|
|
|
191 |
|
✗ |
ret = gate_rasterimage_paste_image(&impl->image_header, ptr_image, dest_x, dest_y, 0, 0, width, height, false); |
192 |
|
✗ |
return ret; |
193 |
|
|
} |
194 |
|
|
|
195 |
|
✗ |
static gate_result_t rasterfb_await_event(void* obj, gate_uint32_t timeout_ms, gate_framebuffer_event_t* ptr_received_evt) |
196 |
|
|
{ |
197 |
|
|
GATE_UNUSED_ARG(obj); |
198 |
|
|
GATE_UNUSED_ARG(timeout_ms); |
199 |
|
|
GATE_UNUSED_ARG(ptr_received_evt); |
200 |
|
✗ |
return GATE_RESULT_NOTSUPPORTED; |
201 |
|
|
} |
202 |
|
|
|
203 |
|
|
static GATE_INTERFACE_VTBL(gate_framebuffer) gate_rasterfb_vtbl; |
204 |
|
✗ |
static void gate_init_rasterfb_vtbl() |
205 |
|
|
{ |
206 |
|
✗ |
if (!gate_rasterfb_vtbl.get_interface_name) |
207 |
|
|
{ |
208 |
|
|
GATE_INTERFACE_VTBL(gate_framebuffer) const local_vtbl = |
209 |
|
|
{ |
210 |
|
|
&rasterfb_get_interface_name, |
211 |
|
|
&rasterfb_release, |
212 |
|
|
&rasterfb_retain, |
213 |
|
|
|
214 |
|
|
&rasterfb_get_info, |
215 |
|
|
&rasterfb_get_property, |
216 |
|
|
&rasterfb_set_property, |
217 |
|
|
|
218 |
|
|
&rasterfb_update, |
219 |
|
|
|
220 |
|
|
&rasterfb_get_pixel, |
221 |
|
|
&rasterfb_set_pixel, |
222 |
|
|
|
223 |
|
|
&rasterfb_get_image, |
224 |
|
|
&rasterfb_set_image, |
225 |
|
|
|
226 |
|
|
&rasterfb_await_event |
227 |
|
|
}; |
228 |
|
|
|
229 |
|
✗ |
gate_rasterfb_vtbl = local_vtbl; |
230 |
|
|
} |
231 |
|
✗ |
} |
232 |
|
|
|
233 |
|
|
|
234 |
|
✗ |
gate_result_t gate_framebuffer_create_image(gate_uint32_t width, gate_uint32_t height, gate_framebuffer_t** ptr_framebuffer) |
235 |
|
|
{ |
236 |
|
✗ |
rasterfb_t* impl = NULL; |
237 |
|
✗ |
gate_result_t ret = GATE_RESULT_FAILED; |
238 |
|
|
gate_size_t datasize; |
239 |
|
|
|
240 |
|
|
do |
241 |
|
|
{ |
242 |
|
✗ |
datasize = sizeof(gate_color_t) * width * height; |
243 |
|
✗ |
impl = (rasterfb_t*)gate_mem_alloc(sizeof(rasterfb_t) + datasize); |
244 |
|
✗ |
if (!impl) |
245 |
|
|
{ |
246 |
|
✗ |
ret = GATE_RESULT_OUTOFMEMORY; |
247 |
|
✗ |
break; |
248 |
|
|
} |
249 |
|
✗ |
gate_init_rasterfb_vtbl(); |
250 |
|
✗ |
impl->vtbl = &gate_rasterfb_vtbl; |
251 |
|
✗ |
gate_atomic_int_init(&impl->ref_counter, 1); |
252 |
|
|
|
253 |
|
✗ |
impl->image_header.width = width; |
254 |
|
✗ |
impl->image_header.height = height; |
255 |
|
✗ |
impl->image_header.line_padding = 0; |
256 |
|
✗ |
impl->image_header.bits_per_pixel = sizeof(gate_color_t) * 8; |
257 |
|
✗ |
impl->image_header.data = &impl->image_data[0]; |
258 |
|
✗ |
impl->image_header.databuffer = NULL; |
259 |
|
|
|
260 |
|
✗ |
gate_mem_clear(&impl->image_data[0], datasize); |
261 |
|
|
|
262 |
|
✗ |
if (ptr_framebuffer) |
263 |
|
|
{ |
264 |
|
✗ |
*ptr_framebuffer = (gate_framebuffer_t*)impl; |
265 |
|
✗ |
impl = NULL; |
266 |
|
|
} |
267 |
|
✗ |
ret = GATE_RESULT_OK; |
268 |
|
|
} while (0); |
269 |
|
|
|
270 |
|
✗ |
if (impl) |
271 |
|
|
{ |
272 |
|
✗ |
gate_mem_dealloc(impl); |
273 |
|
|
} |
274 |
|
✗ |
return ret; |
275 |
|
|
} |
276 |
|
|
|
277 |
|
|
|
278 |
|
|
|
279 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_DIRECTX) |
280 |
|
|
#include "gate/graphics/platform/framebuffers_impl_directx.h" |
281 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_DIRECTX */ |
282 |
|
|
|
283 |
|
|
|
284 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_WIN16) |
285 |
|
|
#include "gate/graphics/platform/framebuffers_impl_win16.h" |
286 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_WIN16 */ |
287 |
|
|
|
288 |
|
|
|
289 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_WIN32) |
290 |
|
|
#include "gate/graphics/platform/framebuffers_impl_win32.h" |
291 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_WIN32 */ |
292 |
|
|
|
293 |
|
|
|
294 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_WAYLAND) |
295 |
|
|
|
296 |
|
|
#include "gate/graphics/platform/framebuffers_impl_wayland.h" |
297 |
|
|
#include "gate/debugging.h" |
298 |
|
|
|
299 |
|
|
#include "gate/graphics/framebuffers.h" |
300 |
|
|
#include "gate/inputs.h" |
301 |
|
|
|
302 |
|
|
#include <wayland-client.h> |
303 |
|
|
#include <wayland-client-core.h> |
304 |
|
|
#include <xdg-shell-client-protocol.h> |
305 |
|
|
#include <time.h> |
306 |
|
|
#include <unistd.h> |
307 |
|
|
#include <sys/types.h> |
308 |
|
|
#include <fcntl.h> |
309 |
|
|
#include <errno.h> |
310 |
|
|
#include <stdio.h> |
311 |
|
|
#include <sys/mman.h> |
312 |
|
|
#include <xkbcommon/xkbcommon.h> |
313 |
|
|
|
314 |
|
|
typedef struct waylandfb_impl |
315 |
|
|
{ |
316 |
|
|
GATE_INTERFACE_VTBL(gate_framebuffer) const* vtbl; |
317 |
|
|
|
318 |
|
|
gate_atomic_int_t ref_counter; |
319 |
|
|
|
320 |
|
|
unsigned int width; |
321 |
|
|
unsigned int height; |
322 |
|
|
|
323 |
|
|
struct wl_display* display; |
324 |
|
|
struct wl_registry* registry; |
325 |
|
|
struct wl_compositor* compositor; |
326 |
|
|
struct wl_shm* shm; |
327 |
|
|
struct xdg_wm_base* wm_base; |
328 |
|
|
|
329 |
|
|
struct wl_surface* surface; |
330 |
|
|
struct xdg_surface* xdgsurface; |
331 |
|
|
struct xdg_toplevel* toplevel; |
332 |
|
|
|
333 |
|
|
struct wl_seat* seat; |
334 |
|
|
struct wl_keyboard* keyboard; |
335 |
|
|
struct xkb_context* kb_context; |
336 |
|
|
struct xkb_keymap* kb_keymap; |
337 |
|
|
struct xkb_state* kb_state; |
338 |
|
|
struct wl_pointer* pointer; |
339 |
|
|
|
340 |
|
|
gate_rasterimage_t current_frame; |
341 |
|
|
|
342 |
|
|
gate_arraylist_t events; |
343 |
|
|
|
344 |
|
|
} waylandfb_t; |
345 |
|
|
|
346 |
|
|
static void waylandfb_push_event(waylandfb_t* impl, gate_framebuffer_event_t const* evt) |
347 |
|
|
{ |
348 |
|
|
GATE_DEBUG_TRACE("Push event"); |
349 |
|
|
gate_arraylist_add(impl->events, evt); |
350 |
|
|
} |
351 |
|
|
|
352 |
|
|
static gate_framebuffer_event_t const* waylandfb_get_event(waylandfb_t* impl) |
353 |
|
|
{ |
354 |
|
|
if (gate_arraylist_length(impl->events) == 0) |
355 |
|
|
{ |
356 |
|
|
return NULL; |
357 |
|
|
} |
358 |
|
|
return (gate_framebuffer_event_t const*)gate_arraylist_get(impl->events, 0); |
359 |
|
|
} |
360 |
|
|
|
361 |
|
|
static void waylandfb_pop_event(waylandfb_t* impl) |
362 |
|
|
{ |
363 |
|
|
GATE_DEBUG_TRACE("Pop event"); |
364 |
|
|
gate_arraylist_remove(impl->events, 0, 1); |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
|
368 |
|
|
|
369 |
|
|
/******************** |
370 |
|
|
* WM_BASE events * |
371 |
|
|
********************/ |
372 |
|
|
|
373 |
|
|
static void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, uint32_t serial) |
374 |
|
|
{ |
375 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
376 |
|
|
xdg_wm_base_pong(xdg_wm_base, serial); |
377 |
|
|
} |
378 |
|
|
|
379 |
|
|
static const struct xdg_wm_base_listener xdg_wm_base_listener = |
380 |
|
|
{ |
381 |
|
|
&xdg_wm_base_ping |
382 |
|
|
}; |
383 |
|
|
|
384 |
|
|
|
385 |
|
|
|
386 |
|
|
/********************* |
387 |
|
|
* KEYBOARD events * |
388 |
|
|
*********************/ |
389 |
|
|
|
390 |
|
|
static void waylandfb_kb_map(void* data, struct wl_keyboard* kb, uint32_t frmt, int32_t fd, uint32_t sz) |
391 |
|
|
{ |
392 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
393 |
|
|
struct xkb_keymap* keymap = NULL; |
394 |
|
|
struct xkb_state* keystate = NULL; |
395 |
|
|
char* ptr_shared_map = MAP_FAILED; |
396 |
|
|
do |
397 |
|
|
{ |
398 |
|
|
if (frmt == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) |
399 |
|
|
{ |
400 |
|
|
if (NULL == impl->kb_context) |
401 |
|
|
{ |
402 |
|
|
impl->kb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); |
403 |
|
|
if (NULL == impl->kb_context) |
404 |
|
|
{ |
405 |
|
|
/* error */ |
406 |
|
|
break; |
407 |
|
|
} |
408 |
|
|
} |
409 |
|
|
|
410 |
|
|
ptr_shared_map = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0); |
411 |
|
|
if (ptr_shared_map == MAP_FAILED) |
412 |
|
|
{ |
413 |
|
|
/* error */ |
414 |
|
|
break; |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
keymap = xkb_keymap_new_from_string(impl->kb_context, ptr_shared_map, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); |
418 |
|
|
keystate = xkb_state_new(keymap); |
419 |
|
|
|
420 |
|
|
if (keymap && keystate) |
421 |
|
|
{ |
422 |
|
|
/* attach new objects to framebuffer object */ |
423 |
|
|
xkb_keymap_unref(impl->kb_keymap); |
424 |
|
|
impl->kb_keymap = keymap; |
425 |
|
|
keymap = NULL; |
426 |
|
|
|
427 |
|
|
xkb_state_unref(impl->kb_state); |
428 |
|
|
impl->kb_state = keystate; |
429 |
|
|
keystate = NULL; |
430 |
|
|
} |
431 |
|
|
} |
432 |
|
|
|
433 |
|
|
} while (0); |
434 |
|
|
|
435 |
|
|
/* cleanup */ |
436 |
|
|
if (ptr_shared_map != MAP_FAILED) |
437 |
|
|
{ |
438 |
|
|
munmap(ptr_shared_map, sz); |
439 |
|
|
close(fd); |
440 |
|
|
} |
441 |
|
|
xkb_keymap_unref(keymap); |
442 |
|
|
xkb_state_unref(keystate); |
443 |
|
|
} |
444 |
|
|
|
445 |
|
|
static void waylandfb_kb_enter(void* data, struct wl_keyboard* kb, uint32_t ser, struct wl_surface* srfc, struct wl_array* keys) |
446 |
|
|
{ |
447 |
|
|
/* surface has received keyboard focus */ |
448 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
449 |
|
|
uint32_t* key; |
450 |
|
|
wl_array_for_each(key, keys) |
451 |
|
|
{ |
452 |
|
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(impl->kb_state, *key + 8); |
453 |
|
|
/* TODO: handle already pressed keys */ |
454 |
|
|
} |
455 |
|
|
} |
456 |
|
|
|
457 |
|
|
static void waylandfb_kb_leave(void* data, struct wl_keyboard* kb, uint32_t ser, struct wl_surface* srfc) |
458 |
|
|
{ |
459 |
|
|
/* surface has lost keyboard focus */ |
460 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
461 |
|
|
} |
462 |
|
|
|
463 |
|
|
static void waylandfb_kb_key(void* data, struct wl_keyboard* kb, uint32_t ser, uint32_t t, uint32_t key, uint32_t stat) |
464 |
|
|
{ |
465 |
|
|
/* receive keyboard key */ |
466 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
467 |
|
|
|
468 |
|
|
uint32_t const keycode = key + 8; |
469 |
|
|
xkb_keysym_t const sym = xkb_state_key_get_one_sym(impl->kb_state, keycode); |
470 |
|
|
gate_bool_t const pressed = (stat == WL_KEYBOARD_KEY_STATE_PRESSED); |
471 |
|
|
uint32_t const chr32 = xkb_state_key_get_utf32(impl->kb_state, keycode); |
472 |
|
|
gate_framebuffer_event_t evt; |
473 |
|
|
|
474 |
|
|
evt.event_type = pressed ? GATE_FRAMEBUFFER_EVENT_KEY_DOWN : GATE_FRAMEBUFFER_EVENT_KEY_UP; |
475 |
|
|
evt.event_data.key.native_code = key; |
476 |
|
|
evt.event_data.key.key_states = 0; /* TODO */ |
477 |
|
|
evt.event_data.key.key_code = chr32; |
478 |
|
|
evt.event_data.key.char_code = chr32; |
479 |
|
|
waylandfb_push_event(impl, &evt); |
480 |
|
|
} |
481 |
|
|
|
482 |
|
|
static void waylandfb_kb_mod(void* data, struct wl_keyboard* kb, uint32_t ser, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) |
483 |
|
|
{ |
484 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
485 |
|
|
if (impl && impl->kb_state) |
486 |
|
|
{ |
487 |
|
|
xkb_state_update_mask(impl->kb_state, depressed, latched, locked, 0, 0, group); |
488 |
|
|
} |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
static void waylandfb_kb_rep(void* data, struct wl_keyboard* kb, int32_t rate, int32_t del) |
492 |
|
|
{ |
493 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
494 |
|
|
} |
495 |
|
|
|
496 |
|
|
|
497 |
|
|
static struct wl_keyboard_listener kb_listener = |
498 |
|
|
{ |
499 |
|
|
&waylandfb_kb_map, |
500 |
|
|
&waylandfb_kb_enter, |
501 |
|
|
&waylandfb_kb_leave, |
502 |
|
|
&waylandfb_kb_key, |
503 |
|
|
&waylandfb_kb_mod, |
504 |
|
|
&waylandfb_kb_rep |
505 |
|
|
}; |
506 |
|
|
|
507 |
|
|
|
508 |
|
|
|
509 |
|
|
/*************************** |
510 |
|
|
* MOUSE / POINER events * |
511 |
|
|
***************************/ |
512 |
|
|
|
513 |
|
|
static void pointer_enter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) |
514 |
|
|
{ |
515 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
516 |
|
|
} |
517 |
|
|
static void pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface) |
518 |
|
|
{ |
519 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
520 |
|
|
} |
521 |
|
|
static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) |
522 |
|
|
{ |
523 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
524 |
|
|
} |
525 |
|
|
static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) |
526 |
|
|
{ |
527 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
528 |
|
|
} |
529 |
|
|
static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) |
530 |
|
|
{ |
531 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
532 |
|
|
} |
533 |
|
|
static void pointer_frame(void* data, struct wl_pointer* wl_pointer) |
534 |
|
|
{ |
535 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
536 |
|
|
} |
537 |
|
|
static void pointer_axis_source(void* data, struct wl_pointer* wl_pointer, uint32_t axis_source) |
538 |
|
|
{ |
539 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
540 |
|
|
} |
541 |
|
|
static void pointer_axis_stop(void* data, struct wl_pointer* wl_pointer, uint32_t time, uint32_t axis) |
542 |
|
|
{ |
543 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
544 |
|
|
} |
545 |
|
|
static void pointer_axis_discrete(void* data, struct wl_pointer* wl_pointer, uint32_t axis, int32_t discrete) |
546 |
|
|
{ |
547 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
548 |
|
|
} |
549 |
|
|
static void pointer_axis_value120(void* data, struct wl_pointer* wl_pointer, uint32_t axis, int32_t value120) |
550 |
|
|
{ |
551 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
552 |
|
|
} |
553 |
|
|
|
554 |
|
|
|
555 |
|
|
static struct wl_pointer_listener pointer_listener = |
556 |
|
|
{ |
557 |
|
|
&pointer_enter, |
558 |
|
|
&pointer_leave, |
559 |
|
|
&pointer_motion, |
560 |
|
|
&pointer_button, |
561 |
|
|
&pointer_axis, |
562 |
|
|
&pointer_frame, |
563 |
|
|
&pointer_axis_source, |
564 |
|
|
&pointer_axis_stop, |
565 |
|
|
&pointer_axis_discrete, |
566 |
|
|
&pointer_axis_value120 |
567 |
|
|
}; |
568 |
|
|
|
569 |
|
|
|
570 |
|
|
|
571 |
|
|
/***************** |
572 |
|
|
* SEAT events * |
573 |
|
|
*****************/ |
574 |
|
|
|
575 |
|
|
static void seat_cap(void* data, struct wl_seat* seat, uint32_t cap) |
576 |
|
|
{ |
577 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
578 |
|
|
|
579 |
|
|
if ((cap & WL_SEAT_CAPABILITY_KEYBOARD) && (impl->keyboard == NULL)) |
580 |
|
|
{ |
581 |
|
|
impl->keyboard = wl_seat_get_keyboard(seat); |
582 |
|
|
wl_keyboard_add_listener(impl->keyboard, &kb_listener, impl); |
583 |
|
|
} |
584 |
|
|
else if ((cap & WL_SEAT_CAPABILITY_POINTER) && (impl->pointer == NULL)) |
585 |
|
|
{ |
586 |
|
|
impl->pointer = wl_seat_get_pointer(seat); |
587 |
|
|
wl_pointer_add_listener(impl->pointer, &pointer_listener, impl); |
588 |
|
|
} |
589 |
|
|
} |
590 |
|
|
|
591 |
|
|
static void seat_name(void* data, struct wl_seat* seat, const char* name) |
592 |
|
|
{ |
593 |
|
|
} |
594 |
|
|
|
595 |
|
|
static struct wl_seat_listener seat_listener = |
596 |
|
|
{ |
597 |
|
|
&seat_cap, |
598 |
|
|
&seat_name |
599 |
|
|
}; |
600 |
|
|
|
601 |
|
|
|
602 |
|
|
/********************* |
603 |
|
|
* REGISTRY events * |
604 |
|
|
*********************/ |
605 |
|
|
|
606 |
|
|
static void waylandfb_registry_global(void* data, struct wl_registry* wl_registry, uint32_t name, const char* interface, uint32_t version) |
607 |
|
|
{ |
608 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
609 |
|
|
|
610 |
|
|
if (gate_str_comp(interface, wl_shm_interface.name) == 0) |
611 |
|
|
{ |
612 |
|
|
impl->shm = wl_registry_bind(wl_registry, name, &wl_shm_interface, 1); |
613 |
|
|
} |
614 |
|
|
else if (gate_str_comp(interface, wl_compositor_interface.name) == 0) |
615 |
|
|
{ |
616 |
|
|
impl->compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4); |
617 |
|
|
} |
618 |
|
|
else if (gate_str_comp(interface, xdg_wm_base_interface.name) == 0) |
619 |
|
|
{ |
620 |
|
|
impl->wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1); |
621 |
|
|
xdg_wm_base_add_listener(impl->wm_base, &xdg_wm_base_listener, impl); |
622 |
|
|
} |
623 |
|
|
else if (gate_str_comp(interface, wl_seat_interface.name) == 0) |
624 |
|
|
{ |
625 |
|
|
impl->seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 1); |
626 |
|
|
wl_seat_add_listener(impl->seat, &seat_listener, impl); |
627 |
|
|
} |
628 |
|
|
} |
629 |
|
|
|
630 |
|
|
static void waylandfb_registry_global_remove(void* data, struct wl_registry* wl_registry, uint32_t name) |
631 |
|
|
{ |
632 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
633 |
|
|
} |
634 |
|
|
|
635 |
|
|
static struct wl_registry_listener const waylandfb_registry_listener = |
636 |
|
|
{ |
637 |
|
|
&waylandfb_registry_global, |
638 |
|
|
&waylandfb_registry_global_remove |
639 |
|
|
}; |
640 |
|
|
|
641 |
|
|
static int open_gate_wl_shm(gate_size_t length) |
642 |
|
|
{ |
643 |
|
|
const gate_uint32_t my_pid = (gate_uint32_t)getpid(); |
644 |
|
|
static gate_uint32_t rnd_counter = 0; |
645 |
|
|
char buffer[255]; |
646 |
|
|
gate_strbuilder_t path; |
647 |
|
|
int fd = -1; |
648 |
|
|
unsigned retries = 1000; |
649 |
|
|
int result; |
650 |
|
|
|
651 |
|
|
do |
652 |
|
|
{ |
653 |
|
|
gate_strbuilder_create_static(&path, buffer, sizeof(buffer), 0); |
654 |
|
|
gate_strbuilder_append_cstr(&path, "/wl_shm-gate-fb-"); |
655 |
|
|
gate_strbuilder_append_uint32(&path, my_pid); |
656 |
|
|
gate_strbuilder_append_cstr(&path, "-"); |
657 |
|
|
gate_strbuilder_append_uint32(&path, rnd_counter); |
658 |
|
|
|
659 |
|
|
fd = shm_open(buffer, O_RDWR | O_CREAT | O_EXCL, 0600); |
660 |
|
|
if (fd >= 0) |
661 |
|
|
{ |
662 |
|
|
shm_unlink(buffer); |
663 |
|
|
break; |
664 |
|
|
} |
665 |
|
|
++rnd_counter; |
666 |
|
|
--retries; |
667 |
|
|
} while ((retries > 0) && (errno == EEXIST)); |
668 |
|
|
|
669 |
|
|
if (fd < 0) |
670 |
|
|
{ |
671 |
|
|
return fd; |
672 |
|
|
} |
673 |
|
|
|
674 |
|
|
do |
675 |
|
|
{ |
676 |
|
|
result = ftruncate(fd, length); |
677 |
|
|
} while ((result < 0) && (errno == EINTR)); |
678 |
|
|
|
679 |
|
|
if (result < 0) |
680 |
|
|
{ |
681 |
|
|
close(fd); |
682 |
|
|
return -1; |
683 |
|
|
} |
684 |
|
|
return fd; |
685 |
|
|
} |
686 |
|
|
|
687 |
|
|
static void waylandfb_buffer_release(void* data, struct wl_buffer* wl_buffer) |
688 |
|
|
{ |
689 |
|
|
wl_buffer_destroy(wl_buffer); |
690 |
|
|
} |
691 |
|
|
|
692 |
|
|
static const struct wl_buffer_listener waylandfb_buffer_listener = |
693 |
|
|
{ |
694 |
|
|
.release = &waylandfb_buffer_release, |
695 |
|
|
}; |
696 |
|
|
|
697 |
|
|
static struct wl_buffer* draw_frame(waylandfb_t* impl) |
698 |
|
|
{ |
699 |
|
|
struct wl_buffer* ret = NULL; |
700 |
|
|
int fd = -1; |
701 |
|
|
gate_size_t stride; |
702 |
|
|
gate_size_t length; |
703 |
|
|
gate_uint32_t* ptr_pixels = NULL; |
704 |
|
|
struct wl_shm_pool* pool = NULL; |
705 |
|
|
unsigned y; |
706 |
|
|
|
707 |
|
|
do |
708 |
|
|
{ |
709 |
|
|
stride = (gate_size_t)impl->width * 4; |
710 |
|
|
length = stride * (gate_size_t)impl->height; |
711 |
|
|
fd = open_gate_wl_shm(length); |
712 |
|
|
if (fd < 0) |
713 |
|
|
{ |
714 |
|
|
break; |
715 |
|
|
} |
716 |
|
|
|
717 |
|
|
ptr_pixels = (gate_uint32_t*)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
718 |
|
|
if (ptr_pixels == MAP_FAILED) |
719 |
|
|
{ |
720 |
|
|
break; |
721 |
|
|
} |
722 |
|
|
|
723 |
|
|
pool = wl_shm_create_pool(impl->shm, fd, length); |
724 |
|
|
if (pool == NULL) |
725 |
|
|
{ |
726 |
|
|
break; |
727 |
|
|
} |
728 |
|
|
|
729 |
|
|
ret = wl_shm_pool_create_buffer(pool, 0, impl->width, impl->height, stride, WL_SHM_FORMAT_XRGB8888); |
730 |
|
|
|
731 |
|
|
if (ret != NULL) |
732 |
|
|
{ |
733 |
|
|
/* attach cleanup-callback */ |
734 |
|
|
wl_buffer_add_listener(ret, &waylandfb_buffer_listener, NULL); |
735 |
|
|
} |
736 |
|
|
|
737 |
|
|
if (!gate_rasterimage_is_empty(&impl->current_frame)) |
738 |
|
|
{ |
739 |
|
|
for (y = 0; y != impl->height; ++y) |
740 |
|
|
{ |
741 |
|
|
void* ptr_src = gate_rasterimage_get_line_ptr(&impl->current_frame, y); |
742 |
|
|
gate_uint32_t* ptr_dst = &ptr_pixels[y * impl->width]; |
743 |
|
|
gate_mem_copy(ptr_dst, ptr_src, stride); |
744 |
|
|
} |
745 |
|
|
} |
746 |
|
|
} while (0); |
747 |
|
|
|
748 |
|
|
if (pool != NULL) |
749 |
|
|
{ |
750 |
|
|
wl_shm_pool_destroy(pool); |
751 |
|
|
} |
752 |
|
|
|
753 |
|
|
if (ptr_pixels != MAP_FAILED) |
754 |
|
|
{ |
755 |
|
|
munmap(ptr_pixels, length); |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
if (fd >= 0) |
759 |
|
|
{ |
760 |
|
|
close(fd); |
761 |
|
|
} |
762 |
|
|
|
763 |
|
|
return ret; |
764 |
|
|
} |
765 |
|
|
|
766 |
|
|
static void paint_frame_on_surface(waylandfb_t* impl) |
767 |
|
|
{ |
768 |
|
|
struct wl_buffer* buffer = draw_frame(impl); |
769 |
|
|
wl_surface_attach(impl->surface, buffer, 0, 0); |
770 |
|
|
wl_surface_commit(impl->surface); |
771 |
|
|
} |
772 |
|
|
|
773 |
|
|
static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial) |
774 |
|
|
{ |
775 |
|
|
waylandfb_t* const impl = (waylandfb_t*)data; |
776 |
|
|
xdg_surface_ack_configure(xdg_surface, serial); |
777 |
|
|
|
778 |
|
|
paint_frame_on_surface(impl); |
779 |
|
|
} |
780 |
|
|
|
781 |
|
|
static const struct xdg_surface_listener xdg_surface_listener = |
782 |
|
|
{ |
783 |
|
|
&xdg_surface_configure, |
784 |
|
|
}; |
785 |
|
|
|
786 |
|
|
|
787 |
|
|
|
788 |
|
|
static int waylandfb_displatch_events(waylandfb_t* impl, gate_uint32_t timeout_ms) |
789 |
|
|
{ |
790 |
|
|
int events_dispatched; |
791 |
|
|
|
792 |
|
|
events_dispatched = wl_display_roundtrip(impl->display); |
793 |
|
|
/* events_dispatched = wl_display_dispatch_pending(impl->display); */ |
794 |
|
|
|
795 |
|
|
if ((timeout_ms > 0) && (events_dispatched >= 0)) |
796 |
|
|
{ |
797 |
|
|
#if 0 |
798 |
|
|
int awaited_events; |
799 |
|
|
struct timespec timeout; |
800 |
|
|
timeout.tv_sec = timeout_ms / 1000; |
801 |
|
|
timeout.tv_nsec = (timeout_ms % 1000) * 1000000; |
802 |
|
|
awaited_events = wl_display_dispatch_timeout(impl->display, &timeout); |
803 |
|
|
if (awaited_events >= 0) |
804 |
|
|
{ |
805 |
|
|
events_dispatched += awaited_events; |
806 |
|
|
} |
807 |
|
|
#endif |
808 |
|
|
} |
809 |
|
|
return events_dispatched; |
810 |
|
|
} |
811 |
|
|
|
812 |
|
|
static gate_result_t waylandfb_init(waylandfb_t* impl) |
813 |
|
|
{ |
814 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
815 |
|
|
do |
816 |
|
|
{ |
817 |
|
|
impl->display = wl_display_connect(NULL); |
818 |
|
|
if (impl->display == NULL) |
819 |
|
|
{ |
820 |
|
|
GATE_DEBUG_TRACE("Failed to connect to wayland display"); |
821 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
822 |
|
|
break; |
823 |
|
|
} |
824 |
|
|
|
825 |
|
|
impl->registry = wl_display_get_registry(impl->display); |
826 |
|
|
if (impl->registry == NULL) |
827 |
|
|
{ |
828 |
|
|
GATE_DEBUG_TRACE("Failed to get wayland registry"); |
829 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
830 |
|
|
break; |
831 |
|
|
} |
832 |
|
|
|
833 |
|
|
wl_registry_add_listener(impl->registry, &waylandfb_registry_listener, impl); |
834 |
|
|
wl_display_roundtrip(impl->display); |
835 |
|
|
|
836 |
|
|
if (impl->compositor == NULL) |
837 |
|
|
{ |
838 |
|
|
GATE_DEBUG_TRACE("Missing wayland compositor"); |
839 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
840 |
|
|
break; |
841 |
|
|
} |
842 |
|
|
|
843 |
|
|
impl->surface = wl_compositor_create_surface(impl->compositor); |
844 |
|
|
if (NULL == impl->surface) |
845 |
|
|
{ |
846 |
|
|
GATE_DEBUG_TRACE("Failed to create wayland surface"); |
847 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
848 |
|
|
break; |
849 |
|
|
} |
850 |
|
|
|
851 |
|
|
if (impl->shm == NULL) |
852 |
|
|
{ |
853 |
|
|
GATE_DEBUG_TRACE("Missing wayland SHM instance"); |
854 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
855 |
|
|
break; |
856 |
|
|
} |
857 |
|
|
|
858 |
|
|
if (impl->wm_base == NULL) |
859 |
|
|
{ |
860 |
|
|
GATE_DEBUG_TRACE("Missing wayland wm_base instance"); |
861 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
862 |
|
|
break; |
863 |
|
|
} |
864 |
|
|
|
865 |
|
|
impl->xdgsurface = xdg_wm_base_get_xdg_surface(impl->wm_base, impl->surface); |
866 |
|
|
if (impl->xdgsurface == NULL) |
867 |
|
|
{ |
868 |
|
|
GATE_DEBUG_TRACE("Missing wayland XDG surface"); |
869 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
870 |
|
|
break; |
871 |
|
|
} |
872 |
|
|
|
873 |
|
|
xdg_surface_add_listener(impl->xdgsurface, &xdg_surface_listener, impl); |
874 |
|
|
|
875 |
|
|
impl->toplevel = xdg_surface_get_toplevel(impl->xdgsurface); |
876 |
|
|
if (impl->toplevel == NULL) |
877 |
|
|
{ |
878 |
|
|
GATE_DEBUG_TRACE("Missing wayland toplevel object"); |
879 |
|
|
ret = GATE_RESULT_OUTOFRESOURCES; |
880 |
|
|
break; |
881 |
|
|
} |
882 |
|
|
|
883 |
|
|
xdg_toplevel_set_title(impl->toplevel, "GATE Framebuffer Window"); |
884 |
|
|
|
885 |
|
|
wl_surface_commit(impl->surface); |
886 |
|
|
|
887 |
|
|
wl_display_roundtrip(impl->display); |
888 |
|
|
|
889 |
|
|
ret = GATE_RESULT_OK; |
890 |
|
|
} while (0); |
891 |
|
|
|
892 |
|
|
return ret; |
893 |
|
|
} |
894 |
|
|
|
895 |
|
|
static void waylandfb_release_resources(waylandfb_t* impl) |
896 |
|
|
{ |
897 |
|
|
if (impl->pointer) |
898 |
|
|
{ |
899 |
|
|
wl_pointer_destroy(impl->pointer); |
900 |
|
|
impl->pointer = NULL; |
901 |
|
|
} |
902 |
|
|
if (impl->keyboard) |
903 |
|
|
{ |
904 |
|
|
wl_keyboard_destroy(impl->keyboard); |
905 |
|
|
impl->keyboard = NULL; |
906 |
|
|
} |
907 |
|
|
if (impl->seat) |
908 |
|
|
{ |
909 |
|
|
wl_seat_destroy(impl->seat); |
910 |
|
|
impl->seat = NULL; |
911 |
|
|
} |
912 |
|
|
if (impl->toplevel) |
913 |
|
|
{ |
914 |
|
|
xdg_toplevel_destroy(impl->toplevel); |
915 |
|
|
impl->toplevel = NULL; |
916 |
|
|
} |
917 |
|
|
|
918 |
|
|
if (impl->xdgsurface) |
919 |
|
|
{ |
920 |
|
|
xdg_surface_destroy(impl->xdgsurface); |
921 |
|
|
impl->xdgsurface = NULL; |
922 |
|
|
} |
923 |
|
|
|
924 |
|
|
if (impl->surface) |
925 |
|
|
{ |
926 |
|
|
wl_surface_destroy(impl->surface); |
927 |
|
|
impl->surface = NULL; |
928 |
|
|
} |
929 |
|
|
|
930 |
|
|
if (impl->wm_base) |
931 |
|
|
{ |
932 |
|
|
xdg_wm_base_destroy(impl->wm_base); |
933 |
|
|
impl->wm_base = NULL; |
934 |
|
|
} |
935 |
|
|
|
936 |
|
|
if (impl->shm) |
937 |
|
|
{ |
938 |
|
|
wl_shm_destroy(impl->shm); |
939 |
|
|
impl->shm = NULL; |
940 |
|
|
} |
941 |
|
|
if (impl->compositor) |
942 |
|
|
{ |
943 |
|
|
wl_compositor_destroy(impl->compositor); |
944 |
|
|
impl->compositor = NULL; |
945 |
|
|
} |
946 |
|
|
if (impl->registry) |
947 |
|
|
{ |
948 |
|
|
wl_registry_destroy(impl->registry); |
949 |
|
|
impl->registry = NULL; |
950 |
|
|
} |
951 |
|
|
if (impl->display) |
952 |
|
|
{ |
953 |
|
|
wl_display_disconnect(impl->display); |
954 |
|
|
impl->display = NULL; |
955 |
|
|
} |
956 |
|
|
} |
957 |
|
|
|
958 |
|
|
|
959 |
|
|
/**************************************** |
960 |
|
|
* GATE wayland framebuffer interface * |
961 |
|
|
****************************************/ |
962 |
|
|
|
963 |
|
|
static char const* waylandfb_get_interface_name(void* obj) |
964 |
|
|
{ |
965 |
|
|
return GATE_INTERFACE_NAME_FRAMEBUFFER; |
966 |
|
|
} |
967 |
|
|
|
968 |
|
|
static void waylandfb_release(void* obj) |
969 |
|
|
{ |
970 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
971 |
|
|
if (0 == gate_atomic_int_dec(&impl->ref_counter)) |
972 |
|
|
{ |
973 |
|
|
waylandfb_release_resources(impl); |
974 |
|
|
gate_mem_dealloc(impl); |
975 |
|
|
} |
976 |
|
|
} |
977 |
|
|
static int waylandfb_retain(void* obj) |
978 |
|
|
{ |
979 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
980 |
|
|
return (int)gate_atomic_int_inc(&impl->ref_counter); |
981 |
|
|
} |
982 |
|
|
|
983 |
|
|
static gate_result_t waylandfb_get_info(void* obj, gate_framebuffer_info_t* ptr_info) |
984 |
|
|
{ |
985 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
986 |
|
|
|
987 |
|
|
ptr_info->format_id = GATE_IMAGE_PIXELFORMAT_RGBA; |
988 |
|
|
ptr_info->bits_per_pixel = 32; |
989 |
|
|
ptr_info->width = impl->width; |
990 |
|
|
ptr_info->height = impl->height; |
991 |
|
|
|
992 |
|
|
return GATE_RESULT_OK; |
993 |
|
|
} |
994 |
|
|
static gate_result_t waylandfb_get_property(void* obj, gate_string_t const* name, gate_property_t* prop) |
995 |
|
|
{ |
996 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
997 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
998 |
|
|
} |
999 |
|
|
static gate_result_t waylandfb_set_property(void* obj, gate_string_t const* name, gate_property_t const* prop) |
1000 |
|
|
{ |
1001 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1002 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
1003 |
|
|
} |
1004 |
|
|
|
1005 |
|
|
static gate_result_t waylandfb_update(void* obj) |
1006 |
|
|
{ |
1007 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1008 |
|
|
|
1009 |
|
|
paint_frame_on_surface(impl); |
1010 |
|
|
wl_surface_damage(impl->surface, 0, 0, impl->width, impl->height); |
1011 |
|
|
return GATE_RESULT_OK; |
1012 |
|
|
} |
1013 |
|
|
|
1014 |
|
|
static gate_result_t waylandfb_get_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t* ptr_col) |
1015 |
|
|
{ |
1016 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1017 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
1018 |
|
|
} |
1019 |
|
|
static gate_result_t waylandfb_set_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t col) |
1020 |
|
|
{ |
1021 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1022 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
1023 |
|
|
} |
1024 |
|
|
|
1025 |
|
|
static gate_result_t waylandfb_get_image(void* obj, gate_uint32_t src_x, gate_uint32_t src_y, gate_uint32_t width, gate_uint32_t height, gate_rasterimage_t* ptr_image) |
1026 |
|
|
{ |
1027 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1028 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
1029 |
|
|
} |
1030 |
|
|
static gate_result_t waylandfb_set_image(void* obj, gate_rasterimage_t const* ptr_image, gate_uint32_t dest_x, gate_uint32_t dest_y) |
1031 |
|
|
{ |
1032 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1033 |
|
|
if (gate_rasterimage_is_empty(&impl->current_frame)) |
1034 |
|
|
{ |
1035 |
|
|
if (NULL == gate_rasterimage_create(&impl->current_frame, GATE_IMAGE_PIXELFORMAT_BGR32, impl->width, impl->height, NULL)) |
1036 |
|
|
{ |
1037 |
|
|
return GATE_RESULT_OUTOFMEMORY; |
1038 |
|
|
} |
1039 |
|
|
} |
1040 |
|
|
return gate_rasterimage_paste_image(&impl->current_frame, ptr_image, dest_x, dest_y, |
1041 |
|
|
0, 0, gate_rasterimage_width(ptr_image), gate_rasterimage_height(ptr_image), false); |
1042 |
|
|
} |
1043 |
|
|
|
1044 |
|
|
static gate_result_t waylandfb_await_event(void* obj, gate_uint32_t timeout_ms, gate_framebuffer_event_t* ptr_received_evt) |
1045 |
|
|
{ |
1046 |
|
|
waylandfb_t* const impl = (waylandfb_t*)obj; |
1047 |
|
|
|
1048 |
|
|
int events_dispatched = waylandfb_displatch_events(impl, timeout_ms); |
1049 |
|
|
gate_framebuffer_event_t const* ptr_evt = waylandfb_get_event(impl); |
1050 |
|
|
|
1051 |
|
|
if (ptr_evt != NULL) |
1052 |
|
|
{ |
1053 |
|
|
gate_mem_copy(ptr_received_evt, ptr_evt, sizeof(gate_framebuffer_event_t)); |
1054 |
|
|
waylandfb_pop_event(impl); |
1055 |
|
|
return GATE_RESULT_OK; |
1056 |
|
|
} |
1057 |
|
|
|
1058 |
|
|
if (events_dispatched == 0) |
1059 |
|
|
{ |
1060 |
|
|
return GATE_RESULT_TIMEOUT; |
1061 |
|
|
} |
1062 |
|
|
else |
1063 |
|
|
{ |
1064 |
|
|
gate_mem_clear(ptr_received_evt, sizeof(gate_framebuffer_event_t)); |
1065 |
|
|
ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_IDLE; |
1066 |
|
|
return GATE_RESULT_OK; |
1067 |
|
|
} |
1068 |
|
|
|
1069 |
|
|
} |
1070 |
|
|
|
1071 |
|
|
static GATE_INTERFACE_VTBL(gate_framebuffer)* gate_init_waylandfb_vtbl() |
1072 |
|
|
{ |
1073 |
|
|
static GATE_INTERFACE_VTBL(gate_framebuffer) gate_waylandfb_vtbl; |
1074 |
|
|
if (!gate_waylandfb_vtbl.get_interface_name) |
1075 |
|
|
{ |
1076 |
|
|
GATE_INTERFACE_VTBL(gate_framebuffer) const local_vtbl = |
1077 |
|
|
{ |
1078 |
|
|
&waylandfb_get_interface_name, |
1079 |
|
|
&waylandfb_release, |
1080 |
|
|
&waylandfb_retain, |
1081 |
|
|
|
1082 |
|
|
&waylandfb_get_info, |
1083 |
|
|
&waylandfb_get_property, |
1084 |
|
|
&waylandfb_set_property, |
1085 |
|
|
|
1086 |
|
|
&waylandfb_update, |
1087 |
|
|
|
1088 |
|
|
&waylandfb_get_pixel, |
1089 |
|
|
&waylandfb_set_pixel, |
1090 |
|
|
|
1091 |
|
|
&waylandfb_get_image, |
1092 |
|
|
&waylandfb_set_image, |
1093 |
|
|
|
1094 |
|
|
&waylandfb_await_event |
1095 |
|
|
}; |
1096 |
|
|
gate_waylandfb_vtbl = local_vtbl; |
1097 |
|
|
} |
1098 |
|
|
return &gate_waylandfb_vtbl; |
1099 |
|
|
} |
1100 |
|
|
|
1101 |
|
|
gate_size_t gate_framebuffer_enum_displays(gate_framebuffer_info_t* ptr_infos, gate_size_t infos_capacity) |
1102 |
|
|
{ |
1103 |
|
|
gate_size_t ret = infos_capacity; |
1104 |
|
|
|
1105 |
|
|
if (ret > 2) |
1106 |
|
|
{ |
1107 |
|
|
ret = 2; |
1108 |
|
|
} |
1109 |
|
|
|
1110 |
|
|
if (ret >= 1) |
1111 |
|
|
{ |
1112 |
|
|
ptr_infos[0].width = 640; |
1113 |
|
|
ptr_infos[0].height = 480; |
1114 |
|
|
ptr_infos[0].bits_per_pixel = 32; |
1115 |
|
|
ptr_infos[0].format_id = 0; |
1116 |
|
|
} |
1117 |
|
|
|
1118 |
|
|
if (ret >= 2) |
1119 |
|
|
{ |
1120 |
|
|
ptr_infos[1].width = 800; |
1121 |
|
|
ptr_infos[1].height = 600; |
1122 |
|
|
ptr_infos[1].bits_per_pixel = 32; |
1123 |
|
|
ptr_infos[1].format_id = 0; |
1124 |
|
|
} |
1125 |
|
|
|
1126 |
|
|
return ret; |
1127 |
|
|
} |
1128 |
|
|
|
1129 |
|
|
gate_result_t gate_framebuffer_find_display(gate_uint32_t required_width, gate_uint32_t required_height, gate_framebuffer_info_t* ptr_found_display_info) |
1130 |
|
|
{ |
1131 |
|
|
/* TODO */ |
1132 |
|
|
ptr_found_display_info->bits_per_pixel = 32; |
1133 |
|
|
ptr_found_display_info->format_id = 0; |
1134 |
|
|
ptr_found_display_info->width = required_width; |
1135 |
|
|
ptr_found_display_info->height = required_height; |
1136 |
|
|
return GATE_RESULT_OK; |
1137 |
|
|
} |
1138 |
|
|
|
1139 |
|
|
gate_result_t gate_framebuffer_open_display(gate_framebuffer_info_t const* ptr_infos, gate_framebuffer_t** ptr_framebuffer) |
1140 |
|
|
{ |
1141 |
|
|
gate_result_t ret = GATE_RESULT_NOTSUPPORTED; |
1142 |
|
|
waylandfb_t* impl = NULL; |
1143 |
|
|
|
1144 |
|
|
do |
1145 |
|
|
{ |
1146 |
|
|
impl = (waylandfb_t*)gate_mem_alloc(sizeof(waylandfb_t)); |
1147 |
|
|
if (impl == NULL) |
1148 |
|
|
{ |
1149 |
|
|
ret = GATE_RESULT_OUTOFMEMORY; |
1150 |
|
|
break; |
1151 |
|
|
} |
1152 |
|
|
|
1153 |
|
|
gate_mem_clear(impl, sizeof(waylandfb_t)); |
1154 |
|
|
impl->vtbl = gate_init_waylandfb_vtbl(); |
1155 |
|
|
gate_atomic_int_init(&impl->ref_counter, 1); |
1156 |
|
|
|
1157 |
|
|
impl->width = ptr_infos->width; |
1158 |
|
|
impl->height = ptr_infos->height; |
1159 |
|
|
|
1160 |
|
|
impl->events = gate_arraylist_create(sizeof(gate_framebuffer_event_t), NULL, 0, NULL, NULL); |
1161 |
|
|
if (impl->events == NULL) |
1162 |
|
|
{ |
1163 |
|
|
ret = GATE_RESULT_OUTOFMEMORY; |
1164 |
|
|
break; |
1165 |
|
|
} |
1166 |
|
|
|
1167 |
|
|
ret = waylandfb_init(impl); |
1168 |
|
|
GATE_BREAK_IF_FAILED(ret); |
1169 |
|
|
|
1170 |
|
|
if (ptr_framebuffer) |
1171 |
|
|
{ |
1172 |
|
|
*ptr_framebuffer = (gate_framebuffer_t*)impl; |
1173 |
|
|
impl = NULL; |
1174 |
|
|
} |
1175 |
|
|
ret = GATE_RESULT_OK; |
1176 |
|
|
|
1177 |
|
|
} while (0); |
1178 |
|
|
|
1179 |
|
|
if (impl) |
1180 |
|
|
{ |
1181 |
|
|
waylandfb_release_resources(impl); |
1182 |
|
|
gate_mem_dealloc(impl); |
1183 |
|
|
} |
1184 |
|
|
|
1185 |
|
|
return ret; |
1186 |
|
|
} |
1187 |
|
|
|
1188 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_WAYLAND */ |
1189 |
|
|
|
1190 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_XLIB) |
1191 |
|
|
#include "gate/graphics/platform/framebuffers_impl_xlib.h" |
1192 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_XLIB */ |
1193 |
|
|
|
1194 |
|
|
|
1195 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_GL) |
1196 |
|
|
#include "gate/graphics/platform/framebuffers_impl_gl.h" |
1197 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_GL */ |
1198 |
|
|
|
1199 |
|
|
|
1200 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_UGA) |
1201 |
|
|
#include "gate/graphics/platform/framebuffers_impl_efigop.h" |
1202 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_UGA */ |
1203 |
|
|
|
1204 |
|
|
|
1205 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_INT10) |
1206 |
|
|
#include "gate/graphics/platform/framebuffers_impl_int10.h" |
1207 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_INT10 */ |
1208 |
|
|
|
1209 |
|
|
|
1210 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_WASM) |
1211 |
|
|
#include "gate/graphics/platform/framebuffers_impl_wasm.h" |
1212 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_WASM */ |
1213 |
|
|
|
1214 |
|
|
#if defined(GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL) |
1215 |
|
|
|
1216 |
|
|
gate_size_t gate_framebuffer_enum_displays(gate_framebuffer_info_t* ptr_infos, gate_size_t infos_capacity) |
1217 |
|
|
{ |
1218 |
|
|
GATE_UNUSED_ARG(ptr_infos); |
1219 |
|
|
GATE_UNUSED_ARG(infos_capacity); |
1220 |
|
|
return 0; |
1221 |
|
|
} |
1222 |
|
|
|
1223 |
|
|
gate_result_t gate_framebuffer_find_display(gate_uint32_t required_width, gate_uint32_t required_height, gate_framebuffer_info_t* ptr_found_display_info) |
1224 |
|
|
{ |
1225 |
|
|
GATE_UNUSED_ARG(required_width); |
1226 |
|
|
GATE_UNUSED_ARG(required_height); |
1227 |
|
|
GATE_UNUSED_ARG(ptr_found_display_info); |
1228 |
|
|
return GATE_RESULT_NOMATCH; |
1229 |
|
|
} |
1230 |
|
|
|
1231 |
|
|
gate_result_t gate_framebuffer_open_display(gate_framebuffer_info_t const* ptr_infos, gate_framebuffer_t** ptr_framebuffer) |
1232 |
|
|
{ |
1233 |
|
|
GATE_UNUSED_ARG(ptr_infos); |
1234 |
|
|
GATE_UNUSED_ARG(ptr_framebuffer); |
1235 |
|
|
return GATE_RESULT_NOMATCH; |
1236 |
|
|
} |
1237 |
|
|
|
1238 |
|
|
|
1239 |
|
|
#endif /* GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL */ |
1240 |
|
|
|