I've recently decided to dive into writing a C++ game using SDL as one of my libraries. During the course of my program writing and learning about SDL, I stumbled across a peculiar bug in my program, and decided to replicate it in an SSCCE to make sure that I wasn't crazy.
The problem appears to be that when I pass SDL_RENDERER_PRESENTVSYNC as a flag to SDL_CreateRenderer, I get inconsistent rendering. To compare, I ran the program 50 times with, and 50 times without the flag, and made that the only change to my program in each case. Without the flag, the display worked 100% of the time. With the flag on, it only rendered successfully 13 out of the 50 times.
Here's the program:
#include <SDL2/SDL.h>
#include <iostream>
int main(int argc, char** argv)
{
if(SDL_Init(SDL_INIT_VIDEO) != 0)
{
std::cerr << "Unable to initialize SDL: " << SDL_GetError() << std::endl;
return -1;
}
SDL_Window* win = SDL_CreateWindow("Testing",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1,
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
for(int x = 0; x < 640; x+=32)
{
for(int y = 0; y < 480; y+=32)
{
SDL_Rect rect = {x+1, y+1, 31, 31};
SDL_RenderFillRect(renderer, &rect);
}
}
SDL_RenderPresent(renderer);
SDL_Delay(500);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
If it makes a difference, I'm compiling and testing the program on Ubuntu 15.04, GCC/G++ 4.9.2, Compiled and linked against SDL 2.0.2.
Being so new to SDL, and still relatively new to both C++ and C (I come from a Java background), I think it's very likely that I've made a simple error that I'm not catching, but I can't think of what I might have done.
For those seeing this question in the future, the problem appears to have resolved itself a little over a year later, as I can no longer replicate my own SSCCE. It may be a change of environment, as I am not using the same system and am now using an Nvidia Graphics Card. The problem, though I can no longer verify this, was almost certainly in the environment or the hardware. That same laptop ended up failing (motherboard issues) a mere month or two later, so take from that what you will. Consider checking your hardware health and attempting a completely clean environment if you are experiencing this same issue.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 months ago.
Improve this question
I'm starting a new project in SDL2 and as I'm still trying out different architectural approaches I usually start out by bringing up a white window to confirm that the new approach I'm trying out satisfies at least the bare minimum to get started with SDL2.
This time, I wanted to try wrapping my application into a separate Application class so as to unclutter main, like so:
#include <SDL2/SDL.h>
#include <stdio.h>
#include <string>
#include "HApplication/HApplication.h"
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main(int argc, char *argv[])
{
HApplication application = HApplication( SCREEN_WIDTH, SCREEN_HEIGHT );
bool hasStarted = application.checkRunning();
if ( hasStarted ){
application.run();
}
else{
std::string msg = "Application failed to initialize.";
SDL_LogError( SDL_LOG_CATEGORY_ERROR, msg.c_str() );
}
// add error codes
return 0;
}
Now, the run method in HApplication is meant to reflect the main loop until the user exits. For test purposes, I'd just like to get two lines crossing in the middle on a white background. After initializing SDL, the window, and the renderer, which all work out fine, I'm presented with a window filled completely back, although I've used very similar code successfully before:
void HApplication::run()
{
// while user doesn't quit, keep going
bool userQuit = false;
SDL_Event e
while( !userQuit )
{
// handle queued events
while ( SDL_PollEvent( &e ) != 0 )
{
if ( e.type == SDL_QUIT )
{
userQuit = true;
}
}
// clear screen
SDL_SetRenderDrawColor( appRenderer, 255, 255, 255, 255);
SDL_RenderClear( appRenderer );
// draw cross
SDL_SetRenderDrawColor( appRenderer, 0, 0, 0, 255 );
SDL_RenderDrawLine( appRenderer, 0, screenHeight/2, screenWidth, screenHeight/2);
SDL_SetRenderDrawColor( appRenderer, 0, 0, 0, 255 );
SDL_RenderDrawLine( appRenderer, screenWidth/2 , 0, screenWidth/2, screenHeight);
// update screen with new scene
SDL_RenderPresent( appRenderer );
SDL_UpdateWindowSurface( appWindow );
}
close();
}
I'm not quite sure why this happens, especially since I can see what I want stepping through the loop step-by-step using the debugger. I am quite honestly pretty much at a loss at where to even start.
I tried looking on Google and Stackoverflow for similar questions. However, these were mostly addressing problems with loading textures, which I haven't even gotten to yet.
If possible, I would like to keep a separate class handling game logic and resources.
EDIT: It seems like I needed to get rid of SDL_UpdateWindow. However, I'm not quite sure why. If anyone has an explanation, I'd be happy to hear!
SDL has both a CPU rendering API and a GPU one.
Everything that works with a SDL_Renderer belongs to the GPU API. For example, you can make a SDL_Texture and use SDL_RenderCopy to render it. The final step is to call SDL_RenderPresent so that everything that was rendered gets displayed.
SDL_UpdateWindowSurface is part of the CPU API. To use this API, you can for example draw to a SDL_Surface and then use SDL_BlitSurface with SDL_GetWindowSurface to render to the window's surface. The final step is to call SDL_UpdateWindowSurface to display the changes, which is the equivalent to SDL_Flip in SDL 1.2.
In short: after the SDL_RenderPresent call, you get what you wanted, but after the SDL_UpdateWindowSurface call, you overwrite that with the CPU window surface which is probably initialized to black. Just remove that SDL_UpdateWindowSurface call and use the GPU API only.
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.
When using SDL2 (2.0.8), drawing a 2D rectangle or a line with SDL_RenderDrawRect or SDL_RenderDrawLine is not pixel perfect. There are some artifacts. Why is that? And is there a way to prevent that?
Code example:
#ifdef WIN32
#include "SDL.h"
#else
#include "SDL2/SDL.h"
#endif
int main(int argc, char* args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, 0,SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_Event event;
bool quit = false;
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
{
quit = true;
break;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderDrawLine(renderer, 40, 10, 60, 10);
SDL_Rect rect{10, 10, 20, 20};
SDL_RenderDrawRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
return 0;
}
Environment:
Acer Laptop, Intel HD Graphics, NVIDIA GEFORCE 940m, Windows 10
In my Windows 10 display settings "Scale and Layout" was set to "125%". After Setting it to "100%" the rendering was pixel perfect.
Windows 10 display settings
Though this is just a workaraound. The real solution is to call the Windows API function "SetProcessDpiAwareness". I found the answer and code to do that on different Windows versions in this link:
SetProcessDpiAwareness
There are different methods to set the DPI awareness depending on the Windows OS version. It can be set programmatically or by Application Manifest. See the
Microsoft docs.
Setting "Scale and Layout" back to "125%" and calling that function at the begin of my application gives the expected result.
this dude is right. But SetProcessDpiAwareness is undefined in my case.
SetProcessDPIAware() work for me.
#ifdef _WIN32
#include <windows.h>
#endif
int main(int, char**)
{
#ifdef _WIN32
SetProcessDPIAware();// Fix DPI settings
#endif
//some code
}
I hope this code helps.
Take a look at this:
https://wiki.libsdl.org/SDL_HINT_RENDER_SCALE_QUALITY
Make sure to disable this and set it to 0. You may also wish to ensure anti-aliasting is disabled in your video drivers/NVIDIA Control Panel.
There are many upstream factors that may cause this.
I've been trying to improve my C++ skills and explore different ways of programming in it by using libraries like SDL.
This particular program is a Particle system and i've followed a guide on youtube that can be found here: http://www.youtube.com/watch?v=6Z5FI5180oo&list=UU6A2B9G_y-fzAXEu2hHPlMg.
The problem is that this guide is using SDL 1.2 and i've been trying to translate the depricated functions used in here to SDL 2.0.
Basically it works fine apart from some functions where i try to retrieve the width/height/pixels/pitch from the Windowsurface. SDL 1.2 uses the function GetVideoSurface() whereas i do believe SDL2.0 should use GetWindowSurface().
I'm having problems with accessing this function outside of my main function and i'm not sure what the problem really is.
For example in my particle::show() function i have this code:
void particle::show()
{
Uint8* pixels=(Uint8*)SDL_GetWindowSurface(window)->pixels;
Uint8* pixel=pixels+(int)y*SDL_GetWindowSurface(window)->pitch+(int)x;
*pixel=color;
}
Here i can't access these functions, i get no error message. Even if i try to use SDL_GetError(). The program crashes with a segmentation fault and no other errors (that i can see.)
This is my main function:
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("My Particles",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, SDL_WINDOW_OPENGL);
bool running = true;
const int FPS = 30;
Uint32 start;
srand(time(0));
particleEngine ps (100, SDL_GetWindowSurface(window)->w/2, SDL_GetWindowSurface(window)->h/2);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
while(running)
{
start = SDL_GetTicks();
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running = false;
break;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
ps.refresh();
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
I've defined my SDL_Window *window outside of every function as a global variable.
I'm running SDL 2.0 and Mac OS X 10.10 Yosemite Beta 2
Any ideas how i should solve this?
SDL_Window *window is a local variable in the int main(int argc, char** argv) function. It will not be visible outside of main unless you either make it a global variable (not nice) or make it a member of a class which you create an instance of.
Alternatively you could pass the pointer to the SDL_Window to the functions which you need it in.
I noticed you said you have declared it as a global variable and in that case that is why it compiles but doesn't work. The variable used in the particle::show() will be using the global variable which will points to nothing (globals are always zero-initialized by default). As you declare SDL_Window again in main() that is what gets assigned the created window.
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