1#define GF_EXPOSE_DRAW_PLATFORM
23#ifdef DO_SWAP_INTERVAL
24#ifndef GLX_MESA_swap_control
25#define GLX_MESA_swap_control 1
26typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void);
27typedef void (*PFNGLXSWAPINTERVALMESAPROC)(int);
30#ifndef GLX_EXT_swap_control
31#define GLX_EXT_swap_control 1
32typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*, GLXDrawable, int);
35#ifndef GLX_SGI_swap_control
36#define GLX_SGI_swap_control 1
37typedef void (*PFNGLXSWAPINTERVALSGIPROC)(int);
41void gf_draw_platform_begin(
void) {}
42void gf_draw_platform_end(
void) {}
44int gf_draw_platform_has_extension(
gf_draw_t* draw,
const char* query) {
45 const char* ext = NULL;
47 const int len = strlen(query);
51 ext = glXQueryExtensionsString(draw->
platform->display, DefaultScreen(draw->
platform->display));
52 ptr = strstr(ext, query);
53 return ((ptr != NULL) && ((ptr[len] ==
' ') || (ptr[len] ==
'\0')));
62 XSetWindowAttributes attr;
66 memset(platform, 0,
sizeof(*platform));
67 platform->engine = engine;
69 platform->display = XOpenDisplay(NULL);
70 if(platform->display == NULL) {
72 gf_draw_platform_destroy(platform);
75 attribs[i++] = GLX_RGBA;
76 attribs[i++] = GLX_DOUBLEBUFFER;
78 attribs[i++] = GLX_RED_SIZE;
80 attribs[i++] = GLX_GREEN_SIZE;
82 attribs[i++] = GLX_BLUE_SIZE;
84 attribs[i++] = GLX_DEPTH_SIZE;
89 screen = DefaultScreen(platform->display);
90 root = RootWindow(platform->display, screen);
92 visual = glXChooseVisual(platform->display, screen, attribs);
95 gf_draw_platform_destroy(platform);
99 attr.colormap = XCreateColormap(platform->display, root, visual->visual, AllocNone);
100 attr.event_mask = StructureNotifyMask | ExposureMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
101 platform->window = XCreateWindow(platform->display, root, draw->
width, draw->
height, draw->
width, draw->
height, 0, visual->depth, InputOutput, visual->visual, CWColormap | CWEventMask, &attr);
105 hints.width = draw->
width;
106 hints.height = draw->
height;
107 hints.flags = USSize | USPosition;
108 XSetNormalHints(platform->display, platform->window, &hints);
109 XSetStandardProperties(platform->display, platform->window, draw->
title,
"GoldFish", None, (
char**)NULL, 0, &hints);
111 platform->wm_delete_window = XInternAtom(platform->display,
"WM_DELETE_WINDOW", False);
112 XSetWMProtocols(platform->display, platform->window, &platform->wm_delete_window, 1);
114 platform->context = glXCreateContext(platform->display, visual, NULL, True);
115 if(platform->context == NULL) {
118 gf_draw_platform_destroy(platform);
124 XMapWindow(platform->display, platform->window);
125 glXMakeCurrent(platform->display, platform->window, platform->context);
127#ifdef DO_SWAP_INTERVAL
128 if(gf_draw_platform_has_extension(draw,
"GLX_EXT_swap_control")) {
129 unsigned int tmp = -1;
130 PFNGLXSWAPINTERVALEXTPROC proc = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB(
"glXSwapIntervalEXT");
132 proc(platform->display, platform->window, 1);
134 glXQueryDrawable(platform->display, platform->window, GLX_SWAP_INTERVAL_EXT, &tmp);
136 }
else if(gf_draw_platform_has_extension(draw,
"GLX_MESA_swap_control")) {
137 PFNGLXGETSWAPINTERVALMESAPROC proc = (PFNGLXGETSWAPINTERVALMESAPROC)glXGetProcAddressARB(
"glXGetSwapIntervalMESA");
138 PFNGLXSWAPINTERVALMESAPROC proc2 = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddressARB(
"glXSwapIntervalMESA");
143 }
else if(gf_draw_platform_has_extension(draw,
"GLX_SGI_swap_control")) {
144 PFNGLXSWAPINTERVALSGIPROC proc = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB(
"glXSwapIntervalSGI");
155int gf_draw_platform_step(
gf_draw_t* draw) {
158 while(XPending(draw->
platform->display) > 0) {
160 XNextEvent(draw->
platform->display, &event);
161 if(event.type == Expose) {
163 }
else if(event.type == MotionNotify) {
164 if(draw->
input != NULL) {
168 }
else if(event.type == ConfigureNotify) {
169 draw->
x =
event.xconfigure.x;
170 draw->
y =
event.xconfigure.y;
171 draw->
width =
event.xconfigure.width;
172 draw->
height =
event.xconfigure.height;
174 gf_draw_reshape(draw);
175 }
else if(event.type == ButtonPress) {
176 if(draw->
input != NULL) {
181 }
else if(event.type == ButtonRelease) {
182 if(draw->
input != NULL) {
187 }
else if(event.type == ClientMessage) {
188 if(event.xclient.data.l[0] == draw->
platform->wm_delete_window) {
195 gf_draw_driver_before(draw);
197 gf_draw_driver_after(draw);
205 if(platform->context != NULL) {
206 glXMakeCurrent(platform->display, None, NULL);
207 glXDestroyContext(platform->display, platform->context);
209 if(platform->display != NULL) {
210 XDestroyWindow(platform->display, platform->window);
211 XCloseDisplay(platform->display);
213 gf_log_function(platform->engine,
"Destroyed platform-dependent part of drawing driver",
"");
#define gf_log_function(engine, fmt,...)
Output log with line number and function name.
Required headers before anything.
gf_input_t * input
Input interface.
char title[128]
Window title.
int close
1 if it was requested to be closed, otherwise 0
gf_draw_platform_t * platform
Platform-dependent part of drawing driver.
int width
Width of window.
int height
Height of window.