SDL和Qt。当从另一个线程渲染时,调整应用程序的大小会导致显示冻结

SDL和Qt。当从另一个线程渲染时,调整应用程序的大小会导致显示冻结,qt,resize,sdl,freeze,Qt,Resize,Sdl,Freeze,Qt:5.14.1 SDL:2.0.12 操作系统:Windows 10 我正在开发一个视频播放器,我正在使用Qt进行UI和SDL来渲染帧。 我通过传递渲染小部件(在布局中)的winId()句柄创建了SDL窗口 当我开始一个非线程播放()时,这个功能非常有效。 但是,在调整或移动应用程序窗口时,这会导致播放出现一些问题。没什么大不了的,但是因为播放代码是非线程的,所以我的帧队列填满了,这会导致视频加速,直到它捕捉到音频 我把我的播放代码放在用CreateThread函数创建的Win32线程中解决

Qt:5.14.1 SDL:2.0.12 操作系统:Windows 10

我正在开发一个视频播放器,我正在使用Qt进行UI和SDL来渲染帧。 我通过传递渲染小部件(在布局中)的winId()句柄创建了SDL窗口

当我开始一个非线程播放()时,这个功能非常有效。 但是,在调整或移动应用程序窗口时,这会导致播放出现一些问题。没什么大不了的,但是因为播放代码是非线程的,所以我的帧队列填满了,这会导致视频加速,直到它捕捉到音频

我把我的播放代码放在用CreateThread函数创建的Win32线程中解决了这个问题。 现在,当我移动窗口时,视频将继续按预期播放,但当调整应用程序大小时,渲染小部件将停止刷新小部件,并且仅显示调整大小事件之前最后显示的帧。 我可以确认视频仍在运行,并且仍在显示正确的帧。显示的图像甚至可以调整大小,但它永远不会刷新

当我用SDL测试Qt线程时,也发生了类似的事情。考虑这个代码

class TestThread: public QThread
{
public:
    TestThread(QObject *parent = NULL) : QThread(parent)
    {
    }

    void run() override
    {
         for (;;)
         {
          SDL_Delay(1000/60);
            // Basic square bouncing animation
            SDL_Rect spos;
            spos.h = 100;
            spos.w = 100;
            spos.y = 100;
            spos.x = position;

            SDL_SetRenderDrawColor(RendererRef, 0, 0, 0, 255);
            SDL_RenderFillRect(RendererRef, 0);
            SDL_SetRenderDrawColor(RendererRef, 0xFF, 0x0, 0x0, 0xFF);
            SDL_RenderFillRect(RendererRef, &spos);
            SDL_RenderPresent(RendererRef);

            if (position >= 500)
                dir = 0;
            else if (position <= 0)
                dir = 1;

            if (dir)
                position += 5;
            else
                position -= 5;

                }
    }
};

// a call from Init SDL and Start Thread button
... 
// create new SDL borderless resizible window.
WindowRef = SDL_CreateWindow("test",10,10,1280,800,SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS);

// create and start thread
 test_thread = new TestThread();
 test_thread->start();

...
classtestthread:publicqthread
{
公众:
TestThread(QObject*parent=NULL):QThread(parent)
{
}
void run()重写
{
对于(;;)
{
SDL_延迟(1000/60);
//基本方形反弹动画
SDL__Rect SPO;
spos.h=100;
spos.w=100;
spos.y=100;
spos.x=位置;
SDL_SetRenderDrawColor(RenderRef,0,0,255);
SDL_RenderFillRect(RenderRef,0);
SDL_SetRenderDrawColor(RenderRef,0xFF,0x0,0x0,0xFF);
SDL_RenderFillRect(RenderRef和SPO);
SDL_RenderPresent(RenderRef);
如果(位置>=500)
dir=0;
else if(位置start();
...
这将从Qt应用程序窗口创建一个单独的窗口,并开始渲染一个有弹性的正方形。但是,如果在Qt应用程序中发生任何调整大小事件,渲染上下文将丢失,在我的视频播放器中发生的相同情况也将在此处发生

我还发现,如果我从Thread对象中删除SDL_RenderPresent函数并将其放在主Qt窗口中,渲染将在resize事件后继续。然而,这被证明是完全不可靠的,有时会完全冻结我的应用程序

我也不明白为什么我完全分离的SDL窗口和渲染器仍然在调整大小时冻结。 我想SDL渲染器/窗口和Qt的绘图工具在某些地方可能会发生冲突,但我在这里不知所措

而且,这只是调整大小的问题,其他的都可以

谢谢。

回答: SDL_渲染器需要在调整窗口大小以及使用以前的渲染器创建的任何SDL_纹理时销毁和重新创建

即使没有qt,同样的事情也会发生

然而,我认为这只是一个解决办法,而不是真正的解决办法

一个简单的代码来重新创建问题

    int position = 0;
    int dir = 0;


SDL_Window *window = NULL;
SDL_Renderer *sdlRenderer_ = NULL;


DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
         for (;;)
         {
          SDL_Delay(1000/60);
            // Basic square bouncing animation
            SDL_Rect spos;
            spos.h = 100;
            spos.w = 100;
            spos.y = 100;
            spos.x = position;

            SDL_SetRenderDrawColor(sdlRenderer_, 0, 0, 0, 255);
            SDL_RenderFillRect(sdlRenderer_, 0);
            SDL_SetRenderDrawColor(sdlRenderer_, 0xFF, 0x0, 0x0, 0xFF);
            SDL_RenderFillRect(sdlRenderer_, &spos);
            SDL_RenderPresent(sdlRenderer_);
    
            if (position >= 500)
                dir = 0;
            else if (position <= 0)
                dir = 1;

            if (dir)
                position += 5;
            else
                position -= 5;

                }
}


int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,  _In_ LPWSTR    lpCmdLine,_In_ int       nCmdShow)
{
  SDL_Init(SDL_INIT_VIDEO);

  window = SDL_CreateWindow("test",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,600,600,SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
  
  if (!window)
      printf("Unable to create window");

  sdlRenderer_ = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
  if (!sdlRenderer_)
      printf("Unable to create renderer");




    HANDLE playHandle = CreateThread(0, 0, MyThreadFunction, 0, 0, 0);
    if (playHandle == NULL)
    {
        return 0;
    }


    SDL_Event e;

    while(1)
    {
     SDL_PollEvent(&e);

     if (e.type == SDL_WINDOWEVENT )
        {
        switch( e.window.event )
              {
               case SDL_WINDOWEVENT_SIZE_CHANGED:
                int mWidth = e.window.data1;
                int mHeight = e.window.data2;
                SDL_DestroyRenderer(sdlRenderer_); // stops rendering on resize if commented out
                sdlRenderer_ = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);

                break;         
              }
        }
     
    }
    


    return 0;
}
int位置=0;
int dir=0;
SDL_Window*Window=NULL;
SDL_渲染器*sdlRenderer_u=NULL;
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
对于(;;)
{
SDL_延迟(1000/60);
//基本方形反弹动画
SDL__Rect SPO;
spos.h=100;
spos.w=100;
spos.y=100;
spos.x=位置;
SDL_SetRenderDrawColor(SDLRender_,0,0,0,255);
SDL_RenderFillRect(sdlRenderer_0);
SDL_SetRenderDrawColor(SDLRender_0;,0xFF,0x0,0x0,0xFF);
SDL_RenderFillRect(SDLRender_和SPO);
SDL_呈现者(SDL呈现者);
如果(位置>=500)
dir=0;
否则,如果(立场)说不要这样做。