mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-10-25 13:31:41 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5d8c3b7b5 |
No files matched your search
@@ -8,8 +8,6 @@
|
||||
<string>Moonlight</string>
|
||||
<key>LSSupportsGameMode</key>
|
||||
<true/>
|
||||
<key>NSApplicationUpdateCycleEnabled</key>
|
||||
<false/>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Stream games and other applications from another PC</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
|
||||
+1
-1
Submodule app/SDL_GameControllerDB updated: 8d9fefd7b8...c1d5289a1f.
@@ -186,7 +186,7 @@ IdentityManager::getSslKey()
|
||||
|
||||
BUF_MEM* mem;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
m_CachedSslKey = QSslKey(QByteArray(mem->data, (int)mem->length), getSslCertificate().publicKey().algorithm());
|
||||
m_CachedSslKey = QSslKey(QByteArray(mem->data, (int)mem->length), QSsl::Rsa);
|
||||
|
||||
BIO_free(bio);
|
||||
EVP_PKEY_free(pk);
|
||||
|
||||
+4
-38
@@ -507,47 +507,23 @@ NvHTTP::openConnection(QUrl baseUrl,
|
||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
|
||||
#endif
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||
// Use fine-grained idle timeouts to avoid calling QNetworkAccessManager::clearAccessCache(),
|
||||
// which tears down the NAM's global thread each time. We must not keep persistent connections
|
||||
// or GFE will puke.
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 12, 0)
|
||||
request.setAttribute(QNetworkRequest::ConnectionCacheExpiryTimeoutSecondsAttribute, -1);
|
||||
#elif QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||
request.setAttribute(QNetworkRequest::ConnectionCacheExpiryTimeoutSecondsAttribute, 0);
|
||||
#endif
|
||||
|
||||
auto sslErrorsConnection = connect(m_Nam, &QNetworkAccessManager::sslErrors, this, &NvHTTP::handleSslErrors);
|
||||
QNetworkReply* reply = m_Nam->get(request);
|
||||
QEventLoop loop;
|
||||
|
||||
// Connect the quit signals
|
||||
// Run the request with a timeout if requested
|
||||
QEventLoop loop;
|
||||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit);
|
||||
|
||||
// Enforce a transfer timeout if requested
|
||||
if (timeoutMs) {
|
||||
QTimer::singleShot(timeoutMs, &loop, &QEventLoop::quit);
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||
// Time the request to distinguish a slow response from an unreachable host
|
||||
auto* connectTimer = new QTimer(reply);
|
||||
connectTimer->setSingleShot(true);
|
||||
connect(connectTimer, &QTimer::timeout, reply, [reply, logLevel, url]() {
|
||||
if (!reply->isFinished()) {
|
||||
if (logLevel >= NvLogLevel::NVLL_ERROR) {
|
||||
qWarning() << "Aborting timed out connection for" << url.toString();
|
||||
}
|
||||
|
||||
reply->setProperty("timeout_reason", "connection_timeout");
|
||||
reply->abort();
|
||||
}
|
||||
});
|
||||
connect(reply, &QNetworkReply::requestSent, connectTimer, &QTimer::stop);
|
||||
connectTimer->start(REQUEST_TIMEOUT_MS);
|
||||
#endif
|
||||
|
||||
if (logLevel >= NvLogLevel::NVLL_VERBOSE) {
|
||||
qInfo() << "Executing request:" << url.toString();
|
||||
}
|
||||
@@ -583,11 +559,7 @@ NvHTTP::openConnection(QUrl baseUrl,
|
||||
throw exception;
|
||||
}
|
||||
else if (reply->error() == QNetworkReply::OperationCanceledError) {
|
||||
QString reason = reply->property("timeout_reason").toString();
|
||||
QtNetworkReplyException exception(QNetworkReply::TimeoutError,
|
||||
reason == "connection_timeout" ?
|
||||
"Connection timed out" :
|
||||
"Request timed out");
|
||||
QtNetworkReplyException exception(QNetworkReply::TimeoutError, "Request timed out");
|
||||
delete reply;
|
||||
throw exception;
|
||||
}
|
||||
@@ -598,11 +570,5 @@ NvHTTP::openConnection(QUrl baseUrl,
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||
// The requestSent signal must have stopped the timer for any successful request,
|
||||
// otherwise we could falsely time out a slow response when we connected fine.
|
||||
Q_ASSERT(!connectTimer->isActive());
|
||||
#endif
|
||||
|
||||
return reply;
|
||||
}
|
||||
@@ -140,9 +140,6 @@ NvPairingManager::getSignatureFromPemCert(const QByteArray& certificate)
|
||||
|
||||
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||
BIO_free_all(bio);
|
||||
if (cert == nullptr) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray signature = getSignatureFromCert(cert);
|
||||
X509_free(cert);
|
||||
@@ -162,15 +159,9 @@ NvPairingManager::verifySignature(const QByteArray& data, const QByteArray& sign
|
||||
|
||||
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||
BIO_free_all(bio);
|
||||
if (cert == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EVP_PKEY* pubKey = X509_get_pubkey(cert);
|
||||
if (pubKey == nullptr) {
|
||||
X509_free(cert);
|
||||
return false;
|
||||
}
|
||||
THROW_BAD_ALLOC_IF_NULL(pubKey);
|
||||
|
||||
EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
|
||||
THROW_BAD_ALLOC_IF_NULL(mdctx);
|
||||
@@ -215,7 +206,7 @@ NvPairingManager::saltPin(const QByteArray& salt, QString pin)
|
||||
NvPairingManager::PairState
|
||||
NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverCert)
|
||||
{
|
||||
int serverMajorVersion = NvHTTP::parseQuad(appVersion).value(0);
|
||||
int serverMajorVersion = NvHTTP::parseQuad(appVersion).at(0);
|
||||
qInfo() << "Pairing with server generation:" << serverMajorVersion;
|
||||
|
||||
QCryptographicHash::Algorithm hashAlgo;
|
||||
@@ -287,7 +278,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC
|
||||
}
|
||||
|
||||
QByteArray challengeResponseData = decrypt(m_Http.getXmlStringFromHex(challengeXml, "challengeresponse"), aesKey);
|
||||
if (challengeResponseData.size() < hashLength + 16) {
|
||||
if (challengeResponseData.size() < hashLength) {
|
||||
qCritical() << "Invalid challengeresponse at stage #2";
|
||||
m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS);
|
||||
return PairState::FAILED;
|
||||
|
||||
+28
-36
@@ -51,7 +51,7 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
// Display any modal dialogs for configuration warnings
|
||||
if (isGuiLaunch) {
|
||||
if (runConfigChecks) {
|
||||
if (SystemProperties.isWow64) {
|
||||
wow64Dialog.open()
|
||||
}
|
||||
@@ -171,28 +171,24 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
// Polling is only managed from the window for a normal GUI launch;
|
||||
// CLI commands (stream/quit/pair) manage it via the ComputerSeeker.
|
||||
if (isGuiLaunch) {
|
||||
// When we become invisible while streaming is going on,
|
||||
// stop polling immediately.
|
||||
if (!visible) {
|
||||
inactivityTimer.stop()
|
||||
// When we become invisible while streaming is going on,
|
||||
// stop polling immediately.
|
||||
if (!visible) {
|
||||
inactivityTimer.stop()
|
||||
|
||||
if (pollingActive) {
|
||||
ComputerManager.stopPollingAsync()
|
||||
pollingActive = false
|
||||
}
|
||||
if (pollingActive) {
|
||||
ComputerManager.stopPollingAsync()
|
||||
pollingActive = false
|
||||
}
|
||||
else if (active) {
|
||||
// When we become visible and active again, start polling
|
||||
inactivityTimer.stop()
|
||||
}
|
||||
else if (active) {
|
||||
// When we become visible and active again, start polling
|
||||
inactivityTimer.stop()
|
||||
|
||||
// Restart polling if it was stopped
|
||||
if (!pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
}
|
||||
// Restart polling if it was stopped
|
||||
if (!pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,25 +197,21 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
// Polling is only managed from the window for a normal GUI launch;
|
||||
// CLI commands (stream/quit/pair) manage it via the ComputerSeeker.
|
||||
if (isGuiLaunch) {
|
||||
if (active) {
|
||||
// Stop the inactivity timer
|
||||
inactivityTimer.stop()
|
||||
if (active) {
|
||||
// Stop the inactivity timer
|
||||
inactivityTimer.stop()
|
||||
|
||||
// Restart polling if it was stopped
|
||||
if (!pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Start the inactivity timer to stop polling
|
||||
// if focus does not return within a few minutes.
|
||||
inactivityTimer.restart()
|
||||
// Restart polling if it was stopped
|
||||
if (!pollingActive) {
|
||||
ComputerManager.startPolling()
|
||||
pollingActive = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Start the inactivity timer to stop polling
|
||||
// if focus does not return within a few minutes.
|
||||
inactivityTimer.restart()
|
||||
}
|
||||
|
||||
// Poll for gamepad input only when the window is in focus
|
||||
SdlGamepadKeyNavigation.notifyWindowFocus(visible && active)
|
||||
|
||||
+2
-11
@@ -465,16 +465,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
s_LoggerFile = new QFile(tempDir.filePath(QString("Moonlight-%1.log").arg(QDateTime::currentSecsSinceEpoch())));
|
||||
|
||||
// The log directory may be shared with other users (/tmp on macOS), so
|
||||
// we must never open a file or symlink that someone else planted there.
|
||||
// NewOnly fails if anything already exists at this path.
|
||||
QIODevice::OpenMode logOpenMode = QIODevice::WriteOnly | QIODevice::Text | QIODevice::NewOnly;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
|
||||
if (s_LoggerFile->open(logOpenMode, QFileDevice::ReadOwner | QFileDevice::WriteOwner)) {
|
||||
#else
|
||||
if (s_LoggerFile->open(logOpenMode)) {
|
||||
#endif
|
||||
if (s_LoggerFile->open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream(stderr) << "Redirecting log output to " << s_LoggerFile->fileName() << Qt::endl;
|
||||
s_LoggerStream.setDevice(s_LoggerFile);
|
||||
}
|
||||
@@ -1043,7 +1034,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (hasGUI) {
|
||||
engine.rootContext()->setContextProperty("initialView", initialView);
|
||||
engine.rootContext()->setContextProperty("isGuiLaunch", commandLineParserResult == GlobalCommandLineParser::NormalStartRequested);
|
||||
engine.rootContext()->setContextProperty("runConfigChecks", commandLineParserResult == GlobalCommandLineParser::NormalStartRequested);
|
||||
|
||||
// Load the main.qml file
|
||||
engine.load(QUrl(QStringLiteral("qrc:/gui/main.qml")));
|
||||
|
||||
@@ -965,7 +965,7 @@ void SdlInputHandler::setAdaptiveTriggers(uint16_t controllerNumber, DualSenseOu
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 16)
|
||||
// Make sure the controller number is within our supported count
|
||||
if (controllerNumber < MAX_GAMEPADS &&
|
||||
if (controllerNumber <= MAX_GAMEPADS &&
|
||||
// and we have a valid controller
|
||||
m_GamepadState[controllerNumber].controller != nullptr &&
|
||||
// and it's a PS5 controller
|
||||
|
||||
+21
-34
@@ -840,8 +840,9 @@ bool Session::initialize(QQuickWindow* qtWindow)
|
||||
// to allow decoding via VideoToolbox on macOS. Since we don't
|
||||
// have fixup code for HEVC, just avoid it if GFE is too old.
|
||||
QVector<int> gfeVersion = NvHTTP::parseQuad(m_Computer->gfeVersion);
|
||||
if (gfeVersion.value(0) < 3 ||
|
||||
(gfeVersion.value(0) == 3 && gfeVersion.value(1) < 11)) {
|
||||
if (gfeVersion.isEmpty() || // Very old versions don't have GfeVersion at all
|
||||
gfeVersion[0] < 3 ||
|
||||
(gfeVersion[0] == 3 && gfeVersion[1] < 11)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Disabling HEVC on macOS due to old GFE version");
|
||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_H265);
|
||||
@@ -1362,48 +1363,34 @@ void Session::getWindowDimensions(int& x, int& y,
|
||||
}
|
||||
}
|
||||
|
||||
// Get the usable display bounds
|
||||
SDL_Rect usableBounds;
|
||||
if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayUsableBounds() failed: %s",
|
||||
SDL_GetError());
|
||||
SDL_zero(usableBounds);
|
||||
}
|
||||
|
||||
// Use the usable display bounds if they are valid
|
||||
if (usableBounds.w != 0 &&
|
||||
WMUtils::hasDisplayUsableBounds() &&
|
||||
m_StreamConfig.width <= usableBounds.w &&
|
||||
if (SDL_GetDisplayUsableBounds(displayIndex, &usableBounds) == 0) {
|
||||
// If the stream resolution fits within the usable display area, use it directly
|
||||
if (m_StreamConfig.width <= usableBounds.w &&
|
||||
m_StreamConfig.height <= usableBounds.h) {
|
||||
// We fit pixel-perfect in the usable area, so don't scale at all
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
else if (usableBounds.w != 0 || SDL_GetDisplayBounds(displayIndex, &usableBounds) == 0) {
|
||||
// Otherwise, use 80% of usable bounds and preserve aspect ratio
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = dst.x = dst.y = 0;
|
||||
src.w = m_StreamConfig.width;
|
||||
src.h = m_StreamConfig.height;
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
} else {
|
||||
// Otherwise, use 80% of usable bounds and preserve aspect ratio
|
||||
SDL_Rect src, dst;
|
||||
src.x = src.y = dst.x = dst.y = 0;
|
||||
src.w = m_StreamConfig.width;
|
||||
src.h = m_StreamConfig.height;
|
||||
|
||||
dst.w = ((int)(usableBounds.w * 0.80f)) & ~0x1; // even width
|
||||
dst.h = ((int)(usableBounds.h * 0.80f)) & ~0x1; // even height
|
||||
dst.w = ((int)(usableBounds.w * 0.80f)) & ~0x1; // even width
|
||||
dst.h = ((int)(usableBounds.h * 0.80f)) & ~0x1; // even height
|
||||
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||
|
||||
// Only scale the size down, never up
|
||||
if (m_StreamConfig.width >= dst.w || m_StreamConfig.height >= dst.h) {
|
||||
width = dst.w;
|
||||
height = dst.h;
|
||||
}
|
||||
else {
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Oh well, hope for the best
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayUsableBounds() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
width = m_StreamConfig.width;
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <asm/hwprobe.h>
|
||||
#include <sys/syscall.h>
|
||||
#else
|
||||
#define __NR_riscv_hwprobe 258
|
||||
struct riscv_hwprobe {
|
||||
int64_t key;
|
||||
uint64_t value;
|
||||
@@ -45,10 +46,6 @@ struct riscv_hwprobe {
|
||||
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
|
||||
#endif
|
||||
|
||||
#ifndef __NR_riscv_hwprobe
|
||||
#define __NR_riscv_hwprobe 258
|
||||
#endif
|
||||
|
||||
// RISC-V Scalar AES [E]ncryption and [D]ecryption
|
||||
#ifndef RISCV_HWPROBE_EXT_ZKND
|
||||
#define RISCV_HWPROBE_EXT_ZKND (1 << 11)
|
||||
|
||||
@@ -60,7 +60,7 @@ D3D11VARenderer::D3D11VARenderer(int decoderSelectionPass)
|
||||
m_DecoderSelectionPass(decoderSelectionPass),
|
||||
m_DevicesWithFL11Support(0),
|
||||
m_DevicesWithCodecSupport(0),
|
||||
m_SwapChainColorTrc(AVCOL_TRC_UNSPECIFIED),
|
||||
m_LastColorTrc(AVCOL_TRC_UNSPECIFIED),
|
||||
m_AllowTearing(false),
|
||||
m_OverlayLock(0),
|
||||
m_HwDeviceContext(nullptr)
|
||||
@@ -800,7 +800,7 @@ void D3D11VARenderer::renderFrame(AVFrame* frame)
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (frame->color_trc != m_SwapChainColorTrc) {
|
||||
if (frame->color_trc != m_LastColorTrc) {
|
||||
if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
|
||||
// Switch to Rec 2020 PQ (SMPTE ST 2084) colorspace for HDR10 rendering
|
||||
hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
|
||||
@@ -820,7 +820,7 @@ void D3D11VARenderer::renderFrame(AVFrame* frame)
|
||||
}
|
||||
}
|
||||
|
||||
m_SwapChainColorTrc = frame->color_trc;
|
||||
m_LastColorTrc = frame->color_trc;
|
||||
}
|
||||
|
||||
// Present according to the decoder parameters
|
||||
|
||||
@@ -90,7 +90,7 @@ private:
|
||||
DXGI_FORMAT m_TextureFormat;
|
||||
int m_DisplayWidth;
|
||||
int m_DisplayHeight;
|
||||
AVColorTransferCharacteristic m_SwapChainColorTrc;
|
||||
AVColorTransferCharacteristic m_LastColorTrc;
|
||||
|
||||
bool m_AllowTearing;
|
||||
|
||||
|
||||
@@ -1307,7 +1307,7 @@ bool DrmRenderer::mapDumbBuffer(uint32_t handle, size_t size, void** mapping)
|
||||
#else
|
||||
*mapping = mmap(nullptr, size, PROT_WRITE, MAP_SHARED, m_DrmFd, mapBuf.offset);
|
||||
#endif
|
||||
if (*mapping == MAP_FAILED) {
|
||||
if (mapping == MAP_FAILED) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"mmap() failed for dumb buffer: %d",
|
||||
errno);
|
||||
|
||||
@@ -426,13 +426,7 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
|
||||
|
||||
D3DDISPLAYMODEEX currentMode;
|
||||
currentMode.Size = sizeof(currentMode);
|
||||
hr = d3d9ex->GetAdapterDisplayModeEx(adapterIndex, ¤tMode, nullptr);
|
||||
if (FAILED(hr)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GetAdapterDisplayModeEx() failed: %x",
|
||||
hr);
|
||||
return false;
|
||||
}
|
||||
d3d9ex->GetAdapterDisplayModeEx(adapterIndex, ¤tMode, nullptr);
|
||||
|
||||
D3DPRESENT_PARAMETERS d3dpp = {};
|
||||
d3dpp.hDeviceWindow = info.info.win.window;
|
||||
@@ -993,7 +987,6 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"StretchRect() failed: %x",
|
||||
hr);
|
||||
m_Device->EndScene();
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_DEVICE_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
@@ -240,7 +240,7 @@ ssize_t EglImageFactory::exportDRMImages(AVFrame* frame, EGLDisplay dpy, EGLImag
|
||||
else {
|
||||
// Cast the EGLAttrib array elements to EGLint for the KHR extension
|
||||
EGLint intAttribs[MAX_ATTRIB_COUNT];
|
||||
for (int i = 0; i < attribIndex; i++) {
|
||||
for (int i = 0; i < MAX_ATTRIB_COUNT; i++) {
|
||||
intAttribs[i] = (EGLint)attribs[i];
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
||||
attribs[attribIndex++] = layer.offset[0];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[0];
|
||||
if (m_EGLExtDmaBuf && object.drm_format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
@@ -343,7 +343,7 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
||||
attribs[attribIndex++] = layer.offset[1];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[1];
|
||||
if (m_EGLExtDmaBuf && object.drm_format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
@@ -358,7 +358,7 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
||||
attribs[attribIndex++] = layer.offset[2];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[2];
|
||||
if (m_EGLExtDmaBuf && object.drm_format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
@@ -373,7 +373,7 @@ ssize_t EglImageFactory::exportVAImages(AVFrame *frame, uint32_t exportFlags, EG
|
||||
attribs[attribIndex++] = layer.offset[3];
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
attribs[attribIndex++] = layer.pitch[3];
|
||||
if (m_EGLExtDmaBuf && object.drm_format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
if (m_EGLExtDmaBuf) {
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
attribs[attribIndex++] = (EGLint)(object.drm_format_modifier & 0xFFFFFFFF);
|
||||
attribs[attribIndex++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
|
||||
@@ -63,7 +63,6 @@ EGLRenderer::EGLRenderer(IFFmpegRenderer *backendRenderer)
|
||||
m_Window(nullptr),
|
||||
m_Backend(backendRenderer),
|
||||
m_VideoVAO(0),
|
||||
m_VideoVBO(0),
|
||||
m_BlockingSwapBuffers(false),
|
||||
m_LastRenderSync(EGL_NO_SYNC),
|
||||
m_glEGLImageTargetTexture2DOES(nullptr),
|
||||
@@ -101,7 +100,6 @@ EGLRenderer::~EGLRenderer()
|
||||
SDL_assert(m_glDeleteVertexArraysOES != nullptr);
|
||||
m_glDeleteVertexArraysOES(1, &m_VideoVAO);
|
||||
}
|
||||
glDeleteBuffers(1, &m_VideoVBO);
|
||||
glDeleteTextures(EGL_MAX_PLANES, m_Textures);
|
||||
|
||||
glDeleteTextures(Overlay::OverlayMax, m_OverlayTextures);
|
||||
@@ -268,9 +266,10 @@ void EGLRenderer::renderOverlay(Overlay::OverlayType type, int viewportWidth, in
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
GLuint EGLRenderer::loadAndBuildShader(int shaderType, const char *file) {
|
||||
int EGLRenderer::loadAndBuildShader(int shaderType,
|
||||
const char *file) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
if (!shader) {
|
||||
if (!shader || shader == GL_INVALID_ENUM) {
|
||||
EGL_LOG(Error, "Can't create shader: %d", glGetError());
|
||||
return 0;
|
||||
}
|
||||
@@ -287,7 +286,6 @@ GLuint EGLRenderer::loadAndBuildShader(int shaderType, const char *file) {
|
||||
char shaderLog[512];
|
||||
glGetShaderInfoLog(shader, sizeof (shaderLog), nullptr, shaderLog);
|
||||
EGL_LOG(Error, "Cannot load shader \"%s\": %s", file, shaderLog);
|
||||
glDeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -299,7 +297,7 @@ unsigned EGLRenderer::compileShader(const char* vertexShaderSrc, const char* fra
|
||||
|
||||
GLuint vertexShader = loadAndBuildShader(GL_VERTEX_SHADER, vertexShaderSrc);
|
||||
if (!vertexShader)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
GLuint fragmentShader = loadAndBuildShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);
|
||||
if (!fragmentShader)
|
||||
@@ -647,12 +645,13 @@ bool EGLRenderer::setupVideoRenderingState() {
|
||||
};
|
||||
|
||||
// Setup the VAO and VBO
|
||||
unsigned int VBO;
|
||||
m_glGenVertexArraysOES(1, &m_VideoVAO);
|
||||
glGenBuffers(1, &m_VideoVBO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
m_glBindVertexArrayOES(m_VideoVAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_VideoVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// compileShader() ensures that aPosition and aTexCoord are indexes 0 and 1 respectively
|
||||
@@ -664,8 +663,7 @@ bool EGLRenderer::setupVideoRenderingState() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
m_glBindVertexArrayOES(0);
|
||||
|
||||
// The VBO is kept alive as a member since the VAO still references it.
|
||||
// It is deleted in ~EGLRenderer() alongside the other GL resources.
|
||||
glDeleteBuffers(1, &VBO);
|
||||
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
@@ -789,7 +787,7 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
}
|
||||
|
||||
ssize_t plane_count = m_Backend->exportEGLImages(frame, m_EGLDisplay, imgs);
|
||||
if (plane_count <= 0)
|
||||
if (plane_count < 0)
|
||||
return;
|
||||
for (ssize_t i = 0; i < plane_count; ++i) {
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
|
||||
@@ -29,7 +29,7 @@ private:
|
||||
bool compileShaders();
|
||||
bool setupVideoRenderingState();
|
||||
bool setupOverlayRenderingState();
|
||||
static GLuint loadAndBuildShader(int shaderType, const char *filename);
|
||||
static int loadAndBuildShader(int shaderType, const char *filename);
|
||||
|
||||
AVPixelFormat m_EGLImagePixelFormat;
|
||||
void *m_EGLDisplay;
|
||||
@@ -44,7 +44,6 @@ private:
|
||||
SDL_Window *m_Window;
|
||||
IFFmpegRenderer *m_Backend;
|
||||
unsigned int m_VideoVAO;
|
||||
unsigned int m_VideoVBO;
|
||||
bool m_BlockingSwapBuffers;
|
||||
EGLSync m_LastRenderSync;
|
||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES;
|
||||
|
||||
@@ -10,8 +10,6 @@ DxVsyncSource::DxVsyncSource(Pacer* pacer) :
|
||||
m_LastMonitor(nullptr)
|
||||
{
|
||||
SDL_zero(m_WaitForVblankEventParams);
|
||||
m_WaitForVblankEventParams.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
|
||||
SDL_zero(m_AdapterLuid);
|
||||
}
|
||||
|
||||
DxVsyncSource::~DxVsyncSource()
|
||||
@@ -74,43 +72,41 @@ bool DxVsyncSource::isAsync()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DxVsyncSource::waitForVsync()
|
||||
void DxVsyncSource::waitForVsync()
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
// If the monitor has changed from last time, open the new adapter
|
||||
HMONITOR currentMonitor = MonitorFromWindow(m_Window, MONITOR_DEFAULTTONEAREST);
|
||||
if (!currentMonitor || currentMonitor != m_LastMonitor) {
|
||||
// Close the old adapter
|
||||
if (m_WaitForVblankEventParams.hAdapter != 0) {
|
||||
D3DKMT_CLOSEADAPTER closeAdapterParams = {};
|
||||
closeAdapterParams.hAdapter = m_WaitForVblankEventParams.hAdapter;
|
||||
m_D3DKMTCloseAdapter(&closeAdapterParams);
|
||||
m_WaitForVblankEventParams.hAdapter = 0;
|
||||
}
|
||||
m_LastMonitor = nullptr;
|
||||
|
||||
// We can't wait if we're not on any monitor
|
||||
if (!currentMonitor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentMonitor != m_LastMonitor) {
|
||||
MONITORINFOEXA monitorInfo = {};
|
||||
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||
if (!GetMonitorInfoA(currentMonitor, &monitorInfo)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GetMonitorInfo() failed: %d",
|
||||
GetLastError());
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
DEVMODEA monitorMode = {};
|
||||
DEVMODEA monitorMode;
|
||||
monitorMode.dmSize = sizeof(monitorMode);
|
||||
if (!EnumDisplaySettingsA(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &monitorMode)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"EnumDisplaySettings() failed: %d",
|
||||
GetLastError());
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Monitor changed: %s %d Hz",
|
||||
monitorInfo.szDevice,
|
||||
monitorMode.dmDisplayFrequency);
|
||||
|
||||
// Close the old adapter
|
||||
if (m_WaitForVblankEventParams.hAdapter != 0) {
|
||||
D3DKMT_CLOSEADAPTER closeAdapterParams = {};
|
||||
closeAdapterParams.hAdapter = m_WaitForVblankEventParams.hAdapter;
|
||||
m_D3DKMTCloseAdapter(&closeAdapterParams);
|
||||
}
|
||||
|
||||
D3DKMT_OPENADAPTERFROMHDC openAdapterParams = {};
|
||||
@@ -119,7 +115,7 @@ bool DxVsyncSource::waitForVsync()
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"CreateDC() failed: %d",
|
||||
GetLastError());
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the new adapter
|
||||
@@ -130,38 +126,21 @@ bool DxVsyncSource::waitForVsync()
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"D3DKMTOpenAdapterFromHdc() failed: %x",
|
||||
status);
|
||||
return false;
|
||||
}
|
||||
|
||||
// VidPnSourceId is scoped to the adapter, so we must also check the adapter LUID
|
||||
if (m_AdapterLuid.LowPart != openAdapterParams.AdapterLuid.LowPart ||
|
||||
m_AdapterLuid.HighPart != openAdapterParams.AdapterLuid.HighPart ||
|
||||
m_WaitForVblankEventParams.VidPnSourceId != openAdapterParams.VidPnSourceId) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Monitor changed: %s %d Hz",
|
||||
monitorInfo.szDevice,
|
||||
monitorMode.dmDisplayFrequency);
|
||||
return;
|
||||
}
|
||||
|
||||
m_WaitForVblankEventParams.hAdapter = openAdapterParams.hAdapter;
|
||||
m_WaitForVblankEventParams.hDevice = 0;
|
||||
m_WaitForVblankEventParams.VidPnSourceId = openAdapterParams.VidPnSourceId;
|
||||
|
||||
m_AdapterLuid = openAdapterParams.AdapterLuid;
|
||||
m_LastMonitor = currentMonitor;
|
||||
}
|
||||
|
||||
status = m_D3DKMTWaitForVerticalBlankEvent(&m_WaitForVblankEventParams);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
if (status != STATUS_GRAPHICS_PRESENT_OCCLUDED) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"D3DKMTWaitForVerticalBlankEvent() failed: %x",
|
||||
status);
|
||||
}
|
||||
|
||||
m_LastMonitor = nullptr;
|
||||
return false;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"D3DKMTWaitForVerticalBlankEvent() failed: %x",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -10,7 +10,6 @@ typedef UINT D3DKMT_HANDLE;
|
||||
typedef UINT D3DDDI_VIDEO_PRESENT_SOURCE_ID;
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
||||
#define STATUS_GRAPHICS_PRESENT_OCCLUDED ((NTSTATUS)0xC01E0006L)
|
||||
#define D3DDDI_ID_UNINITIALIZED (UINT)(~0)
|
||||
typedef struct _D3DKMT_OPENADAPTERFROMHDC {
|
||||
HDC hDc;
|
||||
D3DKMT_HANDLE hAdapter;
|
||||
@@ -40,14 +39,13 @@ public:
|
||||
|
||||
virtual bool isAsync() override;
|
||||
|
||||
virtual bool waitForVsync() override;
|
||||
virtual void waitForVsync() override;
|
||||
|
||||
private:
|
||||
Pacer* m_Pacer;
|
||||
HMODULE m_Gdi32Handle;
|
||||
HWND m_Window;
|
||||
HMONITOR m_LastMonitor;
|
||||
LUID m_AdapterLuid;
|
||||
D3DKMT_WAITFORVERTICALBLANKEVENT m_WaitForVblankEventParams;
|
||||
|
||||
PFND3DKMTOPENADAPTERFROMHDC m_D3DKMTOpenAdapterFromHdc;
|
||||
|
||||
@@ -115,20 +115,13 @@ int Pacer::vsyncThread(void *context)
|
||||
while (!me->m_Stopping) {
|
||||
if (async) {
|
||||
// Wait for the VSync source to invoke signalVsync() or 100ms to elapse
|
||||
QMutexLocker locker(&me->m_FrameQueueLock);
|
||||
me->m_FrameQueueLock.lock();
|
||||
me->m_VsyncSignalled.wait(&me->m_FrameQueueLock, 100);
|
||||
me->m_FrameQueueLock.unlock();
|
||||
}
|
||||
else {
|
||||
// Let the VSync source wait in the context of our thread
|
||||
if (!me->m_VsyncSource->waitForVsync()) {
|
||||
// Fall back to a fixed delay if the VSync source fails
|
||||
//
|
||||
// NB: We don't actually expect signalVsync() to be called, since
|
||||
// this is a synchronous VSync source, but we wait on m_VsyncSignalled
|
||||
// anyway so that the destructor can immediately wake us on shutdown.
|
||||
QMutexLocker locker(&me->m_FrameQueueLock);
|
||||
me->m_VsyncSignalled.wait(&me->m_FrameQueueLock, 1000 / me->m_DisplayFps);
|
||||
}
|
||||
me->m_VsyncSource->waitForVsync();
|
||||
}
|
||||
|
||||
if (me->m_Stopping) {
|
||||
@@ -155,25 +148,24 @@ int Pacer::renderThread(void* context)
|
||||
// Wait for the renderer to be ready for the next frame
|
||||
me->m_VsyncRenderer->waitToRender();
|
||||
|
||||
AVFrame* frame;
|
||||
{
|
||||
// Acquire the frame queue lock to protect the queue and
|
||||
// the not empty condition
|
||||
QMutexLocker locker(&me->m_FrameQueueLock);
|
||||
// Acquire the frame queue lock to protect the queue and
|
||||
// the not empty condition
|
||||
me->m_FrameQueueLock.lock();
|
||||
|
||||
// Wait for a frame to be ready to render
|
||||
while (!me->m_Stopping && me->m_RenderQueue.isEmpty()) {
|
||||
me->m_RenderQueueNotEmpty.wait(&me->m_FrameQueueLock);
|
||||
}
|
||||
|
||||
if (me->m_Stopping) {
|
||||
// Exit this thread
|
||||
break;
|
||||
}
|
||||
|
||||
frame = me->m_RenderQueue.dequeue();
|
||||
// Wait for a frame to be ready to render
|
||||
while (!me->m_Stopping && me->m_RenderQueue.isEmpty()) {
|
||||
me->m_RenderQueueNotEmpty.wait(&me->m_FrameQueueLock);
|
||||
}
|
||||
|
||||
if (me->m_Stopping) {
|
||||
// Exit this thread
|
||||
me->m_FrameQueueLock.unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
AVFrame* frame = me->m_RenderQueue.dequeue();
|
||||
me->m_FrameQueueLock.unlock();
|
||||
|
||||
me->renderFrame(frame);
|
||||
}
|
||||
|
||||
@@ -257,7 +249,7 @@ void Pacer::handleVsync(int timeUntilNextVsyncMillis)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Stopping || m_PacingQueue.isEmpty()) {
|
||||
if (m_Stopping) {
|
||||
m_FrameQueueLock.unlock();
|
||||
return;
|
||||
}
|
||||
@@ -357,7 +349,7 @@ void Pacer::renderFrame(AVFrame* frame)
|
||||
av_frame_free(&frame);
|
||||
|
||||
// Drop frames if we have too many queued up for a while
|
||||
QMutexLocker frameQueueLocker(&m_FrameQueueLock);
|
||||
m_FrameQueueLock.lock();
|
||||
|
||||
int frameDropTarget;
|
||||
|
||||
@@ -390,11 +382,13 @@ void Pacer::renderFrame(AVFrame* frame)
|
||||
AVFrame* frame = m_RenderQueue.dequeue();
|
||||
|
||||
// Drop the lock while we call av_frame_free()
|
||||
frameQueueLocker.unlock();
|
||||
m_FrameQueueLock.unlock();
|
||||
m_VideoStats->pacerDroppedFrames++;
|
||||
av_frame_free(&frame);
|
||||
frameQueueLocker.relock();
|
||||
m_FrameQueueLock.lock();
|
||||
}
|
||||
|
||||
m_FrameQueueLock.unlock();
|
||||
}
|
||||
|
||||
void Pacer::dropFrameForEnqueue(QQueue<AVFrame*>& queue)
|
||||
|
||||
@@ -22,10 +22,9 @@ public:
|
||||
// sources require calls to waitForVsync().
|
||||
virtual bool isAsync() = 0;
|
||||
|
||||
virtual bool waitForVsync() {
|
||||
virtual void waitForVsync() {
|
||||
// Synchronous sources must implement waitForVsync()!
|
||||
SDL_assert(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -769,7 +769,6 @@ bool PlVkRenderer::populateQueues(int videoFormat)
|
||||
vkDeviceContext->nb_comp_queues = m_Vulkan->queue_compute.count;
|
||||
|
||||
// Select a video decode queue that is capable of decoding our chosen format
|
||||
vkDeviceContext->queue_family_decode_index = -1;
|
||||
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
||||
if (queueFamilies[i].queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
|
||||
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||
@@ -898,16 +897,6 @@ void PlVkRenderer::waitToRender()
|
||||
return;
|
||||
}
|
||||
|
||||
// If a swapchain (re)creation failed, m_Swapchain is NULL. We can't render
|
||||
// or resize it, and a device reset has already been requested, so skip this
|
||||
// frame and let the main thread recreate the renderer.
|
||||
if (m_Swapchain == nullptr) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_DEVICE_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
// With libplacebo's Vulkan backend, all swap_buffers does is wait for queued
|
||||
// presents to finish. This happens to be exactly what we want to do here, since
|
||||
|
||||
@@ -533,7 +533,7 @@ public:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
InitFailureReason m_InitFailureReason = InitFailureReason::Unknown;
|
||||
InitFailureReason m_InitFailureReason;
|
||||
|
||||
private:
|
||||
RendererType m_Type;
|
||||
|
||||
@@ -21,10 +21,8 @@
|
||||
VAAPIRenderer::VAAPIRenderer(int decoderSelectionPass)
|
||||
: IFFmpegRenderer(RendererType::VAAPI),
|
||||
m_DecoderSelectionPass(decoderSelectionPass),
|
||||
m_WindowSystem(SDL_SYSWM_UNKNOWN),
|
||||
m_HwContext(nullptr),
|
||||
m_BlacklistedForDirectRendering(false),
|
||||
m_HasRfiLatencyBug(false),
|
||||
m_RequiresExplicitPixelFormat(false),
|
||||
m_OverlayMutex(nullptr)
|
||||
#ifdef HAVE_EGL
|
||||
@@ -161,9 +159,6 @@ VAAPIRenderer::openDisplay(SDL_Window* window)
|
||||
errno);
|
||||
return nullptr;
|
||||
}
|
||||
// This FD is owned by us (not shared with SDL), so it must be
|
||||
// closed when we're done with it or adopted into m_DrmFd.
|
||||
mustCloseFd = true;
|
||||
}
|
||||
|
||||
// If the KMSDRM FD is not a render node FD, open the render node for libva to use.
|
||||
|
||||
@@ -541,12 +541,11 @@ void VDPAURenderer::renderFrame(AVFrame* frame)
|
||||
// We need to create the mixer on the fly, because we don't know the dimensions
|
||||
// of our video surfaces in advance of decoding. We also need to recreate it when
|
||||
// the frame format or size changes.
|
||||
if (hasFrameFormatChanged(frame) && m_VideoMixer != 0) {
|
||||
m_VdpVideoMixerDestroy(m_VideoMixer);
|
||||
m_VideoMixer = 0;
|
||||
}
|
||||
if (hasFrameFormatChanged(frame)) {
|
||||
if (m_VideoMixer != 0) {
|
||||
m_VdpVideoMixerDestroy(m_VideoMixer);
|
||||
}
|
||||
|
||||
if (m_VideoMixer == 0) {
|
||||
VdpChromaType videoSurfaceChroma;
|
||||
uint32_t videoSurfaceWidth, videoSurfaceHeight;
|
||||
status = m_VdpVideoSurfaceGetParameters(videoSurface, &videoSurfaceChroma,
|
||||
@@ -581,7 +580,6 @@ void VDPAURenderer::renderFrame(AVFrame* frame)
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpVideoMixerCreate() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
m_VideoMixer = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,21 +1765,11 @@ void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)
|
||||
int nalStart, nalEnd;
|
||||
bool needsFixup;
|
||||
|
||||
// Find the old SPS NALU
|
||||
if (find_nal_unit((uint8_t*)entry->data, entry->length, &nalStart, &nalEnd) <= 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to find SPS");
|
||||
h264_free(stream);
|
||||
goto WriteUnmodifiedBuffer;
|
||||
}
|
||||
|
||||
// Read the SPS. Pass it through unmodified if we fail to parse it.
|
||||
if (read_nal_unit(stream, (uint8_t*)&entry->data[nalStart], nalEnd - nalStart) < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to read SPS");
|
||||
h264_free(stream);
|
||||
goto WriteUnmodifiedBuffer;
|
||||
}
|
||||
// Read the old NALU
|
||||
find_nal_unit((uint8_t*)entry->data, entry->length, &nalStart, &nalEnd);
|
||||
read_nal_unit(stream,
|
||||
(unsigned char *)&entry->data[nalStart],
|
||||
nalEnd - nalStart);
|
||||
|
||||
SDL_assert(nalStart == 3 || nalStart == 4); // 3 or 4 byte Annex B start sequence
|
||||
SDL_assert(nalEnd == entry->length);
|
||||
@@ -1812,18 +1802,8 @@ void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)
|
||||
|
||||
// Copy the modified NALU data. This clobbers byte 0 and starts NALU data at byte 1.
|
||||
// Since it prepended one extra byte, subtract one from the returned length.
|
||||
//
|
||||
// Pass the SPS through unmodified if the write fails.
|
||||
int writeLength = write_nal_unit(stream, (uint8_t*)&m_DecodeBuffer.data()[initialOffset + nalStart - 1],
|
||||
MAX_SPS_EXTRA_SIZE + entry->length - nalStart);
|
||||
if (writeLength < 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to write modified SPS");
|
||||
h264_free(stream);
|
||||
goto WriteUnmodifiedBuffer;
|
||||
}
|
||||
|
||||
offset += writeLength - 1;
|
||||
offset += write_nal_unit(stream, (uint8_t*)&m_DecodeBuffer.data()[initialOffset + nalStart - 1],
|
||||
MAX_SPS_EXTRA_SIZE + entry->length - nalStart) - 1;
|
||||
|
||||
// Copy the NALU prefix over from the original SPS
|
||||
memcpy(&m_DecodeBuffer.data()[initialOffset], entry->data, nalStart);
|
||||
@@ -1854,7 +1834,6 @@ void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)
|
||||
h264_free(stream);
|
||||
}
|
||||
else {
|
||||
WriteUnmodifiedBuffer:
|
||||
// Write the buffer as-is
|
||||
memcpy(&m_DecodeBuffer.data()[offset],
|
||||
entry->data,
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace WMUtils {
|
||||
bool isRunningWayland();
|
||||
bool isRunningWindowManager();
|
||||
bool isRunningDesktopEnvironment();
|
||||
bool hasDisplayUsableBounds();
|
||||
QString getDrmCardOverride();
|
||||
bool isGpuSlow();
|
||||
}
|
||||
|
||||
-46
@@ -205,52 +205,6 @@ bool WMUtils::isRunningDesktopEnvironment()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WMUtils::hasDisplayUsableBounds()
|
||||
{
|
||||
static SDL_atomic_t hasDisplayUsableBounds;
|
||||
|
||||
// If the value is not set yet, populate it now.
|
||||
int val = SDL_AtomicGet(&hasDisplayUsableBounds);
|
||||
if (!(val & VALUE_SET)) {
|
||||
int numDisplays = SDL_GetNumVideoDisplays();
|
||||
bool hasUsableBounds = false;
|
||||
|
||||
for (int i = 0; i < numDisplays; i++) {
|
||||
SDL_Rect displayBounds;
|
||||
SDL_Rect usableBounds;
|
||||
|
||||
if (SDL_GetDisplayBounds(i, &displayBounds) != 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayBounds(%d) failed: %s",
|
||||
i, SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SDL_GetDisplayUsableBounds(i, &usableBounds) != 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayUsableBounds(%d) failed: %s",
|
||||
i, SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
// If at least one display has usable bounds that differ from the
|
||||
// complete bounds, we assume that usable bounds are accurate.
|
||||
if (!SDL_RectEquals(&displayBounds, &usableBounds)) {
|
||||
hasUsableBounds = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the value to return and have for next time.
|
||||
// This can race with another thread populating the same data,
|
||||
// but that's no big deal.
|
||||
val = VALUE_SET | (hasUsableBounds ? VALUE_TRUE : 0);
|
||||
SDL_AtomicSet(&hasDisplayUsableBounds, val);
|
||||
}
|
||||
|
||||
return !!(val & VALUE_TRUE);
|
||||
}
|
||||
|
||||
bool WMUtils::isGpuSlow()
|
||||
{
|
||||
bool ret;
|
||||
|
||||
+7
-31
@@ -1,25 +1,3 @@
|
||||
/*
|
||||
* h264bitstream - a library for reading and writing H.264 video
|
||||
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||
* Copyright (C) 2008-2011 Avail-TVN
|
||||
*
|
||||
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _H264_BS_H
|
||||
#define _H264_BS_H 1
|
||||
|
||||
@@ -101,7 +79,7 @@ static inline int bs_eof(bs_t* b) { if (b->p >= b->end) { return 1; } else { ret
|
||||
|
||||
static inline int bs_overrun(bs_t* b) { if (b->p > b->end) { return 1; } else { return 0; } }
|
||||
|
||||
static inline int bs_pos(bs_t* b) { if (b->p > b->end) { return (int)(b->end - b->start); } else { return (int)(b->p - b->start); } }
|
||||
static inline int bs_pos(bs_t* b) { if (b->p > b->end) { return (b->end - b->start); } else { return (b->p - b->start); } }
|
||||
|
||||
static inline uint32_t bs_read_u1(bs_t* b)
|
||||
{
|
||||
@@ -178,18 +156,16 @@ static inline uint32_t bs_read_ue(bs_t* b)
|
||||
|
||||
static inline int32_t bs_read_se(bs_t* b)
|
||||
{
|
||||
// Do the math in unsigned space. bs_read_ue() can return values above
|
||||
// INT32_MAX, and (r+1)/2 on a signed INT32_MAX is undefined behavior.
|
||||
// bs_read_ue() returns at most 0xFFFFFFFE, so both results fit in int32_t.
|
||||
uint32_t r = bs_read_ue(b);
|
||||
int32_t r = bs_read_ue(b);
|
||||
if (r & 0x01)
|
||||
{
|
||||
return (int32_t)((r >> 1) + 1);
|
||||
r = (r+1)/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -(int32_t)(r >> 1);
|
||||
r = -(r/2);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void bs_write_u1(bs_t* b, uint32_t v)
|
||||
@@ -210,7 +186,7 @@ static inline void bs_write_u(bs_t* b, int n, uint32_t v)
|
||||
int i;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
bs_write_u1(b, (n - i - 1 >= 32) ? 0 : ((v >> ( n - i - 1 ))&0x01) );
|
||||
bs_write_u1(b, (v >> ( n - i - 1 ))&0x01 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +195,7 @@ static inline void bs_write_u8(bs_t* b, uint32_t v)
|
||||
#ifdef FAST_U8
|
||||
if (b->bits_left == 8 && ! bs_eof(b)) // can do fast write
|
||||
{
|
||||
b->p[0] = (uint8_t)v;
|
||||
b->p[0] = v;
|
||||
b->p++;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,3 @@
|
||||
/*
|
||||
* h264bitstream - a library for reading and writing H.264 video
|
||||
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||
* Copyright (C) 2008-2011 Avail-TVN
|
||||
*
|
||||
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
/*
|
||||
* h264bitstream - a library for reading and writing H.264 video
|
||||
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||
* Copyright (C) 2008-2011 Avail-TVN
|
||||
* Copyright (C) 2012 Alex Izvorski
|
||||
*
|
||||
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -384,11 +361,6 @@ void write_seq_parameter_set_rbsp(sps_t* sps, bs_t* b)
|
||||
}
|
||||
else if( sps->pic_order_cnt_type == 1 )
|
||||
{
|
||||
if (sps->num_ref_frames_in_pic_order_cnt_cycle > 256)
|
||||
{
|
||||
sps->num_ref_frames_in_pic_order_cnt_cycle = 256;
|
||||
}
|
||||
|
||||
bs_write_u1(b, sps->delta_pic_order_always_zero_flag);
|
||||
bs_write_se(b, sps->offset_for_non_ref_pic);
|
||||
bs_write_se(b, sps->offset_for_top_to_bottom_field);
|
||||
@@ -534,11 +506,6 @@ void write_vui_parameters(sps_t* sps, bs_t* b)
|
||||
|
||||
void write_hrd_parameters(hrd_t* hrd, bs_t* b)
|
||||
{
|
||||
if (hrd->cpb_cnt_minus1 > 31)
|
||||
{
|
||||
hrd->cpb_cnt_minus1 = 31;
|
||||
}
|
||||
|
||||
bs_write_ue(b, hrd->cpb_cnt_minus1);
|
||||
bs_write_u(b, 4, hrd->bit_rate_scale);
|
||||
bs_write_u(b, 4, hrd->cpb_size_scale);
|
||||
|
||||
@@ -1,25 +1,3 @@
|
||||
/*
|
||||
* h264bitstream - a library for reading and writing H.264 video
|
||||
* Copyright (C) 2005-2007 Auroras Entertainment, LLC
|
||||
* Copyright (C) 2008-2011 Avail-TVN
|
||||
*
|
||||
* Written by Alex Izvorski <aizvorski@gmail.com> and Alex Giladi <alex.giladi@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _H264_STREAM_H
|
||||
#define _H264_STREAM_H 1
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ TEMPLATE = lib
|
||||
# Build a static library
|
||||
CONFIG += staticlib
|
||||
|
||||
# Disable warnings
|
||||
CONFIG += warn_off
|
||||
|
||||
# Include global qmake defs
|
||||
include(../globaldefs.pri)
|
||||
|
||||
|
||||
Submodule moonlight-common-c/moonlight-common-c updated: 04053843c9...f900dd4767.
@@ -250,7 +250,7 @@ if not x%QT_PATH:\5.=%==x%QT_PATH% (
|
||||
set WINDEPLOYQT_ARGS=--no-qmltooling --no-virtualkeyboard
|
||||
) else (
|
||||
rem Qt 6.8+
|
||||
set WINDEPLOYQT_ARGS=--no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types qmltooling,generic --no-ffmpeg --force-openssl
|
||||
set WINDEPLOYQT_ARGS=--no-system-d3d-compiler --no-system-dxc-compiler --skip-plugin-types qmltooling,generic --no-ffmpeg
|
||||
set WINDEPLOYQT_ARGS=!WINDEPLOYQT_ARGS! --no-quickcontrols2fusion --no-quickcontrols2imagine --no-quickcontrols2universal
|
||||
set WINDEPLOYQT_ARGS=!WINDEPLOYQT_ARGS! --no-quickcontrols2fusionstyleimpl --no-quickcontrols2imaginestyleimpl --no-quickcontrols2universalstyleimpl --no-quickcontrols2windowsstyleimpl --no-quickcontrols2fluentwinui3styleimpl
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user