-1

I want to simulate a tv screen in my game. A 'no signal' image is displayed all along. It will be replaced by a scene of a man shooting another one, that's all. so I wrote this, which load my image every time :

void Display_nosignal(SDL_Texture* Scene, SDL_Renderer* Rendu)
{
    SDL_Rect dest = {416, 0, 416, 416};
    SDL_Rect dest2 = {SCENE};
    SDL_SetRenderTarget(Rendu, Scene);
    SDL_Rect src = {(1200-500)/2,0,500,545};
    /*Scene = IMG_LoadTexture(Rendu, "mages/No_Signal.jpg");
    if (Scene==NULL){printf("Erreur no signal : %s\n", SDL_GetError());}*/
    if (Scene == NULL)
    {
        Scene = IMG_LoadTexture(Rendu, "mages/No_Signal.jpg");
        if (Scene == NULL){printf("Erreur no signal : %s\n", SDL_GetError());}
    }
    
    SDL_RenderCopy(Rendu, Scene, NULL, &src);
    SDL_SetRenderTarget(Rendu, NULL);
    //SDL_DestroyTexture(Scene);
    //500, 545
}

and it causes memory leaks. I've tried to destroy the texture in the loop etc., but nothing changes. so, can you advice me some ways to load the image at the very beginning , keep it , and display it only when needed.

Talha Tayyab
  • 8,111
  • 25
  • 27
  • 44
dMight
  • 19
  • 4
  • 5
    Load the texture outside the function, store it in some variable (or have a dedicated texture manager system)? – UnholySheep Jun 02 '22 at 09:12
  • 2
    Welcome to StackOverflow. I second UnholySheeps post. I usually have some central facility from which I request a named resource (like your texture filename) and that facility checks whether the resource has already been loaded and if not, proceeds to loading it. Also, that facility has some sort of shutdown function to then clean up all loaded resources. This then of course expands to the much broader topic of dependency injection. – PhilMasteG Jun 02 '22 at 09:16
  • PhilMasteG, how do you check if the resource is loaded please? seems interesting too – dMight Jun 02 '22 at 09:23
  • 1
    @dMight you load the resource at some point in your code. Then you known it's loaded. Or maybe I didn't get your question. – Jabberwocky Jun 02 '22 at 09:27
  • @Jabberwocky i use a structure, holding the window, renderer, the scene texture and an array of 10 textures for 10 little squares, in order to associate each texture to a screen zone. The scene texture will have to welcome to things : the little scene i described and the no signal image. I assumed that the scene texture would have to load the image everytime. I'm an sdl noob (still to figure it out), and my deadline is soon, the documentation and thousands of tutorials don't really explain the mechanisms so yeah there's a lot misconception – dMight Jun 02 '22 at 09:39
  • 1
    @dMight You put the call to load the image into a place where it only runs once. Then you know that after that call, it was loaded. – user253751 Jun 02 '22 at 10:02

1 Answers1

1

I agree with the commenters about dedicated texture loader being a correct solution, but if you only want this behavior for one particular texture it may be an overkill. In that case you can write a separate function which loads this particular texture and make sure it is only called once.

Alternatively, you can use static variables. If a variable declared in a function is marked as static it will retain its value across calls to that function. You can find a simple example here (it's a tutorial-grade source but it shows basic usage) or here (SO source).

By modifying your code ever so slightly you should be able to make sure that the texture is loaded only once. By marking a pointer to it as static you ensure that its value (so address of the loaded texture) is not lost bewteen calls to the function. Afterwards the pointer will live in memory until the program terminates. Thanks to this, we do not have to free the texture's memory (unless you explicitly want to free it at some point, but then the texture manager is probably a better idea). A memory leak will not occur, since we are never going to lose the reference to the texture.

void Display_nosignal(SDL_Texture* Scene, SDL_Renderer* Rendu)
{
    static SDL_Texture* Scene_cache = NULL; // Introduce a variable which remembers the texture across function calls
    SDL_Rect dest = {416, 0, 416, 416};
    SDL_Rect dest2 = {SCENE};
    SDL_SetRenderTarget(Rendu, Scene);
    SDL_Rect src = {(1200-500)/2,0,500,545};

    if (Scene_cache == NULL) // First time we call the function, Scene_cache will be NULL, but in next calls it will point to a loaded texture
    {
        Scene_cache = IMG_LoadTexture(Rendu, "mages/No_Signal.jpg"); // If Scene_cache is NULL we load the texture
        if (Scene_cache == NULL){printf("Erreur no signal : %s\n", SDL_GetError());}
    }
    Scene = Scene_cache; // Set Scene to point to the loaded texture
    
    SDL_RenderCopy(Rendu, Scene, NULL, &src);
    SDL_SetRenderTarget(Rendu, NULL);
}

If you care about performance and memory usage etc you should read about consequences of static variables, for instance their impact on cache and how they work internally. This might be considered a "dirty hack" but it might be just enough for a small project that does not need bigger solutions.

msaw328
  • 1,459
  • 10
  • 18
  • i did this (and went to bed) : ```void Display_nosignal(SDL_Texture* Scene, SDL_Renderer* Rendu, SDL_Texture* Origin) { SDL_Rect dest = {416, 0, 416, 416}; SDL_Rect dest2 = {SCENE}; SDL_SetRenderTarget(Rendu, Scene); SDL_Rect src = {(1200-500)/2,0,500,545}; Scene = Origin; SDL_RenderCopy(Rendu, Scene, NULL, &src); SDL_SetRenderTarget(Rendu, NULL); //500, 545 } ``` Origin is loaded in the main (only one time) and there's apparently no leak, any thoughts ? – dMight Jun 02 '22 at 16:07
  • @dMight I would say if it works for you and it fixes your problem then it is okay. You should judge it yourself as you know your use-case the best. Questions about code quality on the other hand belong more on https://codereview.stackexchange.com/ rather than here. – msaw328 Jun 03 '22 at 08:10