Search code examples
csdl

Invalid renderer SDL2


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;
        }

Solution

  • 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.