SDL和Qt。当从另一个线程渲染时,调整应用程序的大小会导致显示冻结
Qt:5.14.1 SDL:2.0.12 操作系统:Windows 10 我正在开发一个视频播放器,我正在使用Qt进行UI和SDL来渲染帧。 我通过传递渲染小部件(在布局中)的winId()句柄创建了SDL窗口 当我开始一个非线程播放()时,这个功能非常有效。 但是,在调整或移动应用程序窗口时,这会导致播放出现一些问题。没什么大不了的,但是因为播放代码是非线程的,所以我的帧队列填满了,这会导致视频加速,直到它捕捉到音频 我把我的播放代码放在用CreateThread函数创建的Win32线程中解决了这个问题。 现在,当我移动窗口时,视频将继续按预期播放,但当调整应用程序大小时,渲染小部件将停止刷新小部件,并且仅显示调整大小事件之前最后显示的帧。 我可以确认视频仍在运行,并且仍在显示正确的帧。显示的图像甚至可以调整大小,但它永远不会刷新 当我用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线程中解决
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;
否则,如果(立场)说不要这样做。