GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/platform/framebuffers_impl_xlib.h
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 317 0.0%
Functions: 0 25 0.0%
Branches: 0 146 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
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/platform/posix/xlib.h"
31 #include "gate/inputs.h"
32
33 typedef struct xlibfb_impl
34 {
35 GATE_INTERFACE_VTBL(gate_framebuffer) const* vtbl;
36
37 gate_atomic_int_t ref_counter;
38
39 gate_uint32_t width;
40 gate_uint32_t height;
41
42 Display* display;
43 int screen;
44 Window root_window;
45 Atom protocols_atom;
46 Atom close_atom;
47
48 Window fb_window;
49 XImage* image;
50 gate_size_t image_size;
51 void* image_data;
52
53 } xlibfb_t;
54
55
56 static void xlibfb_destroy(xlibfb_t* fb)
57 {
58 if (fb->display)
59 {
60 if (fb->image)
61 {
62 xlib.XDestroyImage(fb->image);
63 /* XDestroyImage also deletes the embedded image_data */
64 }
65 else if (fb->image_data)
66 {
67 gate_mem_dealloc(fb->image_data);
68 }
69
70 if (fb->fb_window)
71 {
72 xlib.XDestroyWindow(fb->display, fb->fb_window);
73 }
74 xlib.XCloseDisplay(fb->display);
75 }
76 gate_mem_dealloc(fb);
77 }
78
79
80 static char const* xlibfb_get_interface_name(void* obj)
81 {
82 return GATE_INTERFACE_NAME_FRAMEBUFFER;
83 }
84 static void xlibfb_release(void* obj)
85 {
86 xlibfb_t* impl = (xlibfb_t*)obj;
87 if (0 == gate_atomic_int_dec(&impl->ref_counter))
88 {
89 xlibfb_destroy(impl);
90 }
91 }
92 static int xlibfb_retain(void* obj)
93 {
94 xlibfb_t* impl = (xlibfb_t*)obj;
95 return gate_atomic_int_inc(&impl->ref_counter);
96 }
97
98 static gate_result_t xlibfb_get_info(void* obj, gate_framebuffer_info_t* ptr_info)
99 {
100 xlibfb_t* impl = (xlibfb_t*)obj;
101 gate_result_t ret = GATE_RESULT_INVALIDARG;
102 if (impl && ptr_info)
103 {
104 ptr_info->width = impl->width;
105 ptr_info->height = impl->height;
106 ptr_info->bits_per_pixel = 32;
107 ptr_info->format_id = 0;
108 ret = GATE_RESULT_OK;
109 }
110 return ret;
111 }
112 static gate_result_t xlibfb_get_property(void* obj, gate_string_t const* name, gate_property_t* prop)
113 {
114 return GATE_RESULT_NOTSUPPORTED;
115 }
116 static gate_result_t xlibfb_set_property(void* obj, gate_string_t const* name, gate_property_t const* prop)
117 {
118 return GATE_RESULT_NOTSUPPORTED;
119 }
120
121 static void xlibfb_draw_image(xlibfb_t* fb)
122 {
123 GC gc = xlib.XCreateGC(fb->display, fb->fb_window, 0, 0);
124 xlib.XSetGraphicsExposures(fb->display, gc, 0);
125 xlib.XPutImage(fb->display, fb->fb_window, gc, fb->image, 0, 0, 0, 0, fb->width, fb->height);
126 xlib.XFreeGC(fb->display, gc);
127 }
128
129 static gate_result_t xlibfb_update(void* obj)
130 {
131 xlibfb_t* impl = (xlibfb_t*)obj;
132 xlibfb_draw_image(impl);
133 return GATE_RESULT_OK;
134 }
135
136 static unsigned long XGetRgbPixel(Display* display, Colormap colmap, gate_uint8_t r, gate_uint8_t g, gate_uint8_t b)
137 {
138 XColor col;
139 col.pixel = 0;
140 col.red = ((gate_uint16_t)r << 8);
141 col.green = ((gate_uint16_t)g << 8);
142 col.blue = ((gate_uint16_t)b << 8);
143 col.flags = DoRed | DoGreen | DoBlue;
144
145 xlib.XAllocColor(display, colmap, &col);
146 return col.pixel;
147 }
148
149 static void XResolveRgbPixel(Display* display, Colormap colmap, unsigned long pixel, gate_color_t* ptr_color)
150 {
151 XColor col;
152 col.pixel = pixel;
153 col.flags = DoRed | DoGreen | DoBlue;
154
155 xlib.XQueryColor(display, colmap, &col);
156 ptr_color->r = (gate_uint8_t)(col.red >> 8);
157 ptr_color->g = (gate_uint8_t)(col.green >> 8);
158 ptr_color->b = (gate_uint8_t)(col.blue >> 8);
159 ptr_color->a = 255;
160 }
161
162 static gate_result_t xlibfb_get_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t* ptr_col)
163 {
164 xlibfb_t* impl = (xlibfb_t*)obj;
165 unsigned long pixel;
166 Colormap colmap;
167 if ((x >= impl->width) || (y >= impl->height))
168 {
169 return GATE_RESULT_INVALIDARG;
170 }
171 colmap = xlib.XDefaultColormap(impl->display, impl->screen);
172 pixel = xlib.XGetPixel(impl->image, x, y);
173 XResolveRgbPixel(impl->display, colmap, pixel, ptr_col);
174 return GATE_RESULT_OK;
175 }
176 static gate_result_t xlibfb_set_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t col)
177 {
178 xlibfb_t* impl = (xlibfb_t*)obj;
179 unsigned long pixel;
180 Colormap colmap;
181
182 if ((x >= impl->width) || (y >= impl->height))
183 {
184 return GATE_RESULT_INVALIDARG;
185 }
186
187 colmap = xlib.XDefaultColormap(impl->display, impl->screen);
188 pixel = XGetRgbPixel(impl->display, impl->screen, col.r, col.g, col.b);
189 xlib.XPutPixel(impl->image, x, y, pixel);
190 return GATE_RESULT_OK;
191 }
192
193 static gate_result_t xlibfb_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)
194 {
195 xlibfb_t* impl = (xlibfb_t*)obj;
196 gate_uint32_t x, y;
197 gate_color_t* ptr_color;
198
199 unsigned long pixel;
200 Colormap colmap;
201 if ((src_x >= impl->width) || (src_y >= impl->height) || (width == 0) || (height == 0))
202 {
203 return GATE_RESULT_INVALIDARG;
204 }
205
206 if (!gate_rasterimage_create(ptr_image, GATE_IMAGE_PIXELFORMAT_DEFAULT, width, height, NULL))
207 {
208 return GATE_RESULT_OUTOFMEMORY;
209 }
210
211 if (src_y + height > impl->height)
212 {
213 height = impl->height - src_y;
214 }
215 if (src_x + width > impl->width)
216 {
217 width = impl->width - src_x;
218 }
219
220 colmap = xlib.XDefaultColormap(impl->display, impl->screen);
221
222 for (y = 0; y != width; ++y)
223 {
224 ptr_color = (gate_color_t*)gate_rasterimage_get_line_ptr(ptr_image, y);
225 for (x = 0; x != width; ++x)
226 {
227 pixel = xlib.XGetPixel(impl->image, x + src_x, y + src_y);
228 XResolveRgbPixel(impl->display, colmap, pixel, ptr_color);
229 ++ptr_color;
230 }
231 }
232
233 return GATE_RESULT_OK;
234 }
235
236 static gate_result_t xlibfb_set_image32(xlibfb_t* fb, gate_rasterimage_t const* ptr_image,
237 gate_uint32_t dest_x, gate_uint32_t dest_y,
238 gate_uint32_t width, gate_uint32_t height)
239 {
240 gate_uint32_t x, y;
241 gate_uint32_t* ptr_data = (gate_uint32_t*)fb->image_data;
242 gate_uint32_t* ptr_dst;
243 gate_color_t const* ptr_src;
244 gate_uint32_t pixel;
245
246 for (y = 0; y != height; ++y)
247 {
248 ptr_dst = &ptr_data[fb->width * (dest_y + y) + dest_x];
249 ptr_src = (gate_color_t*)gate_rasterimage_get_line_ptr(ptr_image, y);
250
251 for (x = 0; x != width; ++x)
252 {
253 pixel = (((gate_uint32_t)ptr_src->r) << 16)
254 | (((gate_uint32_t)ptr_src->g) << 8)
255 | (((gate_uint32_t)ptr_src->b))
256 ;
257 *ptr_dst = pixel;
258 ++ptr_src;
259 ++ptr_dst;
260 }
261 }
262 return GATE_RESULT_OK;
263 }
264
265 static gate_result_t xlibfb_set_image_generic(xlibfb_t* fb, gate_rasterimage_t const* ptr_image,
266 gate_uint32_t dest_x, gate_uint32_t dest_y,
267 gate_uint32_t width, gate_uint32_t height)
268 {
269 gate_color_t col;
270 unsigned x, y;
271 unsigned long pixel;
272 Colormap colmap;
273
274 if ((fb->image->bits_per_pixel == 32) && ((fb->image->depth == 24) || (fb->image->depth == 32)))
275 {
276 // frame-buffer is 24/32 bit -> optimize color access
277 gate_uint32_t* ptr_data = (gate_uint32_t*)fb->image_data;
278 gate_uint32_t* ptr_dst;
279
280 for (y = 0; y != height; ++y)
281 {
282 ptr_dst = &ptr_data[fb->width * (dest_y + y) + dest_x];
283
284 for (x = 0; x != width; ++x)
285 {
286 gate_rasterimage_get_pixel(ptr_image, x, y, &col);
287 pixel = (((gate_uint32_t)col.r) << 16)
288 | (((gate_uint32_t)col.g) << 8)
289 | (((gate_uint32_t)col.b))
290 ;
291 *ptr_dst = pixel;
292 ++ptr_dst;
293 }
294 }
295
296 }
297 else
298 {
299 colmap = xlib.XDefaultColormap(fb->display, fb->screen);
300
301 for (y = 0; y != height; ++y)
302 {
303 for (x = 0; x != width; ++x)
304 {
305 gate_rasterimage_get_pixel(ptr_image, x, y, &col);
306 pixel = XGetRgbPixel(fb->display, colmap, col.r, col.g, col.b);
307 xlib.XPutPixel(fb->image, (int)(dest_x + x), (int)(dest_y + y), pixel);
308 }
309 }
310 }
311
312 return GATE_RESULT_OK;
313 }
314
315 static gate_result_t xlibfb_set_image(void* obj, gate_rasterimage_t const* ptr_image, gate_uint32_t dest_x, gate_uint32_t dest_y)
316 {
317 xlibfb_t* impl = (xlibfb_t*)obj;
318
319 gate_uint32_t width, height;
320
321 if ((dest_x >= impl->width) || (dest_y >= impl->height))
322 {
323 return GATE_RESULT_INVALIDARG;
324 }
325
326 width = gate_rasterimage_width(ptr_image);
327 height = gate_rasterimage_height(ptr_image);
328
329 if (dest_y + height > impl->height)
330 {
331 height = impl->height - dest_y;
332 }
333 if (dest_x + width > impl->width)
334 {
335 width = impl->width - dest_x;
336 }
337
338 if ((impl->image->bits_per_pixel == 32) && ((impl->image->depth == 24) || (impl->image->depth == 32))
339 && ((ptr_image->pixel_format == GATE_IMAGE_PIXELFORMAT_RGBA) || (ptr_image->pixel_format == GATE_IMAGE_PIXELFORMAT_RGB32)))
340 {
341 return xlibfb_set_image32(impl, ptr_image, dest_x, dest_y, width, height);
342 }
343
344 return xlibfb_set_image_generic(impl, ptr_image, dest_x, dest_y, width, height);
345 }
346
347 static gate_bool_t xlibfb_decode_event(XEvent* ptr_event, xlibfb_t* impl, gate_framebuffer_event_t* ptr_received_evt)
348 {
349 KeySym keysym;
350 gate_input_keycode_t key_code;
351 gate_uint32_t key_states;
352
353 switch (ptr_event->type)
354 {
355 case KeyPress:
356 {
357 keysym = xlib.XLookupKeysym(&ptr_event->xkey, 0);
358 key_states = 0;
359 if (ptr_event->xkey.state & ShiftMask)
360 {
361 key_states |= GATE_KBD_KEYSTATE_SHIFT;
362 }
363 if (ptr_event->xkey.state & LockMask)
364 {
365 key_states |= GATE_KBD_KEYSTATE_MENU;
366 }
367 if (ptr_event->xkey.state & ControlMask)
368 {
369 key_states |= GATE_KBD_KEYSTATE_CTRL;
370 }
371 key_code = 0;
372 gate_xlib_convert_keysym(keysym, &key_code);
373 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_KEY_DOWN;
374 ptr_received_evt->event_data.key.key_code = key_code;
375 ptr_received_evt->event_data.key.char_code = key_code;
376 return true;
377 }
378 case KeyRelease:
379 {
380 keysym = xlib.XLookupKeysym(&ptr_event->xkey, 0);
381 key_states = 0;
382 if (ptr_event->xkey.state & ShiftMask)
383 {
384 key_states |= GATE_KBD_KEYSTATE_SHIFT;
385 }
386 if (ptr_event->xkey.state & LockMask)
387 {
388 key_states |= GATE_KBD_KEYSTATE_MENU;
389 }
390 if (ptr_event->xkey.state & ControlMask)
391 {
392 key_states |= GATE_KBD_KEYSTATE_CTRL;
393 }
394 key_code = 0;
395 gate_xlib_convert_keysym(keysym, &key_code);
396 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_KEY_UP;
397 ptr_received_evt->event_data.key.key_code = key_code;
398 ptr_received_evt->event_data.key.char_code = key_code;
399 return true;
400 }
401 case ButtonPress:
402 {
403 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_POINTER_BUTTON_DOWN;
404 ptr_received_evt->event_data.pointer.x = ptr_event->xbutton.x;
405 ptr_received_evt->event_data.pointer.y = ptr_event->xbutton.y;
406 switch (ptr_event->xbutton.button)
407 {
408 case Button1: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_1; break;
409 case Button2: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_2; break;
410 case Button3: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_3; break;
411 }
412 return true;
413 }
414 case ButtonRelease:
415 {
416 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_POINTER_BUTTON_UP;
417 ptr_received_evt->event_data.pointer.x = ptr_event->xbutton.x;
418 ptr_received_evt->event_data.pointer.y = ptr_event->xbutton.y;
419 switch (ptr_event->xbutton.button)
420 {
421 case Button1: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_1; break;
422 case Button2: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_2; break;
423 case Button3: ptr_received_evt->event_data.pointer.button = GATE_FRAMEBUFFER_BUTTON_3; break;
424 }
425 return true;
426 }
427 case ClientMessage:
428 {
429 if (ptr_event->xclient.message_type == impl->protocols_atom)
430 {
431 if (ptr_event->xclient.data.l[0] == (long)impl->close_atom)
432 {
433 ptr_received_evt->event_type = GATE_FRAMEBUFFER_EVENT_QUIT;
434 return true;
435 }
436 }
437 break;
438 }
439 }
440 return false;
441 }
442
443 static gate_result_t xlibfb_await_event(void* obj, gate_uint32_t timeout_ms, gate_framebuffer_event_t* ptr_received_evt)
444 {
445 xlibfb_t* impl = (xlibfb_t*)obj;
446 gate_result_t ret = GATE_RESULT_FAILED;
447
448 gate_timecounter_t start_time;
449 gate_timecounter_t current_time;
450 gate_int64_t time_diff;
451 const gate_int64_t timeout_us = (gate_int64_t)timeout_ms * (gate_int64_t)1000;
452
453 XEvent xevent;
454
455 long input_event_mask = FocusChangeMask | PropertyChangeMask
456 | KeyPressMask | KeyReleaseMask | KeymapStateMask
457 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | PointerMotionHintMask
458 | ExposureMask | VisibilityChangeMask
459 | StructureNotifyMask | SubstructureNotifyMask
460 ;
461
462 do
463 {
464 gate_timecounter_now(&start_time);
465
466 xlib.XSelectInput(impl->display, impl->fb_window, input_event_mask);
467
468 for (;;)
469 {
470 if (xlib.XPending(impl->display) > 0)
471 {
472 gate_mem_clear(&xevent, sizeof(xevent));
473 xlib.XNextEvent(impl->display, &xevent);
474
475 if (xlibfb_decode_event(&xevent, impl, ptr_received_evt))
476 {
477 ret = GATE_RESULT_OK;
478 break;
479 }
480 }
481 else
482 {
483 gate_timecounter_now(&current_time);
484 time_diff = gate_timecounter_diff(current_time, start_time);
485
486 if (time_diff >= timeout_us)
487 {
488 ret = GATE_RESULT_TIMEOUT;
489 break;
490 }
491 }
492 }
493 } while (0);
494
495 return ret;
496 }
497
498 static GATE_INTERFACE_VTBL(gate_framebuffer) gate_xlibfb_vtbl;
499 static void gate_init_xlibfb_vtbl()
500 {
501 if (!gate_xlibfb_vtbl.get_interface_name)
502 {
503 GATE_INTERFACE_VTBL(gate_framebuffer) const local_vtbl =
504 {
505 &xlibfb_get_interface_name,
506 &xlibfb_release,
507 &xlibfb_retain,
508
509 &xlibfb_get_info,
510 &xlibfb_get_property,
511 &xlibfb_set_property,
512
513 &xlibfb_update,
514
515 &xlibfb_get_pixel,
516 &xlibfb_set_pixel,
517
518 &xlibfb_get_image,
519 &xlibfb_set_image,
520
521 &xlibfb_await_event
522 };
523
524 gate_xlibfb_vtbl = local_vtbl;
525 }
526 }
527
528
529
530 gate_size_t gate_framebuffer_enum_displays(gate_framebuffer_info_t* ptr_infos, gate_size_t infos_capacity)
531 {
532 gate_size_t ret = infos_capacity;
533
534 if (ret > 2)
535 {
536 ret = 2;
537 }
538
539 if (ret >= 1)
540 {
541 ptr_infos[0].width = 640;
542 ptr_infos[0].height = 480;
543 ptr_infos[0].bits_per_pixel = 32;
544 ptr_infos[0].format_id = 0;
545 }
546
547 if (ret >= 2)
548 {
549 ptr_infos[1].width = 800;
550 ptr_infos[1].height = 600;
551 ptr_infos[1].bits_per_pixel = 32;
552 ptr_infos[1].format_id = 0;
553 }
554
555 return ret;
556 }
557
558 static gate_result_t xlibfb_create_image(xlibfb_t* fb)
559 {
560 Visual* visual = xlib.XDefaultVisual(fb->display, fb->screen);
561 unsigned int depth = (unsigned int)xlib.XDefaultDepth(fb->display, fb->screen);
562 unsigned int padding = xlib.XBitmapPad(fb->display);
563 unsigned int bytes_per_line = fb->width * 4;
564
565 if (bytes_per_line % padding != 0)
566 {
567 bytes_per_line += (padding - (bytes_per_line % padding));
568 }
569
570 fb->image_size = bytes_per_line * fb->height;
571 fb->image_data = gate_mem_alloc(fb->image_size);
572
573 if (!fb->image_data)
574 {
575 return GATE_RESULT_OUTOFMEMORY;
576 }
577
578 fb->image = xlib.XCreateImage(fb->display, visual, depth, ZPixmap, 0, fb->image_data, fb->width, fb->height, padding, 0);
579 if (!fb->image)
580 {
581 return GATE_RESULT_OUTOFRESOURCES;
582 }
583
584 return GATE_RESULT_OK;
585 }
586
587 static gate_result_t xlibfb_create_window(xlibfb_t* fb)
588 {
589 gate_result_t ret = GATE_RESULT_FAILED;
590
591 int depth;
592 Visual* visual;
593 Colormap colmap;
594 XSetWindowAttributes win_attribs;
595 int attr_mask;
596
597 do
598 {
599 ret = gate_xlib_load_functions();
600 GATE_BREAK_IF_FAILED(ret);
601
602 fb->display = xlib.XOpenDisplay(NULL);
603 if (fb->display == NULL)
604 {
605 fb->display = xlib.XOpenDisplay(":0");
606 }
607 if (fb->display == NULL)
608 {
609 ret = GATE_RESULT_OUTOFRESOURCES;
610 break;
611 }
612
613 fb->screen = xlib.XDefaultScreen(fb->display);
614 fb->root_window = xlib.XDefaultRootWindow(fb->display);
615 fb->protocols_atom = xlib.XInternAtom(fb->display, "WM_PROTOCOLS", False);
616 fb->close_atom = xlib.XInternAtom(fb->display, "WM_DELETE_WINDOW", False);
617
618 depth = xlib.XDefaultDepth(fb->display, fb->screen);
619 visual = xlib.XDefaultVisual(fb->display, fb->screen);
620 colmap = xlib.XDefaultColormap(fb->display, fb->screen);
621
622 gate_mem_clear(&win_attribs, sizeof(win_attribs));
623 win_attribs.colormap = colmap;
624 win_attribs.event_mask = StructureNotifyMask;
625 win_attribs.border_pixel = xlib.XBlackPixel(fb->display, fb->screen);
626 win_attribs.background_pixel = xlib.XWhitePixel(fb->display, fb->screen);
627
628 attr_mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
629
630 fb->fb_window = xlib.XCreateWindow(fb->display, fb->root_window, 0, 0, fb->width, fb->height,
631 0, depth, InputOutput, visual, attr_mask, &win_attribs);
632 if (!fb->fb_window)
633 {
634 ret = GATE_RESULT_FAILED;
635 break;
636 }
637
638 ret = xlibfb_create_image(fb);
639 GATE_BREAK_IF_FAILED(ret);
640
641 xlib.XSetWMProtocols(fb->display, fb->fb_window, &fb->close_atom, 1);
642
643 xlib.XMapWindow(fb->display, fb->fb_window);
644
645 xlib.XFlush(fb->display);
646
647 /* successfully initialized: */
648 ret = GATE_RESULT_OK;
649
650 } while (0);
651
652 return ret;
653 }
654
655 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)
656 {
657 /* TODO */
658 ptr_found_display_info->bits_per_pixel = 32;
659 ptr_found_display_info->format_id = 0;
660 ptr_found_display_info->width = required_width;
661 ptr_found_display_info->height = required_height;
662 return GATE_RESULT_OK;
663 }
664
665 gate_result_t gate_framebuffer_open_display(gate_framebuffer_info_t const* ptr_infos, gate_framebuffer_t** ptr_framebuffer)
666 {
667 gate_result_t ret;
668 xlibfb_t* fb = NULL;
669
670 do
671 {
672 if (!ptr_infos)
673 {
674 ret = GATE_RESULT_INVALIDARG;
675 break;
676 }
677
678 fb = (xlibfb_t*)gate_mem_alloc(sizeof(xlibfb_t));
679 if (!fb)
680 {
681 ret = GATE_RESULT_OUTOFMEMORY;
682 break;
683 }
684
685 gate_mem_clear(fb, sizeof(xlibfb_t));
686 gate_init_xlibfb_vtbl();
687 fb->vtbl = &gate_xlibfb_vtbl;
688 gate_atomic_int_init(&fb->ref_counter, 1);
689 fb->width = ptr_infos->width;
690 fb->height = ptr_infos->height;
691
692 ret = xlibfb_create_window(fb);
693 GATE_BREAK_IF_FAILED(ret);
694
695 /* initialization successfully completed: */
696 ret = GATE_RESULT_OK;
697 if (ptr_framebuffer)
698 {
699 *ptr_framebuffer = (gate_framebuffer_t*)fb;
700 fb = NULL;
701 }
702 } while (0);
703
704 if (fb != NULL)
705 {
706 /* destroy partially initialized framebuffer */
707 xlibfb_destroy(fb);
708 }
709 return ret;
710 }
711