1
votes

I have some very simple drawing going on with SDL2 that was working perfectly under Windows but now that I've ported it over to Linux, isn't drawing from the different threads I've spawned.

I'm controlling access to the renderer using mutex's.

The functions process and output logging as expected, the only thing that doesn't appear to be working is that the renderer never updates the display under Linux.

If I comment out the threading, and run the function from main I get the expected result. The code hasn't changed between the Linux and Windows versions.

The code compiles without warnings under -wall and -pedantic. Since I've started compiling with Linux I've added -pthread flag in case that was required (hasn't made any difference).

If anyone is aware of any gotchas or might have an inkling why this isn't working you would be doing me an enormous favour.

        static int thread_processing(void* data) 
    {
        srand(time(NULL));      //randomize 
        
        ThreadData *td = data;  
        Bucket *bucket; 
        int b_Id = -1;
        
        Color threadColor;
        //unique color for each respective thread
        color_randomize(&threadColor);
        threadColor.a = 255;
        
        fprintf(stderr, "%d Buckets to process..\n", td->bArray->size);
        while (1) {
            //check there are buckets left to process
            if (td->bArray->rendered >= td->bArray->size)
                break;
                
            //acquie/lock access to bucket array
            SDL_LockMutex(td->b_mutex);
            
            //retrieve buucket id to process
            b_Id = td->bArray->rendered;
            td->bArray->rendered++;
            
            fprintf(stderr, "Rendering bucket: %d\n", b_Id);
            //release access to bucket array
            SDL_UnlockMutex(td->b_mutex);
            
            //retrieve addr of bucket to process
            bucket = &(td->bArray->buckets[b_Id]);
            
            //lock access to renderer
            SDL_LockMutex(td->r_mutex);
            
            //draw rect on screen where bucket will be processed
            draw_bucketOutline(td->renderer, bucket, &threadColor);
            SDL_RenderPresent(td->renderer);
            
            //release access to renderer object
            SDL_UnlockMutex(td->r_mutex);
            
            //process the bucket
            process_bucket(td->scene, bucket);
            
            //acquire/lock acess to renderer object
            SDL_LockMutex(td->r_mutex);
            
            //draw the processed data ot the screen
            draw_bucket(td->renderer, bucket);
            SDL_RenderPresent(td->renderer);
            
            //release access to renderer object
            SDL_UnlockMutex(td->r_mutex);
        }
        
        return 0;
    }

    void draw_bucketOutline(SDL_Renderer *renderer, Bucket *b, Color *color)
{
    //set the colour of the outline
    SDL_SetRenderDrawColor(renderer, 125, 125, 125, 255);
    
    //set the outline position
    SDL_Rect rect;
    rect.w = b->resolution.width;
    rect.h = b->resolution.height;
    rect.x = b->start.x;
    rect.y = b->start.y;
    
    //draw the outline
    SDL_RenderDrawRect(renderer, &rect);
    
    //crop rectangle inwards for filling inside of outline
    rect.w -= 2;
    rect.h -= 2;
    rect.x += 1;
    rect.y += 1;

    //set colour for fill area
    SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a);
    
    //draw fill area
    SDL_RenderFillRect(renderer, &rect);
}

Main.....

//iterate over threads, do the processing
int t;
for (t = 0; t < THREAD_COUNT; t++) {
    threads[t] = SDL_CreateThread(thread_processing, NULL, &td);
}

//iterate over threads, clean them up
for (t = 0; t < THREAD_COUNT; t++) {
    int status;
    SDL_WaitThread(threads[t], &status);
}

Compiling with

gcc -Wall -pedantic -lm -I/usr/include/SDL2 -D_REENTRANT -lX11 -pthread raytracer.c -lSDL2 -o raytracer
1

1 Answers

0
votes

SDL2 on linux uses OpenGL accelerated rendering (it defaults to d3d acceleration on windows), and OpenGL have thread-local context. You cannot use the same GL context in separate threads. You have to render in single thread, e.g. by putting rendering commands in the queue and then replaying them in rendering thread. And you shouldn't have used multiple rendering threads in the first place.