8 #include "vogl_colorized_console.h"
14 #include <X11/Xutil.h>
17 #include "regex/regex.h"
23 // Store all system info in one place
24 typedef struct RenderContextRec
36 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
37 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
39 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
40 static glXCreateContextAttribsARBProc glXCreateContextAttribsARBFuncPtr;
43 typedef __GLXextFuncPtr (*glXGetProcAddressARBProc)(const GLubyte *procName);
44 static glXGetProcAddressARBProc glXGetProcAddressARBFuncPtr;
46 #warning Using LOAD_LIBGLITRACE path
47 typedef void(GLAPIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
50 #define GL_FUNC(category, ret, name, args, params) typedef ret(*name##_func_ptr_t) args;
51 #define GL_FUNC_VOID(category, name, args, params) typedef void(*name##_func_ptr_t) args;
52 #define GL_EXT(name, major, minor)
58 #define GL_FUNC(category, ret, name, args, params) static name##_func_ptr_t g_##name##_func_ptr;
59 #define GL_FUNC_VOID(category, name, args, params) static name##_func_ptr_t g_##name##_func_ptr;
60 #define GL_EXT(name, major, minor)
66 static void *g_pLib_gl;
71 g_pLib_gl = dlopen("./libvogltrace.so", RTLD_LAZY);
74 fprintf(stderr, "Failed loading libvogltrace.so!\n");
78 glXGetProcAddressARBFuncPtr = (glXGetProcAddressARBProc)dlsym(g_pLib_gl, "gliGetProcAddressRAD");
79 if (!glXGetProcAddressARBFuncPtr)
81 fprintf(stderr, "Failed finding dynamic symbol gliGetProcAddressRAD in libvogltrace.so!\n");
85 #define GL_FUNC(category, ret, name, args, params) \
86 g_##name##_func_ptr = (name##_func_ptr_t) (*glXGetProcAddressARBFuncPtr)((GLubyte *)#name); \
87 if (!g_##name##_func_ptr) \
89 fprintf(stderr, "Failed getting func %s!\n", #name); \
91 #define GL_FUNC_VOID(category, name, args, params) \
92 g_##name##_func_ptr = (name##_func_ptr_t) (*glXGetProcAddressARBFuncPtr)((GLubyte *)#name); \
93 if (!g_##name##_func_ptr) \
95 fprintf(stderr, "Failed getting func %s!\n", #name); \
97 #define GL_EXT(name, major, minor)
103 #define CALL_GL(name) g_##name##_func_ptr
106 #warning Using implicitly loaded libgl path
108 #define CALL_GL(name) name
115 void EarlyInitGLXfnPointers()
118 glXCreateContextAttribsARBFuncPtr = (glXCreateContextAttribsARBProc)CALL_GL(glXGetProcAddressARB)((GLubyte *)"glXCreateContextAttribsARB");
120 //printf("glXCreateContextAttribsARB = %p %p\n", glXCreateContextAttribsARB, &glXCreateContextAttribsARB);
123 //------------------------
125 void CreateWindow(RenderContext *rcx)
127 XSetWindowAttributes winAttribs;
131 XVisualInfo *visualInfo;
133 static int fbAttribs[] =
135 GLX_RENDER_TYPE, GLX_RGBA_BIT,
136 GLX_X_RENDERABLE, True,
137 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
138 GLX_DOUBLEBUFFER, True,
145 EarlyInitGLXfnPointers();
147 // Tell X we are going to use the display
148 rcx->dpy = XOpenDisplay(NULL);
151 CALL_GL(glXQueryVersion)(rcx->dpy, &nMajorVer, &nMinorVer);
152 printf("Supported GLX version - %d.%d\n", nMajorVer, nMinorVer);
154 if (nMajorVer == 1 && nMinorVer < 2)
156 printf("ERROR: GLX 1.2 or greater is necessary\n");
157 XCloseDisplay(rcx->dpy);
161 // Get a new fb config that meets our attrib requirements
162 GLXFBConfig *fbConfigs;
164 fbConfigs = CALL_GL(glXChooseFBConfig)(rcx->dpy, DefaultScreen(rcx->dpy), fbAttribs, &numConfigs);
165 visualInfo = CALL_GL(glXGetVisualFromFBConfig)(rcx->dpy, fbConfigs[0]);
167 // Now create an X window
168 winAttribs.event_mask = ExposureMask | VisibilityChangeMask |
169 KeyPressMask | PointerMotionMask |
172 winAttribs.border_pixel = 0;
173 winAttribs.bit_gravity = StaticGravity;
174 winAttribs.colormap = XCreateColormap(rcx->dpy,
175 RootWindow(rcx->dpy, visualInfo->screen),
176 visualInfo->visual, AllocNone);
177 winmask = CWBorderPixel | CWBitGravity | CWEventMask | CWColormap;
179 rcx->win = XCreateWindow(rcx->dpy, DefaultRootWindow(rcx->dpy), 20, 20,
180 rcx->nWinWidth, rcx->nWinHeight, 0,
181 visualInfo->depth, InputOutput,
182 visualInfo->visual, winmask, &winAttribs);
184 XMapWindow(rcx->dpy, rcx->win);
188 unsigned int width, height;
189 unsigned int border_width;
191 if (XGetGeometry(rcx->dpy, rcx->win, &root, &x, &y, &width, &height, &border_width, &depth) == False)
193 fprintf(stderr, "can't get root window geometry\n");
196 printf("%i %i\n", width, height);
198 // Also create a new GL context for rendering
201 GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
202 GLX_CONTEXT_MINOR_VERSION_ARB, 0,
203 //GLX_CONTEXT_MINOR_VERSION_ARB, 1,
206 rcx->ctx = glXCreateContextAttribsARBFuncPtr(rcx->dpy, fbConfigs[0], 0, True, attribs);
207 Bool status = CALL_GL(glXMakeCurrent)(rcx->dpy, rcx->win, rcx->ctx);
210 fprintf(stderr, "Failed creating GL context!\n");
214 const GLubyte *s = CALL_GL(glGetString)(GL_VERSION);
215 printf("GL Version = %s\n", s);
218 void SetupGLState(RenderContext *rcx)
220 float aspectRatio = rcx->nWinHeight ? (float)rcx->nWinWidth / (float)rcx->nWinHeight : 1.0f;
222 float fYBottom = -fYTop;
223 float fXLeft = fYTop * aspectRatio;
224 float fXRight = fYBottom * aspectRatio;
226 CALL_GL(glViewport)(0, 0, rcx->nWinWidth, rcx->nWinHeight);
227 CALL_GL(glScissor)(0, 0, rcx->nWinWidth, rcx->nWinHeight);
229 CALL_GL(glClearColor)(0.0f, 1.0f, 1.0f, 1.0f);
230 CALL_GL(glClear)(GL_COLOR_BUFFER_BIT);
232 // Clear matrix stack
233 CALL_GL(glMatrixMode)(GL_PROJECTION);
234 CALL_GL(glLoadIdentity)();
235 CALL_GL(glMatrixMode)(GL_MODELVIEW);
236 CALL_GL(glLoadIdentity)();
239 CALL_GL(glFrustum)(fXLeft, fXRight, fYBottom, fYTop, 0.1f, 100.f);
249 // Use a triangle fan with 36 tris for the circle
250 CALL_GL(glBegin)(GL_TRIANGLE_FAN);
252 CALL_GL(glVertex2f)(0.0, 0.0);
253 for (nDegrees = 0; nDegrees < 360; nDegrees += 10)
255 fx = sin((float)nDegrees * PI / 180);
256 fy = cos((float)nDegrees * PI / 180);
257 CALL_GL(glVertex2f)(fx, fy);
259 CALL_GL(glVertex2f)(0.0f, 1.0f);
264 void Draw(RenderContext *rcx)
271 int nLtEyePosX = (rcx->nWinWidth) / 2 - (0.3 * ((rcx->nWinWidth) / 2));
272 int nLtEyePosY = (rcx->nWinHeight) / 2;
273 int nRtEyePosX = (rcx->nWinWidth) / 2 + (0.3 * ((rcx->nWinWidth) / 2));
274 int nRtEyePosY = (rcx->nWinHeight) / 2;
276 double fLtVecMag = 100;
277 double fRtVecMag = 100;
279 // Use the eyeball width as the minimum
280 double fMinLength = (0.1 * ((rcx->nWinWidth) / 2));
282 // Calculate the length of the vector from the eyeball
283 // to the mouse pointer
284 fLtVecMag = sqrt(pow((double)(rcx->nMousePosX - nLtEyePosX), 2.0) +
285 pow((double)(rcx->nMousePosY - nLtEyePosY), 2.0));
287 fRtVecMag = sqrt(pow((double)(rcx->nMousePosX - nRtEyePosX), 2.0) +
288 pow((double)(rcx->nMousePosY - nRtEyePosY), 2.0));
290 // Clamp the minimum magnatude
291 if (fRtVecMag < fMinLength)
292 fRtVecMag = fMinLength;
293 if (fLtVecMag < fMinLength)
294 fLtVecMag = fMinLength;
296 // Normalize the vector components
297 fLeftX = (float)(rcx->nMousePosX - nLtEyePosX) / fLtVecMag;
298 fLeftY = -1.0 * (float)(rcx->nMousePosY - nLtEyePosY) / fLtVecMag;
299 fRightX = (float)(rcx->nMousePosX - nRtEyePosX) / fRtVecMag;
300 fRightY = -1.0 * ((float)(rcx->nMousePosY - nRtEyePosY) / fRtVecMag);
302 CALL_GL(glClear)(GL_COLOR_BUFFER_BIT);
304 // Clear matrix stack
305 CALL_GL(glMatrixMode)(GL_PROJECTION);
306 CALL_GL(glLoadIdentity)();
308 CALL_GL(glMatrixMode)(GL_MODELVIEW);
309 CALL_GL(glLoadIdentity)();
312 CALL_GL(glColor3f)(1.0, 1.0, 1.0);
313 CALL_GL(glScalef)(0.20, 0.20, 1.0);
314 CALL_GL(glTranslatef)(-1.5, 0.0, 0.0);
318 CALL_GL(glColor3f)(0.0, 0.0, 0.0);
319 CALL_GL(glScalef)(0.40, 0.40, 1.0);
320 CALL_GL(glTranslatef)(fLeftX, fLeftY, 0.0);
323 // Draw right eyeball
324 CALL_GL(glColor3f)(1.0, 1.0, 1.0);
325 CALL_GL(glLoadIdentity)();
326 CALL_GL(glScalef)(0.20, 0.20, 1.0);
327 CALL_GL(glTranslatef)(1.5, 0.0, 0.0);
331 CALL_GL(glColor3f)(0.0, 0.0, 0.0);
332 CALL_GL(glScalef)(0.40, 0.40, 1.0);
333 CALL_GL(glTranslatef)(fRightX, fRightY, 0.0);
336 // Clear matrix stack
337 CALL_GL(glMatrixMode)(GL_MODELVIEW);
338 CALL_GL(glLoadIdentity)();
341 CALL_GL(glColor3f)(0.5, 0.0, 0.7);
342 CALL_GL(glScalef)(0.20, 0.20, 1.0);
343 CALL_GL(glTranslatef)(0.0, -1.5, 0.0);
346 CALL_GL(glBegin)(GL_TRIANGLES);
347 CALL_GL(glVertex2f)(0.0, 1.0);
348 CALL_GL(glVertex2f)(-0.5, -1.0);
349 CALL_GL(glVertex2f)(0.5, -1.0);
361 CALL_GL(glVertexPointer)(2, GL_FLOAT, sizeof(float) * 2, verts);
362 CALL_GL(glEnableClientState)(GL_VERTEX_ARRAY);
364 CALL_GL(glDrawArrays)(GL_TRIANGLES, 0, 3);
366 CALL_GL(glDisableClientState)(GL_VERTEX_ARRAY);
367 CALL_GL(glVertexPointer)(4, GL_FLOAT, 0, NULL);
370 // Purposely unset the context to better test the glXSwapBuffers() hook.
371 // This does not work on Mesa 9 with a v2.1 context!
372 //CALL_GL(glXMakeCurrent)(rcx->dpy, None, NULL);
375 CALL_GL(glXSwapBuffers)(rcx->dpy, rcx->win);
377 // Now set the context back.
378 //CALL_GL(glXMakeContextCurrent)(rcx->dpy, rcx->win, rcx->win, rcx->ctx);
381 void Cleanup(RenderContext *rcx)
383 // Unbind the context before deleting
384 CALL_GL(glXMakeCurrent)(rcx->dpy, None, NULL);
386 CALL_GL(glXDestroyContext)(rcx->dpy, rcx->ctx);
389 XDestroyWindow(rcx->dpy, rcx->win);
390 rcx->win = (Window)NULL;
392 XCloseDisplay(rcx->dpy);
396 // TODO: Move this stuff intro voglcore itself
397 #include "vogl_regex.h"
398 #include "vogl_rand.h"
399 #include "vogl_bigint128.h"
400 #include "vogl_sparse_vector.h"
401 #include "vogl_strutils.h"
402 #include "vogl_sort.h"
403 #include "vogl_hash_map.h"
404 #include "vogl_map.h"
405 #include "vogl_timer.h"
406 #include "vogl_md5.h"
407 #include "vogl_rand.h"
408 #include "vogl_introsort.h"
409 #include "vogl_rh_hash_map.h"
410 #include "vogl_object_pool.h"
414 static void print_sep()
416 printf("-------------------------------------------------\n");
419 // TODO: Move this into its own tool.
420 static int run_tests(int argc, char *argv[])
422 VOGL_NOTE_UNUSED(argc);
423 VOGL_NOTE_UNUSED(argv);
425 g_random.seed(12345);
427 uint num_failures = 0;
431 if (!rh_hash_map_test())
433 printf("rh_hash_map_test failed!\n");
438 printf("rh_hash_map_test passed\n");
443 if (!object_pool_test())
445 printf("object_pool_test failed!\n");
450 printf("object_pool_test passed\n");
455 if (!dynamic_string_test())
457 printf("dynamic_string test failed!\n");
462 printf("dynamic_string test passed\n");
467 printf("Running MD5 Test\n");
470 printf("MD5 test failed!\n");
475 printf("MD5 test passed\n");
480 printf("Running introsort test\n");
481 if (!introsort_test())
483 printf("Introsort test failed!\n");
488 printf("Introsort test passed\n");
493 printf("rand test:\n");
494 bool rand_test_results = rand_test();
495 printf("%s\n", rand_test_results ? "Success" : "Failed");
496 num_failures += !rand_test_results;
500 printf("regexp tests:\n");
501 bool regext_test_results = regexp_test();
502 printf("%s\n", regext_test_results ? "Success" : "Failed");
503 num_failures += !regext_test_results;
507 printf("strutils test:\n");
508 bool strutils_test_results = strutils_test();
509 printf("%s\n", strutils_test_results ? "Success" : "Failed");
510 num_failures += !strutils_test_results;
516 map_perf_test(20000);
517 // map_perf_test(200000);
518 // map_perf_test(2000000);
520 printf("skip_list tests:\n");
521 bool map_test_results = map_test();
522 printf("%s\n", map_test_results ? "Success" : "Failed");
523 num_failures += !map_test_results;
527 printf("hash_map tests:\n");
528 bool hashmap_test_results = hash_map_test();
529 printf("%s\n", hashmap_test_results ? "Success" : "Failed");
530 num_failures += !hashmap_test_results;
534 printf("sort tests:\n");
535 bool sort_test_results = sort_test();
536 printf("%s\n", sort_test_results ? "Success" : "Failed");
537 num_failures += !sort_test_results;
541 printf("sparse_vector tests:\n");
542 bool sparse_vector_results = sparse_vector_test();
543 printf("%s\n", sparse_vector_results ? "Success" : "Failed");
544 num_failures += !sparse_vector_results;
548 printf("bigint128 tests:\n");
549 bool bigint_test_results = bigint128_test();
550 printf("%s\n", bigint_test_results ? "Success" : "Failed");
551 num_failures += !bigint_test_results;
556 printf("All tests succeeded\n");
558 fprintf(stderr, "**** %u test(s) failed!\n", num_failures);
560 return num_failures ? EXIT_FAILURE : EXIT_SUCCESS;
563 int main(int argc, char *argv[])
565 colorized_console::init();
566 colorized_console::set_exception_callback();
567 console::set_tool_prefix("(vogltest) ");
570 ((!vogl::vogl_stricmp(argv[1], "-test")) || (!vogl::vogl_stricmp(argv[1], "--test"))))
571 return run_tests(argc, argv);
576 Bool bWinMapped = False;
579 // Set initial window size
581 rcx.nWinHeight = 200;
583 // Set initial mouse position
587 // Setup X window and GLX context
591 // Draw the first frame before checking for messages
594 Atom wmDeleteMessage = XInternAtom(rcx.dpy, "WM_DELETE_WINDOW", False);
595 XSetWMProtocols(rcx.dpy, rcx.win, &wmDeleteMessage, 1);
600 XWindowAttributes winData;
602 // Watch for new X events
603 XNextEvent(rcx.dpy, &newEvent);
605 switch (newEvent.type)
612 case ConfigureNotify:
614 XGetWindowAttributes(rcx.dpy, rcx.win, &winData);
615 rcx.nWinHeight = winData.height;
616 rcx.nWinWidth = winData.width;
620 rcx.nMousePosX = newEvent.xmotion.x;
621 rcx.nMousePosY = newEvent.xmotion.y;
630 if (newEvent.xclient.data.l[0] == (int)wmDeleteMessage)
646 colorized_console::deinit();