Multiple OpenGLX rendering contexts fail on Linux with proprietary Nvidia Drivers - c++

When I try to run over 128 current OpenGLX rendering contexts on individual threads, the call to glXMakeCurrent starts failing.
Display *display = XOpenDisplay(":0")
Window root_win = RootWindow(display, screen);
Window win = XCreateWindow (display, root_win, ...)
GLXContext context = glXCreateContext(display, visinfo, 0, True);
glXMakeCurrent(display, win, context); <---- Fails here on 128th
This issue only occurs with proprietary Nvidia drivers and Nvidia GPUs. I was not able to reproduce with Intel GPUs.
Reproduction code glx.cpp:
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <string.h>
#include <unistd.h>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <chrono>
#define MAX_CONTEXTS 200;
std::mutex mutex;
std::condition_variable cond;
bool will_stop = false;
int numSuccessfulContexts = 0;
#define EXIT_IF(condition, ...) if (condition) { printf(__VA_ARGS__); exit(EXIT_FAILURE);}
#define RETURN_IF(condition, ...) if (condition) { printf(__VA_ARGS__); stop(); return; }
void stop() {
std::lock_guard<std::mutex> lk(mutex);
will_stop = true;
cond.notify_all();
}
void createWindow() {
/* Init X and GLX */
Display *display = XOpenDisplay(":0.0");
RETURN_IF(!display, "Cannot open X display\n");
int screen = DefaultScreen(display);
Window root_win = RootWindow(display, screen);
RETURN_IF(!glXQueryExtension(display, 0, 0),"X Server doesn't support GLX extension\n");
/* Pick an FBconfig and visual */
static const int attributeList[] = { None };
int fbcount;
GLXFBConfig *fbconfig = glXChooseFBConfig(display, screen, attributeList, &fbcount);
EXIT_IF(!fbconfig, "Failed to get GLXFBConfig\n");
XVisualInfo *visinfo = glXGetVisualFromFBConfig(display, *fbconfig);
EXIT_IF(!visinfo, "Failed to get XVisualInfo\n");
/* Create the X window */
XSetWindowAttributes winAttr ;
winAttr.colormap = XCreateColormap(display, root_win, visinfo->visual, AllocNone);
unsigned int mask = CWColormap;
Window win = XCreateWindow (display, root_win, 256, 64, 320, 320, 0,
visinfo->depth, InputOutput, visinfo->visual, mask, &winAttr) ;
/* Create an OpenGL context and attach it to our X window */
GLXContext context = glXCreateContext(display, visinfo, 0, True);
EXIT_IF(!context, "Could not create GL context\n");
RETURN_IF(! glXMakeCurrent(display, win, context), "glXMakeCurrent failed 1. \n");
RETURN_IF(!glXIsDirect (display, glXGetCurrentContext()), "Indirect GLX rendering context obtained\n");
RETURN_IF(!glXMakeCurrent(display, win, context), "glXMakeCurrent failed 2.\n");
numSuccessfulContexts++;
std::unique_lock<std::mutex> lk(mutex);
cond.wait(lk, [] {return will_stop;});
}
int main(int argc, char *argv[]) {
std::vector<std::thread> ts;
printf("Starting, your computer might become unresponsive...\n");
int maxContexts = MAX_CONTEXTS;
while (maxContexts--) {
ts.push_back(std::thread(&createWindow));
}
{
std::unique_lock<std::mutex> lk(mutex);
cond.wait_for(lk, std::chrono::seconds(10), []{return will_stop;});
}
if (!will_stop) {
stop();
}
for (auto& v: ts) {
v.join();
}
printf("Done. Max concurrent contexts: %d\n", numSuccessfulContexts);
return EXIT_SUCCESS;
}
Build & Run:
g++ -std=c++11 glx.cpp -L/usr/lib/nvidia-375 -lGL -lX11 -lGLU -lGLX -lpthread -o glx && ./glx

As discussed in the comments, it seems you're hitting a driver limitation because you're doing something highly unusual and unexpected. I'm answering this to remove it from the list of unanswered questions.

Related

Raspberry Pi OGLES setup

A very easy/hard question.
What packages do i need to download to be able to create a simple X11 window with an EGL/OpenGLES contex.
As i have today the the problem with dri2 failing to authenticate.
But it can’t be that i link to the wrong library else it wouldn’t accept the X11 window at all at eglGetDisplay.
I really don’t want to use any library like glfw or sdl (wrapper
wrapper).
I use raspbian stretch with the default full KMS(driver by VMWare).
My Code is(if it matter's):
#include <X11/Xlib.h>
#include <EGL/egl.h>
#include <EGL/eglplatform.h>
#include <GLES2/gl2.h>
#include <iostream>
struct Pane {
Window win;
Display *display;
Atom windowDeletMessage;
int x11_file;
EGLDisplay egl_display;
EGLContext egl_context;
EGLSurface egl_surface;
EGLConfig egl_config;
EGLint egl_num_config;
EGLint egl_minor;
EGLint egl_major;
};
void setup_window(Pane &self) {
self.display = XOpenDisplay(nullptr);
if (self.display == nullptr) {
exit(0);
}
auto s = DefaultScreen(self.display);
self.win = XCreateSimpleWindow(self.display,
RootWindow(self.display, s),
10,
10,
800,
600,
1,
BlackPixel(self.display, s),
WhitePixel(self.display, s));
self.windowDeletMessage = XInternAtom(self.display, "WM_DELETE_WINDOW", false);
XSetWMProtocols(self.display, self.win, &self.windowDeletMessage, 1);
XStoreName(self.display, self.win, "Default Window");
XSelectInput(self.display,self.win, KeyPressMask | KeyReleaseMask | LeaveWindowMask | EnterWindowMask | PointerMotionMask | ResizeRedirectMask);
XMapWindow(self.display, self.win);
XFlush(self.display);
self.x11_file = ConnectionNumber(self.display);
}
void GetEvent(Pane &self, XEvent &e) {
// Event handling...
}
void setup_egl(Pane &self)
{
const EGLint Attributes[] = //Note to much is to much
{
EGL_RED_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_BLUE_SIZE,8,
EGL_ALPHA_SIZE,8,
EGL_NONE,
};
self.egl_display = eglGetDisplay(self.display);
if(self.egl_display == EGL_NO_DISPLAY)
{
printf("EGL Failed to Obtain Window!") // Note this is not Error handling!
exit(103);
}
if(eglInitialize(self.egl_display,&self.egl_major,&self.egl_minor) == EGL_FALSE)
{
printf("EGL Failed to Initzialize!""");
exit(104);
};
eglChooseConfig(self.egl_display, Attributes, &self.egl_config, 1, &self.egl_num_config);
self.egl_context = eglCreateContext(self.egl_display, self.egl_config,EGL_NO_CONTEXT,nullptr);
self.egl_surface = eglCreateWindowSurface(self.egl_display, self.egl_config, self.win, nullptr);
eglMakeCurrent(self.egl_display, self.egl_surface, self.egl_surface, self.egl_context);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
eglSwapBuffers(self.display, self.egl_surface);
}
int main(int argc, char **argv) {
Pane pane;
setup_window(pane);
setup_egl(pane);
XEvent e;
while (true) {
GetEvent(pane, e);
glClear(GL_COLOR_BUFFER_BIT);
}
}
Edit:
As i used an USB-Drive to boot and not the SD Card. So raspi-config couldn't access the config file on the SD Card and a such it could not enable full KMS.

Visual Studio 2013 and OpenGL

I have recently purchased a new laptop and got a new version of VS from my school. And I'm having a little trouble setting up my libraries.
I created a basic SDL_Window, as well as a SDL_GLContext.
I'm able to include my libraries and run the program, but I can't call functions like glClearColor, or glGetString(GL_VERSION). I get a rather strage warning and an error that I have never seen before, I'm guessing it's related to the 2013 version?
I have tried ignoring all specific default libraries, as well as trying to change the programtype (Multithreaded DLL, those 4).
And I have made sure all the dll-files are in place in my system folder.
What makes me wonder is the fact that glewInit() works, but not glClearColor() etc...
Output:
1>MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib'
conflicts with use of other libs; use /NODEFAULTLIB:library
1>Window.obj : error LNK2019: unresolved external symbol
__imp__glClearColor#16 referenced in function "public: void __thiscall Window::initOpenGL(void)" (?initOpenGL#Window##QAEXXZ)
1>C:\Users\Aleksander\documents\visual studio 2013\Projects\OpenGL
Test\Debug\OpenGL Test.exe : fatal error LNK1120: 1 unresolved
externals
Header:
#pragma once
#include <SDL.h> //Tested OK
#include <SDL_image.h> //Tested OK
#include <SDL_mixer.h> //Tested OK
#include <SDL_net.h> //Tested OK
#include <OpenGL\glew.h> //?
#include <freeglut\freeglut.h> //?
#include <gl\GL.h> //?
#include <glm\glm.hpp> //Tested OK
#include <iostream> //Standard OK
#include <Box2D\Box2D.h> //Tested OK
using namespace std;
class Window {
SDL_Window *window;
SDL_GLContext context;
bool quit;
public:
Window();
~Window();
void initSDL();
void initOpenGL();
void run();
};
Source:
#include "Window.h"
Window::Window() {
printf("Starting window...\n");
//Initialize window
quit = false;
initSDL();
initOpenGL();
//Run window
run();
}
Window::~Window() {
printf("Closing window...\n");
//Clear window memory
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
//Close window library
SDL_Quit();
}
void Window::initSDL() {
if (SDL_Init(SDL_INIT_EVERYTHING) == -1) {
quit = true;
printf("Unable to initialize SDL!\n");
}
else {
//Create window
const char *title = "OpenGL Test";
int pos = SDL_WINDOWPOS_CENTERED;
int w = 800;
int h = 600;
Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
window = SDL_CreateWindow(title, pos, pos, w, h, flags);
//Create OpenGL context
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
context = SDL_GL_CreateContext(window);
}
}
void Window::initOpenGL() {
GLenum init = glewInit();
if (init != GLEW_OK) {
quit = true;
printf("Unable to initialize OpenGL!\n");
printf("Error: %s!\n", glewGetErrorString(init));
}
else {
//printf("Vendor: %s\n", glGetString(GL_VENDOR));
//printf("Version: %s\n", glGetString(GL_VERSION));
//printf("Renderer: %s\n", glGetString(GL_RENDERER));
}
}
void Window::run() {
printf("Window started running!\n");
SDL_Event event;
while (!quit) {
SDL_GL_SwapWindow(window);
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
}
}

OS X Mavericks OpenGL/X11 C code compiling error

I have problem with compiling c code which worked earlier before updating o OS X Mavericks.
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xutil.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
char WINDOW_NAME[] = "Graphics Window";
char ICON_NAME[] = "Icon";
Display *display;
int screen;
Window main_window;
unsigned long foreground, background;
static int snglBuf[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 12, None};
static int dblBuf[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 12,GLX_DOUBLEBUFFER, None};
Bool doubleBuffer = True;
XVisualInfo *vi;
GLXContext cx;
Colormap cmap;
XSetWindowAttributes swa;
Bool recalcModelView = True;
int dummy;
void connectX()
{
display = XOpenDisplay(NULL);
if (display == NULL) {fprintf(stderr, "Cannot connect to X\n");
exit(1);}
screen = DefaultScreen(display);
if (!glXQueryExtension(display, &dummy, &dummy)){
fprintf(stderr, "X server has no OpenGL GLX Extension\n");
exit(1);}
vi = glXChooseVisual(display, screen, dblBuf);
if (vi == NULL){
fprintf(stderr, "Double Buffering not available\n");
vi = glXChooseVisual(display, screen, snglBuf);
if (vi == NULL) fprintf(stderr, "No RGB Visual with depth buffer\n");
doubleBuffer = False;
}
if (doubleBuffer == True) fprintf(stderr, "We have double buffering\n");
if (vi->class != TrueColor){
fprintf(stderr, "Need a TrueColor visual\n");
exit(1);
}
cx = glXCreateContext(display, vi , None, True);
if (cx == NULL){
fprintf(stderr, "No rendering context\n");
exit(1);
}
else printf(stderr, "We have a rendering context\n");
cmap = XCreateColormap(display, RootWindow(display, vi->screen),
vi->visual, AllocNone);
if (cmap == NULL){
fprintf(stderr, "Color map is not available\n");
exit(1);
}
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
KeyPressMask;
}
Window openWindow(int x, int y, int width, int height,
int border_width, int argc, char** argv)
{
XSizeHints size_hints;
Window new_window;
new_window = XCreateWindow(display, RootWindow(display, vi->screen),
x,y, width, height, border_width, vi->depth, InputOutput,
vi->visual, CWBorderPixel | CWColormap | CWEventMask,
&swa);
size_hints.x = x;
size_hints.y = y;
size_hints.width = width;
size_hints.height = height;
size_hints.flags = PPosition | PSize;
XSetStandardProperties(display, new_window, WINDOW_NAME, ICON_NAME,
None, argv, argc, &size_hints);
XSelectInput(display, new_window, (ButtonPressMask | KeyPressMask |
StructureNotifyMask | ExposureMask));
return (new_window);
}
void init(void)
{
const GLubyte *renderer = glGetString(GL_RENDERER);
const GLubyte *vendor = glGetString(GL_VENDOR);
const GLubyte *version = glGetString(GL_VERSION);
const GLubyte *glslversion = glGetString(GL_SHADING_LANGUAGE_VERSION);
GLint major, minor;
//glGetIntegerv(GL_MAJOR_VERSION, &major);
//glGetIntegerv(GL_MINOR_VERSION, &minor);
printf("GL_VENDOR : %s\n", vendor);
printf("GL_RENDERER : %s\n", renderer);
printf("GL_VERSION (string) : %s\n", version);
//printf("GL_VERSION (int) : %d.%d\n", major, minor);
printf("GLSL Version : %s\n", glslversion);
}
void disconnectX()
{
XCloseDisplay(display);
exit(0);
}
void doKeyPressEvent(XKeyEvent *pEvent)
{
int key_buffer_size = 10;
char key_buffer[9];
XComposeStatus compose_status;
KeySym key_sym;
XLookupString(pEvent, key_buffer, key_buffer_size,
&key_sym, &compose_status);
switch(key_buffer[0]){
case 'q':
exit(0);
break;
}
}
void redraw(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glBegin(GL_POLYGON);
glColor3f(1.0,0.0,0.0);
glVertex2f(-0.9,-0.9);
glColor3f(0.0,1.0,0.0);
glVertex2f(0.9,-0.9);
glColor3f(0.0,0.0,1.0);
glVertex2f(0.0,0.9);
glEnd();
if (doubleBuffer) glXSwapBuffers(display,main_window); else
glFlush();
fprintf(stderr, "redraw called\n");
}
void doButtonPressEvent(XButtonEvent *pEvent)
{
fprintf(stderr, "Mouse button pressed\n");
}
int main (int argc, char** argv){
XEvent event;
connectX();
main_window = openWindow(10,20,500,400,5, argc, argv);
glXMakeCurrent(display, main_window, cx);
XMapWindow(display, main_window);
glClear(GL_COLOR_BUFFER_BIT);
init();
/*glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0,1.0, -1.0, 1.0,0.0,10.0);*/
while(1){
do{
XNextEvent(display, &event);
switch (event.type){
case KeyPress:
doKeyPressEvent(&event);
break;
case ConfigureNotify:
glViewport(0,0, event.xconfigure.width, event.xconfigure.height);
case Expose:
redraw();
break;
case ButtonPress:
doButtonPressEvent(&event);
break;
}
}
while (True); //XPending(display));
}
}
I get this error:
ld: symbol(s) not found for architecture x86_64 clang: error: linker
command failed with exit code 1 (use -v to see invocation)
I've already install XQuartz and I'm using -I/opt/X11/include and -L/opt/X11/lib.
OpenGL programs which don't use X11 work perfectly.
#Giorgi Shavgulidze, I think my issue is similar. I had code that compiled fine with Mountain Lion. I upgraded to Mavericks. I go to recompile the code with Mavericks and Xcode 5.0.2, and glEnable(GL_SMOOTH) is causing an error. I just commented the line out and everything is fine. Why I do not know...
I know this is probably a little late for you, however, I believe this may help someone else.
I recently had essentially the exact same problem. It is important to note the difference between including something and linking to it in regards to compiling c code through methods such as gcc, as Andon mentioned above. A good SO post about this can be found here.
Your postbin shows that you are not linking properly to both OpenGL and X11. To link to them, you need to add links to your gcc command. My understanding is that you can either link to them through another path specific to your computer, via -L, or you can use pre-made links in your gcc command, which seems to be the far simpler option.
In regards to X11, while you do link to the directory holding the X11 libraries via -L/opt/X11/lib, you do not specify which library(s) you want to use. I believe the additional link you would need for X11 is -lX11.
In regards to OpenGL, you would use a different flag. While I have not used OpenGL (only used GL), my understanding is these are the appropriate flags you would have to use: -lGLU -lglut.
It is also important to note that order matters when linking and libraries should always go last.
I have included my gcc command, even though it is slightly different than what you would need, as an example.
gcc -I/opt/X11/include -L/opt/X11/lib -lX11 -lncurses -lGL spitmat8w_3.c -o hello

How to simulate a mouse movement

How can I simulate a mouse event causing the pointer to move 500 pixels to the left, then click using C++. How would I do something like this?
Here's some modified Win32 code I had lying around:
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
#define X 123
#define Y 123
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 800
void MouseSetup(INPUT *buffer)
{
buffer->type = INPUT_MOUSE;
buffer->mi.dx = (0 * (0xFFFF / SCREEN_WIDTH));
buffer->mi.dy = (0 * (0xFFFF / SCREEN_HEIGHT));
buffer->mi.mouseData = 0;
buffer->mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
buffer->mi.time = 0;
buffer->mi.dwExtraInfo = 0;
}
void MouseMoveAbsolute(INPUT *buffer, int x, int y)
{
buffer->mi.dx = (x * (0xFFFF / SCREEN_WIDTH));
buffer->mi.dy = (y * (0xFFFF / SCREEN_HEIGHT));
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);
SendInput(1, buffer, sizeof(INPUT));
}
void MouseClick(INPUT *buffer)
{
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN);
SendInput(1, buffer, sizeof(INPUT));
Sleep(10);
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP);
SendInput(1, buffer, sizeof(INPUT));
}
int main(int argc, char *argv[])
{
INPUT buffer[1];
MouseSetup(&buffer);
MouseMoveAbsolute(&buffer, X, Y);
MouseClick(&buffer);
return 0;
}
You'll need to call MouseSetup() to each INPUT buffer before you use it.
Resources
MSDN - SendInput()
MSDN - INPUT
MSDN - MOUSEINPUT
Here is a solution using Xlib for those who use Linux :
#include <X11/Xlib.h>
#include<stdio.h>
#include<unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void mouseClick(int button)
{
Display *display = XOpenDisplay(NULL);
XEvent event;
if(display == NULL)
{
fprintf(stderr, "Errore nell'apertura del Display !!!\n");
exit(EXIT_FAILURE);
}
memset(&event, 0x00, sizeof(event));
event.type = ButtonPress;
event.xbutton.button = button;
event.xbutton.same_screen = True;
XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
event.xbutton.subwindow = event.xbutton.window;
while(event.xbutton.subwindow)
{
event.xbutton.window = event.xbutton.subwindow;
XQueryPointer(display, event.xbutton.window, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
}
if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) fprintf(stderr, "Error\n");
XFlush(display);
usleep(100000);
event.type = ButtonRelease;
event.xbutton.state = 0x100;
if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) fprintf(stderr, "Error\n");
XFlush(display);
XCloseDisplay(display);
}
int main(int argc, char * argv[]) {
int x , y;
x = atoi(argv[1]);
y = atoi(argv[2]);
Display *display = XOpenDisplay(0);
Window root = DefaultRootWindow(display);
XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
mouseClick(Button1);
XFlush(display);
XCloseDisplay(display);
return 0;
}
Just Build it and then to simulate a click at x ,y do:
$ ./a.out x y
i.e.
$g++ -lX11 sgmousesim2.cpp
$./a.out 123 13
Use SendInput to generate the input you want to simulate. From MSDN documentation:
Synthesizes keystrokes, mouse motions, and button clicks.
I have never did this using C++. Nevertheless, there is a Java class called Robot which is able to produce mouse events. I used this back on Java version 1.4 but it does still work. I tried the example from this Simulate a physical mouse move in Mac OS X. It runs smoothly with Oracle Java 1.6.0_26 on MacOSX Lion. The good about Java is that it is platform independent.
import java.awt.AWTException;
import java.awt.Robot;
public final class MovingMouseDemo
{
public static void main(String[] args) throws AWTException
{
Robot robot = new Robot();
robot.setAutoDelay(5);
robot.setAutoWaitForIdle(true);
//put mouse in the top left of the screen
robot.mouseMove(0, 0);
//wait so that you can see the result
robot.delay(1000);
//put the mouse 200 pixels away from the top
//10 pixels away from the left
robot.mouseMove(200, 10);
robot.delay(1000);
robot.mouseMove(40, 130);
}
}
You can still use JNI to bind it with C++.
I hope it helps
C++ alone can't do this. It has no concept of a "mouse", let alone a "click".
You need some sort of library which talks to your windowing system. For example, QT. Then it's a matter of searching through the API and making the right C++ calls.
Use the mouse_event function.

GL/glx isn't linking correctly

System Specs and task
I am using Code::Blocks on Ubuntu 10.10 and playing around with OpenGL and glx. I'm in the process of learning C++(from a background in C and Java), so the style of any code doesn't conform to any real good standards (but I'm open to suggestions on how to improve, even if you don't have an answer to the question)
Edit:
Huge Realization: The default OpenGL Project Code::Blocks creates is C, not C++. I'm looking into this now.
I'm currently trying to modify the default OpenGL project on Code::Blocks into a simple 3d engine. I am currently getting the error:
expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before 'Draw'
Which disappears as soon as I comment out the #include for < GL/glx.h>
I read on a forum somewhere that Code::Blocks doesn't look in usr/include/ by default, but I added that to the search directories for the compiler in the project build options and it didn't seem to fix anything.
Code:
main.cpp: main.c:
#include <time.h>
#include "Draw.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
/*draw init here*/
Draw::Draw renderer = Draw::Draw.getDraw();
printf( "Press left mouse button to rotate around X axis\n" );
printf( "Press middle mouse button to rotate around Y axis\n" );
printf( "Press right mouse button to rotate around Z axis\n" );
printf( "Press ESC to quit the application\n" );
/* timing variable*/
/* Set it to delay half a second before rendering the first frame*/
clock_t flip_time = clock() + 0.5f * CLOCKS_PER_SEC;
while (1)
{
/* Update models */
/* Draw scene */
/* wait until it's been 1/60th of a second*/
while(clock() < flip_time){}
flip_time = clock() + (1.0f/60.0f) * CLOCKS_PER_SEC;
/* Actually flip the frame */
}
}
Draw.h:
#ifndef DRAW_H
#define DRAW_H
#include <GL/glx.h> /* This is the problem line */
#include <GL/gl.h>
#include <X11/X.h> /* X11 constant (e.g. TrueColor) */
#include <X11/keysym.h>
class Draw
{
public:
static Draw getDraw();
virtual ~Draw();
void update();
void render();
protected:
private:
Draw();
bool init();
/* The singleton*/
static Draw *instance;
static bool exists;
/* X Window values */
Display *dpy;
Window win;
GLboolean doubleBuffer;
/* X Parameters*/
XVisualInfo *vi;
Colormap cmap;
XSetWindowAttributes swa;
GLXContext cx;
XEvent event;
int dummy;
};
#endif // DRAW_H
Last, but not least Draw.cpp:
#include "Draw.h"
/* Set up the singleton*/
bool Draw::exists = false;
Draw* Draw::instance = NULL;
Draw::Draw()
{
/*TODO: make this constructor */
}
Draw::~Draw()
{
//dtor
}
Draw Draw::getDraw()
{
if(!exists)
{
instance = new Draw();
instance->init();
exists = true; //Thanks mat, This line was accidentally removed with extraneous comments
}
return *instance;
}
bool Draw::init()
{
/* Get the buffers ready */
static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, None};
static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None};
/* Double Buffered is best*/
doubleBuffer = GL_TRUE;
/*TODO: add constructor if it hasn't been constructed already*/
dpy = XOpenDisplay(NULL);
if (dpy == NULL)
{
return false;
}
/* make sure OpenGL's GLX extension supported */
if(!glXQueryExtension(dpy, &dummy, &dummy))
{
return false;
}
/* find an appropriate visual */
/* find an OpenGL-capable RGB visual with depth buffer */
vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf);
if (vi == NULL)
{
vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
if (vi == NULL)
{
return false;
}
doubleBuffer = GL_FALSE;
}
/*
TODO: Fix or remove this
if(vi->class != TrueColor)
{
return false;
}
*/
/* create an OpenGL rendering context */
/* create an OpenGL rendering context */
cx = glXCreateContext(dpy, vi, /* no shared dlists */ None,
/* direct rendering if possible */ GL_TRUE);
if (cx == NULL)
{
return false;
}
/* create an X window with the selected visual */
/* create an X colormap since probably not using default visual */
cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = KeyPressMask | ExposureMask
| ButtonPressMask | StructureNotifyMask;
win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0,
300, 300, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &swa);
XSetStandardProperties(dpy, win, "main", "main", None,
NULL, NULL, NULL);
/* bind the rendering context to the window */
glXMakeCurrent(dpy, win, cx);
/* request the X window to be displayed on the screen */
XMapWindow(dpy, win);
/* configure the OpenGL context for rendering */
glEnable(GL_DEPTH_TEST); /* enable depth buffering */
glDepthFunc(GL_LESS); /* pedantic, GL_LESS is the default */
glClearDepth(1.0); /* pedantic, 1.0 is the default */
/* frame buffer clears should be to black */
glClearColor(0.0, 0.0, 0.0, 0.0);
/* set up projection transform */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0);
/* establish initial viewport */
/* pedantic, full window size is default viewport */
glViewport(0, 0, 300, 300);
return true;
}
void Draw::update()
{
/*TODO: Add things to draw here*/
}
void Draw::render()
{
/* actually flip buffers here */
}
I removed a ton of comments before posting this here, but that shouldn't affect whether or not it compiles.
Thanks!
This line in your main file is wrong:
Draw::Draw renderer = Draw::Draw.getDraw();
Draw::Draw is not a type. To get this to compile, you just need:
Draw renderer = Draw.getDraw();
It looks like you're trying to build a singleton. You code does not do that at all, you'll get a copy each time. (Note that you're not setting exists anywhere, but that's just an extra bug.) You should be returning a pointer or a reference to the shared instance. See for instance this article to get the syntax right: C++ Singleton design pattern.
I found the issue with the linking.
The default project for OpenGL in Code::Blocks is NOT C++, it's C. I configured it to use g++ and it fixed the issue with glx not linking in correctly. I revised my singleton to look a little more like this and it works correctly now too. I have an issue now with the window not appearing, but I should be able to figure that out.
Thanks!