SDL Window causes mouse to freeze every few seconds - c++

Every time I attempt to run my application it creates a window perfectly fine but when moving the mouse about it becomes obvious that it freezes briefly for a few seconds. I also had this issue in a previous SDL project but didn't fix it as it wasn't very vital but I could never find a solution for it.
I tried looking up my issue but couldn't find anything that matches the issue I'm facing, despite this I attempted a few things that I felt could work like slightly different implementations of an event loop.
I'm not 100% sure on what EVERY line of SDL related code does but I took it from a previous project so I knew what it did at one point but it's not too hard to work out.
int width = 160;
int height = 144;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Window Title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width * 4, height * 4, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
bool quit = false;
while (!quit)
{
SDL_Event E;
while (SDL_PollEvent(&E))
{
if (E.type == SDL_QUIT)
quit = true;
}
}
I expect the window to display smoothly and not have this freezing occur every few seconds. I'm not sure if it only occurs when the mouse is moving or if it happens to freeze every few seconds despite this as the cursor is the only way I have to test it. I saw one post that talked about flooding the event queue but that solution didn't seem to work for me.
Any help is appreciated.

Related

Program still running after return 0; with SDL_Renderer

I'm doing Lazy Foo's tutorial on SDL (I'm using SDL2-2.0.9), and at the texture rendering part I encountered the following problem: the program compiles and runs as expected, no issue here, but when I close the window, the console doesn't close and the process continues running, so I have to close the console separately.
When I tried to debug it, I found out that the program indeed leaves the main cycle and reaches the "return 0" line in the main function successfully, but then it just hangs like that until I close the console.
The issue is only present when I use the SDL renderer with any option other than SDL_RENDERER_SOFTWARE. If I use SDL_RENDERER_SOFTWARE - the program closes as expected. With other options it stays at "return 0" running other threads (crypt32.dll, ntdll.dll and nvd3dum, in this order in the thread view, meaning that the process is stuck in crypt32).
I'm aware that my main function is not the "real main" as it has been hijacked by SDL, so exit(0) works fine as an ad-hoc solution. But I want to know, why exactly does that happen and is there any other way to fix this, so that I don't have to use exit(0) ?
Here is an example (simplified) code, which demonstrates this issue for me:
#include "SDL.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
SDL_Window *win = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *bitmapTex = NULL;
SDL_Surface *bitmapSurface = NULL;
int width = 640, height = 480;
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("Could not initialize SDL");
return 1;
}
win = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0);
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
bitmapSurface = SDL_LoadBMP("res/x.bmp");
bitmapTex = SDL_CreateTextureFromSurface(renderer, bitmapSurface);
SDL_FreeSurface(bitmapSurface);
bool quit = false;
while (!quit) {
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
quit = true;
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bitmapTex, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(bitmapTex);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
printf("REACHED RETURN 0");
return 0;
}
Works as intended, but after closing the window I see "REACHED RETURN 0" printed in console and that's it, the console stays there. The code can be simplified further, the issue will be present as long as there is an instance of SDL_Renderer created.
UPD: The callstack during the hanging:
> ntdll.dll!_NtWaitForMultipleObjects#20()
KernelBase.dll!_WaitForMultipleObjectsEx#20()
crypt32.dll!ILS_WaitForThreadProc()
kernel32.dll!#BaseThreadInitThunk#12()
ntdll.dll!__RtlUserThreadStart()
ntdll.dll!__RtlUserThreadStart#8()
UPD2: The problem is not with the loop at all, I created the simplest application where I just create a window and a renderer and then return 0, it still gives me a hanging console. Like this:
#include <SDL.h>
int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) return 1;
SDL_Window* window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
return 0;
}
Same thing when I destroy them properly. The problem is in the renderer.
UPD3: Here is the Parallel Stack window during the "hanging". There is no "main" thread since I close it successfully, these are the threads which stop the program from closing properly. Other than that, it doesn't give me any understanding of the problem.

Why is the frame rate in my SDL 2 application being halved unless I move the mouse around in a certain position?

There's this extremely odd bug, which came seemingly out of nowhere, where my SDL 2 application has had a massive drop in frame rate (from ~60 to ~30). What's really odd about this bug is that while I move my cursor around quickly and outside of the window the frame rate speeds up back to normal.
What could be the issue? Or, how can I properly limit the framerate to exactly 60 (or whatever I please)?
EDIT: Here's the skeleton code which successfully replicates the problem:
#include <cstdio>
#include <SDL.h>
#define WIDTH 640
#define HEIGHT 480
#define FPS 60
using namespace std;
int main(int argc, char** args) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Cool Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Surface* winsurf = SDL_GetWindowSurface(window);
SDL_Renderer* winren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(winren, 255, 255, 255, 255);
bool quit = false;
int counter = 0;
int looptime = SDL_GetTicks();
while (!quit) {
SDL_RenderClear(winren);
SDL_Event e;
while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT)
quit = true;
printf("%d\n", counter++); // notice how quickly the counter speeds up
// while moving your cursor around outside
// of the window
if (SDL_GetTicks() - looptime < 1000/FPS)
SDL_Delay(1000/FPS - (SDL_GetTicks() - looptime));
looptime = SDL_GetTicks();
SDL_RenderPresent(winren);
}
SDL_Quit();
}
If anyone's interested, I fixed the problem by enabling Vsync. I added the SDL_RENDERER_PRESENTVSYNC flag to my call, like so:
SDL_Renderer* winren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
This makes animation much more fluid.

SDL drop in performance when blitting a large texture

I am currently developing a small game in SDL in CodeBlocks and it seems i got into a little bit of trouble with surface and texture management. My current progress is getting to move a texture on-screen using the arrow keys. However, i have noticed that when loading a relatively large image, FPS drops drastically and thus the texture i move on-screen moves a lot slower.
My draw function looks like this :
const char* assets[5]={"assets/textures/0.tga","assets/textures/1.tga",
"assets/textures/2.tga","assets/textures/3.png","assets/textures/4.png"};
SDL_Surface* tex[5];
void DrawImage(int i, SDL_Surface* &dest, SDL_Rect &rect)
{
if(tex[i]==NULL) tex[i] = IMG_Load(assets[i]);
SDL_BlitSurface(tex[i], NULL, dest, &rect);
}
with the fourth texture in the array being the large one. If i issue any of the following :
DrawImage(0, screenSurface, rect);
DrawImage(1, screenSurface, rect);
DrawImage(2, screenSurface, rect);
DrawImage(4, screenSurface, rect);
everything runs smooth. However, if i issue:
DrawImage(3, screenSurface, rect);
and keep the texture in the window's bounds, everything runs in slow motion. Moving the texture outside the window's bounds makes everything run normal again.
The main loop looks like this :
bool running = true;
while(running)
{
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0, 0, 0));
DrawImage(3, screenSurface, rect);
MovePlayer(rect, state);
MoveCursor(NULL, NULL, screenSurface);
SDL_PumpEvents();
SDL_UpdateWindowSurface(window);
if (state[SDL_SCANCODE_ESCAPE])
{
SDL_DestroyWindow(window);
running = false;
}
}
Is there any way to overcome this problem?
Thanks in advance.
Look into SDL_Renderer to make use of hardware rendering. SDL_UpdateWindowSurface uses software rendering and can be very slow.

cannot display texture in SDL 2

I'm trying to display a texture onto the screen but all I'm getting is a black window.
No SDL Errors are being reported. There's a good chance that I'm missing something stupid, but I can't see it. Hopefully another set of eyes will help. Feel free to ask for more code/info.
main.cpp
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Texture * grass;
SDL_Rect g_dst;
SDL_Event event;
Game app;
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("tmp", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
g_dst.x = g_dst.y = 0;
g_dst.w = 640;
g_dst.h = 480;
grass = IMG_LoadTexture(renderer, "grass.bmp");
while (app.isRunning()) {
app.pollEvents(&event);
app.render_init();
app.render(grass, NULL, &g_dst);
app.render_end();
}
//SDL_Quit() is handled by the Game class' destructor
Game.cpp
//Only functions used for rendering are shown
void render_init(Uint8 red=0, Uint8 green=0, Uint8 blue=0, Uint8 alpha=255)
{
SDL_SetRenderDrawColor(renderer, red, green, blue, alpha);
SDL_RenderClear(renderer);
}
void render(SDL_Texture * texture, SDL_Rect * src, SDL_Rect * dest) {
SDL_RenderCopy(renderer, texture, src, dest);
}
void render_end() { SDL_RenderPresent(renderer); }
First of all, you're initializing everything? please don't do that frequently, mind you that you're also initializing MANY unnecessary stuffs like for game controllers, etc. if the app gets bigger then the efficiency and the possibility of this app running at a smoot speed is at stake.
I also noticed that you are declaring variables in the .cpp file, do that in the header file and just recall the header to the cpp file that will be using it.
You want to render the grass right? and render it as much as the screens size.
(I'll just assume that you used this in the game.cpp part, which is the very first file, thus, not regarding any classes made)
int winWidth = 680; //The reason for this is just in case you make the window resizable
int winHeight = 480; //then the texture would also resize along with the window
SDL_Window *window = window = SDL_CreateWindow("The Space Project", 100, 100, winWidth, winHeight, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = NULL; //I've set this to NULL so that we can know if
the reason as to why your image is not rendering is because the renderer is not properly working.
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED);
if(renderer == NULL)
{
cout >> "Renderer is not working" >> endl;
//This shows a line at the command prompt that your renderer doesn't have any output, thus, only having a NULL as an equivalent
}
SDL_Texture* grass= NULL;
grass= IMG_LoadTexture(renderer, "grass.bmp"); //As you can see, I've set the grass to Null again
if(grass == NULL)
{
cout >> "Grass have failed to initialize" >> endl;
/*I don't normally do this but it's very important if you really need trouble shooting guides
but this time, were here to check IF the grass.bmp entered the SDL_Texture grass, so if the system can't find the .bmp file then it would show this error
since the grass (SDL_Texture) still doesn't have anything inside it (NULL)*/
}
SDL_Rect grass_rect;
grass_rect.x = 0;
grass_rect.y = 0;
grass_rect.w = winWidth;
grass_rect.h = winHeight;
//Loop part, I'll skip some of it
while (!quit && mainEvent->type != SDL_QUIT) //!quit is just an imaginary Boolean I've typed)
{
SDL_PollEvent(mainEvent); //Let's say you created the event already
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, grass, NULL, &grass_rect);
//The NULL part is also similar to a rect but it's a limiting type, we didn't assign anything to it
since I assumed that you wanted the whole image to be rendered
SDL_RenderPresent(renderer);
}
I revised the code and made it more efficient since your code called for useless extras which might result in lower performance.
I also notice that you tried calling for color changes?
use this
SDL_SetTextureColorMod(texture, red-value, green-value, blue-value);
and put it in the loops part under the render present of the same texture.
SDL_SetTextureColorMod(grass, 250, 250, 250);
Doing this would set all color values to 250, thus, having a white color, this change your texture color to white.
You're also wasting space on making the app.is running(), you could easily replace it with a boolean, which consumes much less space or you could omit it if you don't have an exit button inside the application and just make your loop read the SDL_QUIT, this saves space for the file, mind the efficiency.
If this still doesn't work then try replacing the image your using, make a simple one on paint name it something like "grass.png" or anything then try it again.
Don't forget to put the file in the proper folder, in the DEBUG folder if you haven't specified a folder, and also put it in the app folder so it would also read it when it executes as an .exe file and not as part of the debug command.

How to draw pixels in SDL 2.0?

How does one draw with pixels in SDL2.0?
I'm trying to get familiar with C++, but this is very difficult to do without pretty pictures, so I'm trying to get a very basic graphics display thing running. All I really want it to do is give me a window, let me draw rgbα pixels on it, and access information about those pixels. There may be other things I want that I'm not aware of, but that's all that's on my list right now. My research on this has lead me to try using SDL, the current version being 2.0.
Almost all my graphics experience comes from using JavaScript on a <canvas>. Most of the other bit comes from my calculator, which has this really awesome Pxl-On() command, so easy.
I'm using MinGW for my C++, if it matters. Also, if there's something better** out there than SDL2.0 for what I need, advice welcome.
** "better" means "contains what functionality I need, but less total functionality than SDL2.0, and/or has a more intuitive/less complex*** API than SDL2.0."
*** Less lines of code to accomplish the same task.
Runnable example
Draws a diagonal red line pixel by pixel on the screen using SDL_RenderDrawPoint.
main.c
#include <stdlib.h>
#include <SDL2/SDL.h>
#define WINDOW_WIDTH 600
int main(void) {
SDL_Event event;
SDL_Renderer *renderer;
SDL_Window *window;
int i;
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_WIDTH, 0, &window, &renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
for (i = 0; i < WINDOW_WIDTH; ++i)
SDL_RenderDrawPoint(renderer, i, i);
SDL_RenderPresent(renderer);
while (1) {
if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
break;
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
GitHub upstream.
Compile and run:
gcc -std=c89 -Wextra -pedantic-errors -o main.out main.c -lSDL2
./main.out
If you want to set a large rectangle of pixels at once, e.g. the entire screen or a sprite, use SDL_Texture + SDL_RenderCopy and possibly SDL_TEXTUREACCESS_STREAMING, as that will be much faster. Examples at:
What is a Blit in SDL?
Rendering pixels from array of RGB values in SDL 1.2?
Tested on libsdl 2.0.2, Ubuntu 15.10.
I don't know how your code is structured. Assuming you have a SDL_Window and a SDL_Renderer, you just have to call SDL_RenderDrawPoint(renderer, x, y).
If you don't have a renderer nor window, you can create both with SDL_CreateWindowAndRenderer(). For example:
SDL_Window *window;
SDL_Renderer *renderer;
SDL_CreateWindowAndRenderer(800, 600, 0, &window, &renderer);
//Probably on a loop
SDL_RenderDrawPoint(renderer, 400, 300); //Renders on middle of screen.
SDL_RenderPresent(renderer);
This should draw a pixel on the middle of screen. To read a pixel is a little more complicated. You can use SDL_RenderReadPixels(), it is made for read an area, but you can always specify an area of 1x1. Read the wiki page if you really need it.
If you are having much trouble with SDL2 a recommend you to read the Lazy Foo tutorials. The SDL2 section still a work in progress, but there is enough material to begin learning.
I find Python + PySDL2 more easy to prototype with. Debug is also funny, because it is veeeery slooow for pixel graphics. =) Here is the complete code:
"""
The code is placed into public domain
by anatoly techtonik <techtonik#gmail.com>
"""
import sdl2
import sdl2.ext
sdl2.ext.init()
window = sdl2.ext.Window('', size=(300, 100))
window.show()
renderer = sdl2.ext.Renderer(window)
renderer.draw_point([10,10], sdl2.ext.Color(255,255,255))
renderer.present()
running = True
while running:
for e in sdl2.ext.get_events():
if e.type == sdl2.SDL_QUIT:
running = False
break
if e.type == sdl2.SDL_KEYDOWN:
if e.key.keysym.sym == sdl2.SDLK_ESCAPE:
running = False
break