Create the SystemProperties test window on the main thread

This commit is contained in:
Cameron Gutman
2026-01-25 17:10:04 -06:00
parent 05ef938e2c
commit 64fea80ac9
6 changed files with 89 additions and 60 deletions

View File

@@ -29,38 +29,7 @@ private:
bool supportsHdr;
QSize maximumResolution;
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
SDL_GetError());
return;
}
// Update display related attributes (max FPS, native resolution, etc).
m_Properties->refreshDisplays();
SDL_Window* testWindow = SDL_CreateWindow("", 0, 0, 1280, 720,
SDL_WINDOW_HIDDEN | StreamUtils::getPlatformWindowFlags());
if (!testWindow) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Failed to create test window with platform flags: %s",
SDL_GetError());
testWindow = SDL_CreateWindow("", 0, 0, 1280, 720, SDL_WINDOW_HIDDEN);
if (!testWindow) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to create window for hardware decode test: %s",
SDL_GetError());
SDL_QuitSubSystem(SDL_INIT_VIDEO);
return;
}
}
Session::getDecoderInfo(testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, supportsHdr, maximumResolution);
SDL_DestroyWindow(testWindow);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
Session::getDecoderInfo(m_Properties->testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, supportsHdr, maximumResolution);
// Propagate the decoder properties to the SystemProperties singleton and emit any change signals on the main thread
QMetaObject::invokeMethod(m_Properties, "updateDecoderProperties",
@@ -137,12 +106,49 @@ SystemProperties::SystemProperties()
supportsHdr = true;
maximumResolution = QSize(0, 0);
// We initialize the video subsystem and test window on the main thread
// because some platforms (macOS) do not support window creation on
// non-main threads.
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
SDL_GetError());
return;
}
// Update display related attributes (max FPS, native resolution, etc).
refreshDisplays();
testWindow = SDL_CreateWindow("", 0, 0, 1280, 720,
SDL_WINDOW_HIDDEN | StreamUtils::getPlatformWindowFlags());
if (!testWindow) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Failed to create test window with platform flags: %s",
SDL_GetError());
testWindow = SDL_CreateWindow("", 0, 0, 1280, 720, SDL_WINDOW_HIDDEN);
if (!testWindow) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to create window for hardware decode test: %s",
SDL_GetError());
SDL_QuitSubSystem(SDL_INIT_VIDEO);
return;
}
}
systemPropertyQueryThread = new SystemPropertyQueryThread(this);
systemPropertyQueryThread->start();
}
SystemProperties::~SystemProperties()
{
systemPropertyQueryThread->wait();
}
void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr)
{
SDL_assert(testWindow);
if (hasHardwareAcceleration != this->hasHardwareAcceleration) {
this->hasHardwareAcceleration = hasHardwareAcceleration;
emit hasHardwareAccelerationChanged();
@@ -162,6 +168,10 @@ void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, boo
this->supportsHdr = supportsHdr;
emit supportsHdrChanged();
}
SDL_DestroyWindow(testWindow);
testWindow = nullptr;
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
QRect SystemProperties::getNativeResolution(int displayIndex)

View File

@@ -3,6 +3,8 @@
#include <QObject>
#include <QRect>
#include "SDL_compat.h"
class SystemProperties : public QObject
{
Q_OBJECT
@@ -11,6 +13,7 @@ class SystemProperties : public QObject
public:
SystemProperties();
~SystemProperties();
// Static properties queried synchronously during the constructor
Q_PROPERTY(bool isRunningWayland MEMBER isRunningWayland CONSTANT)
@@ -47,6 +50,7 @@ private slots:
private:
QThread* systemPropertyQueryThread;
SDL_Window* testWindow;
// Properties set by the constructor
bool isRunningWayland;

View File

@@ -464,7 +464,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
// to ensure we don't drop any important events.
session->flushWindowEvents();
}
else {
else if (!params->testOnly) {
// If we get here prior to the start of a session, just pump and flush ourselves.
SDL_PumpEvents();
SDL_FlushEvent(SDL_WINDOWEVENT);

View File

@@ -140,6 +140,14 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
return false;
}
// Don't create a renderer or pump events for test-only
// renderers. Test-only renderers might be created on
// a non-main thread where interaction with the SDL
// render API is unsafe.
if (params->testOnly) {
return true;
}
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(params->window, &info)) {

View File

@@ -100,11 +100,11 @@ public:
if (m_DisplayLayer != nullptr) {
[m_DisplayLayer release];
}
// It appears to be necessary to run the event loop after destroying
// the AVSampleBufferDisplayLayer to avoid issue #973.
SDL_PumpEvents();
}
}}
static
@@ -333,7 +333,7 @@ public:
}
// If we're using direct rendering, set up the AVSampleBufferDisplayLayer
if (m_DirectRendering) {
if (m_DirectRendering && !params->testOnly) {
SDL_SysWMinfo info;
SDL_VERSION(&info.version);

View File

@@ -658,6 +658,37 @@ public:
return false;
}
// Create the Metal texture cache for our CVPixelBuffers
CFStringRef keys[1] = { kCVMetalTextureUsage };
NSUInteger values[1] = { MTLTextureUsageShaderRead };
auto cacheAttributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1, nullptr, nullptr);
err = CVMetalTextureCacheCreate(kCFAllocatorDefault, cacheAttributes, device, nullptr, &m_TextureCache);
CFRelease(cacheAttributes);
if (err != kCVReturnSuccess) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"CVMetalTextureCacheCreate() failed: %d",
err);
return false;
}
// Compile our shaders
QString shaderSource = QString::fromUtf8(Path::readDataFile("vt_renderer.metal"));
m_ShaderLibrary = [device newLibraryWithSource:shaderSource.toNSString() options:nullptr error:nullptr];
if (!m_ShaderLibrary) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to compile shaders");
return false;
}
// Create a command queue for submission
m_CommandQueue = [device newCommandQueue];
// Add the Metal view to the window if we're not in test-only mode
//
// NB: Test-only renderers may be created on a non-main thread, so
// we don't want to touch the view hierarchy in that context.
if (!params->testOnly) {
m_MetalView = SDL_Metal_CreateView(m_Window);
if (!m_MetalView) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@@ -676,32 +707,8 @@ public:
// Allow tearing if V-Sync is off (also requires direct display path)
m_MetalLayer.displaySyncEnabled = params->enableVsync;
// Create the Metal texture cache for our CVPixelBuffers
CFStringRef keys[1] = { kCVMetalTextureUsage };
NSUInteger values[1] = { MTLTextureUsageShaderRead };
auto cacheAttributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1, nullptr, nullptr);
err = CVMetalTextureCacheCreate(kCFAllocatorDefault, cacheAttributes, m_MetalLayer.device, nullptr, &m_TextureCache);
CFRelease(cacheAttributes);
if (err != kCVReturnSuccess) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"CVMetalTextureCacheCreate() failed: %d",
err);
return false;
}
// Compile our shaders
QString shaderSource = QString::fromUtf8(Path::readDataFile("vt_renderer.metal"));
m_ShaderLibrary = [m_MetalLayer.device newLibraryWithSource:shaderSource.toNSString() options:nullptr error:nullptr];
if (!m_ShaderLibrary) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to compile shaders");
return false;
}
// Create a command queue for submission
m_CommandQueue = [m_MetalLayer.device newCommandQueue];
return true;
}}