简体   繁体   English

SDL_Texture 在调整大小后呈现黑色,除非重新绘制

[英]SDL_Texture renders black after resize unless it is redrawn

I've got a bit of a nasty bug for you folks.我有一个讨厌的错误给你们。 (Yes, it's probably my bug and not SDL's.) I have been in the process of writing a modern C++ wrapper for SDL and everything appears to be working as intended. (是的,这可能是我的错误,而不是 SDL 的错误。)我一直在为 SDL 编写现代 C++ 包装器,一切似乎都按预期工作。 However, my Texture class has a strange bug: if it is redrawn after a resize, it looks fine, but if it is not, it becomes entirely black.但是,我的纹理 class 有一个奇怪的错误:如果在调整大小后重绘它,它看起来很好,但如果不是,它就会变成全黑。 Here is what that looks like:看起来是这样的:

Before the resize调整大小之前

After the resize调整大小后

I can't exactly post just one part of the code here, so here is the entire folder (hosted on GitLab): SDL wrapper我不能在这里只发布一部分代码,所以这里是整个文件夹(托管在 GitLab 上): SDL wrapper

Here is a small program that reproduces the error using this library:这是一个使用此库重现错误的小程序:

#include "sdl_wrapper/context.hh"
#include "sdl_wrapper/video/context.hh"
#include "sdl_wrapper/render/renderer.hh"
#include "sdl_wrapper/render/texture.hh"
#include "sdl_wrapper/colors.hh"
#include "SDL2/SDL_events.h"

int main()
{
    sdl::Context sdlContext;
    sdl::video::Context videoContext = sdlContext.initVideo();
    sdl::video::Window window = videoContext.createWindow("test", 0, 0, 800, 600).resizable().build();
    int width = 800;
    int height = 600;
    sdl::render::Renderer renderer = window.createRenderer().targetTexture().build();
    sdl::render::Texture example(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 400, 300);
    renderer.setTarget(example);
    renderer.setDrawColor(sdl::colors::Blue);
    renderer.clear();
    renderer.resetTarget();
    bool run = true;
    while (run)
    {
        SDL_Event e;
        while (SDL_PollEvent(&e) != 0)
        {
            if (e.type == SDL_QUIT)
            {
                run = false;
                break;
            }
        }
        renderer.setDrawColor({0x44, 0x44, 0x44, 0xff});
        renderer.clear();
        renderer.copy(example, std::nullopt, {{width / 4, height / 4, example.getWidth(), example.getHeight()}});
        renderer.present();
    }
}

To reproduce, simply run this program and resize the window.要重现,只需运行此程序并调整 window 的大小。 There will be a blue square that becomes black after the resize.调整大小后会有一个蓝色方块变成黑色。

I would greatly appreciate it if someone could point me in the right direction here.如果有人能在这里指出正确的方向,我将不胜感激。 I would really like to avoid redrawing on every resize (feel free to argue with me on that point if I am misguided).我真的很想避免在每次调整大小时重新绘制(如果我被误导了,请随时与我争论)。

SDL doesn't promise to keep target textures data. SDL 不会 promise 保留目标纹理数据。 There are cases, especially with d3d or mobile, where data is lost due to some big state change.在某些情况下,尤其是使用 d3d 或移动设备时,由于 state 的一些大变化而导致数据丢失。 Changing window size may sound not that big, but on some hardware/driver configurations is causes problems, I suppose that's the reason why SDL detects resize and drops all renderer data.更改 window 大小可能听起来没那么大,但在某些硬件/驱动程序配置上会导致问题,我想这就是 SDL 检测调整大小并丢弃所有渲染器数据的原因。 You get SDL_RENDER_TARGETS_RESET event when you need to update your render textures.当您需要更新渲染纹理时,您会收到SDL_RENDER_TARGETS_RESET事件。

That shouldn't happen with eg opengl renderer implementation (that may sound great but reasons behind it are not so great);这不应该发生在例如 opengl 渲染器实现中(这可能听起来不错,但背后的原因并不是那么好); on windows, SDL2 defaults to direct3d, which could be modified by issuing SDL_SetHint or setting envvars.在 windows 上,SDL2 默认为 direct3d,可以通过发出SDL_SetHint或设置 envvars 进行修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM