c++ - OpenGL Multithreaded sample in Ubuntu virtualbox -
i facing weird problem opengl sample on vbox 3d acceleration enabled
- guest: ubuntu 12.04
- host: windows 7, nvidia graphics
- vbox version 4.3.6 guest additions installed
this application runs on vbox when 3d acceleration disabled , have checked on stand alone linux pc well. when same run 3d acceleration enabled, not able gl function pointers giving errors - function no-op
the app simple, main thread creates 2 threads.
- main thread - create thread 1, create thread 2
- thread 1 - create x-window rendering
- thread 2 - create render thread (draw opengl quad on x-window).
here code sample app.
#include<stdio.h> #include<stdlib.h> #include<x11/x.h> #include<x11/xlib.h> #include<gl/gl.h> #include<gl/glx.h> //#include<gl/glu.h> #include <dlfcn.h> /*dlopen*/ #include <pthread.h> #include <unistd.h> /*sleep*/ display *dpy; display *dpy2; window root; glint att[] = { glx_rgba, glx_depth_size, 24, glx_doublebuffer, none }; xvisualinfo *vi; xvisualinfo *vi2; colormap cmap; xsetwindowattributes swa; window win; glxcontext glc; xwindowattributes gwa; xevent xev; bool render; void drawaquad() { glclearcolor(1.0, 1.0, 1.0, 1.0); glclear(gl_color_buffer_bit | gl_depth_buffer_bit); glmatrixmode(gl_projection); glloadidentity(); glortho(-1., 1., -1., 1., 1., 20.); glmatrixmode(gl_modelview); glloadidentity(); //glulookat(0., 0., 10., 0., 0., 0., 0., 1., 0.); gltranslatef(0.0, 0.0, -10.0); glbegin(gl_quads); glcolor3f(1., 0., 0.); glvertex3f(-.75, -.75, 0.); glcolor3f(0., 1., 0.); glvertex3f( .75, -.75, 0.); glcolor3f(0., 0., 1.); glvertex3f( .75, .75, 0.); glcolor3f(1., 1., 0.); glvertex3f(-.75, .75, 0.); glend(); } void *createmainwindow(void* threadid) { dpy = xopendisplay(null); if(dpy == null) { printf("\n\twindow thread: cannot connect x server\n\n"); exit(0); } root = defaultrootwindow(dpy); printf("\n *** createwindow: xopendisplay on *** \n"); vi = (xvisualinfo*)glxchoosevisual(dpy, 0, att); if(vi == null) { printf("\n\twindow thread: no appropriate visual found\n\n"); exit(0); } else { printf("\n\twindow thread: visual %p selected\n", (void *)vi->visualid); } cmap = xcreatecolormap(dpy, root, vi->visual, allocnone); swa.colormap = cmap; swa.event_mask = exposuremask | keypressmask; win = xcreatewindow(dpy, root, 0, 0, 600, 600, 0, vi->depth, inputoutput, vi->visual, cwcolormap | cweventmask, &swa); xmapwindow(dpy, win); xstorename(dpy, win, "very simple application"); while(1) { xnextevent(dpy, &xev); printf("\nxevent\n"); if(xev.type == expose) { render = true; } else if(xev.type == keypress) { xdestroywindow(dpy, win); xclosedisplay(dpy); render = false; break; //exit(0); } } } void *renderthread(void* threadid) { vi2 = (xvisualinfo*)glxchoosevisual(dpy2, 0, att); printf("\n\trenderthread : visual %p selected\n", (void *)vi2->visualid); glc = (glxcontext)glxcreatecontext(dpy2, vi2, null, gl_true); glxmakecurrent(dpy2, win, glc); glenable(gl_depth_test); while(render) { //xgetwindowattributes(dpy, win, &gwa); glviewport(0, 0, 600, 600); drawaquad(); glxswapbuffers(dpy2, win); } /* closes while(render) */ glxmakecurrent(dpy2, none, null); glxdestroycontext(dpy2, glc); xclosedisplay(dpy2); } int main(int argc, char *argv[]) { render = true; pthread_t thread1; pthread_t thread2; char *temp1; char *temp2; //for async issue if(!xinitthreads()) { fprintf(stderr, "xinitthread failed\n"); return 0; } //create main window int err = pthread_create(&thread1, null, createmainwindow, (void*)temp1); if (err != 0) printf("\n error::can't create thread1 :[%d]", err); else printf("\n thread1 created successfully\n"); sleep(1); // wait thread 1 complete dpy2 = xopendisplay(null); if(dpy2 == null) { printf("\n\tmain : cannot connect x server\n\n"); exit(0); } //create render thread err = pthread_create(&thread2, null, renderthread, (void*)temp2); if (err != 0) printf("\n error::can't create thread2 :[%d]", err); else printf("\n thread2 created successfully\n"); pthread_join( thread1, null); pthread_join( thread2, null); } /* } closes int main(int argc, char *argv[]) { */
and compile code -
g++ -o quad quad.cpp -lgl -lx11 -lxmu -lxi -lpthread -lm
help me understand issue lies
whatever thick you're doing, stop!
multithreading + x11 + opengl tricky thing right. , it's impossible correct if you're using xlib. xlib never thread safe.
anyway, first , foremost program lacks call xinitthreads
make @ least safe use in multithreaded programs. it's still unsafe spread out xlib calls on multiple threads. important: whatever do, keep xlib calls 1 thread only.
opengl not tricky. because opengl needs context created glx, in turn builds on xlib. usual approach create opengl context in xlib thread, later on make current in renderer thread. advised if got indirect rendering context opengl calls go through x11 , may mean through xlib , things going unstable again.
because of mess simplest solution is: keep graphics , windowing related 1 thread. there's nothing gained if put opengl operations thread separate rest of gui operations (technically opengl gui operations well). if want use multithreading, use if thing make sense executed concurrently, audio, physics simulation , such.
Comments
Post a Comment