CodeWalrus

General => General Help & Troubleshooting => Topic started by: gameblabla on March 14, 2019, 08:34:42 pm

Title: Implementing triple buffering
Post by: gameblabla on March 14, 2019, 08:34:42 pm
So i'm working on porting an emulator (SMS Plus GX) to using fbdev and i managed to make double buffering work after reading this :http://betteros.org/tut/graphics1.php#doublebuffer (http://betteros.org/tut/graphics1.php#doublebuffer)
It roughly looks like this (Resolution is 320x240 and bitdepth is 16) :
Code: [Select]
static inline void swap_buffers()
{
    if (vinfo.yoffset == 0)
        vinfo.yoffset = screensize;
    else
        vinfo.yoffset = 0;

    //"Pan" to the back buffer
    ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo);

    //Update the pointer to the back buffer so we don't draw on the front buffer
    uint16_t* restrict tmp = front_buffer;
    front_buffer = back_buffer;
    back_buffer = tmp;
}
static void video_update()
{    //Draw our internal buffer to the back buffer
   upscale_SMS_to_320x240((uint32_t* restrict)back_buffer, (uint32_t* restrict)sms_bitmap, vdp.height);
   swap_buffers();
}
However, double buffering has its issues, as it can halve the framerate if it can't keep up, hence why i want triple buffering.
Wiki says this :
Quote
In triple buffering the program has two back buffers and can immediately start drawing in the one that is not involved in such copying. The third buffer, the front buffer, is read by the graphics card to display the image on the monitor. Once the image has been sent to the monitor, the front buffer is flipped with (or copied from) the back buffer holding the most recent complete image.
How would this work in my case though, practically speaking ?I've tried to implement it like so :
Quote
static inline void swap_buffers()
{
    buffer_swap_ready = NOT_READY;
    uint16_t *buffer_ready_tmp = buffer_ready;
    buffer_ready = buffer_render;
    buffer_render = buffer_ready_tmp;
    buffer_swap_ready = READY;
   
    if (buffer_swap_ready == READY)
    {
        if (vinfo.yoffset == 0)
            vinfo.yoffset = screensize;
        else
            vinfo.yoffset = 0;

        //"Pan" to the back buffer
        ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo);

        //Update the pointer to the back buffer so we don't draw on the front buffer
        uint16_t* restrict buffer_screen_tmp = buffer_screen;
        buffer_screen = buffer_ready;
        buffer_ready = buffer_screen_tmp;
    }
}
Obviously it's still wrong... (it's always set to READY)
WalrusRPG (https://github.com/WalrusRPG/WalrusRPG/blob/53d88ef36ca1b2c169b5755dd95ac2c5626b91f5/platform/nspire/CXfb.cpp) was using an interrupt for the buffer swapping.What can i do ? I admit that i'm fairly new to this lol... But i wish to implement it myself.