user3617599
user3617599

Reputation: 11

Using SDL_FreeSurface on Automatically Allocated Surfaces

I'm experiencing severe ram usage in a game I'm developing. I've left it running and seen it use in excess of 1.5 GB of ram, from an initial usage of 30 MB. I've pinpointed the primary cause to 2 functions, which are pasted below. From researching this problem, I've come to the conclusion that the one of the problems is that creating a TTF surface using TTF_RenderText_Blended creates a new surface, which is not getting freed. How do I go about freeing this automatically made surface? I can't use SDL_FreeSurface, since I don't have the surface name.

I'm a little more confused by the what's happening in the second function. I'm assuming something similar is happening (a function getting called and creating a second surface which is not getting freed), but I'm not sure what's causing it. This is less of a problem, since I'm planning on implementing a different version of this function which won't require creating any surfaces..

TTF Function:

void speak(int id, string message, SDL_Renderer *ren, TTF_Font *font, SDL_Color color, int x, int y)
{ 
    SDL_Surface *surf = TTF_RenderText_Blended(font, message.c_str(), color);
    if(surf == nullptr) cout << "surf error";
    SDL_Texture *texture = SDL_CreateTextureFromSurface(ren, surf);
    SDL_FreeSurface(surf);
    if(texture == nullptr) cout << "tex error";
    SDL_Rect rect;
    SDL_QueryTexture(texture, NULL, NULL, &rect.w, &rect.h);
    rect.x = x-rect.w/2 - camera_xpos*10;
    rect.y = y+sprite_set_array[idList[id].sprite].y_offset - rect.h - camera_ypos*10;
    SDL_RenderCopy(ren, texture, NULL, &rect);
}

Second Function (used for displaying sprites):

void displayAtPos(int id, int sprite_num, int x, int y, SDL_Window *win, SDL_Renderer *ren)             
{
   if(idList[id].type == 5) sprite_num = 11;
   string sprite = sprite_set_array[sprite_num].getString(idList[id].facing,     idList[id].sprite_counter);
    SDL_Texture *texture = nullptr;
    SDL_Surface *bmp = SDL_LoadBMP(sprite.c_str());
    if(bmp==nullptr) {bmp = SDL_LoadBMP("junk.bmp");}
    SDL_SetColorKey( bmp, SDL_TRUE, SDL_MapRGB(bmp->format, 255, 0, 255) );
    SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
    SDL_FreeSurface(bmp);
    if (tex == nullptr) { cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << endl; }

    SDL_Rect rect;
    rect.x = x;
    rect.y = y+sprite_set_array[idList[id].sprite].y_offset;

    SDL_QueryTexture(tex, NULL, NULL, &rect.w, &rect.h);
    SDL_RenderCopy(ren, tex, NULL, &rect);

    if(idList[id].active_effect > 0 && idList[id].active_effect_counter > 0)            //Display a texture from the status effects array.
    {
        SDL_RenderCopy(ren, effect_array[idList[id].active_effect_counter%3], NULL, &rect);
        idList[id].active_effect_counter--;
    }
}

Upvotes: 1

Views: 113

Answers (1)

olevegard
olevegard

Reputation: 5532

You need to destroy/free the SDL_Textures as well :

void SDL_DestroyTexture(SDL_Texture* texture)

I also suggest you store the SDL_Texture* if you can. That way you won't have to recreate it all the time.

Upvotes: 1

Related Questions