GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/platform/opengl_xlib_impl.h
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 411 0.0%
Functions: 0 19 0.0%
Branches: 0 171 0.0%

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 #ifndef GATE_GRAPHICS_PLATFORM_OPENGL_XLIB_IMPL_H_INCLUDED
29 #define GATE_GRAPHICS_PLATFORM_OPENGL_XLIB_IMPL_H_INCLUDED
30
31 #include "gate/platform/posix/xlib.h"
32 #include <GL/glx.h>
33
34 typedef struct gate_glx
35 {
36 XVisualInfo* (*glXChooseVisual)(Display* dpy, int screen, int* attribList);
37 } gate_glx_t;
38
39 static gate_glx_t glx = GATE_INIT_EMPTY;
40 static gate_bool_t volatile glx_loaded = false;
41
42 static gate_result_t gate_glx_load_functions()
43 {
44 static gate_string_t glx_lib_name = GATE_STRING_INIT_STATIC("libGL.so");
45 gate_result_t ret = GATE_RESULT_FAILED;
46 static gate_library_t glx_lib = NULL;
47
48 do
49 {
50 if (glx_loaded)
51 {
52 ret = GATE_RESULT_OK;
53 break;
54 }
55
56 if (glx_lib == NULL)
57 {
58 ret = gate_library_open(&glx_lib_name, &glx_lib, GATE_LIBRARY_FLAG_DEFAULT);
59 GATE_BREAK_IF_FAILED(ret);
60 }
61
62 GATE_BREAK_IF_FAILED(ret = gate_library_get_function_name(glx_lib, "glXChooseVisual", &glx.glXChooseVisual));
63
64 glx_loaded = true;
65 ret = GATE_RESULT_OK;
66 } while (0);
67 return ret;
68 }
69
70
71 typedef struct gate_xlib_handle
72 {
73 Display* display;
74 Window root_win;
75 Window surface_win;
76 int cancel_events;
77 Atom wm_protocols;
78 Atom wm_delete_window;
79
80 } gate_xlib_handle_t;
81
82 static int default_xlib_visual_attribs_doublebuffer[] =
83 {
84 GLX_RGBA,
85 GLX_DOUBLEBUFFER,
86 GLX_RED_SIZE, 4,
87 GLX_GREEN_SIZE, 4,
88 GLX_BLUE_SIZE, 4,
89 GLX_DEPTH_SIZE, 16,
90 None
91 };
92 static int default_xlib_visual_attribs_singlebuffer[] =
93 {
94 GLX_RGBA,
95 GLX_RED_SIZE, 4,
96 GLX_GREEN_SIZE, 4,
97 GLX_BLUE_SIZE, 4,
98 GLX_DEPTH_SIZE, 16,
99 None
100 };
101
102 static void gate_xlib_surface_destroy(void* xlib_surface)
103 {
104 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)xlib_surface;
105 if (xhandle->surface_win)
106 {
107 xlib.XDestroyWindow(xhandle->display, xhandle->surface_win);
108 }
109 if (xhandle->display)
110 {
111 xlib.XCloseDisplay(xhandle->display);
112
113 }
114 gate_mem_dealloc(xhandle);
115 }
116
117 void* gate_xlib_surface_create(gate_int32_t x, gate_int32_t y, gate_uint32_t width, gate_uint32_t height)
118 {
119 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)gate_mem_alloc(sizeof(gate_xlib_handle_t));
120 gate_bool_t completed = false;
121 int xdefaultscreen;
122 XVisualInfo visualinfo;
123 XVisualInfo* vi;
124 XWindowAttributes windowattrs;
125
126
127 if (xhandle == NULL)
128 {
129 return NULL;
130 }
131
132 xhandle->display = NULL;
133 xhandle->root_win = 0;
134 xhandle->surface_win = 0;
135 xhandle->cancel_events = 0;
136
137 do
138 {
139 xhandle->display = xlib.XOpenDisplay(NULL);
140 if (xhandle->display == NULL)
141 {
142 xhandle->display = xlib.XOpenDisplay(":0");
143 }
144 if (xhandle->display == NULL)
145 {
146 GATE_DEBUG_TRACE("XOpenDisplay() failed");
147 break;
148 }
149 xhandle->root_win = xlib.XDefaultRootWindow(xhandle->display);
150 xdefaultscreen = xlib.XDefaultScreen(xhandle->display);
151
152 gate_mem_clear(&visualinfo, sizeof(visualinfo));
153
154 if (glx.glXChooseVisual)
155 {
156 vi = glx.glXChooseVisual(xhandle->display, xdefaultscreen, default_xlib_visual_attribs_doublebuffer);
157 if (vi == NULL)
158 {
159 vi = glx.glXChooseVisual(xhandle->display, xdefaultscreen, default_xlib_visual_attribs_singlebuffer);
160 }
161 if (vi == NULL)
162 {
163 GATE_DEBUG_TRACE("glXChooseVisual() failed");
164 break;
165 }
166 visualinfo = *vi;
167 }
168 else
169 {
170 xlib.XMatchVisualInfo(xhandle->display, xdefaultscreen, 16, TrueColor, &visualinfo);
171 }
172
173
174 XSetWindowAttributes swa;
175 gate_mem_clear(&swa, sizeof(swa));
176 swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
177 swa.background_pixel = 0;
178 swa.border_pixel = 0;
179 swa.colormap = xlib.XCreateColormap(xhandle->display, xhandle->root_win, visualinfo.visual, AllocNone);
180
181 if ((width == 0) || (height == 0))
182 {
183 xlib.XGetWindowAttributes(xhandle->display, xhandle->root_win, &windowattrs);
184 if (width == 0)
185 {
186 width = windowattrs.width;
187 }
188 if (height == 0)
189 {
190 height = windowattrs.height;
191 }
192 }
193
194 xhandle->surface_win = xlib.XCreateWindow(xhandle->display, xhandle->root_win,
195 x, y, width, height, 0,
196 /*CopyFromParent*/ visualinfo.depth,
197 InputOutput,
198 /*CopyFromParent*/ visualinfo.visual,
199 CWEventMask | CWBackPixel | CWBorderPixel | CWColormap,
200 &swa);
201
202 xhandle->wm_protocols = xlib.XInternAtom(xhandle->display, "WM_PROTOCOLS", False);
203 xhandle->wm_delete_window = xlib.XInternAtom(xhandle->display, "WM_DELETE_WINDOW", False);
204 xlib.XSetWMProtocols(xhandle->display, xhandle->surface_win, &xhandle->wm_delete_window, 1);
205
206 xlib.XMapWindow(xhandle->display, xhandle->surface_win);
207 xlib.XFlush(xhandle->display);
208
209 //xlib.XGetWindowAttributes(xhandle->surface_win
210
211 completed = true;
212 } while (0);
213
214 if (!completed)
215 {
216 gate_xlib_surface_destroy(xhandle);
217 return NULL;
218 }
219 return xhandle;
220 }
221
222 static void gate_xlib_surface_resize(void* xlib_surface, gate_uint32_t width, gate_uint32_t height)
223 {
224 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)xlib_surface;
225 xlib.XResizeWindow(xhandle->display, xhandle->surface_win, width, height);
226 /* TODO */
227 }
228 static void gate_xlib_surface_get_client_size(void* xlib_surface, gate_uint32_t* ptr_width, gate_uint32_t* ptr_height)
229 {
230 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)xlib_surface;
231 XWindowAttributes windowattrs = GATE_INIT_EMPTY;
232 xlib.XGetWindowAttributes(xhandle->display, xhandle->surface_win, &windowattrs);
233 if (ptr_width)
234 {
235 *ptr_width = windowattrs.width;
236 }
237 if (ptr_height)
238 {
239 *ptr_height = windowattrs.height;
240 }
241 }
242
243 static void* gate_xlib_surface_get_handle(void* xlib_surface)
244 {
245 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)xlib_surface;
246 return (void*)xhandle->surface_win;
247 }
248
249 static void gate_xlib_surface_handle_events(void* xlib_surface, gate_gl_surface_events_t* callbacks, void* user_param)
250 {
251 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)xlib_surface;
252 gate_gl_surface_t* ptr_gl_surface = NULL;
253
254 long mask = FocusChangeMask | PropertyChangeMask
255 | KeyPressMask | KeyReleaseMask | KeymapStateMask
256 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | PointerMotionHintMask
257 | ExposureMask | VisibilityChangeMask
258 | StructureNotifyMask | SubstructureNotifyMask
259 ;
260
261
262 XEvent xevent;
263 KeySym keysym;
264 gate_input_keycode_t keycode;
265 gate_input_keystates_t keystates;
266
267 xlib.XSelectInput(xhandle->display, xhandle->surface_win, mask);
268 for (;;)
269 {
270 if (xhandle->cancel_events)
271 {
272 xhandle->cancel_events = 0;
273 break;
274 }
275 if (callbacks)
276 {
277 if (callbacks->on_render)
278 {
279 callbacks->on_render(ptr_gl_surface, user_param);
280 }
281 }
282 /*
283 if(!xlib.XCheckMaskEvent(xhandle->display, mask, &xevent))
284 {
285 gate_thread_sleep(10);
286 }
287 else
288 {
289 */
290 if (xlib.XPending(xhandle->display) <= 0)
291 {
292 gate_thread_sleep(10);
293 }
294 else
295 {
296 gate_mem_clear(&xevent, sizeof(xevent));
297 xlib.XNextEvent(xhandle->display, &xevent);
298
299 if (callbacks && (xevent.xany.window == xhandle->surface_win))
300 {
301 switch (xevent.type)
302 {
303 case ConfigureNotify:
304 {
305 if (callbacks->on_resize)
306 {
307 callbacks->on_resize(ptr_gl_surface,
308 xevent.xconfigure.width,
309 xevent.xconfigure.height,
310 user_param);
311 }
312 break;
313 }
314 case KeyPress:
315 {
316 if (callbacks->on_key_down)
317 {
318 keysym = xlib.XLookupKeysym(&xevent.xkey, 0);
319 keycode = 0;
320 keystates = 0;
321 if (xevent.xkey.state & ShiftMask)
322 {
323 keystates |= GATE_KBD_KEYSTATE_SHIFT;
324 }
325 if (xevent.xkey.state & LockMask)
326 {
327 keystates |= GATE_KBD_KEYSTATE_MENU;
328 }
329 if (xevent.xkey.state & ControlMask)
330 {
331 keystates |= GATE_KBD_KEYSTATE_CTRL;
332 }
333 gate_xlib_convert_keysym(keysym, &keycode);
334 callbacks->on_key_down(ptr_gl_surface, keycode, keystates, user_param);
335 }
336 break;
337 }
338 case KeyRelease:
339 {
340 if (callbacks->on_key_up)
341 {
342 keysym = xlib.XLookupKeysym(&xevent.xkey, 0);
343 keycode = 0;
344 keystates = 0;
345 if (xevent.xkey.state & ShiftMask)
346 {
347 keystates |= GATE_KBD_KEYSTATE_SHIFT;
348 }
349 if (xevent.xkey.state & LockMask)
350 {
351 keystates |= GATE_KBD_KEYSTATE_MENU;
352 }
353 if (xevent.xkey.state & ControlMask)
354 {
355 keystates |= GATE_KBD_KEYSTATE_CTRL;
356 }
357 gate_xlib_convert_keysym(keysym, &keycode);
358 callbacks->on_key_up(ptr_gl_surface, keycode, keystates, user_param);
359 }
360 break;
361 }
362 case ButtonPress:
363 {
364 if (callbacks->on_pointer_down)
365 {
366 callbacks->on_pointer_down(ptr_gl_surface, xevent.xbutton.button,
367 xevent.xbutton.x, xevent.xbutton.y, user_param);
368 }
369 break;
370 }
371 case ButtonRelease:
372 {
373 if (callbacks->on_pointer_up)
374 {
375 callbacks->on_pointer_up(ptr_gl_surface, xevent.xbutton.button,
376 xevent.xbutton.x, xevent.xbutton.y, user_param);
377 }
378 break;
379 }
380 case ClientMessage:
381 {
382 if (xevent.xclient.message_type == xhandle->wm_protocols)
383 {
384 if (xevent.xclient.data.l[0] == (long)xhandle->wm_delete_window)
385 {
386 if (callbacks->on_exit)
387 {
388 callbacks->on_exit(ptr_gl_surface, user_param);
389 }
390 break;
391 }
392 }
393 break;
394 }
395 default:
396 {
397 break;
398 }
399 }
400 }
401 }
402 }
403 }
404 static void gate_xlib_surface_cancel_events(void* xlib_surface)
405 {
406 gate_xlib_handle_t* xhandle = (gate_xlib_handle_t*)xlib_surface;
407 if (xhandle)
408 {
409 xhandle->cancel_events = 1;
410 }
411 }
412
413
414
415
416
417
418
419
420
421
422
423 gate_result_t gate_gl_surface_init(gate_gl_surface_t* surface)
424 {
425 gate_result_t ret;
426 do
427 {
428 ret = gate_xlib_load_functions();
429 GATE_BREAK_IF_FAILED(ret);
430 ret = gate_egl_load_functions();
431 GATE_BREAK_IF_FAILED(ret);
432 ret = gate_gl_api_load_functions();
433 GATE_BREAK_IF_FAILED(ret);
434 ret = gate_glx_load_functions();
435 GATE_BREAK_IF_FAILED(ret);
436 gate_mem_clear(surface, sizeof(gate_gl_surface_t));
437 } while (0);
438
439 return ret;
440 }
441 gate_result_t gate_gl_surface_uninit(gate_gl_surface_t* surface)
442 {
443 gate_mem_clear(surface, sizeof(gate_gl_surface_t));
444 return GATE_RESULT_OK;
445 }
446
447
448
449 static EGLint gate_egl_attribs_pbuffer[] =
450 {
451 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
452 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
453 //EGL_RED_SIZE, (EGLint)5,
454 //EGL_GREEN_SIZE, (EGLint)6,
455 //EGL_BLUE_SIZE, (EGLint)5,
456 //EGL_ALPHA_SIZE, (EGLint)0,
457 EGL_DEPTH_SIZE, (EGLint)16,
458 //EGL_STENCIL_SIZE, (EGLint)0,
459 EGL_NONE
460 };
461
462 static EGLint gate_egl_attribs_window[] =
463 {
464 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
465 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
466 EGL_RED_SIZE, (EGLint)5,
467 EGL_GREEN_SIZE, (EGLint)5,
468 EGL_BLUE_SIZE, (EGLint)5,
469 EGL_ALPHA_SIZE, (EGLint)0,
470 EGL_DEPTH_SIZE, (EGLint)16,
471 //EGL_STENCIL_SIZE, (EGLint)0,
472 EGL_NONE
473 };
474
475 static gate_result_t gate_gl_surface_egl_prepare(EGLint const* egl_attrib_list, EGLDisplay* ptr_egl_display,
476 EGLContext* ptr_egl_context, EGLConfig* ptr_egl_config)
477 {
478 gate_result_t ret = GATE_RESULT_FAILED;
479 EGLDisplay egl_display = EGL_NO_DISPLAY;
480 EGLint egl_version_major, egl_version_minor;
481 int egl_configs = 0;
482 EGLConfig all_configs[64] = GATE_INIT_EMPTY;
483 EGLint all_configs_count = sizeof(all_configs) / sizeof(all_configs[0]);
484 EGLConfig egl_current_config[64] = GATE_INIT_EMPTY;
485 EGLint ndx;
486 EGLint egl_current_configs_count = sizeof(egl_current_config) / sizeof(egl_current_config[0]);
487 EGLContext egl_context = EGL_NO_CONTEXT;
488 EGLConfig* ptr_egl_current_config = NULL;
489
490 do
491 {
492 egl_display = egl.GetDisplay(EGL_DEFAULT_DISPLAY);
493 if (egl_display == EGL_NO_DISPLAY)
494 {
495 GATE_DEBUG_TRACE("eglGetDisplay() failed");
496 ret = GATE_RESULT_FAILED;
497 break;
498 }
499 if (EGL_FALSE == egl.Initialize(egl_display, &egl_version_major, &egl_version_minor))
500 {
501 GATE_DEBUG_TRACE("eglInitialize() failed");
502 ret = GATE_RESULT_FAILED;
503 break;
504 }
505 if (EGL_FALSE == egl.GetConfigs(egl_display, all_configs, all_configs_count, &egl_configs))
506 {
507 GATE_DEBUG_TRACE("eglGetConfigs() failed");
508 ret = GATE_RESULT_FAILED;
509 break;
510 }
511
512 if (EGL_FALSE == egl.ChooseConfig(egl_display, egl_attrib_list,
513 egl_current_config, egl_current_configs_count,
514 &egl_current_configs_count))
515 {
516 GATE_DEBUG_TRACE("eglChooseConfig() failed");
517 ret = GATE_RESULT_FAILED;
518 break;
519 }
520
521 if (egl_current_configs_count == 0)
522 {
523 GATE_DEBUG_TRACE("eglChooseConfig() failed");
524 ret = GATE_RESULT_FAILED;
525 break;
526 }
527
528 for (ndx = 0; ndx < egl_current_configs_count; ++ndx)
529 {
530 egl_context = egl.CreateContext(egl_display, egl_current_config[ndx], EGL_NO_CONTEXT, NULL);
531 if (egl_context != EGL_NO_CONTEXT)
532 {
533 ptr_egl_current_config = &egl_current_config[ndx];
534 break;
535 }
536 }
537
538 if (egl_context == EGL_NO_CONTEXT)
539 {
540 EGLint egl_error = egl.GetError();
541 GATE_DEBUG_TRACE("eglCreateContext() failed");
542 GATE_DEBUG_TRACE_VALUE(egl_error);
543 ret = GATE_RESULT_OUTOFRESOURCES;
544 break;
545 }
546
547 *ptr_egl_display = egl_display;
548 *ptr_egl_context = egl_context;
549 gate_mem_copy(ptr_egl_config, ptr_egl_current_config, sizeof(EGLConfig));
550 egl_display = EGL_NO_DISPLAY;
551 egl_context = EGL_NO_DISPLAY;
552 ret = GATE_RESULT_OK;
553 } while (0);
554
555 if (egl_context != EGL_NO_CONTEXT)
556 {
557 egl.DestroyContext(egl_display, egl_context);
558 }
559
560 if (egl_display != EGL_NO_DISPLAY)
561 {
562 egl.Terminate(egl_display);
563 }
564
565 return ret;
566 }
567
568
569 gate_result_t gate_gl_surface_open(gate_gl_surface_t* surface, gate_gl_surface_type_t type,
570 gate_uint32_t width, gate_uint32_t height, gate_enumint_t flags)
571 {
572 gate_result_t ret = GATE_RESULT_FAILED;
573 EGLDisplay egl_display = EGL_NO_DISPLAY;
574 EGLContext egl_context = EGL_NO_CONTEXT;
575 EGLSurface egl_surface = EGL_NO_SURFACE;
576 void* xlib_surface = NULL;
577 NativeWindowType egl_native_window;
578 EGLConfig egl_config;
579
580 EGLint gate_egl_pbuffer_surface_attribs[] =
581 {
582 EGL_WIDTH, (EGLint)width,
583 EGL_HEIGHT, (EGLint)height,
584 //EGL_COLORSPACE, (EGLint)GL_RGBA,
585 //EGL_TEXTURE_FORMAT, (EGLint)EGL_TEXTURE_RGB,
586 //EGL_TEXTURE_TARGET, (EGLint)EGL_TEXTURE_2D,
587 EGL_LARGEST_PBUFFER, (EGLint)EGL_TRUE,
588 EGL_NONE
589 };
590
591 do
592 {
593 switch (type)
594 {
595 case gate_gl_surface_type_external:
596 {
597 break;
598 }
599 case gate_gl_surface_type_screen:
600 {
601 xlib_surface = gate_xlib_surface_create(0, 0, width, height);
602 if (xlib_surface == NULL)
603 {
604 GATE_DEBUG_TRACE("gate_xlib_surface_create() failed");
605 ret = GATE_RESULT_OUTOFRESOURCES;
606 break;
607 }
608
609 ret = gate_gl_surface_egl_prepare(gate_egl_attribs_window, &egl_display, &egl_context, &egl_config);
610 GATE_BREAK_IF_FAILED(ret);
611
612
613 egl_native_window = (NativeWindowType)gate_xlib_surface_get_handle(xlib_surface);
614
615 egl_surface = egl.CreateWindowSurface(egl_display, egl_config, egl_native_window, NULL);
616 if (egl_surface == EGL_NO_SURFACE)
617 {
618 GATE_DEBUG_TRACE("eglCreateWindowSurface() failed");
619 ret = GATE_RESULT_OUTOFRESOURCES;
620 break;
621 }
622
623 gate_xlib_surface_get_client_size(xlib_surface, &width, &height);
624
625 gate_gl_api.glViewport(0, 0, width, height);
626
627 ret = GATE_RESULT_OK;
628 break;
629 }
630 case gate_gl_surface_type_image:
631 {
632 ret = gate_gl_surface_egl_prepare(gate_egl_attribs_pbuffer, &egl_display, &egl_context, &egl_config);
633 GATE_BREAK_IF_FAILED(ret);
634
635 egl_surface = egl.CreatePbufferSurface(egl_display, egl_config, gate_egl_pbuffer_surface_attribs);
636 if (egl_surface == EGL_NO_SURFACE)
637 {
638 GATE_DEBUG_TRACE("eglCreateWindowSurface() failed");
639 ret = GATE_RESULT_OUTOFRESOURCES;
640 break;
641 }
642
643 ret = GATE_RESULT_OK;
644 break;
645 }
646 default:
647 {
648 return GATE_RESULT_NOTSUPPORTED;
649 }
650 }
651
652 GATE_BREAK_IF_FAILED(ret);
653
654 if (EGL_FALSE == egl.MakeCurrent(egl_display, egl_surface, egl_surface, egl_context))
655 {
656 GATE_DEBUG_TRACE("eglMakeCurrent() failed");
657 ret = GATE_RESULT_INVALIDSTATE;
658 break;
659 }
660
661
662 surface->surface_type = type;
663 surface->width = width;
664 surface->height = height;
665 surface->native_surface = (void*)egl_surface;
666 surface->native_context = (void*)egl_context;
667 surface->special_resources[0] = (void*)xlib_surface; /* gate_xlib_handle */
668 surface->special_resources[1] = (void*)egl_display;
669 surface->event_handler = NULL;
670 surface->event_handler_param = NULL;
671
672 egl_surface = EGL_NO_SURFACE;
673 egl_context = EGL_NO_CONTEXT;
674 egl_display = EGL_NO_DISPLAY;
675 xlib_surface = NULL;
676
677 } while (0);
678
679 if (egl_surface != EGL_NO_SURFACE)
680 {
681 egl.DestroySurface(egl_display, egl_surface);
682 }
683
684 if (xlib_surface != NULL)
685 {
686 gate_xlib_surface_destroy(xlib_surface);
687 }
688
689 if (egl_context != EGL_NO_CONTEXT)
690 {
691 egl.DestroyContext(egl_display, egl_context);
692 }
693
694 if (egl_display != EGL_NO_DISPLAY)
695 {
696 egl.Terminate(egl_display);
697 }
698
699 return ret;
700 }
701 gate_result_t gate_gl_surface_close(gate_gl_surface_t* surface)
702 {
703 gate_result_t ret = GATE_RESULT_FAILED;
704 EGLDisplay egl_display = EGL_NO_DISPLAY;
705 EGLSurface egl_surface = EGL_NO_SURFACE;
706 EGLContext egl_context = EGL_NO_CONTEXT;
707 gate_xlib_handle_t* xlib_handle = NULL;
708
709 do
710 {
711 if (surface->surface_type == gate_gl_surface_type_external)
712 {
713 gate_mem_clear(surface, sizeof(gate_gl_surface_t));
714 ret = GATE_RESULT_OK;
715 break;
716 }
717
718 egl_surface = (EGLSurface)surface->native_surface;
719 egl_context = (EGLContext)surface->native_context;
720 xlib_handle = (gate_xlib_handle_t*)surface->special_resources[0];
721 egl_display = (EGLDisplay)surface->special_resources[1];
722
723 egl.MakeCurrent(egl_display, NULL, NULL, EGL_NO_CONTEXT);
724 egl.DestroySurface(egl_display, egl_surface);
725 egl.DestroyContext(egl_display, egl_context);
726
727 if (xlib_handle)
728 {
729 gate_xlib_surface_destroy(xlib_handle);
730 }
731
732 gate_mem_clear(surface, sizeof(gate_gl_surface_t));
733 ret = GATE_RESULT_OK;
734 } while (0);
735
736 return ret;
737 }
738
739 gate_result_t gate_gl_surface_resize(gate_gl_surface_t* surface, gate_uint32_t width, gate_uint32_t height)
740 {
741 gate_result_t ret = GATE_RESULT_FAILED;
742 EGLDisplay egl_display = EGL_NO_DISPLAY;
743 EGLSurface egl_surface = EGL_NO_SURFACE;
744 EGLContext egl_context = EGL_NO_CONTEXT;
745 gate_xlib_handle_t* xlib_surface = NULL;
746 gate_gl_surface_t temp_surface = GATE_INIT_EMPTY;
747 NativeWindowType native_window;
748 EGLConfig egl_config;
749
750 do
751 {
752 egl_surface = (EGLSurface)surface->native_surface;
753 egl_context = (EGLContext)surface->native_context;
754 xlib_surface = (gate_xlib_handle_t*)surface->special_resources[0];
755 egl_display = (EGLDisplay)surface->special_resources[1];
756
757 switch (surface->surface_type)
758 {
759 case gate_gl_surface_type_external:
760 {
761 surface->width = width;
762 surface->height = height;
763 ret = GATE_RESULT_OK;
764 break;
765 }
766 case gate_gl_surface_type_image:
767 {
768 if ((surface->width != width) || (surface->height != height))
769 {
770 ret = gate_gl_surface_open(&temp_surface, gate_gl_surface_type_image, width, height, 0);
771 GATE_BREAK_IF_FAILED(ret);
772 gate_gl_surface_close(surface);
773 gate_mem_copy(surface, &temp_surface, sizeof(temp_surface));
774 }
775 break;
776 }
777 case gate_gl_surface_type_screen:
778 {
779 /*
780 egl.MakeCurrent(egl_display, NULL, NULL, EGL_NO_CONTEXT);
781
782 egl.DestroySurface(egl_display, egl_surface);
783 egl.DestroyContext(egl_display, egl_context);
784 egl.Terminate(egl_display);
785
786 ret = gate_gl_surface_egl_prepare(gate_egl_attribs_window, &egl_display, &egl_context, &egl_config);
787 GATE_BREAK_IF_FAILED(ret);
788
789 native_window = (NativeWindowType)gate_xlib_surface_get_handle(xlib_surface);
790
791 egl_surface = egl.CreateWindowSurface(egl_display, egl_config, native_window, NULL);
792 if(egl_surface == EGL_NO_SURFACE)
793 {
794 GATE_DEBUG_TRACE("eglCreateWindowSurface() failed");
795 ret = GATE_RESULT_OUTOFRESOURCES;
796 break;
797 }
798 */
799 gate_xlib_surface_get_client_size(xlib_surface, &width, &height);
800
801 /*
802 if(EGL_FALSE == egl.MakeCurrent(egl_display, egl_surface, egl_surface, egl_context))
803 {
804 GATE_DEBUG_TRACE("eglMakeCurrent() failed");
805 ret = GATE_RESULT_INVALIDSTATE;
806 break;
807 }
808 */
809 gate_gl_api.glViewport(0, 0, width, height);
810 surface->native_surface = egl_surface;
811 surface->native_context = egl_context;
812 surface->special_resources[0] = xlib_surface;
813 surface->special_resources[1] = egl_display;
814 surface->width = width;
815 surface->height = height;
816
817 ret = GATE_RESULT_OK;
818 break;
819 }
820 }
821
822 } while (0);
823
824 return ret;
825 }
826
827 gate_result_t gate_gl_surface_get_size(gate_gl_surface_t* surface, gate_uint32_t* width, gate_uint32_t* height)
828 {
829 if (width != NULL)
830 {
831 *width = surface->width;
832 }
833 if (height != NULL)
834 {
835 *height = surface->height;
836 }
837 return GATE_RESULT_OK;
838 }
839
840 gate_result_t gate_gl_surface_print_image(gate_gl_surface_t* surface, gate_rasterimage_t* target_image)
841 {
842 gate_result_t ret = GATE_RESULT_FAILED;
843 gate_size_t image_size = surface->width * surface->height * 4;
844 GLubyte* gl_image_bytes = NULL;
845 gate_rasterimage_t raster = GATE_INIT_EMPTY;
846 GLubyte const* ptr_src;
847 gate_color_t* ptr_dst;
848 gate_uint32_t y;
849 gate_uint32_t x;
850
851 do
852 {
853 gl_image_bytes = gate_mem_alloc(image_size);
854 if (NULL != gl_image_bytes)
855 {
856 ret = GATE_RESULT_OUTOFMEMORY;
857 break;
858 }
859 gate_mem_clear(gl_image_bytes, image_size);
860
861 if (NULL == gate_rasterimage_create(&raster, GATE_IMAGE_PIXELFORMAT_DEFAULT, surface->width, surface->height, NULL))
862 {
863 ret = GATE_RESULT_OUTOFMEMORY;
864 break;
865 }
866
867 gate_gl_api.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
868 gate_gl_api.glReadPixels(0, 0, surface->width, surface->height, GL_RGBA, GL_UNSIGNED_BYTE, gl_image_bytes);
869
870 ptr_src = gl_image_bytes;
871 y = surface->height;
872 while (y != 0)
873 {
874 --y;
875 ptr_dst = (gate_color_t*)gate_rasterimage_get_line_ptr(&raster, y);
876 for (x = 0; x != surface->width; ++x)
877 {
878 ptr_dst->r = *(ptr_src++);
879 ptr_dst->g = *(ptr_src++);
880 ptr_dst->b = *(ptr_src++);
881 ptr_dst->a = 255;
882 ++ptr_src;
883 ++ptr_dst;
884 }
885 }
886
887 if (target_image)
888 {
889 gate_mem_copy(target_image, &raster, sizeof(raster));
890 gate_mem_clear(&raster, sizeof(raster));
891 }
892
893 ret = GATE_RESULT_OK;
894
895 } while (0);
896
897 gate_rasterimage_release(&raster);
898
899 if (NULL != gl_image_bytes)
900 {
901 gate_mem_dealloc(gl_image_bytes);
902 }
903 return ret;
904 }
905 gate_result_t gate_gl_surface_run_event_loop(gate_gl_surface_t* surface, gate_gl_surface_events_t* event_callbacks, void* user_param)
906 {
907 void* xlib_surface = surface->special_resources[0];
908 gate_xlib_surface_handle_events(xlib_surface, event_callbacks, user_param);
909 return GATE_RESULT_OK;
910 }
911 gate_result_t gate_gl_surface_exit_event_loop(gate_gl_surface_t* surface)
912 {
913 void* xlib_surface = surface->special_resources[0];
914 gate_xlib_surface_cancel_events(xlib_surface);
915 return GATE_RESULT_OK;
916 }
917
918 gate_result_t gate_gl_surface_swap_buffers(gate_gl_surface_t* surface)
919 {
920 EGLSurface egl_surface = (EGLSurface)surface->native_surface;
921 EGLDisplay egl_display = (EGLDisplay)surface->special_resources[1];
922
923 egl.SwapBuffers(egl_display, egl_surface);
924 return true;
925 }
926
927
928
929 #endif
930