mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-02-16 02:30:52 +00:00
Create the SystemProperties test window on the main thread
This commit is contained in:
@@ -29,38 +29,7 @@ private:
|
|||||||
bool supportsHdr;
|
bool supportsHdr;
|
||||||
QSize maximumResolution;
|
QSize maximumResolution;
|
||||||
|
|
||||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
Session::getDecoderInfo(m_Properties->testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, supportsHdr, maximumResolution);
|
||||||
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);
|
|
||||||
|
|
||||||
// Propagate the decoder properties to the SystemProperties singleton and emit any change signals on the main thread
|
// Propagate the decoder properties to the SystemProperties singleton and emit any change signals on the main thread
|
||||||
QMetaObject::invokeMethod(m_Properties, "updateDecoderProperties",
|
QMetaObject::invokeMethod(m_Properties, "updateDecoderProperties",
|
||||||
@@ -137,12 +106,49 @@ SystemProperties::SystemProperties()
|
|||||||
supportsHdr = true;
|
supportsHdr = true;
|
||||||
maximumResolution = QSize(0, 0);
|
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 = new SystemPropertyQueryThread(this);
|
||||||
systemPropertyQueryThread->start();
|
systemPropertyQueryThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemProperties::~SystemProperties()
|
||||||
|
{
|
||||||
|
systemPropertyQueryThread->wait();
|
||||||
|
}
|
||||||
|
|
||||||
void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr)
|
void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, bool rendererAlwaysFullScreen, QSize maximumResolution, bool supportsHdr)
|
||||||
{
|
{
|
||||||
|
SDL_assert(testWindow);
|
||||||
|
|
||||||
if (hasHardwareAcceleration != this->hasHardwareAcceleration) {
|
if (hasHardwareAcceleration != this->hasHardwareAcceleration) {
|
||||||
this->hasHardwareAcceleration = hasHardwareAcceleration;
|
this->hasHardwareAcceleration = hasHardwareAcceleration;
|
||||||
emit hasHardwareAccelerationChanged();
|
emit hasHardwareAccelerationChanged();
|
||||||
@@ -162,6 +168,10 @@ void SystemProperties::updateDecoderProperties(bool hasHardwareAcceleration, boo
|
|||||||
this->supportsHdr = supportsHdr;
|
this->supportsHdr = supportsHdr;
|
||||||
emit supportsHdrChanged();
|
emit supportsHdrChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_DestroyWindow(testWindow);
|
||||||
|
testWindow = nullptr;
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect SystemProperties::getNativeResolution(int displayIndex)
|
QRect SystemProperties::getNativeResolution(int displayIndex)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
|
|
||||||
|
#include "SDL_compat.h"
|
||||||
|
|
||||||
class SystemProperties : public QObject
|
class SystemProperties : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -11,6 +13,7 @@ class SystemProperties : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SystemProperties();
|
SystemProperties();
|
||||||
|
~SystemProperties();
|
||||||
|
|
||||||
// Static properties queried synchronously during the constructor
|
// Static properties queried synchronously during the constructor
|
||||||
Q_PROPERTY(bool isRunningWayland MEMBER isRunningWayland CONSTANT)
|
Q_PROPERTY(bool isRunningWayland MEMBER isRunningWayland CONSTANT)
|
||||||
@@ -47,6 +50,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QThread* systemPropertyQueryThread;
|
QThread* systemPropertyQueryThread;
|
||||||
|
SDL_Window* testWindow;
|
||||||
|
|
||||||
// Properties set by the constructor
|
// Properties set by the constructor
|
||||||
bool isRunningWayland;
|
bool isRunningWayland;
|
||||||
|
|||||||
@@ -464,7 +464,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
|
|||||||
// to ensure we don't drop any important events.
|
// to ensure we don't drop any important events.
|
||||||
session->flushWindowEvents();
|
session->flushWindowEvents();
|
||||||
}
|
}
|
||||||
else {
|
else if (!params->testOnly) {
|
||||||
// If we get here prior to the start of a session, just pump and flush ourselves.
|
// If we get here prior to the start of a session, just pump and flush ourselves.
|
||||||
SDL_PumpEvents();
|
SDL_PumpEvents();
|
||||||
SDL_FlushEvent(SDL_WINDOWEVENT);
|
SDL_FlushEvent(SDL_WINDOWEVENT);
|
||||||
|
|||||||
@@ -140,6 +140,14 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
|
|||||||
return false;
|
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_SysWMinfo info;
|
||||||
SDL_VERSION(&info.version);
|
SDL_VERSION(&info.version);
|
||||||
if (!SDL_GetWindowWMInfo(params->window, &info)) {
|
if (!SDL_GetWindowWMInfo(params->window, &info)) {
|
||||||
|
|||||||
@@ -100,11 +100,11 @@ public:
|
|||||||
|
|
||||||
if (m_DisplayLayer != nullptr) {
|
if (m_DisplayLayer != nullptr) {
|
||||||
[m_DisplayLayer release];
|
[m_DisplayLayer release];
|
||||||
}
|
|
||||||
|
|
||||||
// It appears to be necessary to run the event loop after destroying
|
// It appears to be necessary to run the event loop after destroying
|
||||||
// the AVSampleBufferDisplayLayer to avoid issue #973.
|
// the AVSampleBufferDisplayLayer to avoid issue #973.
|
||||||
SDL_PumpEvents();
|
SDL_PumpEvents();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -333,7 +333,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we're using direct rendering, set up the AVSampleBufferDisplayLayer
|
// If we're using direct rendering, set up the AVSampleBufferDisplayLayer
|
||||||
if (m_DirectRendering) {
|
if (m_DirectRendering && !params->testOnly) {
|
||||||
SDL_SysWMinfo info;
|
SDL_SysWMinfo info;
|
||||||
|
|
||||||
SDL_VERSION(&info.version);
|
SDL_VERSION(&info.version);
|
||||||
|
|||||||
@@ -658,30 +658,11 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_MetalView = SDL_Metal_CreateView(m_Window);
|
|
||||||
if (!m_MetalView) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"SDL_Metal_CreateView() failed: %s",
|
|
||||||
SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_MetalLayer = (CAMetalLayer*)SDL_Metal_GetLayer(m_MetalView);
|
|
||||||
|
|
||||||
// Choose a device
|
|
||||||
m_MetalLayer.device = device;
|
|
||||||
|
|
||||||
// Allow EDR content if we're streaming in a 10-bit format
|
|
||||||
m_MetalLayer.wantsExtendedDynamicRangeContent = !!(params->videoFormat & VIDEO_FORMAT_MASK_10BIT);
|
|
||||||
|
|
||||||
// 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
|
// Create the Metal texture cache for our CVPixelBuffers
|
||||||
CFStringRef keys[1] = { kCVMetalTextureUsage };
|
CFStringRef keys[1] = { kCVMetalTextureUsage };
|
||||||
NSUInteger values[1] = { MTLTextureUsageShaderRead };
|
NSUInteger values[1] = { MTLTextureUsageShaderRead };
|
||||||
auto cacheAttributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1, nullptr, nullptr);
|
auto cacheAttributes = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1, nullptr, nullptr);
|
||||||
err = CVMetalTextureCacheCreate(kCFAllocatorDefault, cacheAttributes, m_MetalLayer.device, nullptr, &m_TextureCache);
|
err = CVMetalTextureCacheCreate(kCFAllocatorDefault, cacheAttributes, device, nullptr, &m_TextureCache);
|
||||||
CFRelease(cacheAttributes);
|
CFRelease(cacheAttributes);
|
||||||
|
|
||||||
if (err != kCVReturnSuccess) {
|
if (err != kCVReturnSuccess) {
|
||||||
@@ -693,7 +674,7 @@ public:
|
|||||||
|
|
||||||
// Compile our shaders
|
// Compile our shaders
|
||||||
QString shaderSource = QString::fromUtf8(Path::readDataFile("vt_renderer.metal"));
|
QString shaderSource = QString::fromUtf8(Path::readDataFile("vt_renderer.metal"));
|
||||||
m_ShaderLibrary = [m_MetalLayer.device newLibraryWithSource:shaderSource.toNSString() options:nullptr error:nullptr];
|
m_ShaderLibrary = [device newLibraryWithSource:shaderSource.toNSString() options:nullptr error:nullptr];
|
||||||
if (!m_ShaderLibrary) {
|
if (!m_ShaderLibrary) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Failed to compile shaders");
|
"Failed to compile shaders");
|
||||||
@@ -701,7 +682,33 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a command queue for submission
|
// Create a command queue for submission
|
||||||
m_CommandQueue = [m_MetalLayer.device newCommandQueue];
|
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,
|
||||||
|
"SDL_Metal_CreateView() failed: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_MetalLayer = (CAMetalLayer*)SDL_Metal_GetLayer(m_MetalView);
|
||||||
|
|
||||||
|
// Choose a device
|
||||||
|
m_MetalLayer.device = device;
|
||||||
|
|
||||||
|
// Allow EDR content if we're streaming in a 10-bit format
|
||||||
|
m_MetalLayer.wantsExtendedDynamicRangeContent = !!(params->videoFormat & VIDEO_FORMAT_MASK_10BIT);
|
||||||
|
|
||||||
|
// Allow tearing if V-Sync is off (also requires direct display path)
|
||||||
|
m_MetalLayer.displaySyncEnabled = params->enableVsync;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user