mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-01 23:35:55 +00:00
Enable transparent resizing and display changes for supported renderers
This commit is contained in:
parent
481f23b6e9
commit
2a05b890d8
@ -1915,6 +1915,52 @@ void Session::execInternal()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow the renderer to handle the state change without being recreated
|
||||||
|
if (m_VideoDecoder) {
|
||||||
|
bool forceRecreation = false;
|
||||||
|
|
||||||
|
WINDOW_STATE_CHANGE_INFO windowChangeInfo = {};
|
||||||
|
windowChangeInfo.window = m_Window;
|
||||||
|
|
||||||
|
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||||
|
windowChangeInfo.stateChangeFlags |= WINDOW_STATE_CHANGE_SIZE;
|
||||||
|
|
||||||
|
windowChangeInfo.width = event.window.data1;
|
||||||
|
windowChangeInfo.height = event.window.data2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newDisplayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||||
|
if (newDisplayIndex != currentDisplayIndex) {
|
||||||
|
windowChangeInfo.stateChangeFlags |= WINDOW_STATE_CHANGE_DISPLAY;
|
||||||
|
|
||||||
|
windowChangeInfo.displayIndex = newDisplayIndex;
|
||||||
|
|
||||||
|
// If the refresh rates have changed, we will need to go through the full
|
||||||
|
// decoder recreation path to ensure Pacer is switched to the new display
|
||||||
|
// and that we apply any V-Sync disablement rules that may be needed for
|
||||||
|
// this display.
|
||||||
|
SDL_DisplayMode oldMode, newMode;
|
||||||
|
if (SDL_GetCurrentDisplayMode(currentDisplayIndex, &oldMode) < 0 ||
|
||||||
|
SDL_GetCurrentDisplayMode(newDisplayIndex, &newMode) < 0 ||
|
||||||
|
oldMode.refresh_rate != newMode.refresh_rate) {
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Forcing renderer recreation due to refresh rate change between displays");
|
||||||
|
forceRecreation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!forceRecreation && m_VideoDecoder->notifyWindowChanged(&windowChangeInfo)) {
|
||||||
|
// Update the window display mode based on our current monitor
|
||||||
|
// NB: Avoid a useless modeset by only doing this if it changed.
|
||||||
|
if (newDisplayIndex != currentDisplayIndex) {
|
||||||
|
currentDisplayIndex = newDisplayIndex;
|
||||||
|
updateOptimalWindowDisplayMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Recreating renderer for window event: %d (%d %d)",
|
"Recreating renderer for window event: %d (%d %d)",
|
||||||
event.window.event,
|
event.window.event,
|
||||||
|
@ -45,6 +45,21 @@ typedef struct _DECODER_PARAMETERS {
|
|||||||
bool testOnly;
|
bool testOnly;
|
||||||
} DECODER_PARAMETERS, *PDECODER_PARAMETERS;
|
} DECODER_PARAMETERS, *PDECODER_PARAMETERS;
|
||||||
|
|
||||||
|
#define WINDOW_STATE_CHANGE_SIZE 0x01
|
||||||
|
#define WINDOW_STATE_CHANGE_DISPLAY 0x02
|
||||||
|
|
||||||
|
typedef struct _WINDOW_STATE_CHANGE_INFO {
|
||||||
|
SDL_Window* window;
|
||||||
|
uint32_t stateChangeFlags;
|
||||||
|
|
||||||
|
// Populated if WINDOW_STATE_CHANGE_SIZE is set
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
// Populated if WINDOW_STATE_CHANGE_DISPLAY is set
|
||||||
|
int displayIndex;
|
||||||
|
} WINDOW_STATE_CHANGE_INFO, *PWINDOW_STATE_CHANGE_INFO;
|
||||||
|
|
||||||
class IVideoDecoder {
|
class IVideoDecoder {
|
||||||
public:
|
public:
|
||||||
virtual ~IVideoDecoder() {}
|
virtual ~IVideoDecoder() {}
|
||||||
@ -59,4 +74,5 @@ public:
|
|||||||
virtual int submitDecodeUnit(PDECODE_UNIT du) = 0;
|
virtual int submitDecodeUnit(PDECODE_UNIT du) = 0;
|
||||||
virtual void renderFrameOnMainThread() = 0;
|
virtual void renderFrameOnMainThread() = 0;
|
||||||
virtual void setHdrMode(bool enabled) = 0;
|
virtual void setHdrMode(bool enabled) = 0;
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info) = 0;
|
||||||
};
|
};
|
||||||
|
@ -168,6 +168,12 @@ void EGLRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EGLRenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info)
|
||||||
|
{
|
||||||
|
// We can transparently handle size and display changes
|
||||||
|
return !(info->stateChangeFlags & ~(WINDOW_STATE_CHANGE_SIZE | WINDOW_STATE_CHANGE_DISPLAY));
|
||||||
|
}
|
||||||
|
|
||||||
bool EGLRenderer::isPixelFormatSupported(int videoFormat, AVPixelFormat pixelFormat)
|
bool EGLRenderer::isPixelFormatSupported(int videoFormat, AVPixelFormat pixelFormat)
|
||||||
{
|
{
|
||||||
// Pixel format support should be determined by the backend renderer
|
// Pixel format support should be determined by the backend renderer
|
||||||
|
@ -17,6 +17,7 @@ public:
|
|||||||
virtual void renderFrame(AVFrame* frame) override;
|
virtual void renderFrame(AVFrame* frame) override;
|
||||||
virtual bool testRenderFrame(AVFrame* frame) override;
|
virtual bool testRenderFrame(AVFrame* frame) override;
|
||||||
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) override;
|
||||||
virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override;
|
virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override;
|
||||||
virtual AVPixelFormat getPreferredPixelFormat(int videoFormat) override;
|
virtual AVPixelFormat getPreferredPixelFormat(int videoFormat) override;
|
||||||
|
|
||||||
|
@ -320,6 +320,8 @@ bool PlVkRenderer::isExtensionSupportedByPhysicalDevice(VkPhysicalDevice device,
|
|||||||
|
|
||||||
bool PlVkRenderer::initialize(PDECODER_PARAMETERS params)
|
bool PlVkRenderer::initialize(PDECODER_PARAMETERS params)
|
||||||
{
|
{
|
||||||
|
m_Window = params->window;
|
||||||
|
|
||||||
unsigned int instanceExtensionCount = 0;
|
unsigned int instanceExtensionCount = 0;
|
||||||
if (!SDL_Vulkan_GetInstanceExtensions(params->window, &instanceExtensionCount, nullptr)) {
|
if (!SDL_Vulkan_GetInstanceExtensions(params->window, &instanceExtensionCount, nullptr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -429,10 +431,6 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS params)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vkDrawableW, vkDrawableH;
|
|
||||||
SDL_Vulkan_GetDrawableSize(params->window, &vkDrawableW, &vkDrawableH);
|
|
||||||
pl_swapchain_resize(m_Swapchain, &vkDrawableW, &vkDrawableH);
|
|
||||||
|
|
||||||
m_Renderer = pl_renderer_create(m_Log, m_Vulkan->gpu);
|
m_Renderer = pl_renderer_create(m_Log, m_Vulkan->gpu);
|
||||||
if (m_Renderer == nullptr) {
|
if (m_Renderer == nullptr) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -599,6 +597,11 @@ bool PlVkRenderer::isSurfacePresentationSupportedByPhysicalDevice(VkPhysicalDevi
|
|||||||
|
|
||||||
void PlVkRenderer::waitToRender()
|
void PlVkRenderer::waitToRender()
|
||||||
{
|
{
|
||||||
|
// Handle the swapchain being resized
|
||||||
|
int vkDrawableW, vkDrawableH;
|
||||||
|
SDL_Vulkan_GetDrawableSize(m_Window, &vkDrawableW, &vkDrawableH);
|
||||||
|
pl_swapchain_resize(m_Swapchain, &vkDrawableW, &vkDrawableH);
|
||||||
|
|
||||||
// Get the next swapchain buffer for rendering. If this fails, renderFrame()
|
// Get the next swapchain buffer for rendering. If this fails, renderFrame()
|
||||||
// will try again.
|
// will try again.
|
||||||
//
|
//
|
||||||
@ -866,6 +869,12 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
SDL_AtomicUnlock(&m_OverlayLock);
|
SDL_AtomicUnlock(&m_OverlayLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlVkRenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info)
|
||||||
|
{
|
||||||
|
// We can transparently handle size and display changes
|
||||||
|
return !(info->stateChangeFlags & ~(WINDOW_STATE_CHANGE_SIZE | WINDOW_STATE_CHANGE_DISPLAY));
|
||||||
|
}
|
||||||
|
|
||||||
int PlVkRenderer::getRendererAttributes()
|
int PlVkRenderer::getRendererAttributes()
|
||||||
{
|
{
|
||||||
int attributes = 0;
|
int attributes = 0;
|
||||||
|
@ -17,6 +17,7 @@ public:
|
|||||||
virtual void waitToRender() override;
|
virtual void waitToRender() override;
|
||||||
virtual void cleanupRenderContext() override;
|
virtual void cleanupRenderContext() override;
|
||||||
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) override;
|
||||||
virtual int getRendererAttributes() override;
|
virtual int getRendererAttributes() override;
|
||||||
virtual int getDecoderCapabilities() override;
|
virtual int getDecoderCapabilities() override;
|
||||||
virtual bool needsTestFrame() override;
|
virtual bool needsTestFrame() override;
|
||||||
@ -41,6 +42,9 @@ private:
|
|||||||
// The backend renderer if we're frontend-only
|
// The backend renderer if we're frontend-only
|
||||||
IFFmpegRenderer* m_Backend;
|
IFFmpegRenderer* m_Backend;
|
||||||
|
|
||||||
|
// SDL state
|
||||||
|
SDL_Window* m_Window = nullptr;
|
||||||
|
|
||||||
// The libplacebo rendering state
|
// The libplacebo rendering state
|
||||||
pl_log m_Log = nullptr;
|
pl_log m_Log = nullptr;
|
||||||
pl_vk_inst m_PlVkInstance = nullptr;
|
pl_vk_inst m_PlVkInstance = nullptr;
|
||||||
|
@ -233,6 +233,11 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) {
|
||||||
|
// Assume the renderer cannot handle window state changes
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Allow renderers to expose their type
|
// Allow renderers to expose their type
|
||||||
enum class RendererType {
|
enum class RendererType {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
@ -492,3 +492,9 @@ bool SdlRenderer::testRenderFrame(AVFrame* frame)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SdlRenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info)
|
||||||
|
{
|
||||||
|
// We can transparently handle size and display changes
|
||||||
|
return !(info->stateChangeFlags & ~(WINDOW_STATE_CHANGE_SIZE | WINDOW_STATE_CHANGE_DISPLAY));
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ public:
|
|||||||
virtual bool isRenderThreadSupported() override;
|
virtual bool isRenderThreadSupported() override;
|
||||||
virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override;
|
virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override;
|
||||||
virtual bool testRenderFrame(AVFrame* frame) override;
|
virtual bool testRenderFrame(AVFrame* frame) override;
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderOverlay(Overlay::OverlayType type);
|
void renderOverlay(Overlay::OverlayType type);
|
||||||
|
@ -681,6 +681,12 @@ void VAAPIRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VAAPIRenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info)
|
||||||
|
{
|
||||||
|
// We can transparently handle size and display changes
|
||||||
|
return !(info->stateChangeFlags & ~(WINDOW_STATE_CHANGE_SIZE | WINDOW_STATE_CHANGE_DISPLAY));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VAAPIRenderer::renderFrame(AVFrame* frame)
|
VAAPIRenderer::renderFrame(AVFrame* frame)
|
||||||
{
|
{
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
virtual int getDecoderColorspace() override;
|
virtual int getDecoderColorspace() override;
|
||||||
virtual int getDecoderCapabilities() override;
|
virtual int getDecoderCapabilities() override;
|
||||||
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) override;
|
||||||
|
|
||||||
#ifdef HAVE_EGL
|
#ifdef HAVE_EGL
|
||||||
virtual bool canExportEGL() override;
|
virtual bool canExportEGL() override;
|
||||||
|
@ -99,6 +99,11 @@ void FFmpegVideoDecoder::setHdrMode(bool enabled)
|
|||||||
m_FrontendRenderer->setHdrMode(enabled);
|
m_FrontendRenderer->setHdrMode(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FFmpegVideoDecoder::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info)
|
||||||
|
{
|
||||||
|
return m_FrontendRenderer->notifyWindowChanged(info);
|
||||||
|
}
|
||||||
|
|
||||||
int FFmpegVideoDecoder::getDecoderCapabilities()
|
int FFmpegVideoDecoder::getDecoderCapabilities()
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
virtual int submitDecodeUnit(PDECODE_UNIT du) override;
|
virtual int submitDecodeUnit(PDECODE_UNIT du) override;
|
||||||
virtual void renderFrameOnMainThread() override;
|
virtual void renderFrameOnMainThread() override;
|
||||||
virtual void setHdrMode(bool enabled) override;
|
virtual void setHdrMode(bool enabled) override;
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info) override;
|
||||||
|
|
||||||
virtual IFFmpegRenderer* getBackendRenderer();
|
virtual IFFmpegRenderer* getBackendRenderer();
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Window state changes are not supported by SLVideo
|
||||||
|
virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void slLogCallback(void* context, ESLVideoLog logLevel, const char* message);
|
static void slLogCallback(void* context, ESLVideoLog logLevel, const char* message);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user