【问题标题】:SDL_ttf clearing all my prior and future rendersSDL_ttf 清除我之前和未来的所有渲染
【发布时间】:2020-01-02 11:16:44
【问题描述】:

我一直在努力让 SDL 和 SDL_ttf 一起工作。我的最小可重现案例(如下)在 VC++ 中工作,但对于我来说,我无法让它在 MinGW 环境中工作。

  • SDL 版本:2.0.10(撰写本文时的最新版本)
  • SDL_ttf 版本:2.0.15(撰写本文时的最新版本)

我的设置如下:

  • 将 SDL 和 SDL_ttf lib 和包含文件夹复制到我的项目根目录。
  • 设置我的链接并包含在我的 Makefile 中,如下所示:
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
  • 将 dll 添加到 MinGW 的 bin 文件夹中。

这是一个最小的可重现测试用例,适用于 Visual Studio,但不适用于 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;
}

无论我将SDL_RenderFillRect 放在哪里(在drawText 之前或之后),我看到的唯一内容就是文本。矩形不再可见。

我目前正在处理混合的操作系统开发环境(mac 和 windows),因此我希望它使用 make 来构建。

【问题讨论】:

  • 您忘记在字体上调用TTF_CloseFont。这将为每个渲染的帧创建内存泄漏,并且由于您不使用SDL_WaitEvent,因此帧将在您的硬件允许的情况下以最快的速度渲染。这似乎与问题无关,但我强烈建议在循环之前渲染文本一次,保留纹理并每次都渲染它。
  • 顺便说一句,一定要展示你完整的 Makefile!从您所展示的内容来看,您没有链接到 SDL 具有加速渲染器所需的 OpenGL(Windows 上的-lopengl32,macOS 上的-framework OpenGL)。附带说明一下,从不同的链接标志中可以看出,Makefile 不是进行多操作系统定位的好工具,您可能想看看 CMake。使用 CMake,您可以在 Windows 上生成一个 VS 项目,在 macOS 上生成一个 XCode 项目,这可能是您想要的,而不必在 Windows 上处理 MinGW。
  • @flyx 我很清楚内存泄漏,这只是一个测试设置,不会运行超过一秒钟来查看文本渲染:) 我将添加我的整个makefile 到最初的帖子。
  • 好吧,你没有在任何地方链接到 OpenGL,我只能猜测 SDL 使用了软件渲染后备。这并不能真正解释您的问题,但请尝试将 -lopengl32 添加到您的 Windows 版本中。
  • @flyx 我添加了 -lopengl32 并没有看到任何变化。它正在使用我的大量 GPU 处理能力(预期,因为我尽可能快地渲染),所以无论是否链接 opengl,它都在使用我的 GPU。 imgur.com/kJ4T86k

标签: c++ makefile mingw sdl sdl-ttf


【解决方案1】:

似乎是 SDL_RENDERER_ACCELERATED 和 openGL 未链接的问题。链接 openGL 并没有解决问题,但是,切换到软件渲染器 (SDL_RENDERER_SOFTWARE) 确实修复了渲染错误。很奇怪,它确实适用于 VS。我想这仍然是一个谜......

【讨论】:

  • 嗯,这可能是由于您的SDL_CreateWindow 调用中缺少SDL_WINDOW_OPENGL 标志造成的。我刚刚看到它不见了。
  • ……我完全忘记了 SDL 也可以使用 Direct3D。这可能是您在 VS 中的代码正在使用的内容以及它工作的原因,但它需要在 MinGW 中进行额外的编译开关。不知道细节,没用过。
  • 所描述的行为非常类似于 SDL2 的 d3d 渲染器的错误,该错误已在上游修复但未在 2.0.10 版本中修复(如果我没记错的话,它首先发生在 2.0.9 和 2.0.10 之间)。您可以更新到尚未发布的最新 SDL、降级到以前的版本或使用 opengl 渲染器。
  • SDL_WINDOW_OPENGL 标志会有意义:)。我会做更多的实验。很高兴知道这是一个已知的错误,我会留意未来的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
相关资源
最近更新 更多