GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/framebuffers.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 87 95 91.6%
Functions: 14 14 100.0%
Branches: 18 34 52.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, 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 1
36 #elif defined(GATE_SYS_NDS)
37 # define GATE_GRAPHICS_FRAMEBUFFERS_NDS 1
38 #elif defined(GATE_SYS_WIN16)
39 # define GATE_GRAPHICS_FRAMEBUFFERS_WIN16 1
40 #elif defined(GATE_SYS_WIN)
41 # define GATE_GRAPHICS_FRAMEBUFFERS_WIN32 1
42 #elif defined(GATE_SYS_ANDROID)
43 # define GATE_GRAPHICS_FRAMEBUFFERS_GL 1
44 #elif defined(GATE_SYS_OPENBSD) || defined(GATE_SYS_BEOS)
45 # define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL 1
46 #elif defined(GATE_SYS_DARWIN)
47 # define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL 1
48 #elif defined(GATE_SYS_POSIX)
49 # if defined(GATE_GRAPHICS_WAYLAND)
50 # define GATE_GRAPHICS_FRAMEBUFFERS_WAYLAND 1
51 # else
52 # if defined(HAVE_X11_HEADERS)
53 # define GATE_GRAPHICS_FRAMEBUFFERS_XLIB 1
54 # else
55 # define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL 1
56 # endif
57 # endif
58 #elif defined(GATE_SYS_EFI)
59 # define GATE_GRAPHICS_FRAMEBUFFERS_UGA 1
60 #elif defined(GATE_SYS_DOS)
61 # define GATE_GRAPHICS_FRAMEBUFFERS_INT10 1
62 #elif defined(GATE_SYS_WASM)
63 # define GATE_GRAPHICS_FRAMEBUFFERS_WASM 1
64 #else
65 # define GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL 1
66 #endif
67
68
69
70 /**************************************************
71 * generic rasterimage framebuffer implementation *
72 **************************************************/
73
74 typedef struct rasterfb_impl
75 {
76 GATE_INTERFACE_VTBL(gate_framebuffer) const* vtbl;
77
78 gate_atomic_int_t ref_counter;
79 gate_rasterimage_t image_header;
80 gate_uint8_t image_data[8];
81 } rasterfb_t;
82
83
84 1 static char const* rasterfb_get_interface_name(void* obj)
85 {
86 GATE_UNUSED_ARG(obj);
87 1 return GATE_INTERFACE_NAME_FRAMEBUFFER;
88 }
89 4 static void rasterfb_release(void* obj)
90 {
91 4 rasterfb_t* const impl = (rasterfb_t*)obj;
92
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (0 == gate_atomic_int_dec(&impl->ref_counter))
93 {
94 2 gate_mem_clear(impl, sizeof(rasterfb_t));
95 2 gate_mem_dealloc(impl);
96 }
97 4 }
98 2 static int rasterfb_retain(void* obj)
99 {
100 2 rasterfb_t* const impl = (rasterfb_t*)obj;
101 2 return gate_atomic_int_inc(&impl->ref_counter);
102 }
103
104 1 static gate_result_t rasterfb_get_info(void* obj, gate_framebuffer_info_t* ptr_info)
105 {
106 1 rasterfb_t* const impl = (rasterfb_t*)obj;
107 1 gate_result_t ret = GATE_RESULT_INVALIDARG;
108
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (impl && ptr_info)
109 {
110 1 ptr_info->width = gate_rasterimage_width(&impl->image_header);
111 1 ptr_info->height = gate_rasterimage_height(&impl->image_header);
112 1 ptr_info->bits_per_pixel = 32;
113 1 ptr_info->format_id = 0;
114 1 ret = GATE_RESULT_OK;
115 }
116 1 return ret;
117 }
118
119 1 static gate_result_t rasterfb_get_property(void* obj, gate_string_t const* name, gate_property_t* prop)
120 {
121 GATE_UNUSED_ARG(obj);
122 GATE_UNUSED_ARG(name);
123 GATE_UNUSED_ARG(prop);
124 1 return GATE_RESULT_NOTSUPPORTED;
125 }
126
127 1 static gate_result_t rasterfb_set_property(void* obj, gate_string_t const* name, gate_property_t const* prop)
128 {
129 GATE_UNUSED_ARG(obj);
130 GATE_UNUSED_ARG(name);
131 GATE_UNUSED_ARG(prop);
132 1 return GATE_RESULT_NOTSUPPORTED;
133 }
134
135 11 static gate_result_t rasterfb_update(void* obj)
136 {
137 /* rasterimage framebuffer is always up-to-date */
138 GATE_UNUSED_ARG(obj);
139 11 return GATE_RESULT_OK;
140 }
141
142 11 static gate_result_t rasterfb_get_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t* ptr_col)
143 {
144 11 rasterfb_t* const impl = (rasterfb_t*)obj;
145 11 return gate_rasterimage_get_pixel(&impl->image_header, x, y, ptr_col);
146 }
147
148 11 static gate_result_t rasterfb_set_pixel(void* obj, gate_uint32_t x, gate_uint32_t y, gate_color_t col)
149 {
150 11 rasterfb_t* const impl = (rasterfb_t*)obj;
151 11 return gate_rasterimage_set_pixel(&impl->image_header, x, y, &col);
152 }
153
154 11 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)
155 {
156 11 rasterfb_t* const impl = (rasterfb_t*)obj;
157 11 gate_result_t ret = GATE_RESULT_FAILED;
158 11 gate_uint32_t fb_width = gate_rasterimage_width(&impl->image_header);
159 11 gate_uint32_t fb_height = gate_rasterimage_height(&impl->image_header);
160
161
6/12
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
11 if ((src_x == 0) && (src_y == 0) && (((width == 0) && (height == 0)) || ((width == fb_width) && (height == fb_height))))
162 {
163
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 if (gate_rasterimage_copy(ptr_image, &impl->image_header))
164 {
165 6 ret = GATE_RESULT_OK;
166 }
167 }
168 else
169 {
170 do
171 {
172
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (!gate_rasterimage_create(ptr_image, GATE_IMAGE_PIXELFORMAT_RGBA, width, height, NULL))
173 {
174 ret = GATE_RESULT_OUTOFMEMORY;
175 break;
176 }
177 5 ret = gate_rasterimage_paste_image(ptr_image, &impl->image_header, 0, 0, src_x, src_y, width, height, false);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (GATE_FAILED(ret))
179 {
180 gate_rasterimage_release(ptr_image);
181 }
182 } while (0);
183 }
184 11 return ret;
185 }
186
187 11 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)
188 {
189 11 rasterfb_t* const impl = (rasterfb_t*)obj;
190 11 gate_result_t ret = GATE_RESULT_FAILED;
191 11 gate_uint32_t width = gate_rasterimage_width(ptr_image);
192 11 gate_uint32_t height = gate_rasterimage_height(ptr_image);
193
194 11 ret = gate_rasterimage_paste_image(&impl->image_header, ptr_image, dest_x, dest_y, 0, 0, width, height, false);
195 11 return ret;
196 }
197
198 1 static gate_result_t rasterfb_await_event(void* obj, gate_uint32_t timeout_ms, gate_framebuffer_event_t* ptr_received_evt)
199 {
200 GATE_UNUSED_ARG(obj);
201 GATE_UNUSED_ARG(timeout_ms);
202 GATE_UNUSED_ARG(ptr_received_evt);
203 1 return GATE_RESULT_NOTSUPPORTED;
204 }
205
206 static GATE_INTERFACE_VTBL(gate_framebuffer) gate_rasterfb_vtbl;
207 2 static void gate_init_rasterfb_vtbl()
208 {
209
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!gate_rasterfb_vtbl.get_interface_name)
210 {
211 GATE_INTERFACE_VTBL(gate_framebuffer) const local_vtbl =
212 {
213 &rasterfb_get_interface_name,
214 &rasterfb_release,
215 &rasterfb_retain,
216
217 &rasterfb_get_info,
218 &rasterfb_get_property,
219 &rasterfb_set_property,
220
221 &rasterfb_update,
222
223 &rasterfb_get_pixel,
224 &rasterfb_set_pixel,
225
226 &rasterfb_get_image,
227 &rasterfb_set_image,
228
229 &rasterfb_await_event
230 };
231
232 2 gate_rasterfb_vtbl = local_vtbl;
233 }
234 2 }
235
236
237 2 gate_result_t gate_framebuffer_create_image(gate_uint32_t width, gate_uint32_t height, gate_framebuffer_t** ptr_framebuffer)
238 {
239 2 rasterfb_t* impl = NULL;
240 2 gate_result_t ret = GATE_RESULT_FAILED;
241 gate_size_t datasize;
242
243 do
244 {
245 gate_rasterimage_t dummy_image;
246
247 2 datasize = sizeof(gate_color_t) * width * height;
248 2 impl = (rasterfb_t*)gate_mem_alloc(sizeof(rasterfb_t) + datasize);
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!impl)
250 {
251 ret = GATE_RESULT_OUTOFMEMORY;
252 break;
253 }
254 2 gate_init_rasterfb_vtbl();
255 2 impl->vtbl = &gate_rasterfb_vtbl;
256 2 gate_atomic_int_init(&impl->ref_counter, 1);
257
258
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_rasterimage_create(&dummy_image, GATE_IMAGE_PIXELFORMAT_RGBA, 4, 4, NULL))
259 {
260 ret = GATE_RESULT_OUTOFMEMORY;
261 break;
262 }
263
264 2 impl->image_header.width = width;
265 2 impl->image_header.height = height;
266 2 impl->image_header.bits_per_pixel = sizeof(gate_color_t) * 8;
267 2 impl->image_header.line_padding = 0;
268 2 impl->image_header.pixel_format = GATE_IMAGE_PIXELFORMAT_RGBA;
269 2 impl->image_header.pixel_length = 4;
270 2 impl->image_header.get_ptr = dummy_image.get_ptr;
271 2 impl->image_header.write_pixel = dummy_image.write_pixel;
272 2 impl->image_header.read_pixel = dummy_image.read_pixel;
273 2 impl->image_header.data = &impl->image_data[0];
274 2 impl->image_header.databuffer = NULL;
275
276 2 gate_rasterimage_release(&dummy_image);
277
278 2 gate_mem_clear(&impl->image_data[0], datasize);
279
280
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_framebuffer)
281 {
282 2 *ptr_framebuffer = (gate_framebuffer_t*)impl;
283 2 impl = NULL;
284 }
285 2 ret = GATE_RESULT_OK;
286 } while (0);
287
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl)
289 {
290 gate_mem_dealloc(impl);
291 }
292 2 return ret;
293 }
294
295
296
297 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_DIRECTX)
298 #include "gate/graphics/platform/framebuffers_impl_directx.h"
299 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_DIRECTX */
300
301
302 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_NDS)
303 #include "gate/graphics/platform/framebuffers_impl_nds.h"
304 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_NDS */
305
306
307 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_WIN16)
308 #include "gate/graphics/platform/framebuffers_impl_win16.h"
309 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_WIN16 */
310
311
312 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_WIN32)
313 #include "gate/graphics/platform/framebuffers_impl_win32.h"
314 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_WIN32 */
315
316
317 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_WAYLAND)
318 #include "gate/graphics/platform/framebuffers_impl_wayland.h"
319 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_WAYLAND */
320
321 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_XLIB)
322 #include "gate/graphics/platform/framebuffers_impl_xlib.h"
323 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_XLIB */
324
325
326 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_GL)
327 #include "gate/graphics/platform/framebuffers_impl_gl.h"
328 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_GL */
329
330
331 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_UGA)
332 #include "gate/graphics/platform/framebuffers_impl_efigop.h"
333 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_UGA */
334
335
336 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_INT10)
337 #include "gate/graphics/platform/framebuffers_impl_int10.h"
338 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_INT10 */
339
340
341 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_WASM)
342 #include "gate/graphics/platform/framebuffers_impl_wasm.h"
343 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_WASM */
344
345 #if defined(GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL)
346
347 gate_size_t gate_framebuffer_enum_displays(gate_framebuffer_info_t* ptr_infos, gate_size_t infos_capacity)
348 {
349 GATE_UNUSED_ARG(ptr_infos);
350 GATE_UNUSED_ARG(infos_capacity);
351 return 0;
352 }
353
354 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)
355 {
356 GATE_UNUSED_ARG(required_width);
357 GATE_UNUSED_ARG(required_height);
358 GATE_UNUSED_ARG(ptr_found_display_info);
359 return GATE_RESULT_NOMATCH;
360 }
361
362 gate_result_t gate_framebuffer_open_display(gate_framebuffer_info_t const* ptr_infos, gate_framebuffer_t** ptr_framebuffer)
363 {
364 GATE_UNUSED_ARG(ptr_infos);
365 GATE_UNUSED_ARG(ptr_framebuffer);
366 return GATE_RESULT_NOMATCH;
367 }
368
369
370 #endif /* GATE_GRAPHICS_FRAMEBUFFERS_NOIMPL */
371