Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b100e674dd | ||
|
|
c0c4d60565 | ||
|
|
8b18d58aa0 | ||
|
|
5e1ac6df87 | ||
|
|
0c8970364c | ||
|
|
1516464f82 | ||
|
|
fd34a1fd28 | ||
|
|
9067db8915 | ||
|
|
177f845183 | ||
|
|
c9b03f80f8 | ||
|
|
a27589fe35 | ||
|
|
561d824814 |
@@ -42,7 +42,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: libsdl-org/SDL
|
||||
ref: a5e02a0927a2dd999718c1903f2d59440319ca99
|
||||
ref: release-3.4.12
|
||||
path: deps/SDL
|
||||
|
||||
- name: Build SDL3
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: intel/libva
|
||||
ref: 2.23.0
|
||||
ref: 2.24.1
|
||||
path: deps/libva
|
||||
|
||||
- name: Build libva
|
||||
|
||||
+46
-43
@@ -812,38 +812,64 @@ Flickable {
|
||||
ToolTip.text: qsTr("Fullscreen generally provides the best performance, but borderless windowed may work better with features like macOS Spaces, Alt+Tab, screenshot tools, on-screen overlays, etc.")
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: vsyncCheck
|
||||
Row {
|
||||
spacing: 5
|
||||
width: parent.width
|
||||
hoverEnabled: true
|
||||
text: qsTr("V-Sync")
|
||||
font.pointSize: 12
|
||||
checked: StreamingPreferences.enableVsync
|
||||
onCheckedChanged: {
|
||||
StreamingPreferences.enableVsync = checked
|
||||
|
||||
CheckBox {
|
||||
id: vsyncCheck
|
||||
hoverEnabled: true
|
||||
text: qsTr("V-Sync")
|
||||
font.pointSize: 12
|
||||
checked: StreamingPreferences.enableVsync
|
||||
onCheckedChanged: {
|
||||
StreamingPreferences.enableVsync = checked
|
||||
}
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: qsTr("Disabling V-Sync allows sub-frame rendering latency, but it can display visible tearing")
|
||||
}
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: qsTr("Disabling V-Sync allows sub-frame rendering latency, but it can display visible tearing")
|
||||
CheckBox {
|
||||
id: framePacingCheck
|
||||
hoverEnabled: true
|
||||
text: qsTr("Frame pacing")
|
||||
font.pointSize: 12
|
||||
enabled: StreamingPreferences.enableVsync
|
||||
checked: StreamingPreferences.enableVsync && StreamingPreferences.framePacing
|
||||
onCheckedChanged: {
|
||||
StreamingPreferences.framePacing = checked
|
||||
}
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: qsTr("Frame pacing reduces micro-stutter by delaying frames that come in too early")
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: framePacingCheck
|
||||
id: enableHdr
|
||||
width: parent.width
|
||||
hoverEnabled: true
|
||||
text: qsTr("Frame pacing")
|
||||
font.pointSize: 12
|
||||
enabled: StreamingPreferences.enableVsync
|
||||
checked: StreamingPreferences.enableVsync && StreamingPreferences.framePacing
|
||||
text: qsTr("Enable HDR")
|
||||
font.pointSize: 12
|
||||
|
||||
enabled: SystemProperties.supportsHdr
|
||||
checked: enabled && StreamingPreferences.enableHdr
|
||||
onCheckedChanged: {
|
||||
StreamingPreferences.framePacing = checked
|
||||
StreamingPreferences.enableHdr = checked
|
||||
}
|
||||
|
||||
// Updating StreamingPreferences.videoCodecConfig is handled above
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: qsTr("Frame pacing reduces micro-stutter by delaying frames that come in too early")
|
||||
ToolTip.text: enabled ?
|
||||
qsTr("The stream will be HDR-capable, but some games may require an HDR monitor on your host PC to enable HDR mode.")
|
||||
:
|
||||
qsTr("HDR streaming is not supported on this PC.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1630,29 +1656,6 @@ Flickable {
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: enableHdr
|
||||
width: parent.width
|
||||
text: qsTr("Enable HDR")
|
||||
font.pointSize: 12
|
||||
|
||||
enabled: SystemProperties.supportsHdr
|
||||
checked: enabled && StreamingPreferences.enableHdr
|
||||
onCheckedChanged: {
|
||||
StreamingPreferences.enableHdr = checked
|
||||
}
|
||||
|
||||
// Updating StreamingPreferences.videoCodecConfig is handled above
|
||||
|
||||
ToolTip.delay: 1000
|
||||
ToolTip.timeout: 5000
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: enabled ?
|
||||
qsTr("The stream will be HDR-capable, but some games may require an HDR monitor on your host PC to enable HDR mode.")
|
||||
:
|
||||
qsTr("HDR streaming is not supported on this PC.")
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: enableYUV444
|
||||
width: parent.width
|
||||
|
||||
@@ -627,6 +627,8 @@ bool EGLRenderer::setupVideoRenderingState() {
|
||||
glGenTextures(EGL_MAX_PLANES, m_Textures);
|
||||
for (size_t i = 0; i < EGL_MAX_PLANES; ++i) {
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, m_Textures[i]);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
@@ -784,16 +786,6 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
}
|
||||
}
|
||||
|
||||
int drawableWidth, drawableHeight;
|
||||
SDL_GL_GetDrawableSize(m_Window, &drawableWidth, &drawableHeight);
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = dst.x = dst.y = 0;
|
||||
src.w = frame->width;
|
||||
src.h = frame->height;
|
||||
dst.w = drawableWidth;
|
||||
dst.h = drawableHeight;
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
|
||||
ssize_t plane_count = m_Backend->exportEGLImages(frame, m_EGLDisplay, imgs);
|
||||
if (plane_count < 0)
|
||||
return;
|
||||
@@ -801,16 +793,6 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, m_Textures[i]);
|
||||
m_glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, imgs[i]);
|
||||
|
||||
// Use GL_NEAREST to reduce sampling if the video region is a multiple of the frame size
|
||||
if (dst.w % frame->width == 0 && dst.h % frame->height == 0) {
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
else {
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
// We already called glClear() after last frame's SDL_GL_SwapWindow()
|
||||
@@ -819,7 +801,17 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
int drawableWidth, drawableHeight;
|
||||
SDL_GL_GetDrawableSize(m_Window, &drawableWidth, &drawableHeight);
|
||||
|
||||
// Set the viewport to the size of the aspect-ratio-scaled video
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = dst.x = dst.y = 0;
|
||||
src.w = frame->width;
|
||||
src.h = frame->height;
|
||||
dst.w = drawableWidth;
|
||||
dst.h = drawableHeight;
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
glViewport(dst.x, dst.y, dst.w, dst.h);
|
||||
|
||||
glUseProgram(m_ShaderProgram);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <SDL_vulkan.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/hwcontext_drm.h>
|
||||
#include <libavutil/hwcontext_vulkan.h>
|
||||
}
|
||||
|
||||
@@ -942,6 +943,8 @@ void PlVkRenderer::waitToRender()
|
||||
}
|
||||
endRenderTiming();
|
||||
#endif
|
||||
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1146,6 +1149,24 @@ bool PlVkRenderer::testRenderFrame(AVFrame *frame)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (frame->format == AV_PIX_FMT_DRM_PRIME) {
|
||||
auto drmFrame = (AVDRMFrameDescriptor*)frame->data[0];
|
||||
|
||||
// This can happen with out-of-tree FFmpeg patches if the V4L2
|
||||
// format lacks a mapping to a DRM format.
|
||||
if (drmFrame->nb_layers == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Current versions of libplacebo only support one plane per layer
|
||||
// and will assert if provided a frame that violates this constraint.
|
||||
for (int i = 0; i < drmFrame->nb_layers; i++) {
|
||||
if (drmFrame->layers[i].nb_planes != 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test if the frame can be mapped to libplacebo
|
||||
pl_frame mappedFrame;
|
||||
if (!mapAvFrameToPlacebo(frame, &mappedFrame)) {
|
||||
|
||||
@@ -576,11 +576,6 @@ ReadbackRetry:
|
||||
// Ensure the viewport is set to the desired video region
|
||||
SDL_RenderSetViewport(m_Renderer, &dst);
|
||||
|
||||
// Use nearest pixel sampling if the video region size is a multiple of the frame size
|
||||
SDL_SetTextureScaleMode(m_Texture,
|
||||
dst.w % frame->width == 0 && dst.h % frame->height == 0 ?
|
||||
SDL_ScaleModeNearest : SDL_ScaleModeLinear);
|
||||
|
||||
// Draw the video content itself
|
||||
SDL_RenderCopy(m_Renderer, m_Texture, nullptr, nullptr);
|
||||
|
||||
|
||||
@@ -149,10 +149,12 @@ void OverlayManager::notifyOverlayUpdated(OverlayType type)
|
||||
(void**)&m_Overlays[type].surface,
|
||||
m_Overlays[type].enabled ?
|
||||
// The _Wrapped variant is required for line breaks to work
|
||||
TTF_RenderText_Blended_Wrapped(m_Overlays[type].font,
|
||||
m_Overlays[type].text,
|
||||
m_Overlays[type].color,
|
||||
1024)
|
||||
RenderTextOutlinedWrapped(m_Overlays[type].font,
|
||||
m_Overlays[type].text,
|
||||
m_Overlays[type].color,
|
||||
{0, 0, 0, 255},
|
||||
4,
|
||||
1024)
|
||||
: nullptr);
|
||||
|
||||
// Notify the renderer
|
||||
@@ -163,3 +165,47 @@ void OverlayManager::notifyOverlayUpdated(OverlayType type)
|
||||
SDL_FreeSurface(oldSurface);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* OverlayManager::RenderTextOutlinedWrapped(TTF_Font* font, const char* text, SDL_Color textColor, SDL_Color outlineColor, int outlineWidth, int wrapWidth) {
|
||||
if (text == nullptr || text[0] == '\0') {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int oldOutline = TTF_GetFontOutline(font);
|
||||
TTF_SetFontOutline(font, outlineWidth);
|
||||
|
||||
// Verify that the string won't require wrapping (which could cause the outline and the text
|
||||
// to diverge due to different wrapping positions).
|
||||
//
|
||||
// FIXME: We do this rather than just disabling wrapping entirely (wrapWidth = 0) because we
|
||||
// need further testing to ensure that all renderers can handle non-NPOT overlay textures.
|
||||
for (const QString& line : QString(text).split('\n')) {
|
||||
int extent, count;
|
||||
if (TTF_MeasureUTF8(font, line.toUtf8(), wrapWidth, &extent, &count) == 0 && count < line.size()) {
|
||||
// If it requires wrapping, render it without the outline
|
||||
TTF_SetFontOutline(font, oldOutline);
|
||||
return TTF_RenderUTF8_Blended_Wrapped(font, text, textColor, wrapWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw text twice, but outline is a bit bigger
|
||||
auto outlineSurface = TTF_RenderUTF8_Blended_Wrapped(font, text, outlineColor, wrapWidth);
|
||||
TTF_SetFontOutline(font, 0);
|
||||
auto textSurface = TTF_RenderUTF8_Blended_Wrapped(font, text, textColor, wrapWidth);
|
||||
TTF_SetFontOutline(font, oldOutline);
|
||||
|
||||
if (outlineSurface == nullptr || textSurface == nullptr) {
|
||||
SDL_FreeSurface(outlineSurface);
|
||||
SDL_FreeSurface(textSurface);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Merge the texts
|
||||
SDL_Rect dst = { outlineWidth, outlineWidth, textSurface->w, textSurface->h };
|
||||
SDL_BlitSurface(textSurface, nullptr, outlineSurface, &dst);
|
||||
|
||||
SDL_FreeSurface(textSurface);
|
||||
return outlineSurface;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
|
||||
private:
|
||||
void notifyOverlayUpdated(OverlayType type);
|
||||
SDL_Surface* RenderTextOutlinedWrapped(TTF_Font* font, const char* text, SDL_Color textColor, SDL_Color outlineColor, int outlineWidth, int wrapWidth);
|
||||
|
||||
struct {
|
||||
bool enabled;
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ CONFIG(release, debug|release) {
|
||||
# Enable ASan for Windows
|
||||
#QMAKE_CFLAGS += -fsanitize=address
|
||||
#QMAKE_CXXFLAGS += -fsanitize=address
|
||||
#QMAKE_LFLAGS += -incremental:no -wholearchive:clang_rt.asan_dynamic-x86_64.lib -wholearchive:clang_rt.asan_dynamic_runtime_thunk-x86_64.lib
|
||||
#QMAKE_LFLAGS += -incremental:no
|
||||
|
||||
# Propagate environment variable flags
|
||||
QMAKE_CFLAGS += $$(CFLAGS)
|
||||
|
||||
Submodule moonlight-common-c/moonlight-common-c updated: 2600beaf13...2ea47752c3
@@ -50,7 +50,9 @@ SOURCES += \
|
||||
$$ENET_DIR/protocol.c \
|
||||
$$ENET_DIR/unix.c \
|
||||
$$ENET_DIR/win32.c \
|
||||
$$COMMON_C_DIR/src/rswrapper.c \
|
||||
$$COMMON_C_DIR/nanors/deps/obl/oblas_common.c \
|
||||
$$COMMON_C_DIR/nanors/deps/obl/oblas_lite.c \
|
||||
$$COMMON_C_DIR/nanors/rs.c \
|
||||
$$COMMON_C_DIR/src/AudioStream.c \
|
||||
$$COMMON_C_DIR/src/ByteBuffer.c \
|
||||
$$COMMON_C_DIR/src/Connection.c \
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ $Organization = "moonlight-stream"
|
||||
$PrebuiltRepo = "moonlight-qt-deps"
|
||||
$TargetDir = Join-Path $PSScriptRoot "libs\windows"
|
||||
$Assets = @("windows-x64.zip", "windows-ARM64.zip")
|
||||
$Tag = "v7.2"
|
||||
$Tag = "v8"
|
||||
|
||||
if (Test-Path $TargetDir) {
|
||||
Write-Host "Cleaning target directory..." -ForegroundColor Cyan
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import shutil
|
||||
|
||||
ORGANIZATION = "moonlight-stream"
|
||||
PREBUILT_REPO = "moonlight-qt-deps"
|
||||
TAG = "v7.2"
|
||||
TAG = "v8"
|
||||
|
||||
def get_platform_config():
|
||||
system = platform.system()
|
||||
|
||||
Reference in New Issue
Block a user