-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
invalid swapInterval behavior - wrong display buffer update rate #367
Comments
Strange, I wonder why the OP is seeing different behaviour between 1 and 2 then? 🤔 But as this is exploiting functionality which isn't mentioned in the SDL docs, I'll close this issue as undefined behaviour. |
This is doc mistake, because basically this is just a wrapper for OpenGL SwapInterval extenstion function. Which supports value > 1. Actually I catch this issue with direct call to OpenGL SwapInterval extension, with no using SDL2 at all. This is OpenGL bug of Raspberry Pi driver, don't confuse it with SDL2. I just using SDL2 to demonstrate the issue. But you can call OpenGL extension directly and reproduce this bug with no SDL2 library at all. It shows exactly the same behavior. I tested it on NVidia/AMD drivers and it works with any swapInterval value as expected. See official OpenGL specification for swapInterval extension:
As you can see it mention swapInterval=2 (see "e.g. a value of two means") as example to explain how it should work. But Raspberry Pi OpenGL driver works incorrectly for value 2 and above and breaks OpenGL specification, see steps of this issue to reproduce it for test. I suspect this issue also may lead to graphics issues in chromium browser. Do I need to open a separate issue about the incorrect OpenGL implementation of the swapInterval extension, or will you reopen this issue? |
Steps to reproduce:
create test app:
1.1) install SDL2 libs with command
sudo apt install libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev
1.2) compile test app from source (see source code in the spoiler at the end of issue details) code with command
gcc -o test-vblank4 test-vblank4.c -Wall -lGL -lSDL2 -lSDL2_ttf -lSDL2_image
run test app with the following command
./test-vblank4
. It should open window which shows realtime graph which displays time periods measured between SDL_GL_SwapWindow calls, which represent actual window surface update rate.switch swap interval with keyboard key F1.
When you press the F1 button, it leads to call swapInterval() to change swapInterval value, the values change in a cycle: 1, 2, 3, 0. When you run the test application, the initial value is swapInterval=1.
The last value passed to SDL_GL_SetSwapInterval() function is displayed as "need: 1".
The currently reported swapInterval value reported by SDL_GL_GetSwapInterval() function is displayed as "swap: 1", when value is < 0 it also dispaying the string returned from SDL_GetError().
Current display mode, include display refresh rate is displayed as "mode: 1280x1024@75".
You can take app screenshot with button F12, it will save screenshot to the current app folder.
The expected time interval between SDL_GL_SwapWindow calls for current swapInterval value is highlighted with yellow color.
The correct behavior for swapInterval value is the following:
0 = max possible update rate, with no vblank synchronization
1 = the update rate time interval is equals to the current display refresh rate time interval
2 = the update rate time interval is exactly 2x times longer than for value 1
3 = the update rate time interval is exactly 3x times longer than for value 1
For example, if your display has 60 Hz refresh rate, then it's refresh time period is 1/60 = 16.6 ms. So, it should have the following results for different swapInterval values:
0 = min possible time interval (actual result is about 1-2 ms)
1 = 16.6 ms
2 = 33.3 ms
3 = 50.0 ms
Now check how it actually works on raspberry pi OS bookworm with latest updates for different swapInterval values:
swapInterval=1
Expected result: 16.6 ms for 60 fps display
Actual result: as expected (16.6 ms for 60 fps display)
swapInterval=2
Expected result: 33.3 ms for 60 fps display
Actual result: 22.4 ms for 60 fps display - INVALID
swapInterval=3
Expected result: 50.0 ms for 60 fps display
Actual result: 40.6 ms for 60 fps display - INVALID
swapInterval=0
Expected result: min possible time interval
Actual result: as expected (1.9 ms)
As you can see swapInterval works correctly for values 0 and 1 only. For swapInterval > 1 it gives invalid results. And different drivers (x11, wayland, kmsdrm) produce different time intervals for swapInterval > 1 which is even more confusing.
The behavior of swapInteval value is pretty simple - it just should skip N-1 dispaly frames and then do 1 buffer update. For N=0 it should disable vblank sync and do buffer swap as fast as possible. For N>0 vblank sync should be enabled, for N=1 it should skip 1-1=0 frames - as result it should update buffer on every display frame. For N=2 it should skip 2-1=1 frame, etc.
But for some unknown reason, raspberry pi OS shows some random values for N > 1. Please fix it.
Test code
test-vblank4.c
The text was updated successfully, but these errors were encountered: