diff options
Diffstat (limited to 'example')
| -rwxr-xr-x | example/b | 40 | ||||
| -rwxr-xr-x | example/linux | bin | 0 -> 63392 bytes | |||
| -rw-r--r-- | example/linux.c | 308 | ||||
| -rw-r--r-- | example/simple.c | 16 |
4 files changed, 364 insertions, 0 deletions
diff --git a/example/b b/example/b new file mode 100755 index 0000000..4ccb9a4 --- /dev/null +++ b/example/b @@ -0,0 +1,40 @@ +#!/bin/sh + +echorun() +{ + echo $1 + $1 +} + +compile() +{ + echorun "$cc -c $cflags $include $lflags -o $1.o $1.c $libs" +} + +compile_and_link() +{ + echorun "$cc $cflags $include $lflags -o $1 $1.c $libs" +} + +start=`pwd` +dir=`realpath $0` +dir=`dirname $dir` + +echorun "cd $dir" + +if [ "$1" = 'clean' ] ; then + echorun "rm -f *.o linux" + echorun "cd $start" + exit +fi + +cc='gcc' +cflags='-g' + +include="-I../../prb -I../../prge" +lflags="-L../../prb -L../../prge" +libs='-lprb -lprge -lGL -lX11 -lm' + +compile_and_link linux + +echorun "cd $start" diff --git a/example/linux b/example/linux Binary files differnew file mode 100755 index 0000000..f244e76 --- /dev/null +++ b/example/linux diff --git a/example/linux.c b/example/linux.c new file mode 100644 index 0000000..48be3a2 --- /dev/null +++ b/example/linux.c @@ -0,0 +1,308 @@ +#include <GL/glx.h> +#include "types.h" +#include "sys.h" +#include <string.h> +#include <sys/time.h> +#include "gldefs.h" +#include "context.h" + +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 + +typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + +struct xcontext { + Display *dpy; + Window win; + i32 w; + i32 h; + i32 stop; + f64 last_time; + f64 time; + f64 dt; +}; + +static GLXFBConfig +find_best_fbconfig(Display *dpy, i32 *attribs) +{ + i32 fbcount; + GLXFBConfig *fbconfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &fbcount); + if (!fbconfigs) + die("failed to retrieve a framebuffer configs"); + i32 best = 0, best_samples = 0; + for (i32 i = 0; i < fbcount; i++) { + XVisualInfo *vi = glXGetVisualFromFBConfig(dpy, fbconfigs[i]); + if (!vi) + continue; + i32 buffers, samples; + glXGetFBConfigAttrib(dpy, fbconfigs[i], GLX_SAMPLE_BUFFERS, &buffers); + glXGetFBConfigAttrib(dpy, fbconfigs[i], GLX_SAMPLES, &samples); + if (buffers && samples > best_samples) { + best = i; + best_samples = samples; + } + XFree(vi); + } + GLXFBConfig fbconfig = fbconfigs[best]; + XFree(fbconfigs); + return fbconfig; +} + +static GLXContext +create_gl_context(struct xcontext xctx, GLXFBConfig fbconfig) +{ + const char *extensions = glXQueryExtensionsString(xctx.dpy, DefaultScreen(xctx.dpy)); + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB("glXCreateContextAttribsARB"); + if (!strstr(extensions, "GLX_ARB_create_context") || !glXCreateContextAttribsARB) + die("glXCreateContextAttribsARB not found"); + i32 context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + None + }; + GLXContext ctx = glXCreateContextAttribsARB(xctx.dpy, fbconfig, 0, 1, context_attribs); + XFree(fbconfig); + if (!ctx) + die("failed to create gl 3.3 context "); + return ctx; +} + +static f64 +get_time(void) +{ + struct timeval tv; + gettimeofday(&tv, 0); + return (f64)tv.tv_sec + tv.tv_usec / 1000000.0; +} + +#define check_gl_function(f) if (!#f) die("failed to load #f"); + +static void +check_gl_functions(void) +{ + check_gl_function(gl_create_shader); + + if (!gl_create_shader) + die("failed to load glCreateShader"); + if (!gl_clear_color) + die("failed to load glClearColor"); + if (!gl_clear) + die("failed to load glClear"); + if (!gl_viewport) + die("failed to load glViewport"); + if (!gl_gen_vertex_arrays) + die("failed to load glGenVertexArrays"); + if (!gl_delete_vertex_arrays) + die("failed to load glDeleteVertexArrays"); + if (!gl_bind_vertex_array) + die("failed to load glBindVertexArray"); + if (!gl_enable_vertex_attrib_array) + die("failed to load glEnableVertexAttribArray"); + if (!gl_disable_vertex_attrib_array) + die("failed to load glDisableVertexAttribArray"); + if (!gl_vertex_attrib_pointer) + die("failed to load glVertexAttribPointer"); + if (!gl_gen_buffers) + die("failed to load glGenBuffers"); + if (!gl_delete_buffers) + die("failed to load glDeleteBuffers"); + if (!gl_bind_buffer) + die("failed to load glBindBuffer"); + if (!gl_buffer_data) + die("failed to load glBufferData"); + if (!gl_create_shader) + die("failed to load glCreateShader"); + if (!gl_delete_shader) + die("failed to load glDeleteShader"); + if (!gl_shader_source) + die("failed to load glShaderSource"); + if (!gl_compile_shader) + die("failed to load glCompileShader"); + if (!gl_get_shader_iv) + die("failed to load glGetShaderiv"); + if (!gl_get_shader_info_log) + die("failed to load glGetShaderInfoLog"); + if (!gl_create_program) + die("failed to load glCreateProgram"); + if (!gl_attach_shader) + die("failed to load glAttachShader"); + if (!gl_link_program) + die("failed to load glLinkProgram"); + if (!gl_use_program) + die("failed to load glUseProgram"); + if (!gl_get_uniform_location) + die("failed to load glGetUniformLocation"); + if (!gl_uniform_matrix4fv) + die("failed to load glUniformMatrix4fv"); + if (!gl_get_program_iv) + die("failed to load glGetProgramiv"); + if (!gl_get_program_info_log) + die("failed to load glGetProgramInfoLog"); + if (!gl_draw_arrays) + die("failed to load glDrawArrays"); +} + +void +load_gl_functions(void) +{ + gl_clear_color = (void (*)(f32, f32, f32, f32))glXGetProcAddress("glClearColor"); + gl_clear = (void (*)(u32))glXGetProcAddress("glClear"); + + gl_viewport = (void (*)(i32, i32, i32, i32))glXGetProcAddress("glViewport"); + + gl_gen_vertex_arrays = (void (*)(i32, u32 *))glXGetProcAddress("glGenVertexArrays"); + gl_delete_vertex_arrays = (void (*)(i32, const u32 *))glXGetProcAddress("glDeleteVertexArrays"); + gl_bind_vertex_array = (void (*)(u32))glXGetProcAddress("glBindVertexArray"); + gl_enable_vertex_attrib_array = (void (*)(u32))glXGetProcAddress("glEnableVertexAttribArray"); + gl_disable_vertex_attrib_array = (void (*)(u32))glXGetProcAddress("glDisableVertexAttribArray"); + gl_vertex_attrib_pointer = (void (*)(u32, i32, u32, u8, i32, const void *))glXGetProcAddress("glVertexAttribPointer"); + + gl_gen_buffers = (void (*)(i32, u32 *))glXGetProcAddress("glGenBuffers"); + gl_delete_buffers = (void (*)(i32, const u32 *))glXGetProcAddress("glDeleteBuffers"); + gl_bind_buffer = (void (*)(u32, u32))glXGetProcAddress("glBindBuffer"); + gl_buffer_data = (void (*)(u32, i64, const void *, u32))glXGetProcAddress("glBufferData"); + + gl_create_shader = (u32 (*)(u32))glXGetProcAddress("glCreateShader"); + gl_delete_shader = (void (*)(u32))glXGetProcAddress("glDeleteShader"); + gl_shader_source = (void (*)(u32, i32, const char *const *, const i32 *))glXGetProcAddress("glShaderSource"); + gl_compile_shader = (void (*)(u32))glXGetProcAddress("glCompileShader"); + gl_get_shader_iv = (void (*)(u32, u32, i32 *))glXGetProcAddress("glGetShaderiv"); + gl_get_shader_info_log = (void (*)(u32, i32, i32 *, char *))glXGetProcAddress("glGetShaderInfoLog"); + + gl_create_program = (u32 (*)(void))glXGetProcAddress("glCreateProgram"); + gl_attach_shader = (void (*)(u32, u32))glXGetProcAddress("glAttachShader"); + gl_link_program = (void (*)(u32))glXGetProcAddress("glLinkProgram"); + gl_use_program = (void (*)(u32))glXGetProcAddress("glUseProgram"); + + gl_get_uniform_location = (i32 (*)(u32, const char *))glXGetProcAddress("glGetUniformLocation"); + gl_uniform_matrix4fv = (void (*)(i32, i32, u8, const f32 *))glXGetProcAddress("glUniformMatrix4fv"); + gl_get_program_iv = (void (*)(u32, u32, i32 *))glXGetProcAddress("glGetProgramiv"); + gl_get_program_info_log = (void (*)(u32, i32, i32 *, char *))glXGetProcAddress("glGetProgramInfoLog"); + + gl_draw_arrays = (void (*)(u32, i32, i32))glXGetProcAddress("glDrawArrays"); + + check_gl_functions(); +} + +static struct xcontext +xinit(struct prge_context prge, const char *name) +{ + struct xcontext xctx = {0}; + Display *dpy = XOpenDisplay(0); + if (!dpy) + die("failed to open x dpy"); + xctx.dpy = dpy; + i32 major, minor; + if (!glXQueryVersion(dpy, &major, &minor)) + die("failed to get glx version"); + if ((major < 1) || ((major == 1) && (minor < 3))) + die("invalid glx version"); + i32 attribs[] = { + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_DOUBLEBUFFER, True, + None + }; + GLXFBConfig fbconfig = find_best_fbconfig(dpy, attribs); + XVisualInfo *vi = glXGetVisualFromFBConfig(dpy, fbconfig); + XSetWindowAttributes swattribs = {0}; + swattribs.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), + vi->visual, AllocNone); + swattribs.event_mask = StructureNotifyMask | KeyPressMask; + Window root = RootWindow(xctx.dpy, vi->screen); + u32 flags = CWBorderPixel | CWColormap | CWEventMask; + xctx.w = prge.width; + xctx.h = prge.height; + xctx.win = XCreateWindow(xctx.dpy, root, 0, 0, xctx.w, xctx.h, 0, vi->depth, + InputOutput, vi->visual, flags, &swattribs); + if (!xctx.win) + die("failed to create window"); + XFree(vi); + XStoreName(xctx.dpy, xctx.win, name); + XMapWindow(xctx.dpy, xctx.win); + GLXContext glctx = create_gl_context(xctx, fbconfig); + glXMakeCurrent(xctx.dpy, xctx.win, glctx); + load_gl_functions(); + + i32 (*glXGetSwapInterval)(void) = 0; + i32 (*glXSwapInterval)(u32) = 0; + glXGetSwapInterval = (i32 (*)(void))glXGetProcAddressARB("glXGetSwapIntervalMESA"); + glXSwapInterval = (i32 (*)(u32))glXGetProcAddressARB("glXSwapIntervalMESA"); + if (glXGetSwapInterval && glXSwapInterval) { + i32 swap_interval = glXGetSwapInterval(); + info("swap interval %d", swap_interval); + i32 swap = glXSwapInterval(0); + swap_interval = glXGetSwapInterval(); + info("swap %d interval %d", swap, swap_interval); + } else { + info("cannot get swap interval"); + } + + xctx.last_time = get_time(); + return xctx; +} + +void +handle_keyboard(struct xcontext *xctx, i32 code) +{ + switch (code) { + case XK_Escape: + xctx->stop = 1; + break; + } +} + +void +handle_events(struct xcontext *xctx) +{ + while (XPending(xctx->dpy)) { + XEvent ev; + XNextEvent(xctx->dpy, &ev); + switch (ev.type) { + case KeyPress: + handle_keyboard(xctx, XLookupKeysym(&ev.xkey, 0)); + break; + case ConfigureNotify: + info("%d %d", ev.xconfigure.width, ev.xconfigure.height); + gl_viewport(0, 0, ev.xconfigure.width, ev.xconfigure.height); + break; + } + } +} + +static void +update_time(struct xcontext *xctx) +{ + f64 current_time = get_time(); + xctx->dt = current_time - xctx->last_time; + xctx->time += xctx->dt; + xctx->last_time = current_time; +} + +i32 +main(void) +{ + struct prge_context prge = init_prge(800, 600); + struct xcontext xctx = xinit(prge, "loadgl"); + f64 ms = 16.666; + f64 last = get_time(); + f64 dt = 0.0; + while (!xctx.stop) { + handle_events(&xctx); + update_time(&xctx); + info("%f", xctx.dt); + gl_clear_color(0.16f, 0.16f, 0.16f, 1.0f); + gl_clear(gl_color_buffer_bit); + glXSwapBuffers(xctx.dpy, xctx.win); + } + return 0; +} diff --git a/example/simple.c b/example/simple.c new file mode 100644 index 0000000..b53b47b --- /dev/null +++ b/example/simple.c @@ -0,0 +1,16 @@ +void +init(struct prge_context *prge_ctx) +{ +} + +void +update(struct prge_context *prge_ctx, f32 dt) +{ +} + +void +render(struct prge_context prge_ctx) +{ + gl_clear_color(0.18f, 0.18f, 0.18f, 1.0f); + gl_clear(gl_color_buffer_bit); +} |
