diff --git a/app/streaming/input/mouse.cpp b/app/streaming/input/mouse.cpp index cf53b926..6c6369b9 100644 --- a/app/streaming/input/mouse.cpp +++ b/app/streaming/input/mouse.cpp @@ -227,6 +227,21 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) LiSendHighResScrollEvent((short)(event->preciseY * 120)); // WHEEL_DELTA } + + if (event->preciseX != 0.0f) { + // Invert the scroll direction if needed + if (m_ReverseScrollDirection) { + event->preciseX = -event->preciseY; + } + +#ifdef Q_OS_DARWIN + // HACK: Clamp the scroll values on macOS to prevent OS scroll acceleration + // from generating wild scroll deltas when scrolling quickly. + event->preciseX = SDL_clamp(event->preciseX, -1.0f, 1.0f); +#endif + + LiSendHighResHScrollEvent((short)(event->preciseX * 120)); // WHEEL_DELTA + } #else if (event->y != 0) { // Invert the scroll direction if needed @@ -241,6 +256,20 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event) LiSendScrollEvent((signed char)event->y); } + + if (event->x != 0) { + // Invert the scroll direction if needed + if (m_ReverseScrollDirection) { + event->x = -event->x; + } + +#ifdef Q_OS_DARWIN + // See comment above + event->x = SDL_clamp(event->x, -1, 1); +#endif + + LiSendHScrollEvent((signed char)event->x); + } #endif } diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index db7f92f2..1897334e 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -235,10 +235,6 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, params.testOnly = testOnly; params.vds = vds; - memset(¶ms.hdrMetadata, 0, sizeof(params.hdrMetadata)); - params.hdrMetadata.eotf = 2; // SMPTE ST 2084 - params.hdrMetadata.staticMetadataDescriptorId = 0; // Static Metadata Type 1 - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "V-sync %s", enableVsync ? "enabled" : "disabled"); diff --git a/app/streaming/video/decoder.h b/app/streaming/video/decoder.h index e96350f8..1432dbb4 100644 --- a/app/streaming/video/decoder.h +++ b/app/streaming/video/decoder.h @@ -28,23 +28,6 @@ typedef struct _VIDEO_STATS { uint32_t measurementStartTimestamp; } VIDEO_STATS, *PVIDEO_STATS; -typedef struct _HDR_MASTERING_METADATA { - uint8_t eotf; - uint8_t staticMetadataDescriptorId; - struct { - uint16_t x; - uint16_t y; - } displayPrimaries[3]; - struct { - uint16_t x; - uint16_t y; - } whitePoint; - uint16_t maxDisplayMasteringLuminance; - uint16_t minDisplayMasteringLuminance; - uint16_t maxContentLightLevel; - uint16_t maxFrameAverageLightLevel; -} HDR_MASTERING_METADATA, *PHDR_MASTERING_METADATA; - typedef struct _DECODER_PARAMETERS { SDL_Window* window; StreamingPreferences::VideoDecoderSelection vds; @@ -56,7 +39,6 @@ typedef struct _DECODER_PARAMETERS { bool enableVsync; bool enableFramePacing; bool testOnly; - HDR_MASTERING_METADATA hdrMetadata; } DECODER_PARAMETERS, *PDECODER_PARAMETERS; class IVideoDecoder { diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp index 6713c4b1..b94783e6 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp @@ -512,19 +512,25 @@ void D3D11VARenderer::setHdrMode(bool enabled) if (enabled) { DXGI_HDR_METADATA_HDR10 hdr10Metadata; + SS_HDR_METADATA sunshineHdrMetadata; - hdr10Metadata.RedPrimary[0] = m_DecoderParams.hdrMetadata.displayPrimaries[0].x; - hdr10Metadata.RedPrimary[1] = m_DecoderParams.hdrMetadata.displayPrimaries[0].y; - hdr10Metadata.GreenPrimary[0] = m_DecoderParams.hdrMetadata.displayPrimaries[1].x; - hdr10Metadata.GreenPrimary[1] = m_DecoderParams.hdrMetadata.displayPrimaries[1].y; - hdr10Metadata.BluePrimary[0] = m_DecoderParams.hdrMetadata.displayPrimaries[2].x; - hdr10Metadata.BluePrimary[1] = m_DecoderParams.hdrMetadata.displayPrimaries[2].y; - hdr10Metadata.WhitePoint[0] = m_DecoderParams.hdrMetadata.whitePoint.x; - hdr10Metadata.WhitePoint[1] = m_DecoderParams.hdrMetadata.whitePoint.y; - hdr10Metadata.MaxMasteringLuminance = m_DecoderParams.hdrMetadata.maxDisplayMasteringLuminance; - hdr10Metadata.MinMasteringLuminance = m_DecoderParams.hdrMetadata.minDisplayMasteringLuminance; - hdr10Metadata.MaxContentLightLevel = m_DecoderParams.hdrMetadata.maxContentLightLevel; - hdr10Metadata.MaxFrameAverageLightLevel = m_DecoderParams.hdrMetadata.maxFrameAverageLightLevel; + // Sunshine will have HDR metadata but GFE will not + if (!LiGetHdrMetadata(&sunshineHdrMetadata)) { + RtlZeroMemory(&sunshineHdrMetadata, sizeof(sunshineHdrMetadata)); + } + + hdr10Metadata.RedPrimary[0] = sunshineHdrMetadata.displayPrimaries[0].x; + hdr10Metadata.RedPrimary[1] = sunshineHdrMetadata.displayPrimaries[0].y; + hdr10Metadata.GreenPrimary[0] = sunshineHdrMetadata.displayPrimaries[1].x; + hdr10Metadata.GreenPrimary[1] = sunshineHdrMetadata.displayPrimaries[1].y; + hdr10Metadata.BluePrimary[0] = sunshineHdrMetadata.displayPrimaries[2].x; + hdr10Metadata.BluePrimary[1] = sunshineHdrMetadata.displayPrimaries[2].y; + hdr10Metadata.WhitePoint[0] = sunshineHdrMetadata.whitePoint.x; + hdr10Metadata.WhitePoint[1] = sunshineHdrMetadata.whitePoint.y; + hdr10Metadata.MaxMasteringLuminance = sunshineHdrMetadata.maxDisplayLuminance; + hdr10Metadata.MinMasteringLuminance = sunshineHdrMetadata.minDisplayLuminance; + hdr10Metadata.MaxContentLightLevel = sunshineHdrMetadata.maxContentLightLevel; + hdr10Metadata.MaxFrameAverageLightLevel = sunshineHdrMetadata.maxFrameAverageLightLevel; hr = m_SwapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(hdr10Metadata), &hdr10Metadata); if (SUCCEEDED(hr)) { diff --git a/app/streaming/video/ffmpeg-renderers/drm.cpp b/app/streaming/video/ffmpeg-renderers/drm.cpp index 26741d1b..7d891783 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.cpp +++ b/app/streaming/video/ffmpeg-renderers/drm.cpp @@ -421,35 +421,6 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params) drmModeFreeObjectProperties(props); } - // If we have an HDR output metadata property, construct the metadata blob - // to apply when we are called to enter HDR mode. - if (m_HdrOutputMetadataProp != nullptr) { - DrmDefs::hdr_output_metadata outputMetadata; - - outputMetadata.metadata_type = 0; // HDMI_STATIC_METADATA_TYPE1 - outputMetadata.hdmi_metadata_type1.eotf = params->hdrMetadata.eotf; - outputMetadata.hdmi_metadata_type1.metadata_type = params->hdrMetadata.staticMetadataDescriptorId; - for (int i = 0; i < 3; i++) { - outputMetadata.hdmi_metadata_type1.display_primaries[i].x = params->hdrMetadata.displayPrimaries[i].x; - outputMetadata.hdmi_metadata_type1.display_primaries[i].y = params->hdrMetadata.displayPrimaries[i].y; - } - outputMetadata.hdmi_metadata_type1.white_point.x = params->hdrMetadata.whitePoint.x; - outputMetadata.hdmi_metadata_type1.white_point.y = params->hdrMetadata.whitePoint.y; - outputMetadata.hdmi_metadata_type1.max_display_mastering_luminance = params->hdrMetadata.maxDisplayMasteringLuminance; - outputMetadata.hdmi_metadata_type1.min_display_mastering_luminance = params->hdrMetadata.minDisplayMasteringLuminance; - outputMetadata.hdmi_metadata_type1.max_cll = params->hdrMetadata.maxContentLightLevel; - outputMetadata.hdmi_metadata_type1.max_fall = params->hdrMetadata.maxFrameAverageLightLevel; - - err = drmModeCreatePropertyBlob(m_DrmFd, &outputMetadata, sizeof(outputMetadata), &m_HdrOutputMetadataBlobId); - if (err < 0) { - m_HdrOutputMetadataBlobId = 0; - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "drmModeCreatePropertyBlob() failed: %d", - errno); - // Non-fatal - } - } - // If we got this far, we can do direct rendering via the DRM FD. m_SupportsDirectRendering = true; @@ -495,8 +466,46 @@ int DrmRenderer::getRendererAttributes() } void DrmRenderer::setHdrMode(bool enabled) -{ - if (m_HdrOutputMetadataProp != nullptr && m_HdrOutputMetadataBlobId != 0) { +{ + if (m_HdrOutputMetadataProp != nullptr) { + if (m_HdrOutputMetadataBlobId != 0) { + drmModeDestroyPropertyBlob(m_DrmFd, m_HdrOutputMetadataBlobId); + m_HdrOutputMetadataBlobId = 0; + } + + if (enabled) { + DrmDefs::hdr_output_metadata outputMetadata; + SS_HDR_METADATA sunshineHdrMetadata; + + // Sunshine will have HDR metadata but GFE will not + if (!LiGetHdrMetadata(&sunshineHdrMetadata)) { + memset(&sunshineHdrMetadata, 0, sizeof(sunshineHdrMetadata)); + } + + outputMetadata.metadata_type = 0; // HDMI_STATIC_METADATA_TYPE1 + outputMetadata.hdmi_metadata_type1.eotf = 2; // SMPTE ST 2084 + outputMetadata.hdmi_metadata_type1.metadata_type = 0; // Static Metadata Type 1 + for (int i = 0; i < 3; i++) { + outputMetadata.hdmi_metadata_type1.display_primaries[i].x = sunshineHdrMetadata.displayPrimaries[i].x; + outputMetadata.hdmi_metadata_type1.display_primaries[i].y = sunshineHdrMetadata.displayPrimaries[i].y; + } + outputMetadata.hdmi_metadata_type1.white_point.x = sunshineHdrMetadata.whitePoint.x; + outputMetadata.hdmi_metadata_type1.white_point.y = sunshineHdrMetadata.whitePoint.y; + outputMetadata.hdmi_metadata_type1.max_display_mastering_luminance = sunshineHdrMetadata.maxDisplayLuminance; + outputMetadata.hdmi_metadata_type1.min_display_mastering_luminance = sunshineHdrMetadata.minDisplayLuminance; + outputMetadata.hdmi_metadata_type1.max_cll = sunshineHdrMetadata.maxContentLightLevel; + outputMetadata.hdmi_metadata_type1.max_fall = sunshineHdrMetadata.maxFrameAverageLightLevel; + + err = drmModeCreatePropertyBlob(m_DrmFd, &outputMetadata, sizeof(outputMetadata), &m_HdrOutputMetadataBlobId); + if (err < 0) { + m_HdrOutputMetadataBlobId = 0; + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "drmModeCreatePropertyBlob() failed: %d", + errno); + // Non-fatal + } + } + int err = drmModeObjectSetProperty(m_DrmFd, m_ConnectorId, DRM_MODE_OBJECT_CONNECTOR, m_HdrOutputMetadataProp->prop_id, enabled ? m_HdrOutputMetadataBlobId : 0); diff --git a/moonlight-common-c/moonlight-common-c b/moonlight-common-c/moonlight-common-c index 7d9df5b7..07beb0f0 160000 --- a/moonlight-common-c/moonlight-common-c +++ b/moonlight-common-c/moonlight-common-c @@ -1 +1 @@ -Subproject commit 7d9df5b731fa9c90535bc94f74a9d92b7f7d79a0 +Subproject commit 07beb0f0a520106c49fda7664369b29e6938ea6e