Search code examples
c++makefilemingwsdlsdl-ttf

SDL_ttf clearing all my prior and future renders


I've been struggling with getting SDL and SDL_ttf to work together. My minimal reproducible case (down below) works in VC++ but for the life of me I can't get it to work in a MinGW environment.

  • SDL version: 2.0.10 (latest at moment of writing)
  • SDL_ttf version: 2.0.15 (latest at moment of writing)

My set up looks like this:

  • Copied SDL and SDL_ttf lib and include folders to my project root.
  • Set up my link and include in my Makefile like so:
SRC_DIR=./app/src
INC_DIR=./app/inc
OBJ_DIR=./.obj
BUILD_DIR=./build

NAME=$(BUILD_DIR)/out
all: $(NAME)

CC=gcc
CXX=g++
CXXFLAGS=-Wall -Wextra -pedantic --std=c++17 -g

# Objects to build
STNAMES=\
        main \

OBJECTS=$(patsubst %,$(OBJ_DIR)/%.o, $(STNAMES))

# Windows specific settings
ifeq ($(OS), Windows_NT)

LINK=\
     -L./SDL2/lib \
     -L./SDL2_ttf/lib \
     -lmingw32 \
     -lSDL2main \
     -lSDL2 \
     -lSDL2_ttf \
     -lstdc++ \

INCLUDE=\
        -I$(INC_DIR) \
        -I./SDL2/include \
        -I./SDL2_ttf/include \

define mkdir =
    if not exist "$(1)" mkdir "$(1)"
endef

define rmdir =
    if exist "$(1)" del /S/Q "$(1)"
endef

EXECUTABLE=$(NAME).exe

# macOS specific settings
# UNTESTED, assumes dependencies are installed with brew
else

LINK=$(shell sdl2-config --libs) -lc++
INCLUDE=\
        -I$(shell brew --prefix)/include/SDL2 \

define mkdir
    mkdir -p $(1)
endef

define rmdir =
    rm -rf $(1)
endef

EXECUTABLE=$(NAME)

endif

$(NAME): $(OBJECTS)
    @$(call mkdir,$(BUILD_DIR))
    $(CC) -o $@ $(OBJECTS) $(LINK)
    @$(EXECUTABLE)

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    @$(call mkdir,$(OBJ_DIR))
    @$(CXX) -o $@ -c $< $(CXXFLAGS) $(INCLUDE)

re:
    @$(call rmdir,$(OBJ_DIR))
    make
  • Added the dlls to MinGW's bin folder.

Here's a minimal reproducible test case which works for me on Visual Studio, but not on MinGW:

#include <iostream>
#include <SDL.h>
#include <SDL_ttf.h>

void drawText(SDL_Renderer* renderer, TTF_Font* font, int x, int y, const char* text) {
    auto surface = TTF_RenderText_Solid(font, text, SDL_Color{ 255, 255, 255, 255 });
    auto texture = SDL_CreateTextureFromSurface(renderer, surface);

    SDL_Rect dstRect = { x, y, surface->w, surface->h };
    SDL_RenderCopy(renderer, texture, NULL, &dstRect);

    SDL_DestroyTexture(texture);
    SDL_FreeSurface(surface);
}

int main(int argc, char* argv[]) {
    (void)argc;
    (void)argv;

    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window* window = SDL_CreateWindow("some title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1920, 1080, SDL_WINDOW_SHOWN);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);

    TTF_Init();

    bool running = true;
    SDL_Event event;
    auto font = TTF_OpenFont("assets/courier_prime.ttf", 36);

    while (running) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT)
                running = false;
        }

        SDL_SetRenderDrawColor(renderer, 25, 25, 25, 255);
        SDL_RenderClear(renderer);

        drawText(renderer, font, 10, 10, "Test string");

        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255 );
        auto rect = SDL_Rect{10, 100, 110, 200};
        SDL_RenderFillRect(renderer, &rect);

        SDL_RenderPresent(renderer);
    }

    TTF_CloseFont(font);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    TTF_Quit();
    SDL_Quit();
    return 0;
}

Regardless of where I place that SDL_RenderFillRect (before or after the drawText), the only thing I see is the text. The Rectangle is no longer visible.

I'm currently dealing with a mixed OS dev environment (mac and windows), hence why I'd like it to build on both using make.


Solution

  • Seems like it was an issue with SDL_RENDERER_ACCELERATED and openGL not being linked. Linking openGL did not fix the issue, however, swapping to the software renderer (SDL_RENDERER_SOFTWARE) did fix the rendering bug. Very strange that it does work on VS though. I guess that'll remain a mystery...