Invalid renderer SDL2 - c

I am looking through the code and i cant find solution for the problem of invalid renderer. I am beginner with SDL2 and i have to write code in pure C.
I think that in my code there is more errors but because of this one i cant go further. Code is half in polish language so if u cant get what is where i can rewrite this a bit . Problem occure when in main i try to load function"Odczyt_z_Pliku". Probably somewhere there is a problem.
SDL_GetError() says" invalid renderer.
#include<SDL.h>
#include<stdio.h>
#include<SDL_image.h>
#pragma warning(disable : 4996)
#define WYSOKOSC_EKRANU 768
#define SZEROKOSC_EKRANU 1024
typedef enum bool{
false,true
}bool;
typedef struct sTekstura {
int wysokosc;
int szerokosc;
SDL_Texture *Tekstura;
}sTekstura;
void IniTekstury(sTekstura T)
{
T.wysokosc = 0;
T.szerokosc = 0;
T.Tekstura = NULL;
}
void free(sTekstura T)
{
//Free texture if it exists
if (T.Tekstura != NULL)
{
SDL_DestroyTexture(T.Tekstura);
T.Tekstura = NULL;
T.szerokosc = 0;
T.wysokosc = 0;
}
}
int Odczyt_z_Pliku(char nazwa[50],sTekstura T,SDL_Renderer* Renderer)
{
free(T);
SDL_Texture* nTekstura = NULL;
//Load image at specified path
SDL_Surface* Powierzchnia = IMG_Load(nazwa);
if (Powierzchnia == NULL)
{
printf("Unable to load image %s! SDL_image Error: %s\n", nazwa, IMG_GetError());
}
else
{
SDL_SetColorKey(Powierzchnia, SDL_TRUE, SDL_MapRGB(Powierzchnia->format, 0xFF, 0xFF, 0xFF));
//Create texture from surface pixels
nTekstura = SDL_CreateTextureFromSurface(Renderer, Powierzchnia);
if (nTekstura == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", nazwa, SDL_GetError());
}
else
{
//Get image dimensions
T.szerokosc = Powierzchnia->w;
T.wysokosc = Powierzchnia->h;
}
//Get rid of old loaded surface
SDL_FreeSurface(Powierzchnia);
}
//Return success
T.Tekstura = nTekstura;
if (T.Tekstura != NULL)
{
return 1;
}
else
{
return 0;
}
}
bool Inicjalizacja(SDL_Window *Okno,SDL_Renderer *Renderer)
{
//Initialization flag
bool success = true;
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
printf("Warning: Linear texture filtering not enabled!");
}
//Create window
Okno = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SZEROKOSC_EKRANU, WYSOKOSC_EKRANU, SDL_WINDOW_SHOWN);
if (Okno == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create renderer for window
Renderer = SDL_CreateRenderer(Okno, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (Renderer == NULL)
{
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor(Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
success = false;
}
}
}
}
return success;
}
void setBlendMode(sTekstura T, SDL_BlendMode blending) //MK: Funkcja ustawiająca przezroczystosc
{
//Set blending function
SDL_SetTextureBlendMode(T.Tekstura, blending);
}
void setAlpha(sTekstura T,Uint8 alpha) //MK: Funkcja ustawiająca przezroczystość
{
//Modulate texture alpha
SDL_SetTextureAlphaMod(T.Tekstura, alpha);
}
void render(int x, int y,sTekstura T,SDL_Renderer *Renderer)
{
//Set rendering space and render to screen
SDL_Rect renderQuad = { x, y, T.szerokosc, T.wysokosc };
SDL_RenderCopy(Renderer, T.Tekstura, NULL, &renderQuad);
}
int main(int argc, char *argv[])
{
SDL_Window * Okno = NULL;
SDL_Renderer* Renderer = NULL;
sTekstura TloMenu;
TloMenu.szerokosc = 0;
TloMenu.wysokosc = 0;
TloMenu.Tekstura = NULL;
sTekstura TloGra;
TloGra.szerokosc = 0;
TloGra.wysokosc = 0;
TloGra.Tekstura = NULL;
sTekstura Pudlo;
Pudlo.szerokosc = 0;
Pudlo.wysokosc = 0;
Pudlo.Tekstura = NULL;
sTekstura Sciana;
Sciana.szerokosc = 0;
Sciana.wysokosc = 0;
Sciana.Tekstura = NULL;
sTekstura StartGry;
StartGry.szerokosc = 0;
StartGry.wysokosc = 0;
StartGry.Tekstura = NULL;
sTekstura KoniecGry;
KoniecGry.szerokosc = 0;
KoniecGry.wysokosc = 0;
KoniecGry.Tekstura = NULL;
SDL_Event e;
//Start up SDL and create window
if (!Inicjalizacja(Okno,Renderer))
{
printf("Failed to initialize!\n");
}
else
{
if(!Odczyt_z_Pliku("MENU BOMBERMAN.png", Sciana, Renderer))
{
puts("Nie wczytano kostki");
return 0;
}
if (!Odczyt_z_Pliku("pudlo3.bmp", Pudlo, Renderer))
{
puts("Nie wczytano pudla");
return 0;
}
if (!Odczyt_z_Pliku("MenuBomberman.bmp", TloMenu, Renderer))
{
puts("Nie wczytano menu");
return 0;
}
if (!Odczyt_z_Pliku("Mapa.bmp", TloGra, Renderer))
{
puts("Nie wczytano mapy");
return 0;
}
if (!Odczyt_z_Pliku("NEW GAME.bmp", StartGry, Renderer))
{
puts("Nie wczytano napisu nowej gry");
return 0;
}
else
{
//Set standard alpha blending
setBlendMode(StartGry, SDL_BLENDMODE_BLEND);
}
if (!Odczyt_z_Pliku("exitgimp.bmp", KoniecGry, Renderer))
{
puts("Nie wczytano napisu koniec gry");
return 0;
}
else
{
//Set standard alpha blending
setBlendMode(StartGry, SDL_BLENDMODE_BLEND);
}
//Main loop flag
bool quit = false;
//Modulation component
Uint8 AlphaStartu = 255;
Uint8 AlphaKonca = 127;
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
//Handle key presses
else if (e.type == SDL_KEYDOWN)
{
//Increase alpha on w
if (e.key.keysym.sym == SDLK_w)
{
AlphaKonca = 127;
AlphaStartu = 255;
}
//Decrease alpha on s
else if (e.key.keysym.sym == SDLK_s)
{
AlphaKonca = 256;
AlphaStartu = 127;
}
}
}
//Clear screen
SDL_SetRenderDrawColor(Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(Renderer);
//Render background
render(0, 0, TloMenu, Renderer);
//Render front blended
setAlpha(KoniecGry,AlphaKonca);
setAlpha(StartGry, AlphaStartu);
render(0, 0,StartGry,Renderer);
render(0, 0,KoniecGry,Renderer);
//Update screen
SDL_RenderPresent(Renderer);
}
}
//Free resources and close SDL
close();
return 0;
}

When you get to Odczyt_z_Pliku, Renderer is still a NULL pointer.
As it stands, in your main() function you have a variable Renderer of type SDL_Renderer* (initialized to NULL). You then pass that value NULL into SDL_Renderer* which also takes an argument of type SDL_Renderer*.
However, in C this is just a pass by copy of the value of the pointer itself (not the value pointed to by the pointer). In other words, the argument Renderer to your function just creates a local variable in that function. So in Odczyt_z_Pliku when you do Renderer = SDL_CreateRenderer(...); that may return a new pointer but it's only assigning it to the local variable Renderer, but this has no effect on the Renderer variable in your main() function.
In C, the way to write a function that sets the value of a pointer that is a local variable in the calling function is to use a double pointer. That is, change the signature of Inicjalizacja to
bool Inicjalizacja(SDL_Window **Okno, SDL_Renderer **Renderer)
then in main() (or wherever else) call it like:
SDL_Window * Okno = NULL;
SDL_Renderer* Renderer = NULL;
...
if (!Inicjalizacja(&Okno, &Renderer)) {
...
}
and so on. (Note: You made the same mistake with the SDL_Window Okno as well, and possibly elsewhere--I haven't read the full code).
The syntax &Okno means pass the address of (i.e. a pointer to) the variable Okno. Since Okno is itself a pointer, the address of the pointer is a double pointer.
Then in Inicjalizacja write:
*Renderer = SDL_CreateRenderer(...);
and similarly with Okno. The *Renderer syntax (which I find somewhat confusing) means the value pointed to by a pointer. Since Renderer here is a double pointer, this means assign the single pointer (of type Renderer*) into the pointer pointed to by Renderer. Now the Renderer* pointer in your main() function will be properly initialized.
Note, similarly you should change the following check to:
if (*Renderer == NULL) {...}
and so on. We know Renderer != NULL since it's a pointer to a local variable allocated in our main() function. The interesting question is what value SDL_CreateRenderer returned, so we want to look at *Renderer.

Related

Crash when opening a SDL window in a thread on MacOs [duplicate]

I am trying to create a process with two windows. Each window has a different thread for drawing. The problem is that when I run the program, after a random amount of time something goes wrong and gives me a segmentation fault. Here is my code:
main.cpp
std::thread *thr1 = new std::thread(thread_func);
std::thread *thr2 = new std::thread(thread_func);
thread.cpp:
Window *win = new Window(display_name, 1024, 768);
Renderer *rend = win->CreateRenderer();
Texture *pic = new Texture(rend, path);
while (!quit)
{
usleep (10000);
pic->DrawToWindow(src_rect,rect);
rend->SetColor(255,255,255,255);
rend->DrawLine(10,10,300,300,4);
}
delete pic;
delete rend;
delete win;
Window.cpp:
Window::Window(std::string &name, uint32_t w, uint32_t h, uint32_t x, uint32_t y)
: window(nullptr),
windowRect()
{
if (!SDL_WasInit(SDL_INIT_VIDEO))
{
PDEBUG("ERROR: SDL Was not inited please init platform first!\n");
return;
}
//Create Window
window = SDL_CreateWindow(name.c_str(), x, y, w, h, SDL_WINDOW_OPENGL);
if (window == nullptr)
{
PDEBUG("ERROR: SDL_CreateWindow() %s\n", SDL_GetError());
return;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
}
Window::~Window()
{
if (window != nullptr)
{
SDL_DestroyWindow(window);
window = nullptr;
}
}
void
Window::Flush()
{
SDL_GL_SwapWindow(window);
}
Renderer*
Window::CreateRenderer()
{
return new Renderer(this);
}
Renderer.cpp:
Renderer::Renderer(Window *win)
: window(win),
render(nullptr),
context()
{
if (win == nullptr)
{
PDEBUG("ERROR: Window is NULL\n");
return;
}
//Create Renderer
render = SDL_CreateRenderer(win->window, -1, SDL_RENDERER_ACCELERATED);
if (render == nullptr)
{
PDEBUG("ERROR: SDL_CreateRenderer(): %s\n", SDL_GetError());
return;
}
//Create Window OpenGL Context
//context = SDL_GL_CreateContext(win->window);
//if (SDL_GL_MakeCurrent(window->window, context) != 0)
// PDEBUG("ERROR: SDL_GL_MakeCurrent() %s\n", SDL_GetError());
Clear();
}
Renderer::~Renderer()
{
if (render != nullptr)
{
SDL_DestroyRenderer(render);
render = nullptr;
//SDL_GL_DeleteContext(context);
}
}
bool
Renderer::DrawLine(int xStart, int yStart, int xEnd, int yEnd, int width)
{
//if (SDL_GL_MakeCurrent(window->window, context) != 0)
// PDEBUG("ERROR: SDL_GL_MakeCurrent() %s\n", SDL_GetError());
//}
glLineWidth(width);
if (SDL_RenderDrawLine(render, xStart, yStart, xEnd, yEnd) < 0)
{
PDEBUG("ERROR: SDL_RenderDrawLine() %s\n", SDL_GetError());
return false;
}
return true;
}
Do I have to draw in only one thread for two windows, use synchronization to drawing, or use SDL_Thread for threads?
Did i have to draw in only one thread for two windows
Yes.
From the SDL2 threading documentation:
NOTE: You should not expect to be able to create a window, render, or receive events on any thread other than the main one. For platform-specific exceptions or complicated options ask on the mailing list or forum.
Hello I found a solution for 2 windows in different threads.
Here is example:
static bool quit = false;
void
thread_function(SDL_Window* win, SDL_Renderer *rend)
{
SDL_Event event;
while(!quit)
{
//DO THINGS with renderer and window. (Draw, Fill, Present Textures and others)
SDL_PollEvent(&event);
}
}
For Every thread you need to poll event because window events also are in Event Query.

Issue closing window with SDL2 in C

I have this code that is setting up a window, along with the close button functionality.
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
int initialize();
void handle_input();
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
bool running;
int FPS;
int width;
int height;
bool close_requested;
} Game;
Game game = {
.running = true,
.FPS = 60,
.width = 600,
.height = 600,
.close_requested = false,
};
int main(int argc, char* argv[]) {
initialize();
handle_input();
while(game.running) { //Game loop
SDL_SetRenderDrawColor(game.renderer, 255, 0, 0, 255);
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
} //End of game loop
SDL_DestroyRenderer(game.renderer);
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}
int initialize() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { //return 0 on success
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, game.width, game.height, 0); //creates window
if (!window) {
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //creates a renderer
game.renderer = SDL_CreateRenderer(window, -1, render_flags);
if (!game.renderer) {
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
void handle_input() {
SDL_Event event;
while (!game.close_requested) { //close button
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
}
}
}
However, whenever I try to run this program, the window won't even open and I'm getting 0 errors in the console, besides a warning that states control may reach end of non-void function at the initialize() function. What does that warning mean? What is going on with my code? What did I do wrong?
I see 2 issues here:
you call handle_input() in your main before you enter the main loop and it gets stuck there until you exit, so SDL_RenderPresent() is never called.
the initialize function doesn't return anything in case of success, this is why you see the warning.
Try with the following changes, in main() move your input handling inside the loop:
int main(int argc, char* argv[]) {
initialize();
while(game.running && !game.close_requested) {
handle_input(); // <-- move here
SDL_SetRenderDrawColor(game.renderer, 255, 0, 0, 255);
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
}
// the rest...
}
In initialize() add a return 0; at the end.
In handle_input() remove the outer loop:
void handle_input() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
}
}

C SDL VS Code image is not displaying

I have recently started learning game programming in C. I am using a virtual studio code on linux Ubuntu, and image star.png is not displaying on the screen, there are no errors or problems reported by vs code. I have tried reinstalling sdl2-dev and sdl2-image-dev libraries. Maybe it is a problem with SDL, or maybe with my code (it was written in 2013).
The code should draw a white ractangl, which i can move around, on a blue screen and place a star in upper left corner of a window. It does everything except placing a star.
The code: (doesn't show "Cannot dinf star.png!" so I guess it is not that)
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
typedef struct
{
int x, y;
short life;
char *name;
}Man;
typedef struct
{
//players
Man man;
//image
SDL_Texture *star;
} GameState;
/////////////////////////////////////////////////////////////////////processEvents
int processEvents(SDL_Window *window , GameState *game)
{
SDL_Event event;
int done = 0;
//Check for events
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_WINDOWEVENT_CLOSE:
{
if (window)
{
SDL_DestroyWindow(window);
window = NULL;
done = 1;
}
}
break;
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
done = 1;
break;
}
}
break;
case SDL_QUIT:
done = 1;
break;
}
}
const Uint8 *state = SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_LEFT])
{
game->man.x -= 1;
}
if(state[SDL_SCANCODE_RIGHT])
{
game->man.x += 1;
}
if(state[SDL_SCANCODE_UP])
{
game->man.y -= 1;
}
if(state[SDL_SCANCODE_DOWN])
{
game->man.y += 1;
}
SDL_Delay(10);
return done;
}
/////////////////////////////////////////////////////////////////////////////////////doRender
void doRedner(SDL_Renderer *renderer, GameState *game)
{
SDL_SetRenderDrawColor(renderer , 0, 0, 255, 255); //blue
//screen clean up into blue
SDL_RenderClear(renderer);
//set color
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Rect rect = {game->man.x, game->man.y, 80, 80};
SDL_RenderFillRect(renderer, &rect);
//draw a star
SDL_Rect starRect = { 50, 50, 64, 64 };
SDL_RenderCopy(renderer, game->star, NULL, &starRect);
SDL_RenderPresent(renderer);
}
/////////////////////////////////////////////////////////////////////////////////////main funkction
int main(int argc, char *argv[])
{
GameState gameState;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Surface *starSurface = NULL;
SDL_Init(SDL_INIT_VIDEO);
gameState.man.x = 340-40;
gameState.man.y = 240-40;
window = SDL_CreateWindow("Game Widnow",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
0
);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
//load image
starSurface = IMG_Load("star.png");
if(starSurface = NULL)
{
printf("Cannot find star.png!\n\n");
SDL_Quit();
return 1;
}
gameState.star = SDL_CreateTextureFromSurface(renderer, starSurface);
SDL_FreeSurface(starSurface);
int done = 0;
while(!done)
{
//check events
done = processEvents(window, &gameState);
//render
doRedner(renderer, &gameState);
}
SDL_Delay(1000);
//exit game and free memory
SDL_DestroyTexture(gameState.star);
//destroy and close window
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
TL;DR: Your intention is to perform a comparison, but you are using the assignment operator (i.e., =) instead of the comparison operator ==.
The conditional expression in your if statement:
if(starSurface = NULL)
{
...
}
does not check whether starSurface is NULL. The expression starSurface = NULL assigns NULL to starSurface and evaluates to NULL. Therefore, the condition evaluates to false and no error message is displayed.
Instead, you should write (note the double = below):
if (starSurface == NULL)
or just:
if (!starSurface)

SDL2 doesn't render multiple viewports

I'm working through Lazy Foo's SDL2 tutorials and stuck trying to render multiple viewports. The idea is to load a PNG as a texture, create SDL_Rect structs for 3 different viewports (top left, top right, bottom), then copy the texture onto each viewport, and finally render all 3 viewports. My code is only rendering the first viewport.
I've tried changing the order - in every case, whichever viewport is defined first is the only one that renders.
I also tried changing the viewport dimensions, in case overlap was the issue - same problem.
The only question I found about multiple viewports didn't point me in the right direction. But it did start me thinking - my code is written in C, the tutorial in C++. Although I think I'm translating everything correctly (the other lessons work fine), maybe I'm missing something obvious here?
I'm compiling with CFLAGS = -Wall -Wextra -pedantic -std=c99 - no warnings or errors.
Edit: I tried rendering filled rectangles instead of a loaded PNG, but the issue is the same - only the first one renders.
Here's my code:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
int init_renderer();
int load_media();
SDL_Texture *load_texture(char *);
void close_renderer();
SDL_Window *g_window = NULL;
SDL_Renderer *g_renderer = NULL;
SDL_Texture *g_texture = NULL;
int main()
{
if (init_renderer() != 1) {
return -1;
}
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
printf("Warning: Linear texture filtering not enabled!\n");
}
if (load_media() != 1) {
return -1;
}
int quit = 0;
SDL_Event e;
while (quit != 1) {
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT || e.key.keysym.sym == SDLK_q) {
quit = 1;
}
}
SDL_SetRenderDrawColor(g_renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(g_renderer);
SDL_Rect top_left_vp;
top_left_vp.x = 0;
top_left_vp.y = 0;
top_left_vp.w = SCREEN_WIDTH / 2;
top_left_vp.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport(g_renderer, &top_left_vp);
SDL_RenderCopy(g_renderer, g_texture, NULL, NULL);
SDL_Rect top_right_vp;
top_right_vp.x = SCREEN_WIDTH / 2;
top_right_vp.y = 0;
top_right_vp.w = SCREEN_WIDTH / 2;
top_right_vp.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport(g_renderer, &top_right_vp);
SDL_RenderCopy(g_renderer, g_texture, NULL, NULL);
SDL_Rect bottom_vp;
bottom_vp.x = 0;
bottom_vp.y = SCREEN_HEIGHT / 2;
bottom_vp.w = SCREEN_WIDTH;
bottom_vp.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport(g_renderer, &bottom_vp);
SDL_RenderCopy(g_renderer, g_texture, NULL, NULL);
SDL_RenderPresent(g_renderer);
}
close_renderer();
return 0;
}
int init_renderer()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Failed to initialize SDL. Error: %s\n", SDL_GetError());
return 0;
}
g_window = SDL_CreateWindow("SDL Tuts",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
if (g_window == NULL) {
printf("Failed to create window. Error: %s\n", SDL_GetError());
return 0;
}
g_renderer = SDL_CreateRenderer(g_window, -1, SDL_RENDERER_ACCELERATED);
if (g_renderer == NULL) {
printf("Failed to create renderer. Error: %s\n", SDL_GetError());
return 0;
}
SDL_SetRenderDrawColor(g_renderer, 0x29, 0xAB, 0x87, 0xFF);
int img_flags = IMG_INIT_PNG;
if (!(IMG_Init(img_flags) & img_flags)) {
printf("Failed to initialize SDL Image. SDL_Image Error: %s\n", IMG_GetError());
return 0;
}
return 1;
}
int load_media()
{
g_texture = load_texture("assets/texture.png");
if (g_texture == NULL) {
return 0;
}
return 1;
}
SDL_Texture *load_texture(char *path)
{
SDL_Texture *new_texture = NULL;
SDL_Surface *loaded_surface = IMG_Load(path);
if (loaded_surface == NULL) {
printf("Failed to load image. SDL_Image Error: %s\n", IMG_GetError());
} else {
new_texture = SDL_CreateTextureFromSurface(g_renderer, loaded_surface);
if (new_texture == NULL) {
printf("Failed to create texture from %s. Error: %s\n", path, SDL_GetError());
}
SDL_FreeSurface(loaded_surface);
}
return new_texture;
}
void close_renderer()
{
SDL_DestroyTexture(g_texture);
g_texture = NULL;
SDL_DestroyRenderer(g_renderer);
SDL_DestroyWindow(g_window);
g_renderer = NULL;
g_window = NULL;
IMG_Quit();
SDL_Quit();
}
To check for more errors, you should see what the calls to SDL_RenderSetViewPort are returning. According to the docs, it returns an int, which is 0 on success or a negative int if there's an error. It's entirely possible that something deeper in SDL is having a fit.
Additional pro tips: you can define the SDL_Rect structs outside of your while loop to save a miniscule margin of processing power. And to spare yourself some typing, you can initialize a SDL_Rect using a list constructor instead of manually punching each property. E.G.:
SDL_Rect top_left_vp;
top_left_vp.x = 0;
top_left_vp.y = 0;
top_left_vp.w = SCREEN_WIDTH / 2;
top_left_vp.h = SCREEN_HEIGHT / 2;
is more simply
SDL_Rect top_left_vp = {
0,
0,
SCREEN_WIDTH / 2,
SCREEN_HEIGHT / 2
};

SDL2 - 'SDL_HWSURFACE' undeclared (first use in this function)

I got an existing old project in C language with old version of SDL 1.2,
i am trying to make it run and after installing the SDL, I found out that my PC is 64 bit so I need the new SDL2, after re-installing the right SDL2, i configured the include lines to point to SDL2 folder instead of the old SDL and when i try to run I am receiving 2 errors:
1 - 'SDL_HWSURFACE' undeclared (first use in this function)
2 - 'SDL_SetColorKey' undeclared (first use in this function)
PS - working with MINGW compiler
any ideas?
I am attaching the code, but it is a long one...
/*
* GuiFramework.c
*
* Created on: 24 áñôè 2014
* Author: Ilias
*/
#include "GuiFramework.h"
static Control* root = NULL;
static SDL_Surface* surface = NULL;
static SDL_Surface* image = NULL;
static int click_x, click_y;
static Control* foundButton = NULL;
static int quit = FALSE;
static int enabled = FALSE;
static int visible = FALSE;
static int onlyEnabled = TRUE;
Control* allocControl() {
Control* control = malloc(sizeof(Control));
if (control == NULL) {
perror_message("malloc");
freeControls(root);
exit(0);
}
control->children = NULL;
control->parent = NULL;
control->next = NULL;
control->clip = NULL;
control->onClick = NULL;
control->onDraw = NULL;
control->enabled = TRUE;
control->visible = TRUE;
return control;
}
SDL_Rect* createRect(int x, int y, int w, int h) {
SDL_Rect* rect = malloc(sizeof(SDL_Rect));
if (rect == NULL) {
perror_message("malloc");
freeControls(root);
exit(0);
}
rect->w = w;
rect->h = h;
rect->x = x;
rect->y = y;
return rect;
}
Control* createButton(Control* parent, SDL_Rect* dim, SDL_Rect* clip, void (*func)(Control*), int enabled) {
Control* control = allocControl();
appendControl(parent, control);
control->type = BUTTON;
control->dim = dim;
control->abs = createRect(parent->abs->x + dim->x, parent->abs->y + dim->y, dim->w, dim->h);
control->clip = clip;
control->onClick = func;
control->visible = parent->visible;
control->enabled = enabled && control->visible;
return control;
}
Control* createPanel(Control* parent, SDL_Rect* dim, void (*func)(Control*), int visible) {
Control* control = allocControl();
appendControl(parent, control);
control->type = PANEL;
control->dim = dim;
control->abs = createRect(parent->abs->x + dim->x, parent->abs->y + dim->y, dim->w, dim->h);
control->onDraw = func;
control->visible = parent->visible && visible;
return control;
}
Control* createImage(Control* parent, SDL_Rect* dim, SDL_Rect* clip) {
Control* control = allocControl();
appendControl(parent, control);
control->type = IMAGE;
control->dim = dim;
control->abs = createRect(parent->abs->x + dim->x, parent->abs->y + dim->y, dim->w, dim->h);
control->clip = clip;
control->visible = parent->visible;
return control;
}
Control* createWindow(int width, int height, char* caption) {
Control* control = allocControl(NULL);
control->type = WINDOW;
control->dim = createRect(0, 0, width, height);
control->abs = createRect(0, 0, width, height);
/* Initialize the surface for resize issues */
if (surface != NULL) {
SDL_FreeSurface(surface);
}
surface = SDL_SetVideoMode(width, height, 0, SDL_HWSURFACE);
if (surface == NULL) {
printf("ERROR: failed to set video mode: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
/* Color the window background */
colorRect(control->dim, 0xFF, 0xFF, 0xFF);
SDL_WM_SetCaption(caption, caption);
return control;
}
void appendControl(Control* parent, Control* child) {
Control* currChild;
child->parent = parent;
/* Appends the control to the end list of the children of parent */
if (parent->children == NULL) {
parent->children = child;
} else {
currChild = parent->children;
while (currChild->next != NULL) {
currChild = currChild->next;
}
currChild->next = child;
}
}
void initializeSDL() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("ERROR: unable to init SDL: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
atexit(SDL_Quit);
}
void loadImage(char* name) {
SDL_Surface* loadedImage = SDL_LoadBMP(name);
if (loadedImage == NULL) {
printf("ERROR: unable to load image: %s\n", SDL_GetError());
exit(0);
}
image = loadedImage;
}
void colorRect(SDL_Rect* rect, int r, int g, int b) {
if (SDL_FillRect(surface, rect, SDL_MapRGB(surface->format, r, g, b)) < 0) {
printf("ERROR: failed to fill rect with color: %s\n", SDL_GetError());
freeControls(root);
exit(0);;
}
}
void drawBorders(SDL_Rect* rect, int width, int r, int g, int b) {
int i;
SDL_Rect* borderClips[4];
borderClips[0] = createRect(rect->x - width, rect->y - width, rect->w + 2 * width, width);
borderClips[1] = createRect(rect->x - width, rect->y - width, width, rect->h + 2 * width);
borderClips[2] = createRect(rect->x + rect->w, rect->y - width, width, rect->h + 2 * width);
borderClips[3] = createRect(rect->x - width, rect->y + rect->h, rect->w + 2 * width, width);
/* Draw Borders around given rect */
for (i = 0; i < 4; i++) {
colorRect(borderClips[i], r, g, b);
}
free(borderClips[0]);
free(borderClips[1]);
free(borderClips[2]);
free(borderClips[3]);
}
void optimizeImage() {
Uint32 colorKey;
SDL_Surface* optimizedImage = SDL_DisplayFormat(image);
SDL_FreeSurface(image);
if (optimizedImage == NULL) {
printf("ERROR: unable to optimize image: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
/* RGB: 250,255,255 is the key color */
colorKey = SDL_MapRGB(optimizedImage->format, 0xFA, 0xFF, 0xFF);
SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorKey);
image = optimizedImage;
}
void freeControls(Control* root) {
traverseTree(root, freeControl, TRUE);
if (quit) {
SDL_FreeSurface(image);
}
}
int freeControl(Control* control) {
if (control->dim != NULL) {
free(control->dim);
}
if (control->abs != NULL) {
free(control->abs);
}
free(control);
return 1;
}
void drawRoot() {
traverseTree(root, drawControl, FALSE);
/* After controls are drawn we flip */
if (SDL_Flip(surface) < 0) {
printf("ERROR: unable to flip screen: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
}
int drawControl(Control* control) {
if (control->visible) {
/* Draw if there is an onDraw function (used mostly by panels) */
if (control->onDraw != NULL) {
control->onDraw(control);
}
/* Draw also if there is an image to draw */
if (control->clip != NULL) {
if (SDL_BlitSurface(image, control->clip, surface, control->abs) < 0) {
printf("ERROR: unable to blit surface: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
}
}
return 1;
}
int setControlEnabled(Control* control) {
control->enabled = enabled && control->visible;
return 1;
}
int setControlVisible(Control* control) {
control->visible = visible;
return 1;
}
int findButton(Control* control) {
/* Check only if control is clickable */
if (control->onClick != NULL) {
if (click_x >= control->abs->x && click_x < control->abs->x + control->abs->w &&
click_y >= control->abs->y && click_y < control->abs->y + control->abs->h) {
if (!onlyEnabled || control->enabled) {
/* Found a button in the area, no need to keep looping */
foundButton = control;
return 0;
}
}
}
return 1;
}
int traverseTree(Control* control, int(*func)(Control*), int postOrder) {
Control* child;
Control* next;
int keepLooping = 1;
if (control != NULL) {
/* Perform func before recursion if not post order */
if (!postOrder && keepLooping) {
keepLooping = func(control);
}
/* Recurse the tree */
child = control->children;
while (child != NULL && keepLooping) {
next = child->next;
keepLooping = traverseTree(child, func, postOrder);
child = next;
}
/* Perform func after recursion if post order */
if (postOrder && keepLooping) {
keepLooping = func(control);
}
}
return keepLooping;
}
void handleEvents() {
SDL_Event e;
while (!quit) {
if (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) { /* A quit was detected */
quitGuiLoop();
} else if (e.type == SDL_MOUSEBUTTONDOWN) { /* Mouse click was detected */
if (e.button.button == SDL_BUTTON_LEFT) {
click_x = e.button.x;
click_y = e.button.y;
/* Find the button that was pressed */
onlyEnabled = TRUE;
traverseTree(root, findButton, TRUE);
if (foundButton != NULL) {
foundButton->onClick(foundButton);
foundButton = NULL;
}
}
}
drawRoot();
delay(10);
}
}
}
void delay(int ms) {
SDL_Delay(ms);
}
void quitGuiLoop() {
quit = 1;
}
Control* getControlByDimension(int x, int y) {
Control* control;
click_x = x;
click_y = y;
/* Find the button located at specified coordinates */
onlyEnabled = FALSE;
traverseTree(root, findButton, TRUE);
control = foundButton;
foundButton = NULL;
return control;
}
Control* getRoot() {
return root;
}
void setRoot(Control* newRoot) {
root = newRoot;
}
void setControlsVisible(Control* root, int visibleValue) {
visible = visibleValue;
traverseTree(root, setControlVisible, TRUE);
}
void setControlsEnabled(Control* root, int enabledValue) {
enabled = enabledValue;
traverseTree(root, setControlEnabled, TRUE);
}

Resources