WIERD glX problem

Im writing a NeHe tutorial on how to use modules (.so and .dll) and how to
separate generic code that works on both OSs from whats not.

Okay here is the problem:
The window never gets created (and YES I am calling create_window()) and
the screen freezes in the create_window() code. However you can still
terminate the app without any probs. The wierd thing is that it sometimes
freezes at different places!

It usually freezes somewhere here, but sometimes a bit futher down:

cout << "Creating glX context
";
    m_ctx = glXCreateContext(a_bp_x11_window.m_display, vi, 0, GL_TRUE);
    //m_ctx = glXCreateContext(m_x11_window->m_display, vi, 0, GL_TRUE);
    // create a color map
    cout << "Creating colormap
";
    cmap = XCreateColormap(m_x11_window->m_display, RootWindow(m_x11_window->m_display, vi->screen),
        vi->visual, AllocNone);
    m_x11_window->m_attr.colormap = cmap;
    m_x11_window->m_attr.border_pixel = 0;

Because of this I suspect that there might be some problem with the linking
or something, but since im not an expert on neither glX or libs I dunno.
Also I know its not a driver problem since I have another program that does
the exact thing (the create_window() code is almost EXACTLY the same)
with the difference that both generic OpenGL and GLX code are in the same
class.

Futhermore I have been able to compile and run the windows version.

There is quite alot of code so here is a quick brief:
I have two final targets: lesson48_linux and renderer_glx.so

lesson48_linux doesnt do much except setting up a X11 loop, loading the
renderer from renderer_glx.so and telling it to start rendering.

Its in renderer_glx.so that everything happens.
Its composed of:
#1: Generic OpenGL that has been tested on windows (renderer_opengl.o)
this does all the actual rendering
#2: GLX code for setting up a glX context and stuff (glx_renderer.o)
Here lies the problem
#3: GLX renderer factory which simply returns a instance of cRenderer_glx
(C++ name mangling thingy)

Given the complexity i doubt anyone can help me but its worth a shoot.

Anyway here is the code (note that there is alot of **** that im going
to remove/fix afterwards like for example texture loading),
all the glX code is at the end so you might want to quickly scroll there.

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>// Main Makefile:
// ->lesson/linux/

CC = g++
LD = g++

CFLAGS = -fPIC -Wall -pedantic -ansi

DYNLINKFLAGS = -fPIC -Wall -pedantic -ansi -shared -rdynamic

default: lesson48_linux

lesson48_linux: lesson48_linux.o
(CC) (CFLAGS) -o lesson48_linux lesson48_linux.o -L/usr/X11R6/lib -lXxf86vm

lesson48_linux.o: lesson48_linux.cc renderer_x11.hpp
(CC) (CFLAGS) -c lesson48_linux.cc

clean:
@echo Cleaning up…
@rm ./lesson48_linux
@rm ./*.o
@echo Done.

// Renderer Makefile:
// ->lesson/linux/glx/

CC = g++
LD = g++

CFLAGS = -fPIC -Wall -pedantic -ansi

DYNLINKFLAGS = -fPIC -Wall -pedantic -ansi -shared -rdynamic

default: renderer_glx.so

#The final module
renderer_glx.so: renderer_opengl.o renderer_glx.o renderer_glx_factory.o
(LD) -o renderer_glx.so renderer_glx.o renderer_opengl.o renderer_glx_factory.o -L/usr/X11R6/lib -lGL -lGLU -lXxf86vm (DYNLINKFLAGS)

#The factory object-file (this will end up in final module and simply return an instance of cRenderer_glx
renderer_glx_factory.o: renderer_glx.o
(CC) -c renderer_glx_factory.cc -o renderer_glx_factory.o (CFLAGS)

renderer_glx.o: renderer_glx.cc renderer_glx.hpp …/renderer_x11.hpp
(CC) -c renderer_glx.cc -o renderer_glx.o (CFLAGS)

#Object-file for generic OpenGL code
renderer_opengl.o: …/…/opengl/renderer_opengl.hpp …/…/opengl/renderer_opengl.cc
(CC) -c ../../opengl/renderer_opengl.cc -o renderer_opengl.o (CFLAGS)

clean:
@echo Cleaning up…
@rm ./.o
@rm ./
.so
@echo Done.

// Lesson48_linux.cc

// ->lesson/linux/

/*

*/

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>

#include <iostream>
using namespace std;

#include <dlfcn.h>

#include “renderer_x11.hpp”

bp_x11_window g_x11_window;
iRenderer_x11 *g_x11_renderer = NULL;

bool g_done = false;

void keyPressed(KeySym a_key)
{
switch (a_key)
{
case XK_Escape:
g_done = true;
break;

    case XK_q:
        g_done = true;
        break;

    case XK_F1:
        g_x11_renderer-&gt;m_kill_window();
        g_x11_window.m_fullscreen = !g_x11_window.m_fullscreen;
        g_x11_renderer-&gt;m_create_x11_window(g_x11_window);
        break;
}

}

int main(int argc, char **argv)
{
XEvent event;
KeySym key;

g_done = false;
// default to fullscreen
g_x11_window.m_fullscreen = false;

void *x11_renderer_lib = dlopen("./glx/renderer_glx.so", RTLD_LAZY);

if (!x11_renderer_lib)
 {
  cout &lt;&lt; "Could not load renderer lib!

";
cout << "Error: " << dlerror() << " .
";
return 1;
}

x11_renderer_factory_ptr *x11_renderer_factory =
 (x11_renderer_factory_ptr*) dlsym(x11_renderer_lib, "renderer_x11_factory");

g_x11_renderer = x11_renderer_factory();

g_x11_window.m_width = 1024;
g_x11_window.m_height = 768;
g_x11_window.m_fullscreen = true;

g_x11_window.m_window_test = 5;

g_x11_renderer-&gt;m_create_x11_window(g_x11_window);

cout &lt;&lt; "m_x11_window-&gt;m_window_test is: " &lt;&lt; g_x11_window.m_window_test &lt;&lt; "

";

XSelectInput(g_x11_window.m_display, g_x11_window.m_win, ExposureMask | PointerMotionMask | ButtonMotionMask);

// wait for events
while (!g_done)
{
    // handle the events in the queue
    while (XPending(g_x11_window.m_display) &gt; 0)
    {
        XNextEvent(g_x11_window.m_display, &event);
        switch (event.type)
        {
			    case MotionNotify:
              //g_x11_renderer-&gt;m_notify_cursor_pos(event.xmotion.x, event.xmotion.y);
				 break;
            case Expose:
                if (event.xexpose.count != 0)
                    break;
                g_x11_renderer-&gt;m_render_frame();
     	        break;
            case ConfigureNotify:
            // call resizeGLScene only if our window-size changed
                if ((event.xconfigure.width != g_x11_window.m_width)

Im writing a NeHe tutorial on how to use modules (.so and .dll) and how to
separate generic code that works on both OSs from whats not.

Okay here is the problem:
The window never gets created (and YES I am calling create_window()) and
the screen freezes in the create_window() code. However you can still
terminate the app without any probs. The wierd thing is that it sometimes
freezes at different places!

It usually freezes somewhere here, but sometimes a bit futher down:

cout << "Creating glX context
";
    m_ctx = glXCreateContext(a_bp_x11_window.m_display, vi, 0, GL_TRUE);
    //m_ctx = glXCreateContext(m_x11_window->m_display, vi, 0, GL_TRUE);
    // create a color map
    cout << "Creating colormap
";
    cmap = XCreateColormap(m_x11_window->m_display, RootWindow(m_x11_window->m_display, vi->screen),
        vi->visual, AllocNone);
    m_x11_window->m_attr.colormap = cmap;
    m_x11_window->m_attr.border_pixel = 0;

Because of this I suspect that there might be some problem with the linking
or something, but since im not an expert on neither glX or libs I dunno.
Also I know its not a driver problem since I have another program that does
the exact thing (the create_window() code is almost EXACTLY the same)
with the difference that both generic OpenGL and GLX code are in the same
class.

Futhermore I have been able to compile and run the windows version.

There is quite alot of code so here is a quick brief:
I have two final targets: lesson48_linux and renderer_glx.so

lesson48_linux doesnt do much except setting up a X11 loop, loading the
renderer from renderer_glx.so and telling it to start rendering.

Its in renderer_glx.so that everything happens.
Its composed of:
#1: Generic OpenGL that has been tested on windows (renderer_opengl.o)
this does all the actual rendering
#2: GLX code for setting up a glX context and stuff (glx_renderer.o)
Here lies the problem
#3: GLX renderer factory which simply returns a instance of cRenderer_glx
(C++ name mangling thingy)

Given the complexity i doubt anyone can help me but its worth a shoot.

Anyway here is the code (note that there is alot of **** that im going
to remove/fix afterwards like for example texture loading),
all the glX code is at the end so you might want to quickly scroll there.

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>// Main Makefile:
// ->lesson/linux/

CC = g++
LD = g++

CFLAGS = -fPIC -Wall -pedantic -ansi

DYNLINKFLAGS = -fPIC -Wall -pedantic -ansi -shared -rdynamic

default: lesson48_linux

lesson48_linux: lesson48_linux.o
(CC) (CFLAGS) -o lesson48_linux lesson48_linux.o -L/usr/X11R6/lib -lXxf86vm

lesson48_linux.o: lesson48_linux.cc renderer_x11.hpp
(CC) (CFLAGS) -c lesson48_linux.cc

clean:
@echo Cleaning up…
@rm ./lesson48_linux
@rm ./*.o
@echo Done.

// Renderer Makefile:
// ->lesson/linux/glx/

CC = g++
LD = g++

CFLAGS = -fPIC -Wall -pedantic -ansi

DYNLINKFLAGS = -fPIC -Wall -pedantic -ansi -shared -rdynamic

default: renderer_glx.so

#The final module
renderer_glx.so: renderer_opengl.o renderer_glx.o renderer_glx_factory.o
(LD) -o renderer_glx.so renderer_glx.o renderer_opengl.o renderer_glx_factory.o -L/usr/X11R6/lib -lGL -lGLU -lXxf86vm (DYNLINKFLAGS)

#The factory object-file (this will end up in final module and simply return an instance of cRenderer_glx
renderer_glx_factory.o: renderer_glx.o
(CC) -c renderer_glx_factory.cc -o renderer_glx_factory.o (CFLAGS)

renderer_glx.o: renderer_glx.cc renderer_glx.hpp …/renderer_x11.hpp
(CC) -c renderer_glx.cc -o renderer_glx.o (CFLAGS)

#Object-file for generic OpenGL code
renderer_opengl.o: …/…/opengl/renderer_opengl.hpp …/…/opengl/renderer_opengl.cc
(CC) -c ../../opengl/renderer_opengl.cc -o renderer_opengl.o (CFLAGS)

clean:
@echo Cleaning up…
@rm ./.o
@rm ./
.so
@echo Done.

// Lesson48_linux.cc

// ->lesson/linux/

/*

*/

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>

#include <iostream>
using namespace std;

#include <dlfcn.h>

#include “renderer_x11.hpp”

bp_x11_window g_x11_window;
iRenderer_x11 *g_x11_renderer = NULL;

bool g_done = false;

void keyPressed(KeySym a_key)
{
switch (a_key)
{
case XK_Escape:
g_done = true;
break;

    case XK_q:
        g_done = true;
        break;

    case XK_F1:
        g_x11_renderer-&gt;m_kill_window();
        g_x11_window.m_fullscreen = !g_x11_window.m_fullscreen;
        g_x11_renderer-&gt;m_create_x11_window(g_x11_window);
        break;
}

}

int main(int argc, char **argv)
{
XEvent event;
KeySym key;

g_done = false;
// default to fullscreen
g_x11_window.m_fullscreen = false;

void *x11_renderer_lib = dlopen("./glx/renderer_glx.so", RTLD_LAZY);

if (!x11_renderer_lib)
 {
  cout &lt;&lt; "Could not load renderer lib!

";
cout << "Error: " << dlerror() << " .
";
return 1;
}

x11_renderer_factory_ptr *x11_renderer_factory =
 (x11_renderer_factory_ptr*) dlsym(x11_renderer_lib, "renderer_x11_factory");

g_x11_renderer = x11_renderer_factory();

g_x11_window.m_width = 1024;
g_x11_window.m_height = 768;
g_x11_window.m_fullscreen = true;

g_x11_window.m_window_test = 5;

g_x11_renderer-&gt;m_create_x11_window(g_x11_window);

cout &lt;&lt; "m_x11_window-&gt;m_window_test is: " &lt;&lt; g_x11_window.m_window_test &lt;&lt; "

";

XSelectInput(g_x11_window.m_display, g_x11_window.m_win, ExposureMask | PointerMotionMask | ButtonMotionMask);

// wait for events
while (!g_done)
{
    // handle the events in the queue
    while (XPending(g_x11_window.m_display) &gt; 0)
    {
        XNextEvent(g_x11_window.m_display, &event);
        switch (event.type)
        {
			    case MotionNotify:
              //g_x11_renderer-&gt;m_notify_cursor_pos(event.xmotion.x, event.xmotion.y);
				 break;
            case Expose:
                if (event.xexpose.count != 0)
                    break;
                g_x11_renderer-&gt;m_render_frame();
     	        break;
            case ConfigureNotify:
            // call resizeGLScene only if our window-size changed
                if ((event.xconfigure.width != g_x11_window.m_width))
                {
                   if((event.xconfigure.height != g_x11_window.m_height))
                    {
                    g_x11_window.m_width = event.xconfigure.width;
                    g_x11_window.m_height = event.xconfigure.height;
                    printf("Resize event

");
g_x11_renderer->m_set_resolution(event.xconfigure.width, event.xconfigure.height);
}
}
break;
// exit in case of a mouse button press
case ButtonPress:
g_done = True;
break;
case KeyPress:
key = XLookupKeysym(&event.xkey, 0);
keyPressed(key);
break;
case KeyRelease:
//key = XLookupKeysym(&event.xkey, 0);
//keyReleased(key);
break;
case ClientMessage:
if (*XGetAtomName(g_x11_window.m_display, event.xclient.message_type) ==
*“WM_PROTOCOLS”)
{
printf("Exiting sanely…
");
g_done = True;
}
break;
default:
break;
}
}
g_x11_renderer->m_render_frame();
}
cout << "Killing X11 window
";
g_x11_renderer->m_kill_window();

cout &lt;&lt; "Releasing X11 renderer

";
g_x11_renderer->m_release();

cout &lt;&lt; "Closing X11 renderer lib

";
dlclose(x11_renderer_lib);

return 0;

}

// Generic Renderer inteface:
// ->lesson/renderer.hpp

// renderer.hpp

#ifndef RENDERER_HPP
#define RENDERER_HPP

#define uint unsigned int

class iRenderer
{
public:
virtual ~iRenderer() { }

virtual bool m_set_resolution(uint a_width, uint a_height) = 0;

virtual bool m_render_frame(void) = 0;
virtual void m_add_cube(float a_pos, float a_size) = 0;
virtual bool m_kill_window(void) = 0;

enum {m_default_screen_width = 1024 };
enum {m_default_screen_height = 768 };
}; // end class iRenderer

#endif // #ifndef RENDERER_HPP

// X11 interface
// ->lesson/linux/
// i_renderer_x11.hpp

#ifndef RENDERER_X11_HPP
#define RENDERER_X11_HPP

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>

#include “…/renderer.hpp”

// X11 window blueprint
class bp_x11_window
{
public:
Display *m_display;
int m_screen_id;
Window m_win;
//GLXContext ctx;
XSetWindowAttributes m_attr;
bool m_fullscreen;
XF86VidModeModeInfo m_deskMode;
int m_x, m_y;
unsigned int m_width, m_height;
unsigned int m_depth;
int m_window_test;
}; // end struct bp_x11_window

class iRenderer_x11 : virtual public iRenderer
{
public:
virtual bool m_pure_virtual(void) { return true; }
virtual bool m_create_x11_window(bp_x11_window &a_bp_x11_window) = 0;
//{ a_bp_x11_window->m_window_test = 6; }

virtual void m_release(void) { delete this; }

}; // end class iRenderer_x11 : virtual public iRenderer

typedef iRenderer_x11* x11_renderer_factory_ptr();

#endif // #ifndef I_RENDERER_X11_HPP

// OpenGL renderer header:
// -> lesson/opengl/renderer_opengl.hpp

// renderer_opengl.hpp

#ifndef RENDERER_OPENGL_HPP
#define RENDERER_OPENGL_HPP

#include “…/renderer.hpp”

#include <iostream>
using namespace std;

#include <stdio.h>
#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>

struct sTextureImage
{
int width;
int height;
unsigned char *data;
};

class cOpenGL_renderer : virtual public iRenderer
{
public:
cOpenGL_renderer() { m_rot = 0.0f; }
virtual bool m_render_frame(void);
virtual void m_add_cube(float a_pos, float a_size);
virtual int m_initGL(void);
virtual int m_load_bmp(char *filename, sTextureImage *texture);
virtual bool m_set_resolution(uint a_width, uint a_height);

protected:
float m_rot;
}; // end class cOpenGL_renderer : public virtual cRenderer

#endif // #ifndef RENDERER_OPENGL_HPP

// renderer_opengl.cc

#include “renderer_opengl.hpp”

bool cOpenGL_renderer::m_render_frame(void)
{
m_rot = m_rot + 0.1f;
if(m_rot > 1.0f)
{ m_rot = 0.0f; }
float red_color, green_color, blue_color = 0.5f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f, 0.0f, -12.0f);

glBegin(GL_QUADS);
glColor3f(red_color, m_rot, blue_color);
glVertex3f(10.0f, -1.0f, 10.0f);
glVertex3f(10.0f, -1.0f, -10.0f);
glVertex3f(-10.0f, -1.0f, -10.0f);
glVertex3f(-10.0f, -1.0f, 10.0f);

glEnd();   

} // end void cOpenGL_renderer::m_render_frame(void)

void cOpenGL_renderer::m_add_cube(float a_pos, float a_size)
{ } // end void cOpenGL_renderer::m_add_cube(float a_pos, float a_size)

int cOpenGL_renderer::m_initGL(void)
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.3f, 0.8f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return 1;
} // end int cOpenGL_renderer::m_initGL(void)

int cOpenGL_renderer::m_load_bmp(char *filename, sTextureImage *texture)
{
// Simple BMP loader I stole from a NeHe Linux port (this way we don’t have to use
// glAux wich nobody seems to like)
FILE *file;
unsigned short int bfType;
long int bfOffBits;
short int biPlanes;
short int biBitCount;
long int biSizeImage;
int i;
unsigned char temp;
// make sure the file is there and open it read-only (binary)
if ((file = fopen(filename, “rb”)) == NULL)
{
printf("File not found : %s
", filename);
return 0;
}
if(!fread(&bfType, sizeof(short int), 1, file))
{
printf("Error reading file!
");
return 0;
}
// check if file is a bitmap
if (bfType != 19778)
{
printf("Not a Bitmap-File!
");
return 0;
}
// get the file size
// skip file size and reserved fields of bitmap file header
fseek(file, 8, SEEK_CUR);
// get the position of the actual bitmap data
if (!fread(&bfOffBits, sizeof(long int), 1, file))
{
printf("Error reading file!
");
return 0;
}
printf("Data at Offset: %ld
", bfOffBits);
// skip size of bitmap info header
fseek(file, 4, SEEK_CUR);
// get the width of the bitmap
fread(&texture->width, sizeof(int), 1, file);
printf("Width of Bitmap: %d
", texture->width);
// get the height of the bitmap
fread(&texture->height, sizeof(int), 1, file);
printf("Height of Bitmap: %d
", texture->height);
// get the number of planes (must be set to 1)
fread(&biPlanes, sizeof(short int), 1, file);
if (biPlanes != 1)
{
printf("Error: number of Planes not 1!
");
return 0;
}
// get the number of bits per pixel
if (!fread(&biBitCount, sizeof(short int), 1, file))
{
printf("Error reading file!
");
return 0;
}
printf("Bits per Pixel: %d
", biBitCount);
if (biBitCount != 24)
{
printf("Bits per Pixel not 24
");
return 0;
}
// calculate the size of the image in bytes
biSizeImage = texture->width * texture->height * 3;
printf("Size of the image data: %ld
", biSizeImage);
texture->data = new unsigned char[biSizeImage]; //malloc(biSizeImage);
// seek to the actual data
fseek(file, bfOffBits, SEEK_SET);
if (!fread(texture->data, biSizeImage, 1, file))
{
printf("Error loading file!
");
return 0;
}
// swap red and blue (bgr -> rgb)
for (i = 0; i < biSizeImage; i += 3)
{
temp = texture->data[i];
texture->data[i] = texture->data[i + 2];
texture->data[i + 2] = temp;
}
return 1;
} // end int cOpenGL_renderer::m_load_bmp(char *filename, sTextureImage *texture)

bool cOpenGL_renderer::m_set_resolution(uint a_width, uint a_height)
{

if (a_height==0

(sorry for second repost but if
there is two vertical lines in the post it get
cut off)

Im writing a NeHe tutorial on how to use modules (.so and .dll) and how to
separate generic code that works on both OSs from whats not.

Okay here is the problem:
The window never gets created (and YES I am calling create_window()) and
the screen freezes in the create_window() code. However you can still
terminate the app without any probs. The wierd thing is that it sometimes
freezes at different places!

It usually freezes somewhere here, but sometimes a bit futher down:

cout << "Creating glX context
";
    m_ctx = glXCreateContext(a_bp_x11_window.m_display, vi, 0, GL_TRUE);
    //m_ctx = glXCreateContext(m_x11_window->m_display, vi, 0, GL_TRUE);
    // create a color map
    cout << "Creating colormap
";
    cmap = XCreateColormap(m_x11_window->m_display, RootWindow(m_x11_window->m_display, vi->screen),
        vi->visual, AllocNone);
    m_x11_window->m_attr.colormap = cmap;
    m_x11_window->m_attr.border_pixel = 0;

Because of this I suspect that there might be some problem with the linking
or something, but since im not an expert on neither glX or libs I dunno.
Also I know its not a driver problem since I have another program that does
the exact thing (the create_window() code is almost EXACTLY the same)
with the difference that both generic OpenGL and GLX code are in the same
class.

Futhermore I have been able to compile and run the windows version.

There is quite alot of code so here is a quick brief:
I have two final targets: lesson48_linux and renderer_glx.so

lesson48_linux doesnt do much except setting up a X11 loop, loading the
renderer from renderer_glx.so and telling it to start rendering.

Its in renderer_glx.so that everything happens.
Its composed of:
#1: Generic OpenGL that has been tested on windows (renderer_opengl.o)
this does all the actual rendering
#2: GLX code for setting up a glX context and stuff (glx_renderer.o)
Here lies the problem
#3: GLX renderer factory which simply returns a instance of cRenderer_glx
(C++ name mangling thingy)

Given the complexity i doubt anyone can help me but its worth a shoot.

Anyway here is the code (note that there is alot of **** that im going
to remove/fix afterwards like for example texture loading),
all the glX code is at the end so you might want to quickly scroll there.

// Main Makefile:
// ->lesson/linux/

CC = g++
LD = g++

CFLAGS = -fPIC -Wall -pedantic -ansi

DYNLINKFLAGS = -fPIC -Wall -pedantic -ansi -shared -rdynamic

default: lesson48_linux

lesson48_linux: lesson48_linux.o
	$(CC) $(CFLAGS) -o lesson48_linux lesson48_linux.o -L/usr/X11R6/lib -lXxf86vm
	
lesson48_linux.o: lesson48_linux.cc renderer_x11.hpp
	$(CC) $(CFLAGS) -c lesson48_linux.cc

clean:
	@echo Cleaning up...
	@rm ./lesson48_linux
	@rm ./*.o
	@echo Done.


// Renderer Makefile:
// ->lesson/linux/glx/

CC = g++
LD = g++

CFLAGS = -fPIC -Wall -pedantic -ansi

DYNLINKFLAGS = -fPIC -Wall -pedantic -ansi -shared -rdynamic

default: renderer_glx.so

#The final module
renderer_glx.so: renderer_opengl.o renderer_glx.o renderer_glx_factory.o
	$(LD) -o renderer_glx.so renderer_glx.o renderer_opengl.o renderer_glx_factory.o -L/usr/X11R6/lib -lGL -lGLU -lXxf86vm $(DYNLINKFLAGS)

#The factory object-file (this will end up in final module and simply return an instance of cRenderer_glx
renderer_glx_factory.o: renderer_glx.o
	$(CC) -c  renderer_glx_factory.cc -o renderer_glx_factory.o $(CFLAGS)

renderer_glx.o: renderer_glx.cc renderer_glx.hpp ../renderer_x11.hpp
	$(CC) -c renderer_glx.cc -o renderer_glx.o $(CFLAGS)

#Object-file for generic OpenGL code
renderer_opengl.o: ../../opengl/renderer_opengl.hpp ../../opengl/renderer_opengl.cc
	$(CC) -c ../../opengl/renderer_opengl.cc -o renderer_opengl.o $(CFLAGS)

clean:
	@echo Cleaning up...
	@rm ./*.o
	@rm ./*.so
	@echo Done.

// Lesson48_linux.cc

// ->lesson/linux/

/*
 * This code was created by Alexander "BBB" Brink 2005 for NeHe
 *
 * Visit NeHe's site at http://nehe.gamedev.net/
 * 
 *
 */
 
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>


#include <iostream>
using namespace std;

#include <dlfcn.h>

#include "renderer_x11.hpp"

bp_x11_window g_x11_window;
iRenderer_x11 *g_x11_renderer = NULL;

bool g_done = false;

void keyPressed(KeySym a_key)
{
    switch (a_key)
    {
        case XK_Escape:
            g_done = true;
            break;

        case XK_q:
            g_done = true;
            break;

        case XK_F1:
            g_x11_renderer->m_kill_window();
            g_x11_window.m_fullscreen = !g_x11_window.m_fullscreen;
            g_x11_renderer->m_create_x11_window(g_x11_window);
            break;
    }
}

int main(int argc, char **argv)
{
    XEvent event;
    KeySym key;
    
    g_done = false;
    // default to fullscreen
    g_x11_window.m_fullscreen = false;

    void *x11_renderer_lib = dlopen("./glx/renderer_glx.so", RTLD_LAZY);

    if (!x11_renderer_lib)
     {
      cout << "Could not load renderer lib!
";
		cout << "Error: " << dlerror() << " .
";
      return 1;
     }

    x11_renderer_factory_ptr *x11_renderer_factory =
     (x11_renderer_factory_ptr*) dlsym(x11_renderer_lib, "renderer_x11_factory");

    g_x11_renderer = x11_renderer_factory();

    g_x11_window.m_width = 1024;
    g_x11_window.m_height = 768;
    g_x11_window.m_fullscreen = true;

    g_x11_window.m_window_test = 5;

    g_x11_renderer->m_create_x11_window(g_x11_window);

    cout << "m_x11_window->m_window_test is: " << g_x11_window.m_window_test << "
";

    XSelectInput(g_x11_window.m_display, g_x11_window.m_win, ExposureMask | PointerMotionMask | ButtonMotionMask);

    // wait for events
    while (!g_done)
    {
        // handle the events in the queue
        while (XPending(g_x11_window.m_display) > 0)
        {
            XNextEvent(g_x11_window.m_display, &event);
            switch (event.type)
            {
				    case MotionNotify:
                  //g_x11_renderer->m_notify_cursor_pos(event.xmotion.x, event.xmotion.y);
					 break;
                case Expose:
	                if (event.xexpose.count != 0)
	                    break;
                    g_x11_renderer->m_render_frame();
         	        break;
	            case ConfigureNotify:
	            // call resizeGLScene only if our window-size changed
	                if ((event.xconfigure.width != g_x11_window.m_width))
	                {
                       if((event.xconfigure.height != g_x11_window.m_height))
                        {
	                    g_x11_window.m_width = event.xconfigure.width;
	                    g_x11_window.m_height = event.xconfigure.height;
                        printf("Resize event
");
	                    g_x11_renderer->m_set_resolution(event.xconfigure.width, event.xconfigure.height);
                       }
	                }
	                break;
                // exit in case of a mouse button press
                case ButtonPress:
                    g_done = True;
                    break;
                case KeyPress:
                    key = XLookupKeysym(&event.xkey, 0);
                    keyPressed(key);
                    break;
                case KeyRelease:
                    //key = XLookupKeysym(&event.xkey, 0);
                    //keyReleased(key);
                    break;
                case ClientMessage:
                    if (*XGetAtomName(g_x11_window.m_display, event.xclient.message_type) == 
                        *"WM_PROTOCOLS")
                    {
                        printf("Exiting sanely...
");
                        g_done = True;
                    }
                    break;
                default:
                    break;
            }
        }
        g_x11_renderer->m_render_frame();
    }
    cout << "Killing X11 window
";
    g_x11_renderer->m_kill_window();

    cout << "Releasing X11 renderer
";
    g_x11_renderer->m_release();

    cout << "Closing X11 renderer lib
";
    dlclose(x11_renderer_lib);

    return 0;
}

// Generic Renderer inteface:
// ->lesson/renderer.hpp

// renderer.hpp

#ifndef _RENDERER_HPP_
#define _RENDERER_HPP_

#define uint unsigned int

class iRenderer
 {
  public:
  virtual ~iRenderer() { }
  
  virtual bool m_set_resolution(uint a_width, uint a_height) = 0;
  
  virtual bool m_render_frame(void) = 0;
  virtual void m_add_cube(float a_pos, float a_size) = 0;
  virtual bool m_kill_window(void) = 0;
  
  enum {m_default_screen_width = 1024 };
  enum {m_default_screen_height = 768 };
 }; // end class iRenderer

#endif // #ifndef _RENDERER_HPP_


// X11 interface
// ->lesson/linux/
// i_renderer_x11.hpp

#ifndef _RENDERER_X11_HPP_
#define _RENDERER_X11_HPP_

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>

#include "../renderer.hpp"

// X11 window blueprint
class bp_x11_window
 {
    public:
    Display *m_display;
    int m_screen_id;
    Window m_win;
    //GLXContext ctx;
    XSetWindowAttributes m_attr;
    bool m_fullscreen;
    XF86VidModeModeInfo m_deskMode;
    int m_x, m_y;
    unsigned int m_width, m_height;
    unsigned int m_depth;
    int m_window_test;
 }; // end struct bp_x11_window

class iRenderer_x11 : virtual public iRenderer
 {
  public:
  virtual bool m_pure_virtual(void) { return true; }
  virtual bool m_create_x11_window(bp_x11_window &a_bp_x11_window) = 0;
   //{ a_bp_x11_window->m_window_test = 6; }

  virtual void m_release(void) { delete this; }

 }; // end class iRenderer_x11 : virtual public iRenderer

typedef iRenderer_x11* x11_renderer_factory_ptr();

#endif // #ifndef _I_RENDERER_X11_HPP_

// OpenGL renderer header:
// -> lesson/opengl/renderer_opengl.hpp

// renderer_opengl.hpp

#ifndef _RENDERER_OPENGL_HPP_
#define _RENDERER_OPENGL_HPP_


#include "../renderer.hpp"

#include <iostream>
using namespace std;

#include <stdio.h>
#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>

struct sTextureImage
 {
    int width;
    int height;
    unsigned char *data;
 };

class cOpenGL_renderer : virtual public iRenderer
 {
  public:
  cOpenGL_renderer() { m_rot = 0.0f; }
  virtual bool m_render_frame(void);
  virtual void m_add_cube(float a_pos, float a_size);
  virtual int  m_initGL(void);
  virtual int  m_load_bmp(char *filename, sTextureImage *texture);
  virtual bool m_set_resolution(uint a_width, uint a_height);
  
  protected:
  float m_rot;
 }; // end class cOpenGL_renderer : public virtual cRenderer

#endif // #ifndef _RENDERER_OPENGL_HPP_



// renderer_opengl.cc

#include "renderer_opengl.hpp"

bool cOpenGL_renderer::m_render_frame(void)
 {
  m_rot = m_rot + 0.1f;
  if(m_rot > 1.0f)
   { m_rot = 0.0f; }
    float red_color, green_color, blue_color = 0.5f;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(-1.5f, 0.0f, -12.0f);


  glBegin(GL_QUADS);
        glColor3f(red_color, m_rot, blue_color);
        glVertex3f(10.0f, -1.0f, 10.0f); 
        glVertex3f(10.0f, -1.0f, -10.0f);
        glVertex3f(-10.0f, -1.0f, -10.0f);
        glVertex3f(-10.0f, -1.0f, 10.0f);
 
    glEnd();   
 } // end void cOpenGL_renderer::m_render_frame(void)

void cOpenGL_renderer::m_add_cube(float a_pos, float a_size)
 { } // end void cOpenGL_renderer::m_add_cube(float a_pos, float a_size)
 
int  cOpenGL_renderer::m_initGL(void)
 {
    glShadeModel(GL_SMOOTH);
    glClearColor(0.0f, 0.3f, 0.8f, 0.0f);
    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    return 1;
 } // end int  cOpenGL_renderer::m_initGL(void)
 
int  cOpenGL_renderer::m_load_bmp(char *filename, sTextureImage *texture)
 {
    // Simple BMP loader I stole from a NeHe Linux port (this way we don't have to use
    // glAux wich nobody seems to like)
    FILE *file;
    unsigned short int bfType;
    long int bfOffBits;
    short int biPlanes;
    short int biBitCount;
    long int biSizeImage;
    int i;
    unsigned char temp;
    // make sure the file is there and open it read-only (binary)
    if ((file = fopen(filename, "rb")) == NULL)
    {
        printf("File not found : %s
", filename);
        return 0;
    }
    if(!fread(&bfType, sizeof(short int), 1, file))
    {
        printf("Error reading file!
");
        return 0;
    }
    // check if file is a bitmap
    if (bfType != 19778)
    {
        printf("Not a Bitmap-File!
");
        return 0;
    }        
    // get the file size
    // skip file size and reserved fields of bitmap file header
    fseek(file, 8, SEEK_CUR);
    // get the position of the actual bitmap data
    if (!fread(&bfOffBits, sizeof(long int), 1, file))
    {
        printf("Error reading file!
");
        return 0;
    }
    printf("Data at Offset: %ld
", bfOffBits);
    // skip size of bitmap info header 
    fseek(file, 4, SEEK_CUR);
    // get the width of the bitmap 
    fread(&texture->width, sizeof(int), 1, file);
    printf("Width of Bitmap: %d
", texture->width);
    // get the height of the bitmap 
    fread(&texture->height, sizeof(int), 1, file);
    printf("Height of Bitmap: %d
", texture->height);
    // get the number of planes (must be set to 1) 
    fread(&biPlanes, sizeof(short int), 1, file);
    if (biPlanes != 1)
    {
        printf("Error: number of Planes not 1!
");
        return 0;
    }
    // get the number of bits per pixel 
    if (!fread(&biBitCount, sizeof(short int), 1, file))
    {
        printf("Error reading file!
");
        return 0;
    }
    printf("Bits per Pixel: %d
", biBitCount);
    if (biBitCount != 24)
    {
        printf("Bits per Pixel not 24
");
        return 0;
    }
    // calculate the size of the image in bytes 
    biSizeImage = texture->width * texture->height * 3;
    printf("Size of the image data: %ld
", biSizeImage);
    texture->data = new unsigned char[biSizeImage]; //malloc(biSizeImage);
    // seek to the actual data
    fseek(file, bfOffBits, SEEK_SET);
    if (!fread(texture->data, biSizeImage, 1, file))
    {
        printf("Error loading file!
");
        return 0;
    }
    // swap red and blue (bgr -> rgb) 
    for (i = 0; i < biSizeImage; i += 3)
    {
        temp = texture->data[i];
        texture->data[i] = texture->data[i + 2];
        texture->data[i + 2] = temp;
    }
    return 1;     
 } // end int  cOpenGL_renderer::m_load_bmp(char *filename, sTextureImage *texture)

bool cOpenGL_renderer::m_set_resolution(uint a_width, uint a_height)
 {
 
   if (a_height==0)											// Prevent A Divide By Zero By
    {
        a_width  = m_default_screen_width;
		a_height = m_default_screen_height;
    }

	glViewport(0,0,a_width,a_height);							// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);							// Select The Projection Matrix
	glLoadIdentity();										// Reset The Projection Matrix

	gluPerspective(45.0f,(GLfloat)a_width/(GLfloat)a_height,0.1f,100.0f);

	glMatrixMode(GL_MODELVIEW);								// Select The Modelview Matrix
	glLoadIdentity();										// Reset The Modelview Matrix     
 } // end bool cOpenGL_renderer:m_set_resolution(uint a_width, uint a_height)





// GLX renderer:
// ->lesson/linux/glx/renderer_glx.hpp

#ifndef _RENDERER_GLX_HPP_
#define _RENDERER_GLX_HPP_

#include "../renderer_x11.hpp"
#include "../../opengl/renderer_opengl.hpp"


#include <iostream>
using namespace std;

#include <stdio.h>
#include <stdlib.h>

#include <GL/glx.h>


class cRenderer_glx : public iRenderer_x11, public cOpenGL_renderer
 {
  protected:
  GLXContext m_ctx;
  bp_x11_window *m_x11_window;

  int m_attrListSgl[10];

  int m_attrListDbl[11];

  public:
  cRenderer_glx();
  virtual bool m_pure_virtual(void) { return false; }
  virtual bool m_create_x11_window(bp_x11_window &a_bp_x11_window);
  virtual bool m_kill_window(void);

  virtual void m_release(void) { delete this; }

 }; // end class cRenderer_glx : virtual public cOpenGL_renderer , public iRenderer_x11

#endif // #ifndef _RENDERER_GLX_HPP_


// renderer_glx.cc

#include "renderer_glx.hpp"

cRenderer_glx::cRenderer_glx()
 {



 } // end cRenderer_glx::cRenderer_glx()

bool cRenderer_glx::m_create_x11_window(bp_x11_window &a_bp_x11_window)
 {
  m_attrListSgl[0] = GLX_RGBA;
  m_attrListSgl[1] = GLX_RED_SIZE;
  m_attrListSgl[2] = 4;
  m_attrListSgl[3] = GLX_GREEN_SIZE;
  m_attrListSgl[4] = 4;
  m_attrListSgl[5] = GLX_BLUE_SIZE;
  m_attrListSgl[6] = 4;
  m_attrListSgl[7] = GLX_DEPTH_SIZE;
  m_attrListSgl[8] = 16;
  m_attrListSgl[9] = None;

  m_attrListDbl[0] = GLX_RGBA;
  m_attrListDbl[1] = GLX_DOUBLEBUFFER;
  m_attrListDbl[2] = GLX_RED_SIZE;
  m_attrListDbl[3] = 4;
  m_attrListDbl[4] = GLX_GREEN_SIZE;
  m_attrListDbl[5] = 4;
  m_attrListDbl[6] = GLX_BLUE_SIZE;
  m_attrListDbl[7] = 4;
  m_attrListDbl[8] = GLX_DEPTH_SIZE;
  m_attrListDbl[9] = 16;
  m_attrListDbl[10] = None;

  m_x11_window = &a_bp_x11_window;
  m_x11_window->m_window_test = 8;

    char* title = "BBB & NeHe's module loading tutorial (linux version)\0";
    int width = m_x11_window->m_width;
    int height = m_x11_window->m_height;
    //int bits = 24;

    XVisualInfo *vi;
    Colormap cmap;
    int dpyWidth, dpyHeight;
    int i;
    int glxMajorVersion, glxMinorVersion;
    int vidModeMajorVersion, vidModeMinorVersion;
    XF86VidModeModeInfo **modes;
    int modeNum;
    int bestMode;
    Atom wmDelete;
    Window winDummy;
    unsigned int borderDummy;
    
    //a_bp_x11_window.m_fullscreen = fullscreenflag;
    // set best mode to current
    bestMode = 0;
    // get a connection
    m_x11_window->m_display = XOpenDisplay(0);
    m_x11_window->m_screen_id = DefaultScreen(m_x11_window->m_display);

    XF86VidModeQueryVersion(m_x11_window->m_display, &vidModeMajorVersion,
        &vidModeMinorVersion);

    //printf("XF86VidModeExtension-Version %d.%d
", vidModeMajorVersion,
    //    vidModeMinorVersion);

    XF86VidModeGetAllModeLines(m_x11_window->m_display, m_x11_window->m_screen_id, &modeNum, &modes);
    // save desktop-resolution before switching modes
    m_x11_window->m_deskMode = *modes[0];
    // look for mode with requested resolution
    for (i = 0; i < modeNum; i++)
    {
        if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height))
        {
            bestMode = i;
        }
    }
    // get an appropriate visual
    vi = glXChooseVisual(m_x11_window->m_display, m_x11_window->m_screen_id, m_attrListDbl);
    if (vi == NULL)
    {
        vi = glXChooseVisual(m_x11_window->m_display, m_x11_window->m_screen_id, m_attrListSgl);
        cout << "Only Singlebuffered Visual!
";
    }
    else
    {
        cout << "Got Doublebuffered Visual!
";
    }
    cout << "Running glXQueryVersion
";
    // Here is where the trouble starts ------------------------------------
    // -----------------------------------------------------------------
    // ------------------------------------------------------
  
    cout << "Lalalala....
";
    glXQueryVersion(m_x11_window->m_display, &glxMajorVersion, &glxMinorVersion);
    //printf("glX-Version %d.%d
", glxMajorVersion, glxMinorVersion);
    // create a GLX context
    cout << "Creating glX context
";
    m_ctx = glXCreateContext(a_bp_x11_window.m_display, vi, 0, GL_TRUE);
    //m_ctx = glXCreateContext(m_x11_window->m_display, vi, 0, GL_TRUE);
    // create a color map
    cout << "Creating colormap
";
    cmap = XCreateColormap(m_x11_window->m_display, RootWindow(m_x11_window->m_display, vi->screen),
        vi->visual, AllocNone);
    m_x11_window->m_attr.colormap = cmap;
    m_x11_window->m_attr.border_pixel = 0;

    if (m_x11_window->m_fullscreen)
    {
		  cout << "Using fullscreen mode
";
        XF86VidModeSwitchToMode(m_x11_window->m_display, m_x11_window->m_screen_id, modes[bestMode]);
        XF86VidModeSetViewPort(m_x11_window->m_display, m_x11_window->m_screen_id, 0, 0);
        dpyWidth = modes[bestMode]->hdisplay;
        dpyHeight = modes[bestMode]->vdisplay;
        //printf("Resolution %dx%d
", dpyWidth, dpyHeight);
        XFree(modes);
    
        // create a fullscreen window
        m_x11_window->m_attr.override_redirect = true;
        m_x11_window->m_attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
            StructureNotifyMask;
        m_x11_window->m_win = XCreateWindow(m_x11_window->m_display, RootWindow(m_x11_window->m_display, vi->screen),
            0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
            CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
            &m_x11_window->m_attr);
        XWarpPointer(m_x11_window->m_display, None, m_x11_window->m_win, 0, 0, 0, 0, 0, 0);
		XMapRaised(m_x11_window->m_display, m_x11_window->m_win);
        XGrabKeyboard(m_x11_window->m_display, m_x11_window->m_win, True, GrabModeAsync,
            GrabModeAsync, CurrentTime);
        XGrabPointer(m_x11_window->m_display, m_x11_window->m_win, True, ButtonPressMask,
            GrabModeAsync, GrabModeAsync, m_x11_window->m_win, None, CurrentTime);
    }
    else
    {
        // create a window in window mode
		  cout << "Using windowed mode
";
        m_x11_window->m_attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
            StructureNotifyMask;
        m_x11_window->m_win = XCreateWindow(m_x11_window->m_display, RootWindow(m_x11_window->m_display, vi->screen),
            0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
            CWBorderPixel | CWColormap | CWEventMask, &m_x11_window->m_attr);
        // only set window title and handle wm_delete_events if in windowed mode
        wmDelete = XInternAtom(m_x11_window->m_display, "WM_DELETE_WINDOW", true);
        XSetWMProtocols(m_x11_window->m_display, m_x11_window->m_win, &wmDelete, 1);
        XSetStandardProperties(m_x11_window->m_display, m_x11_window->m_win, title,
            title, None, NULL, 0, NULL);
        XMapRaised(m_x11_window->m_display, m_x11_window->m_win);
    }       
    // connect the glx-context to the window
    glXMakeCurrent(m_x11_window->m_display, m_x11_window->m_win, m_ctx);
    XGetGeometry(m_x11_window->m_display, m_x11_window->m_win, &winDummy, &m_x11_window->m_x, &m_x11_window->m_y,
        &m_x11_window->m_width, &m_x11_window->m_height, &borderDummy, &m_x11_window->m_depth);
    //printf("Depth %d
", GLWin.depth);
    if (glXIsDirect(m_x11_window->m_display, m_ctx)) 
        { } //printf("Congrats, you have Direct Rendering!
");
    else
      { } // printf("Sorry, no Direct Rendering possible!
");
    m_initGL();
    return true;    
 } // end bool cRenderer_glx::m_create_x11_window(bp_x11_window &a_bp_x11_window)

bool cRenderer_glx::m_kill_window(void)
 {
   if (m_ctx)
    {
        if (!glXMakeCurrent(m_x11_window->m_display, None, NULL))
        {
            //printf("Could not release drawing context.
");
        }
        glXDestroyContext(m_x11_window->m_display, m_ctx);
        m_ctx = NULL;
    }
    /* switch back to original desktop resolution if we were in fs */
    if (m_x11_window->m_fullscreen)
    {
        XF86VidModeSwitchToMode(m_x11_window->m_display, m_x11_window->m_screen_id, &m_x11_window->m_deskMode);
        XF86VidModeSetViewPort(m_x11_window->m_display, m_x11_window->m_screen_id, 0, 0);
    }
    XCloseDisplay(m_x11_window->m_display);
    return true;
 } // end bool cRenderer_glx::m_kill_window(void)



// glx_renderer_factory.cc
// ->lesson/linux/glx/
// This ens up in the final .so and simply returns a cRenderer_glx instance.
#include "renderer_glx.hpp"

extern "C" iRenderer_x11* renderer_x11_factory()
 {
  return new cRenderer_glx;
 } // end extern "C" iRenderer_x11* renderer_x11_factory()

During mine development time ive learned
that a single line - glXSwapBuffers(…); -
can have a huge difference.
hits his head into the table multiple times
Oh well atleast it works :stuck_out_tongue: .

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.