Skip to content

Instantly share code, notes, and snippets.

@GlassGhost
Created October 10, 2011 19:23
Show Gist options
  • Save GlassGhost/1276265 to your computer and use it in GitHub Desktop.
Save GlassGhost/1276265 to your computer and use it in GitHub Desktop.
proper use of xcb and opengl involves x11 since most manufacturers only write libs for x11
/* glxcb.c taken from:
http://xcb.freedesktop.org/opengl/
to compile it use :
gcc -std=c99 -Wall glxcb.c -lxcb -lX11 -lGL -lX11-xcb -o glxcb
*/
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
/*
If you get linking errors when using C++, you need
to add extern "C" here or in X11-xcb.h, unless
this bug is already fixed in your version:
http://bugs.freedesktop.org/show_bug.cgi?id=22252
*/
#include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */
#include <xcb/xcb.h>
#include <GL/glx.h>
#include <GL/gl.h>
void draw(){
glClearColor(0.2, 0.4, 0.9, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
}
int main_loop(Display *display, xcb_connection_t *connection, xcb_window_t window, GLXDrawable drawable){
int running = 1;
while(running)
{
/* Wait for event */
xcb_generic_event_t *event = xcb_wait_for_event(connection);
if(!event)
{
fprintf(stderr, "i/o error in xcb_wait_for_event");
return -1;
}
switch(event->response_type & ~0x80)
{
case XCB_KEY_PRESS:
/* Quit on key press */
running = 0;
break;
case XCB_EXPOSE:
/* Handle expose event, draw and swap buffers */
draw();
glXSwapBuffers(display, drawable);
break;
default:
break;
}
free(event);
}
return 0;
}
int setup_and_run(Display* display, xcb_connection_t *connection, int default_screen, xcb_screen_t *screen){
int visualID = 0;
/* Query framebuffer configurations */
GLXFBConfig *fb_configs = 0;
int num_fb_configs = 0;
fb_configs = glXGetFBConfigs(display, default_screen, &num_fb_configs);
if(!fb_configs || num_fb_configs == 0)
{
fprintf(stderr, "glXGetFBConfigs failed\n");
return -1;
}
/* Select first framebuffer config and query visualID */
GLXFBConfig fb_config = fb_configs[0];
glXGetFBConfigAttrib(display, fb_config, GLX_VISUAL_ID , &visualID);
GLXContext context;
/* Create OpenGL context */
context = glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True);
if(!context)
{
fprintf(stderr, "glXCreateNewContext failed\n");
return -1;
}
/* Create XID's for colormap and window */
xcb_colormap_t colormap = xcb_generate_id(connection);
xcb_window_t window = xcb_generate_id(connection);
/* Create colormap */
xcb_create_colormap(
connection,
XCB_COLORMAP_ALLOC_NONE,
colormap,
screen->root,
visualID
);
/* Create window */
uint32_t eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
uint32_t valuelist[] = { eventmask, colormap, 0 };
uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
xcb_create_window(
connection,
XCB_COPY_FROM_PARENT,
window,
screen->root,
0, 0,
150, 150,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
visualID,
valuemask,
valuelist
);
// NOTE: window must be mapped before glXMakeContextCurrent
xcb_map_window(connection, window);
/* Create GLX Window */
GLXDrawable drawable = 0;
GLXWindow glxwindow =
glXCreateWindow(
display,
fb_config,
window,
0
);
if(!window)
{
xcb_destroy_window(connection, window);
glXDestroyContext(display, context);
fprintf(stderr, "glXDestroyContext failed\n");
return -1;
}
drawable = glxwindow;
/* make OpenGL context current */
if(!glXMakeContextCurrent(display, drawable, drawable, context))
{
xcb_destroy_window(connection, window);
glXDestroyContext(display, context);
fprintf(stderr, "glXMakeContextCurrent failed\n");
return -1;
}
/* run main loop */
int retval = main_loop(display, connection, window, drawable);
/* Cleanup */
glXDestroyWindow(display, glxwindow);
xcb_destroy_window(connection, window);
glXDestroyContext(display, context);
return retval;
}
int main(int argc, char* argv[]){
Display *display;
int default_screen;
/* Open Xlib Display */
display = XOpenDisplay(0);
if(!display)
{
fprintf(stderr, "Can't open display\n");
return -1;
}
default_screen = DefaultScreen(display);
/* Get the XCB connection from the display */
xcb_connection_t *connection =
XGetXCBConnection(display);
if(!connection)
{
XCloseDisplay(display);
fprintf(stderr, "Can't get xcb connection from display\n");
return -1;
}
/* Acquire event queue ownership */
XSetEventQueueOwner(display, XCBOwnsEventQueue);
/* Find XCB screen */
xcb_screen_t *screen = 0;
xcb_screen_iterator_t screen_iter =
xcb_setup_roots_iterator(xcb_get_setup(connection));
for(int screen_num = default_screen;
screen_iter.rem && screen_num > 0;
--screen_num, xcb_screen_next(&screen_iter));
screen = screen_iter.data;
/* Initialize window and OpenGL context, run main loop and deinitialize */
int retval = setup_and_run(display, connection, default_screen, screen);
/* Cleanup */
XCloseDisplay(display);
return retval;
}
@Synray
Copy link

Synray commented Jun 3, 2018

I'm trying to write something based off this code, but it doesn't seem to work.
I've narrowed the problem down to xcb_create_colormap, but I'm not sure what the problem is, and there's no documentation for create_colormap. It's also pretty hard to figure out what the function does since the source code is generated.

Has anyone gotten this to work?

@houzhj58
Copy link

houzhj58 commented Sep 6, 2021

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment