(openGL repaint) thread problem

Hi,

I have some problems using threads.

If I try to do some drawing stuff in a thread created with SDL_CreateThread,
the application exits with
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0x66)!

If I do the same drawing within the main thread, the application runs as
expexted.

example code:
#include “SDL/SDL.h”
#include “SDL/SDL_thread.h”

#include “GL/gl.h”

bool quitThread;

int eventLoop(void * data) {
SDL_Event event;

while(!quitThread) {
    SDL_WaitEvent(&event);
        switch( event.type ) {
            case SDL_KEYDOWN:
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    quitThread = true;
            break;
            case SDL_QUIT:
                quitThread = true;
            break;
            default:
            break;
        }
}
return -1;

}

int repaint(void * data) {
while(!quitThread) {
glClear( GL_COLOR_BUFFER_BIT );
glLoadIdentity();

    glBegin( GL_QUADS );
    glVertex2i(10, 10);
    glVertex2i(10, 100);
    glVertex2i(100, 100);
    glVertex2i(100, 10);
    glEnd();

    SDL_GL_SwapBuffers();
}
return -1;

}

int main( int argc, char * argv[] ) {
SDL_Init(SDL_INIT_VIDEO);
SDL_SetVideoMode( 320, 240, 32, SDL_OPENGL);

glViewport(0, 0, 320, 240);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 320, 0, 240, -1, 1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

quitThread = false;

SDL_Thread * thr1;
SDL_Thread * thr2;

thr1 = SDL_CreateThread(eventLoop, NULL);

// separate thread
// comment this line to create a working application
thr2 = SDL_CreateThread(repaint, NULL);

// no separate thread, call function directly
// uncomment this line to create a working application
//repaint(NULL);

SDL_WaitThread(thr1, NULL);

return 0;

}

Regards,
Johannes

The SDL graphics calls aren’t thread safe. (Although it probably could be
without too many API changes. However, it’s not trivial to implement that
without performance issues.) Nor are the underlying protocols, X and GLX.

As to OpenGL, think about it; how could a state machine style API like
OpenGL possibly be thread safe…? (Oh well, every library call could
check which thread is running upon entry, but that wouldn’t exactly help
performance! :slight_smile:

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------> http://www.linuxaudiodev.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |--------------------------------------> david at linuxdj.com -'On Tuesday 07 August 2001 21:13, Johannes Schmidt wrote:

Hi,

I have some problems using threads.

If I try to do some drawing stuff in a thread created with
SDL_CreateThread, the application exits with
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0x66)!

If I do the same drawing within the main thread, the application runs
as expexted.

Hi,

I have some problems using threads.

If I try to do some drawing stuff in a thread created with SDL_CreateThread,
the application exits with
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0x66)!

Your X server does not support multi-threading. You have to do all your
calls to the Xlib from one single thread. I guess you may even have to use
only the main thread.

If I do the same drawing within the main thread, the application runs
asOn Tue, 7 Aug 2001, Johannes Schmidt wrote:
expexted.

[…]


Johann Deneux
http://www.esil.univ-mrs.fr/~jdeneux/projects/

That seems to be reasonable.
I have tried to compile the code under windows( mingw32 ) and it works.
Also, I packed all graphic things into one repaint function and created a
thread out of it. That works, too.

example:
int paintThread(void * data) {
SDL_SetVideoMode( 320, 240, 32, SDL_OPENGL);

glViewport(0, 0, 320, 240);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 320, 0, 240, -1, 1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

while(!quitThread) {
    glClear( GL_COLOR_BUFFER_BIT );
    glLoadIdentity();

    glBegin( GL_QUADS );
    glVertex2i(10, 10);
    glVertex2i(10, 100);
    glVertex2i(100, 100);
    glVertex2i(100, 10);
    glEnd();

    SDL_GL_SwapBuffers();
}
return -1;

}

But it is a bit unhandy to have all paint things in one thread.

Is this a general problem of X servers or just of mine ( XFree86 4.1 )?
Which X servers are multi-threaded?

Regards,
JohannesOn Tuesday 07 August 2001 21:30, Johann Deneux wrote:

I have some problems using threads.

If I try to do some drawing stuff in a thread created with
SDL_CreateThread, the application exits with
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0x66)!

Your X server does not support multi-threading. You have to do all your
calls to the Xlib from one single thread. I guess you may even have to use
only the main thread.

After some tests, I think it has something to do with OpenGL.

Consider the following code
( SDL initialized with SDL_SWSURFACE, next time with SDL_OPENGLBLIT ).

#include “SDL/SDL.h”
#include “SDL/SDL_thread.h”

#include “GL/gl.h”

SDL_Surface * screen;

int draw( void * data) {
SDL_Rect dstrect = {10, 10, 100, 100 };
SDL_FillRect(screen, &dstrect,
SDL_MapRGB(screen->format, 0xff, 0x00, 0x00) );
SDL_UpdateRect(screen,0, 0, 0, 0);
}

int main( int argc, char * argv[] ) {
SDL_Init(SDL_INIT_VIDEO);
// if you start the application with an opengl context, it will crash
// with an Seg fault.
//screen = SDL_SetVideoMode( 320, 240, 16, SDL_OPENGLBLIT);
screen = SDL_SetVideoMode( 320, 240, 16, SDL_SWSURFACE);

SDL_Thread * thr;
thr = SDL_CreateThread(draw, NULL);
SDL_WaitThread(thr, NULL);

SDL_Delay(3000);

SDL_Quit();

return 0;

}

Regards,
JohannesOn Tuesday 07 August 2001 21:30, Johann Deneux wrote:

I have some problems using threads.

If I try to do some drawing stuff in a thread created with
SDL_CreateThread, the application exits with
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0x66)!

Your X server does not support multi-threading. You have to do all your
calls to the Xlib from one single thread. I guess you may even have to use
only the main thread.

I have some problems using threads.

If I try to do some drawing stuff in a thread created with
SDL_CreateThread, the application exits with
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0x66)!

Your X server does not support multi-threading. You have to do all your
calls to the Xlib from one single thread. I guess you may even have to use
only the main thread.

That seems to be reasonable.

I know for sure using threads with the Xlib is in general dangerous. That
means using anything that uses the Xlib is trickt too: Qt, gtk, OpenGL,
SDL…

I have tried to compile the code under windows( mingw32 ) and it works.
Also, I packed all graphic things into one repaint function and created a
thread out of it. That works, too.

example:
int paintThread(void * data) {
SDL_SetVideoMode( 320, 240, 32, SDL_OPENGL);

glViewport(0, 0, 320, 240);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 320, 0, 240, -1, 1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

while(!quitThread) {
    glClear( GL_COLOR_BUFFER_BIT );
    glLoadIdentity();

    glBegin( GL_QUADS );
    glVertex2i(10, 10);
    glVertex2i(10, 100);
    glVertex2i(100, 100);
    glVertex2i(100, 10);
    glEnd();

    SDL_GL_SwapBuffers();
}
return -1;

}

But it is a bit unhandy to have all paint things in one thread.

Is this a general problem of X servers or just of mine ( XFree86 4.1 )?

It is a general “problem”.

Which X servers are multi-threaded?

I know XFree 3 could be compiled with threads support. But even then, you
would need to use some macros or functions (whose names I forgot) to
peform locking/unlocking. Anyway, you probably do not want to force your
users to recompile their X Server, do you ?

I don’t really see why you want to use a thread to paint. As soon
as another threads tries to read events, your application may crash. My
advice is: avoid threads in this kind of situation.On Wed, 8 Aug 2001, Johannes Schmidt wrote:

On Tuesday 07 August 2001 21:30, Johann Deneux wrote:


Johann Deneux
http://www.esil.univ-mrs.fr/~jdeneux/projects/

Johann Deneux wrote:

I know for sure using threads with the Xlib is in general dangerous. That
means using anything that uses the Xlib is trickt too: Qt, gtk, OpenGL,
SDL…

Xlib is thread-safe if you follow the rules in the Xlib docs, and you
may call Xlib functions from different threads if you are careful.
SDL is not thread-safe in that respect, so never use the SDL API from
any other thread than the main thread. (Also avoid SDL functions in
callbacks.)

The chief exception is SDL_PushEvent() (and I think we can safely proclaim
SDL_GetTicks to be safe as well)

[…]

I don’t really see why you want to use a thread to paint. As soon
as another threads tries to read events, your application may crash. My
advice is: avoid threads in this kind of situation.

I can see a few reasons to use more than one thread to render. Although
there are other ways to deal with it, it may simplify things a lot if
multiple threads can render at the same time. (Usually in different areas
of the screen - it wouldn’t work very well any other way…)

What to do? Well, you could use some kind of wrapper API for the
rendering functions, designed with asynchronous execution in mind. Then
implement that wrapper API on top of some thread safe queue mechanism
(one lock-free FIFO per client thread, perhaps), so that the API calls
enqueue “commands” instead of calling the “real” API. Finally, implement
a “server” that takes commands from the queue (possibly with some
priority system, and perhaps even splitting/interleaving of large
operations) and performs them using the underlying “real” API.

(BTW, I was working on a proof-of-concept hack for SDL that could
really use something like this… However, don’t count on me getting
around to code it anytime soon. heh)

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |--------------------------------------> david at linuxdj.com -'On Friday 10 August 2001 15:20, Johann Deneux wrote:

What to do? Well, you could use some kind of wrapper API for the
rendering functions, designed with asynchronous execution in mind. Then
implement that wrapper API on top of some thread safe queue mechanism
(one lock-free FIFO per client thread, perhaps), so that the API calls
enqueue “commands” instead of calling the “real” API. Finally, implement
a “server” that takes commands from the queue (possibly with some
priority system, and perhaps even splitting/interleaving of large
operations) and performs them using the underlying “real” API.

…or don’t use OpenGL in immediate mode. To a degree, you’re describing
what happens under the hood between your first OpenGL call and glFlush().

–ryan.

Not really, unless I’m missing something… The very point of my proposed
solution is to be able to interleave the actual rendering operations with
whatever timing granularity you may need.

For example, I’ve developed a method of doing buffered, flicker and
tearing free animation on targets without hardware pageflipping. The
"trick" is based on two fundamental principles:

1) Refresh only part of the screen at a time, to reduce
   the timing accuracy requirements for the raster sync.
   This could be seen as a "pageflipping emulator".

2) Provide as much buffering as possible (keeping the
   latency at an acceptable level) between the rendering
   engine and the "pageflipping emulator".

That is, the “pageflipping emulator” has to blit from off-screen buffers
generated by the actual actual rendering code. The refreshing has to be
done either by polling a timer inside every rendering API call - or by a
higher priority thread. In the latter case, you can’t use a rendering API
that isn’t thread safe, so you have to resort to something like the queue
hack described above.

Both methods would require an API wrapper and some timer thread or
polling stuff for the “flipping”. The only difference is whether the
latter is done in another thread in the other end of a FIFO, or directly
inside every rendering API call. (Note that the latter relies on the
application using those calls rather frequently, without stalling. If it
doesn’t, the “pageflipping emulator” won’t work!)

//David Olofson — Programmer, Reologica Instruments AB

.- M A I A -------------------------------------------------.
| Multimedia Application Integration Architecture |
| A Free/Open Source Plugin API for Professional Multimedia |
----------------------------> http://www.linuxdj.com/maia -' .- David Olofson -------------------------------------------. | Audio Hacker - Open Source Advocate - Singer - Songwriter |--------------------------------------> david at linuxdj.com -'On Friday 10 August 2001 19:35, Ryan C. Gordon wrote:

What to do? Well, you could use some kind of wrapper API for the
rendering functions, designed with asynchronous execution in mind.
Then implement that wrapper API on top of some thread safe queue
mechanism (one lock-free FIFO per client thread, perhaps), so that
the API calls enqueue “commands” instead of calling the “real” API.
Finally, implement a “server” that takes commands from the queue
(possibly with some priority system, and perhaps even
splitting/interleaving of large operations) and performs them using
the underlying “real” API.

…or don’t use OpenGL in immediate mode. To a degree, you’re
describing what happens under the hood between your first OpenGL call
and glFlush().

Ok, a special repaint thread isn?t that necessary.

But my program crashes with every call to any openGL function
( I don?t think glGetString calls Xlib functions and I think this thread
should be thread-safe ).

example code:
#include “SDL/SDL.h”
#include “SDL/SDL_thread.h”

#include “GL/gl.h”

int my_thread( void * data ) {
glGetString( GL_VERSION );
}

int main( int argc, char * argv[] ) {
SDL_Init(SDL_INIT_VIDEO);
SDL_SetVideoMode( 320, 240, 32, SDL_OPENGL);

SDL_Thread * test = SDL_CreateThread(my_thread, NULL);

SDL_WaitThread(test, NULL);

SDL_Quit();

return 0;

}

I don?t know why this code should seg fault.
( or is it a problem of my openGL driver?)

Regards,
JohannesOn Friday 10 August 2001 16:25, you wrote:

Johann Deneux wrote:

I know for sure using threads with the Xlib is in general dangerous. That
means using anything that uses the Xlib is trickt too: Qt, gtk, OpenGL,
SDL…

Xlib is thread-safe if you follow the rules in the Xlib docs, and you
may call Xlib functions from different threads if you are careful.
SDL is not thread-safe in that respect, so never use the SDL API from
any other thread than the main thread. (Also avoid SDL functions in
callbacks.)