PDA

View Full Version : multi head/multi window simple program



advorak
06-09-2015, 04:15 PM
I am trying to create a program like the example on this site under "Programming OpenGL in Linux: GLX and XLib", but with three windows on three different monitors. For some reason the system will not compare the window variables. will work fine with one window since there is no decision to make, but when there are three windows I need to determine which window I should operate on. That's when the if statements die and I get a segmentation fault. Help!

I have tried three times to attach the file, but the system will not upload it. I will include in the message body.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/glu.h>

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.);

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();
}

int main (int argc, char *argv[])
{
Display *display;
XVisualInfo *visual[3];
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
Colormap cmap;
XSetWindowAttributes swa_attributes[3];
XWindowAttributes gwa_attributes[3];
int screen_num;
int i;
unsigned int display_width[3], display_height[3];
Window frame_window[3] = { 0 };
GLXContext glx_ctxt[3];
XKeyEvent event;
display = XOpenDisplay(NULL);

for( i = 0; i < 3; i++ )
{
screen_num = i+1;

if((visual[i] = glXChooseVisual( display, screen_num, att )) == NULL )
{
fprintf( stdout, "No appropriate visual found.\n" );
exit( 0 );
}
else
{
fprintf( stdout, "Visual %p selected.\n", (void*)visual[i]->visualid );
}

cmap = XCreateColormap( display,
XRootWindow(display, screen_num),
visual[i]->visual,
AllocNone );

display_width[i] = DisplayWidth(display, screen_num);
display_height[i] = DisplayHeight(display, screen_num);

swa_attributes[i].colormap = cmap;
swa_attributes[i].event_mask = ExposureMask;
swa_attributes[i].background_pixel = XBlackPixel(display, screen_num);
swa_attributes[i].override_redirect = 1;

/* create the application window */
frame_window[i] = XCreateWindow( display,
XRootWindow(display, screen_num),
0, 0, display_width[i], display_height[i],
0, visual[i]->depth, InputOutput,
visual[i]->visual,
CWColormap|CWEventMask|CWBackPixel|CWOverrideRedir ect,
&swa_attributes[i]);

XMapWindow(display, frame_window[i]);

glx_ctxt[i] = glXCreateContext( display, visual[i], NULL, GL_TRUE );
}

glEnable( GL_DEPTH_TEST );

while ( 1 ) {
XNextEvent(display, (XEvent *)&event);

if( event.window == frame_window[1] )
{
i = 0;
}
else if( event.window == frame_window[1] )
{
i = 1;
}
else if( event.window == frame_window[2] )
{
i = 2;
}
else
{
printf( "Compares failed.\n" );
i = 0;
}

glXMakeCurrent( display, frame_window[i], glx_ctxt[i] );

switch ( event.type ) {
case Expose:
{
XGetWindowAttributes(display, frame_window[i], &gwa_attributes[i]);
glViewport( 0, 0, gwa_attributes[i].width, gwa_attributes[i].height );
DrawAQuad();
glXSwapBuffers( display, frame_window[i] );
break;
}
default:
break;
}
}
return(0);
}

Dark Photon
06-13-2015, 07:03 AM
...when there are three windows I need to determine which window I should operate on. That's when the if statements die and I get a segmentation fault. ...


if( event.window == frame_window[1] )
{
i = 0;
}
else if( event.window == frame_window[1] )
{
i = 1;
}
else if( event.window == frame_window[2] )
{
i = 2;
}
else
{
printf( "Compares failed.\n" );
i = 0;
}


I haven't tried your code yet (not at a Linux box now). But your first frame_window[1] should be [0] above. Not the cause of the seg fault, but nevertheless a bug.

Also, where exactly do you see a segfault?

Dark Photon
06-13-2015, 06:56 PM
I think you want these changes:



--- tst.old.cxx 2015-06-13 20:35:51.535304032 -0500
+++ tst.cxx 2015-06-13 20:48:59.973345849 -0500
@@ -43,8 +43,12 @@

for( i = 0; i < 3; i++ )
{
- screen_num = i+1;
-
+ printf( "Setting up for screen %d\n", i );
+
+ //screen_num = i+1;
+ screen_num = i; // <----------- You're going to want this one
+ //screen_num = DefaultScreen( display );
+
if((visual[i] = glXChooseVisual( display, screen_num, att )) == NULL )
{
fprintf( stdout, "No appropriate visual found.\n" );
@@ -87,7 +91,8 @@
while ( 1 ) {
XNextEvent(display, (XEvent *)&event);

- if( event.window == frame_window[1] )
+ //if( event.window == frame_window[1] )
+ if( event.window == frame_window[0] )
{
i = 0;
}



First, screen numbers in the API are 0-based. So I think you're going to want "screen = i" not "screen == i+1". I only have one screen here, so when I tried the latter it wouldn't even successfully query the visual for that screen (screen 1, because it doesn't exist).

Second, you had a bug in your window matching code where it wasn't looking at frame_window[0].

With those two changes, and forcing "screen_num = DefaultScreen( display )" here (since I only have one screen), it seems to work fine (displays image, without generating any "Compares failed." window matching errors).

Edit: Also, follow GClements advice here:

* Re:value returned by XCreateWindow (https://www.opengl.org/discussion_boards/showthread.php/187094-value-returned-by-XCreateWindow?p=1267710&viewfull=1#post1267710)

Basically use XEvent instead of XKeyEvent.