mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-08-27 12:41:18 +00:00
Fix GEM handle leak in DRM renderer
Huge thanks to @oliverlj for identifying this longstanding bug. This is likely responsible for many different issues with the DRM renderer randomly failing.
This commit is contained in:
@@ -74,6 +74,7 @@ extern "C" {
|
|||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#ifdef HAVE_DRM_MASTER_HOOKS
|
#ifdef HAVE_DRM_MASTER_HOOKS
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -1750,6 +1751,7 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode
|
|||||||
uint32_t offsets[4] = {};
|
uint32_t offsets[4] = {};
|
||||||
uint64_t modifiers[4] = {};
|
uint64_t modifiers[4] = {};
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
std::unordered_set<uint32_t> handleSet;
|
||||||
|
|
||||||
// DRM requires composed layers rather than separate layers per plane
|
// DRM requires composed layers rather than separate layers per plane
|
||||||
SDL_assert(drmFrame->nb_layers == 1);
|
SDL_assert(drmFrame->nb_layers == 1);
|
||||||
@@ -1763,9 +1765,16 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"drmPrimeFDToHandle() failed: %d",
|
"drmPrimeFDToHandle() failed: %d",
|
||||||
errno);
|
errno);
|
||||||
|
for (uint32_t handle : handleSet) {
|
||||||
|
drmCloseBufferHandle(m_DrmFd, handle);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handles aren't unique for calls with the same FD, so we need to
|
||||||
|
// keep track of only the unique handles to avoid double-closing.
|
||||||
|
handleSet.emplace(handles[i]);
|
||||||
|
|
||||||
pitches[i] = layer.planes[i].pitch;
|
pitches[i] = layer.planes[i].pitch;
|
||||||
offsets[i] = layer.planes[i].offset;
|
offsets[i] = layer.planes[i].offset;
|
||||||
modifiers[i] = object.format_modifier;
|
modifiers[i] = object.format_modifier;
|
||||||
@@ -1784,6 +1793,12 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode
|
|||||||
handles, pitches, offsets,
|
handles, pitches, offsets,
|
||||||
(flags & DRM_MODE_FB_MODIFIERS) ? modifiers : NULL,
|
(flags & DRM_MODE_FB_MODIFIERS) ? modifiers : NULL,
|
||||||
newFbId, flags);
|
newFbId, flags);
|
||||||
|
|
||||||
|
// Handles can be closed immediately after drmModeAddFB2WithModifiers()
|
||||||
|
for (uint32_t handle : handleSet) {
|
||||||
|
drmCloseBufferHandle(m_DrmFd, handle);
|
||||||
|
}
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"drmModeAddFB2[WithModifiers]() failed: %d",
|
"drmModeAddFB2[WithModifiers]() failed: %d",
|
||||||
|
|||||||
Reference in New Issue
Block a user