SDL_CreateWindow fails, SDL_GetError shows nothing. Why does it fail? - sdl

I have a project that uses SDL 1.2 and want to migrate it to SDL 2.0. To keep things simple I tried writing a simple program just to get familiar with the changes.
However, SDL_CreateWindow is failing, and SDL_GetError is not showing anything. So I don't know why creating the window isn't working.
The window is actually created, but then disappears.
#include <SDL.h>
#include <stdio.h> // printf etc
#include <stdlib.h> // abs, malloc, realloc
#include <stdint.h> // uint8_t, uint16_t, int32_t
#define WIDTH 853
#define HEIGHT 480
int main(int argc, char** argv) {
SDL_Renderer* renderer;
SDL_Window* window;
SDL_Texture* screenTexture;
SDL_Event event;
Uint8* screenBuffer;
FILE* fp;
int quit = 0;
fp = fopen("SDL2test.log", "w");
if (!fp) {
printf("\nCould not create log file");
return -1;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(fp, "\nCould not initialise SDL: %s\n", SDL_GetError() );
return -2;
}
window = NULL;
if ( NULL == ( window = SDL_CreateWindow("SDL2 test",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, 0)));{
fprintf(fp, "Could not create SDL window: %s\n", SDL_GetError() );
SDL_Delay(3000);
SDL_Quit();
return -3;
}
if ( !( renderer = SDL_CreateRenderer(window, -1, 0) ) ); {
SDL_Quit();
return -4;
}
if ( !( screenTexture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT)));
screenBuffer = (Uint8*)malloc( sizeof(Uint8) * 3 * WIDTH * HEIGHT );
if (NULL == screenBuffer){
SDL_Quit();
return -5;
}
memset(screenBuffer, 0, 3 * WIDTH * HEIGHT); //set to black
SDL_UpdateTexture( screenTexture,
NULL,
screenBuffer,
WIDTH * sizeof(Uint8) );
while( !quit && ( SDL_WaitEvent(&event) ) ) {
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, screenTexture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}

This is your create window if statement:
if ( NULL == ( window = SDL_CreateWindow( ...code... ) ) ); //what is ; doing here
{
fprintf(fp, "Could not create SDL window: %s\n", SDL_GetError() );
SDL_Delay(3000);
SDL_Quit();
return -3;
}
Did you notice the ; at the end of first line?
This means the part of the code in the brackets gets executed every time. Basically the code looks like this:
if ( NULL == ( window = SDL_CreateWindow( ...code... ) ) ); //end of if
{ //gets executed every time
fprintf(fp, "Could not create SDL window: %s\n", SDL_GetError() );
SDL_Delay(3000);
SDL_Quit();
return -3;
}
There is at least one such error in the code.

Related

C++ SDL2 window not opening

i coded this.
#include <iostream>
#include "SDL.h"
int main(int argc , char** args)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* win = SDL_CreateWindow("my window", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (!win)
{
std :: cout << "Failed to create a window! Error: " << SDL_GetError() << "\n";
}
SDL_Surface* winSurface = SDL_GetWindowSurface(win);
SDL_UpdateWindowSurface(win);
SDL_FillRect(winSurface, NULL, SDL_MapRGB(winSurface->format, 255, 90, 120));
SDL_DestroyWindow(win);
win = NULL;
winSurface = NULL;
return 0;
}
when i compile it, it opens the window, and it immediately closes. But the console doesn't. Here is a screenshot of my console(maybe it could help solving the problem?)
Would there be any solution to get the Window to not close?
Would there be any solution to get the Window to not close?
Start up an event-handling loop and handle some events:
// g++ main.cpp `pkg-config --cflags --libs sdl2`
#include <SDL.h>
#include <iostream>
int main( int argc, char** argv )
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* win = SDL_CreateWindow("my window", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (!win)
{
std :: cout << "Failed to create a window! Error: " << SDL_GetError() << "\n";
}
SDL_Surface* winSurface = SDL_GetWindowSurface(win);
bool running = true;
while( running )
{
SDL_Event ev;
while( SDL_PollEvent( &ev ) )
{
if( ( SDL_QUIT == ev.type ) ||
( SDL_KEYDOWN == ev.type && SDL_SCANCODE_ESCAPE == ev.key.keysym.scancode ) )
{
running = false;
break;
}
}
SDL_FillRect(winSurface, NULL, SDL_MapRGB(winSurface->format, 255, 90, 120));
SDL_UpdateWindowSurface(win);
}
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}

SDL_Renderer works as global variable, but not if declared in main, and passed to the functions that require it instead

I've been going back over some SDL tutorials I did a while back to practice pointers/references, but I got stuck on something.
If I declare the SDL_Renderer globally everything works, but if I try to declare it in main, and pass the renderer to the functions that need it, I eventually get an SDL_Error saying "invalid renderer".
What works:
...
// Global vars
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;
SDL_Rect gSpriteClips[ 4 ];
LTexture gSpriteSheetTexture;
...
// called from main after SDL initialization
bool loadMedia()
{
bool success = true;
//Load sprite sheet texture
if( !gSpriteSheetTexture.loadFromFile( gRenderer, "img/dots.png" ) )
{
printf( "Failed to load sprite sheet texture!\n" );
success = false;
}
...
What doesn't work:
...
bool init( SDL_Window* window, SDL_Renderer* renderer, const int SCREEN_WIDTH, const int SCREEN_HEIGHT )
{
...
}
...
bool load_media( SDL_Renderer* renderer, LTexture& sprite_sheet_texture, SDL_Rect* sprite_clips )
{
bool success = true;
//Load sprite sheet texture
if( !sprite_sheet_texture.loadFromFile( renderer, "img/dots.png" ) )
{
printf( "Failed to load sprite sheet texture!\n" );
success = false;
}
...
int main(int argc, char* args[])
{
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Rect sprite_clips[ 4 ];
LTexture sprite_sheet_texture;
if( !init( window, renderer, SCREEN_WIDTH, SCREEN_HEIGHT ) )
{
std::cout << "Failed to initialize!\n";
}
else
{
if( !load_media( renderer, sprite_sheet_texture, sprite_clips ) )
{
std::cout << "Failed to load media!\n";
}
...
The texture class: (same file for both versions)
bool LTexture::loadFromFile( SDL_Renderer* gRenderer, const std::string &path )
{
// Get rid of preexisting texture
free();
// The final texture
SDL_Texture* newTexture = NULL;
// Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
std::cout << "Unable to load image! SDL_Image error: " << IMG_GetError() << std::endl;
}
else
{
// color key image
SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0, 0xFF, 0xFF ) );
// Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface ); <-- POINT OF FAILURE
if( newTexture == NULL )
{
std::cout << "Unable to create texture! SDL error: " << SDL_GetError() << std::endl; <-- THE ERROR I GET
}
...
The way I see it, SDL_CreateTextureFromSurface expects a pointer to an SDL_Renderer, which is what I'm passing. I don't understand why it matters if it's globally declared or declared in main. It should still just be a chunk of memory I'm pointing to somewhere.
I understand I must be passing it wrong, but I can't figure out how to do it correctly, and everything I've tried has produced the same error (passing the pointer as a reference, as a pointer to the pointer, etc.).
Side-note: I know I could just declare it globally or create a Singleton and be done with it, but this is more a learning exercise for me - so the point is to understand the pointer/reference aspect of the problem.
In the second snippet, if init changes the variable renderer, it will only change its local copy of the variable. It will not change the original variable renderer in the function main. This is because you are passing the variable by value. If you instead pass it by pointer or by reference, you will also modify the original variable's value. That way, your program will behave the same way as your global variable version.
Note that in order to pass a pointer to another function by pointer, you will need a pointer to a pointer. In your case you will need an SDL_Renderer **.
From the answer and advice by Andreas Wenzel, I now have a working solution. I thought I was passing by pointer, when I was actually passing by value. By passing a pointer to a pointer instead it works as intended.
I've included snippets below to show the difference from the code in the original question.
int main(int argc, char* args[])
{
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Rect sprite_clips[ 4 ];
LTexture sprite_sheet_texture;
if( !init( &window, &renderer, SCREEN_WIDTH, SCREEN_HEIGHT ) )
{
std::cout << "Failed to initialize!\n";
}
else
{
if( !load_media( &renderer, sprite_sheet_texture, sprite_clips ) )
{
std::cout << "Failed to load media!\n";
}
...
bool init( SDL_Window** window, SDL_Renderer** renderer, const int SCREEN_WIDTH, const int SCREEN_HEIGHT )
{
bool success = true;
// initialize SDL
if( SDL_Init( SDL_INIT_VIDEO) < 0 )
{
std::cout << "SDL could not initialize! SDL error: " << SDL_GetError() << std::endl;
success = false;
}
else
{
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
{
std::cout << "Warning: Linear texture filtering not enabled!\n";
}
// Create window
*window = SDL_CreateWindow(
"SDL Tutorial",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN
);
if( window == NULL )
{
std::cout << "Window could not be created! SDL error: " << SDL_GetError() << std::endl;
success = false;
}
else
{
// Create renderer for window
*renderer = SDL_CreateRenderer( *window, -1, SDL_RENDERER_ACCELERATED );
if( renderer == NULL )
{
std::cout << "Renderer could not be created! SDL error: " << SDL_GetError() << std::endl;
success = false;
}
...
bool load_media( SDL_Renderer** renderer, LTexture& sprite_sheet_texture, SDL_Rect* sprite_clips )
{
bool success = true;
//Load sprite sheet texture
if( !sprite_sheet_texture.loadFromFile( *renderer, "img/dots.png" ) )
{
printf( "Failed to load sprite sheet texture!\n" );
success = false;
}
...
void close( SDL_Window** window, SDL_Renderer** renderer )
{
//Destroy Window
SDL_DestroyRenderer( *renderer );
SDL_DestroyWindow( *window );
*window = NULL;
*renderer = NULL;
IMG_Quit();
SDL_Quit();
}

SDL2 empty transparent window in Linux

Here is some sample SDL2 code I tried to run on my Linux computer running Ubuntu 18.04 with KDE Plasma Desktop Environment (I have multiple desktop environments installed in case it is relevant):
#include<iostream>
#include<SDL2/SDL.h>
int main(int argc, char** argv)
{
if(SDL_Init(SDL_INIT_VIDEO) != 0){
std::cerr << "SDL_Init() Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window* win = SDL_CreateWindow(
"Hello world",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640,480,
0
);
if(win == nullptr){
std::cerr << "SDL_CreateWindow() Error: " << SDL_GetError() << std::endl;
return 1;
}
//Create and init the renderer
SDL_Renderer* ren = SDL_CreateRenderer(win, -1, 0);
if(ren == nullptr){
std::cerr << "SDL_CreateRenderer() Error: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(win);
return 1;
}
//Render something
SDL_RenderSetLogicalSize(ren,640,480);
//Set colour of renderer
SDL_SetRenderDrawColor(ren,255,0,0,255);
//Clear the screen to the set colour
SDL_RenderClear(ren);
//Show all the has been done behind the scenes
SDL_RenderPresent(ren);
//Delay so that we can see what is on the screen
SDL_Delay(5000);
//Clean Up
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
The red window that is supposed to appear appears only once when I run the program for the first time. All subsequent executions produce an empty transparent window with whatever is in the background. The background image drags along with the window.
I have tried SDL_WINDOW_SHOWN flag in SDL_CreateWindow() as well as SDL_RENDER_ACCELERATED flag for SDL_CreateRenderer().
The only way to produce the red screen again is to reboot the system.
I even compiled and ran this with an IDE (CodeLite) and I still got the same results.
This particular question on SO shows similar problems. But the OP isn't using Linux and the problem isn't exactly the same.
Other posts on this website mention event processing but I haven't gotten that far. If at all it is necessary, I would be grateful for some resources on it as the documentation doesn't explain much.
Update:This program runs fine on another computer running Lubuntu 18.10.
Replace the SDL_Delay() (which blocks all event processing like notifying X11/Wayland & your window manager that your process is still alive) with a loop that calls SDL_PumpEvents() somehow, either directly (like below) or indirectly via SDL_PollEvent()/SDL_WaitEvent():
const Uint32 startMs = SDL_GetTicks();
while( SDL_GetTicks() - startMs < 5000 )
{
SDL_PumpEvents();
//Render something
SDL_RenderSetLogicalSize(ren,640,480);
//Set colour of renderer
SDL_SetRenderDrawColor(ren,255,0,0,255);
//Clear the screen to the set colour
SDL_RenderClear(ren);
//Show all the has been done behind the scenes
SDL_RenderPresent(ren);
}
All together:
#include <iostream>
#include <SDL2/SDL.h>
int main( int argc, char** argv )
{
if( SDL_Init( SDL_INIT_VIDEO ) != 0 )
{
std::cerr << "SDL_Init() Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window* win = SDL_CreateWindow
(
"Hello world",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640, 480,
0
);
if( win == nullptr )
{
std::cerr << "SDL_CreateWindow() Error: " << SDL_GetError() << std::endl;
return 1;
}
//Create and init the renderer
SDL_Renderer* ren = SDL_CreateRenderer( win, -1, 0 );
if( ren == nullptr )
{
std::cerr << "SDL_CreateRenderer() Error: " << SDL_GetError() << std::endl;
SDL_DestroyWindow( win );
return 1;
}
const Uint32 startMs = SDL_GetTicks();
while( SDL_GetTicks() - startMs < 5000 )
{
SDL_PumpEvents();
//Render something
SDL_RenderSetLogicalSize( ren, 640, 480 );
//Set colour of renderer
SDL_SetRenderDrawColor( ren, 255, 0, 0, 255 );
//Clear the screen to the set colour
SDL_RenderClear( ren );
//Show all the has been done behind the scenes
SDL_RenderPresent( ren );
}
//Clean Up
SDL_DestroyRenderer( ren );
SDL_DestroyWindow( win );
SDL_Quit();
return 0;
}

Memset Segmentation Fault Core Dumped

#include <cstdlib>
#include <stdlib.h>
#include <iostream>
#include <SDL2/SDL.h>
int main ( int argc, char** argv )
{
const int height = 700;
const int width = 800;
if (SDL_Init(SDL_INIT_EVERYTHING) < 0){
std::cout << "SDL Failed to initalize" << std::endl;
return 1;
}
SDL_Window *window = SDL_CreateWindow("Particle Fire Explosion", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);
if (window == NULL){
SDL_Quit();
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, width, height);
if(renderer == NULL){
std::cout << "COULD NOT CREATE RENDERER" << std::endl;
SDL_DestroyTexture(texture);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
if(texture == NULL){
std::cout << "COULD NOT CREATE TEXTURE" << std::endl;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
Uint32 *buffer = new Uint32(width * height);
Uint32 *memsett = new Uint32(width * height * sizeof(Uint32));
memset(buffer, 0xFF, width*height*sizeof(Uint32));
SDL_UpdateTexture(texture, NULL, buffer, width*sizeof(Uint32));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer,texture, NULL, NULL);
SDL_RenderPresent(renderer);
bool quit = false;
SDL_Event event;
while (quit == false){
while(SDL_PollEvent(&event)){
if(event.type == SDL_QUIT){
quit = true;
}
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyTexture(texture);
delete [] buffer;
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
this Is my code, Im trying to make an all white window in SDL an dim trying to use memset to so this but it is not working. The bug says: Segmentation fault core dumped. It goes away when I remove the memset function, so I know that the memory meaning that memset is using is using memory not free so how do I change this?
Uin32 *buffer = new Uint32(width * height) allocates a single Uint32 with the value width * height, not an array of width * height Uint32s. Your call to memset then writes beyond the end of that single Uin32 and off into unowned memory.
You want [] instead of ():
Uint32* buffer = new Uint32[width * height];

Why the game window closes after specific time?

Why the window that created by SDL Game Library are automatically closed after specific time.
I know the reason is SDL_Delay() function, but if not used that function, the game will appear runtime error.
How can I create a window that continuously work without appear in specific period time ?
My code(Simplest code):
SDL_Window *window;
SDL_Renderer *render;
int main(int argc, char* args[]){
if(SDL_Init(SDL_INIT_EVERYTHING) >= 0){
window = SDL_CreateWindow("Simple game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
if(window != 0){
render = SDL_CreateRenderer(window, -1, 0);
}
}else{
return 1;
}
SDL_SetRenderDrawColor(render, 0, 0, 0, 255);
SDL_RenderClear(render);
SDL_RenderPresent(render);
SDL_Delay(3000);
SDL_Quit();
return 0
}
You need to loop forever and call SDL update screen functions. Read LazyFoo tutorials found here: http://lazyfoo.net/SDL_tutorials
Or here a short code to get you started:
#include <iostream>
#include "SDL/SDL.h" // basic SDL
#include <string>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BBP = 32; // bits per-pixel
SDL_Surface* screen = NULL; // display screen
SDL_Event event; // grab events
using namespace std;
bool init() {
// initialize SDL
if(SDL_Init( SDL_INIT_EVERYTHING ) == -1)
return false;
//the screen image
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT,
SCREEN_BBP, SDL_SWSURFACE );
if(!screen) {
cout << "error creating screen" << endl;
return false;
}
//Set the window caption
SDL_WM_SetCaption("Event Test", NULL );
return true;
}
int main(int argc, char* argv[])
{
try
{
// make sure the program waits for a quit
bool quit = false;
cout << "Starting SDL..." << endl;
// Start SDL
if(!init()) {
cout << "initialize error" << endl;
return false;
}
// main loop
while( quit == false )
{
if (SDL_PollEvent(&event))
{
// The x button click
if(event.type == SDL_QUIT)
{
//quit the program
quit = true;
}
}
// Fill the screen white
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB(
screen->format, 0xFF, 0xFF, 0xFF ) );
//Update screen
if(SDL_Flip(screen) == -1)
return -1;
}
}
catch (exception& e)
{
cerr << "exception caught: " << e.what() << endl;
return -1;
}
return 0;
}