Slow window creation with SDL_WINDOW_OPENGL flag - c++

I've just started to testing SDL library. I've notice that SDL_CreateWindow() is very slow when I set SDL_WINDOW_OPENGL flag (takes about 10x longer). And I'm talking only about the window creation, not creation of OpenGl context.
Basically this line takes about 55 ms on my machine:
SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);
And this takes about 500 ms:
SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
And I feel this is much faster today. Yesterday I't feelt like it took about 2s to show the window (though I didn't measure it)
Is this normal to take so long or am I missing something? I'm also new to OpenGL so I can't even guess what it is doing under the hood.

The thing that takes a long time is loading the OpenGL driver from your graphics card vendor.
I was having a similar issue, so I rebuild SDL with symbols and profiled it. Almost all the time was spent in the ChoosePixelFormat function, which is part of wgl, the windows specific opengl interface. For me, today, with an Nvidia card, it takes a whole second to do this initialization.
There is a nice thread here that describes the issues in more detail:
https://hero.handmade.network/forums/code-discussion/t/2503-%5Bday_235%5D_opengls_pixel_format_takes_a_long_time

Related

How can I modify the sdl2 window frame?

I am using sdl2 in c++, and want to modify the window frame in my application. Can this be achieved and implemented?
I had a look here: How to change window style/theme in c++ - but I'm not sure how it can mix in.
#include "SDL.h"
SDL_Window *window;
void main()
{
window = SDL_CreateWindow("TEST", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Delay(3000);
}
I would like to build in a file menu and edit menu to the actual frame on the header and possibly change the color or make tabs in the frame as with google chrome.
One of SDL's main goals is to abstract window creation, so you don't have to deal with each OS's little tweaks. Said that, I don't think there is a portable, clean way to that using SDL.
What I would do is to go down the level of abstraction: Use WinAPI or MFC or one of Microsoft abstractions over the WinAPI to actually customize the window and then use DirectX or OpenGL to do all graphics. You can still use SDL for audio, input, etc. though.

SDL_RenderPresent() not waiting for vsync - how to wait?

I initialize SDL with this code:
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* win = SDL_CreateWindow(
"SDL Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
WIDTH,
HEIGHT,
SDL_WINDOW_SHOWN
);
SDL_Renderer* ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE);
SDL_GL_SetSwapInterval(1); // probably has no effect since it's not using GL
I then render with a non-SDL software renderer and present it to the window with this code:
SDL_UpdateTexture(screenBuffer, NULL, screenData, WIDTH*4);
SDL_RenderClear(ren);
SDL_RenderCopy(ren, screenBuffer, NULL, NULL);
SDL_RenderPresent(ren);
The framerate is completely uncapped, and I have no idea why.
Adding | SDL_RENDERER_PRESENTVSYNC to the SDL_CreateRenderer flags simply makes the window a blank white screen. Though I need to use the SDL_RENDERER_SOFTWARE flag (even though I'm not using SDL's software renderer other than to present the screen) or else will SDL_RenderPresent() will stall for a very, very long time resulting in about 1 frame per second.
How can I make SDL_RenderPresent() wait for vsync, or wait for it (accurately) myself?
VSync is a hardware feature. When VSync is enabled, the video card stops the renderer from presenting a frame until a signal from the monitor indicating vertical syncronism arrives (which means it finished displaying the last frame).
If you are using a software renderer there's no way to detect this signal since you're not using the video card to render. It's up to you to set a framerate and wait for the next frame.
An example for 60 frames per second:
#define TICKS_FOR_NEXT_FRAME (1000 / 60)
int lastTime = 0;
void update() {
while (lastTime - SDL_GetTicks() < TICKS_FOR_NEXT_FRAME) {
SDL_Delay(1);
}
... // SDL_RenderCopy...
SDL_RenderPresent(renderer);
lastTime = SDL_GetTicks();
}
A call to update will only present the frame if at least 15 ms have passed. 15 ms is the time needed for a framerate of 60 FPS.
I know this question is old, but i decided to post the answer for other people who might need it.
EDIT
As stated in the comments, this will not prevent tearing since you are not syncing to the vblank signal. This code only helps on capping the framerate. As far as I know there is no way to prevent tearing when using a software renderer (because you can't detect the vblank signal).

SDL_GL_SwapWindow crashes upon third call

I have made a very basic SDL application which kept going for a few iterations of the main loop, but then crashed. I have located the error to lie in SDL_GL_SwapWindow, which works the first two times, then crashes. This is a very simplified version that I have actually tried and it did the same thing.
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* SDLWindow = SDL_CreateWindow("Balls", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
SDL_GLContext SDLGLContext = SDL_GL_CreateContext(SDLWindow);
glewInit();
glViewport(0, 0, 800, 600);
SDL_GL_SwapWindow(SDLWindow);
SDL_GL_SwapWindow(SDLWindow);
SDL_GL_SwapWindow(SDLWindow); //crashes here
return 0;
First two calls work just fine, the third one crashes the program. Strangely, the crash occured in igd10umd32.dll and the debugger didn't allow me to read that file. I looked that up on the internet, but no attempts to fix the library worked. Besides, if the problem was in this library, it probably wouldn't appear under such strange conditions.
And what's even weirder is that the program works fine on my second laptop. And when I compiled it there and ran it on this laptop, it also worked fine.
I'm using Windows 10. I've worked with SDL/OpenGL many times and never encountered anything like this. Any ideas what may cause this very chaotic behavior?
Solved. It was nothing more than an NVIDIA bug. Updating the driver got rid of all problems.

Explanation of SDL2 windows/surfaces?

I made a short program to test out SDL2, though there are some things I don't understand how they work.
So I have created a window and a surface:
SDL_Window *window = nullptr;
SDL_Surface *windowSurface = nullptr;
Now I have this (the part I don't get):
window = SDL_CreateWindow("Window name", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windowSurface = SDL_GetWindowSurface(window);
So the first line: I use the SDL_createWindow() function to create a window called window I assume. The second line, I got no idea whats going on - explanation?
Finally I have this:
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
followed by some clean up code to set the pointers back to nullptr and exit the program/destroy windows etc.
The code you have pasted does the following things: Creates a SDL window called "Window name", sets its horizontal and vertical positions to center, sets the window size to 640 x 480 and marks it as shown.
The second line acquires the SDL surface bind to this window.
What this means is: Create Window , actually sets up and openGL window and a GPU texture (the Surface, althou SDL2 has seperate class for Textures), to which it is going to draw. Modifying the surface acquired with GetWindowSurface will modify the pixel on the window you have just created.
Bliting is applying a array of pixel to a target texture, in the meaning : hey i got this image/prerendered frame etc.. and I want to apply it to this surface so i can show it. Blit it.
I hope this is helpful : >
You can find more information for SDL here
Official SDL wiki
LazyFoo
LazyFoo provides a full tutorial and explanations of everything for the old SDL, but a lot of the things are the same in SDL2

Fullscreening a window in SDL2 with openGL

My program starts with a loading window while it is compiling shaders, loading textures etc. I then want to be able to launch a fullscreen application and use these resources. My understanding is that the openGL context must be the same before and after. I tried two methods for this: first of all I tried making a second window which was fullscreen, and used the SDL_GL_makecurrent command on this window to 'transfer' the context across (couldn't find where I read about this method), and secondly tried just fullscreening the loading window. Both of these methods resulted in the loading screen being moved to the top left corner of the screen. However opengl commands no longer ran properly in fullscreen, including clearing buffers which meant that the window contained the contents of my desktop/background applications.
Is there a proper way of doing this? Or is this a strange bug in sdl/opengl drivers?
Code to fullscreen original window:
//opengl commands work fine up to here
//now to fullscreen
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_SetWindowSize(window, 1366, 768); //tried this on either side of line above and without either line
glViewport(0, 0, 1366, 768); //update viewport
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
//window should be whited, other draw commands tried and all fail or distort
SDL_GL_SwapWindow(window);
Creating a new window and using previous context:
//Fine up to here
window2 = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1366, 768, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_SHOWN);
SDL_GL_MakeCurrent(window2, glContext); //created with SDL_GL_CreateContext(oldwindow);
//draw commands dont work
PS: running ubuntu
Update: In the second code, reusing the context in a new window, it returns an error saying 'invalid window' when it fails, which is most of the time but not always. When it fails, the screen ends up completely corrupted(black with weird white squares and patterns), ending the program will not clear the screen of this (although screenshots are perfectly fine?), but it can be restored by ctrl+f1 to terminal then ctrl+f7 back
I dont really know if its a bug. I experienced the same issue with sdl2 and opengl.
Create an regular window
attach to opengl context.
fullscreen
BOOM. black screen and crashed window.
I only noticed that issue in ubuntu.
Trought some tests i found a quick way to fix it:
Uint32 flags = 0;
flags |= SDL_WINDOW_RESIZABLE;
//bla bla bla your tags
flags |= SDL_WINDOW_OPENGL;
m_window = SDL_CreateWindow( "hello gl", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_screen.x, m_screen.y,flags);
m_glContext = SDL_GL_CreateContext(m_window);
//Set right the way the screen to fullscrene false
SDL_SetWindowFullscreen(m_window, SDL_FALSE);
Now the fullscreen seems to work without problem.