mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-07 13:18:04 +02:00
Merge 2991eb7934 into a531c2ed6b
This commit is contained in:
commit
4f07bceece
14 changed files with 230 additions and 164 deletions
|
|
@ -148,6 +148,8 @@
|
|||
---| "ecosystem.enforce_permissions"
|
||||
---| "ecosystem.no_donation_nag"
|
||||
---| "ecosystem.no_update_news"
|
||||
---| "experimental.deadline_client_buffer"
|
||||
---| "experimental.deadline_main_buffer"
|
||||
---| "experimental.wp_cm_1_2"
|
||||
---| "general.allow_tearing"
|
||||
---| "general.border_size"
|
||||
|
|
@ -984,6 +986,8 @@ hl = {}
|
|||
---@field ['ecosystem.enforce_permissions'] boolean
|
||||
---@field ['ecosystem.no_donation_nag'] boolean
|
||||
---@field ['ecosystem.no_update_news'] boolean
|
||||
---@field ['experimental.deadline_client_buffer'] boolean
|
||||
---@field ['experimental.deadline_main_buffer'] boolean
|
||||
---@field ['experimental.wp_cm_1_2'] boolean
|
||||
---@field ['general.allow_tearing'] boolean
|
||||
---@field ['general.border_size'] integer|boolean
|
||||
|
|
|
|||
|
|
@ -674,6 +674,8 @@ std::vector<SP<IValue>> Values::getConfigValues() {
|
|||
*/
|
||||
|
||||
MS<Bool>("experimental:wp_cm_1_2", "Allow wp-cm-v1 version 2", false),
|
||||
MS<Bool>("experimental:deadline_client_buffer", "set deadline on client buffers", false),
|
||||
MS<Bool>("experimental:deadline_main_buffer", "set deadline on main buffers", false),
|
||||
|
||||
/*
|
||||
* quirks:
|
||||
|
|
|
|||
|
|
@ -4,8 +4,19 @@
|
|||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/sync_file.h>
|
||||
#endif
|
||||
|
||||
#include <libsync.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "Drm.hpp"
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
namespace {
|
||||
using SDRMNodePair = std::array<dev_t, 2>;
|
||||
|
||||
|
|
@ -67,3 +78,61 @@ bool DRM::sameGpu(int fd1, int fd2) {
|
|||
|
||||
return same;
|
||||
}
|
||||
|
||||
int DRM::doIoctl(int fd, unsigned long request, void* arg) {
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = ioctl(fd, request, arg);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_buf_export_sync_file
|
||||
// returns a sync file that will be signalled when dmabuf is ready to be read
|
||||
CFileDescriptor DRM::exportFence(int fd) {
|
||||
#ifndef __linux__
|
||||
return {};
|
||||
#endif
|
||||
|
||||
#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
|
||||
if (fd < 0)
|
||||
return {};
|
||||
|
||||
dma_buf_export_sync_file request{
|
||||
.flags = DMA_BUF_SYNC_READ,
|
||||
.fd = -1,
|
||||
};
|
||||
|
||||
if (doIoctl(fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &request) == 0)
|
||||
return CFileDescriptor{request.fd};
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
CFileDescriptor DRM::mergeFence(int fence1, int fence2) {
|
||||
#ifdef __linux__
|
||||
sync_accumulate("merged release fence", &fence1, fence2);
|
||||
|
||||
if (fence2 >= 0)
|
||||
close(fence2);
|
||||
|
||||
return CFileDescriptor{fence1};
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
void DRM::setDeadline(const Time::steady_tp& deadline, const Hyprutils::OS::CFileDescriptor& fence) {
|
||||
#ifdef SYNC_IOC_SET_DEADLINE
|
||||
if (!fence.isValid())
|
||||
return;
|
||||
|
||||
sync_set_deadline args{
|
||||
.deadline_ns = uint64_t(duration_cast<std::chrono::nanoseconds>(deadline.time_since_epoch()).count()),
|
||||
.pad = 0,
|
||||
};
|
||||
|
||||
doIoctl(fence.get(), SYNC_IOC_SET_DEADLINE, &args);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2,8 +2,14 @@
|
|||
|
||||
#include <optional>
|
||||
#include <sys/types.h>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include "time/Time.hpp"
|
||||
|
||||
namespace DRM {
|
||||
std::optional<dev_t> devIDFromFD(int fd);
|
||||
bool sameGpu(int fd1, int fd2);
|
||||
std::optional<dev_t> devIDFromFD(int fd);
|
||||
bool sameGpu(int fd1, int fd2);
|
||||
int doIoctl(int fd, unsigned long request, void* arg);
|
||||
Hyprutils::OS::CFileDescriptor exportFence(int fd);
|
||||
Hyprutils::OS::CFileDescriptor mergeFence(int fence1, int fence2);
|
||||
void setDeadline(const Time::steady_tp& deadline, const Hyprutils::OS::CFileDescriptor& fence);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,6 +155,12 @@ void CMonitor::onConnect(bool noRule) {
|
|||
});
|
||||
}
|
||||
|
||||
if (m_pendingFrame) { // if no pending frame, VFR etc we cant estimate this.
|
||||
auto minVBlankInterval = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(1.0 / m_refreshRate));
|
||||
m_estimatedNextVblank = (ts ? Time::fromTimespec(ts) + minVBlankInterval : Time::steadyNow()) + minVBlankInterval;
|
||||
} else
|
||||
m_estimatedNextVblank = std::nullopt;
|
||||
|
||||
m_frameScheduler->onPresented();
|
||||
|
||||
m_events.presented.emit();
|
||||
|
|
|
|||
|
|
@ -106,71 +106,72 @@ class CMonitor {
|
|||
CMonitor(SP<Aquamarine::IOutput> output);
|
||||
~CMonitor();
|
||||
|
||||
Vector2D m_position = Vector2D(-1, -1); // means unset
|
||||
Vector2D m_xwaylandPosition = Vector2D(-1, -1); // means unset
|
||||
Config::eAutoDirs m_autoDir = Config::DIR_AUTO_NONE;
|
||||
Vector2D m_size = Vector2D(0, 0);
|
||||
Vector2D m_pixelSize = Vector2D(0, 0);
|
||||
Vector2D m_transformedSize = Vector2D(0, 0);
|
||||
Vector2D m_position = Vector2D(-1, -1); // means unset
|
||||
Vector2D m_xwaylandPosition = Vector2D(-1, -1); // means unset
|
||||
Config::eAutoDirs m_autoDir = Config::DIR_AUTO_NONE;
|
||||
Vector2D m_size = Vector2D(0, 0);
|
||||
Vector2D m_pixelSize = Vector2D(0, 0);
|
||||
Vector2D m_transformedSize = Vector2D(0, 0);
|
||||
|
||||
MONITORID m_id = MONITOR_INVALID;
|
||||
PHLWORKSPACE m_activeWorkspace = nullptr;
|
||||
PHLWORKSPACE m_activeSpecialWorkspace = nullptr;
|
||||
float m_setScale = 1; // scale set by cfg
|
||||
float m_scale = 1; // real scale
|
||||
MONITORID m_id = MONITOR_INVALID;
|
||||
PHLWORKSPACE m_activeWorkspace = nullptr;
|
||||
PHLWORKSPACE m_activeSpecialWorkspace = nullptr;
|
||||
float m_setScale = 1; // scale set by cfg
|
||||
float m_scale = 1; // real scale
|
||||
|
||||
std::string m_name = "";
|
||||
std::string m_description = "";
|
||||
std::string m_shortDescription = "";
|
||||
std::string m_name = "";
|
||||
std::string m_description = "";
|
||||
std::string m_shortDescription = "";
|
||||
|
||||
drmModeModeInfo m_customDrmMode = {};
|
||||
drmModeModeInfo m_customDrmMode = {};
|
||||
|
||||
Desktop::CReservedArea m_reservedArea;
|
||||
Desktop::CReservedArea m_reservedArea;
|
||||
|
||||
CMonitorState m_state;
|
||||
CDamageRing m_damage;
|
||||
CMonitorState m_state;
|
||||
CDamageRing m_damage;
|
||||
|
||||
SP<Aquamarine::IOutput> m_output;
|
||||
float m_refreshRate = 60; // Hz
|
||||
int m_forceFullFrames = 0;
|
||||
bool m_scheduledRecalc = false;
|
||||
wl_output_transform m_transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float m_xwaylandScale = 1.f;
|
||||
SP<Aquamarine::IOutput> m_output;
|
||||
float m_refreshRate = 60; // Hz
|
||||
int m_forceFullFrames = 0;
|
||||
bool m_scheduledRecalc = false;
|
||||
wl_output_transform m_transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
float m_xwaylandScale = 1.f;
|
||||
|
||||
std::optional<Vector2D> m_forceSize;
|
||||
SP<Aquamarine::SOutputMode> m_currentMode;
|
||||
SP<Aquamarine::CSwapchain> m_cursorSwapchain;
|
||||
uint32_t m_drmFormat = DRM_FORMAT_INVALID;
|
||||
uint32_t m_prevDrmFormat = DRM_FORMAT_INVALID;
|
||||
std::optional<Vector2D> m_forceSize;
|
||||
SP<Aquamarine::SOutputMode> m_currentMode;
|
||||
SP<Aquamarine::CSwapchain> m_cursorSwapchain;
|
||||
uint32_t m_drmFormat = DRM_FORMAT_INVALID;
|
||||
uint32_t m_prevDrmFormat = DRM_FORMAT_INVALID;
|
||||
|
||||
CMonitorZoomController m_zoomController;
|
||||
CMonitorZoomController m_zoomController;
|
||||
|
||||
bool m_dpmsStatus = true;
|
||||
bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
NCMType::eCMType m_cmType = NCMType::CM_SRGB;
|
||||
NTransferFunction::eTF m_sdrEotf = NTransferFunction::TF_DEFAULT;
|
||||
float m_sdrSaturation = 1.0f;
|
||||
float m_sdrBrightness = 1.0f;
|
||||
float m_sdrMinLuminance = 0.2f;
|
||||
int m_sdrMaxLuminance = 80;
|
||||
bool m_createdByUser = false;
|
||||
bool m_isUnsafeFallback = false;
|
||||
bool m_dpmsStatus = true;
|
||||
bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
NCMType::eCMType m_cmType = NCMType::CM_SRGB;
|
||||
NTransferFunction::eTF m_sdrEotf = NTransferFunction::TF_DEFAULT;
|
||||
float m_sdrSaturation = 1.0f;
|
||||
float m_sdrBrightness = 1.0f;
|
||||
float m_sdrMinLuminance = 0.2f;
|
||||
int m_sdrMaxLuminance = 80;
|
||||
bool m_createdByUser = false;
|
||||
bool m_isUnsafeFallback = false;
|
||||
|
||||
SP<CEventLoopTimer> m_dpmsRetryTimer;
|
||||
SP<CEventLoopTimer> m_dpmsRetryTimer;
|
||||
|
||||
bool m_pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool m_renderingActive = false;
|
||||
bool m_pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool m_renderingActive = false;
|
||||
|
||||
bool m_ratsScheduled = false;
|
||||
CTimer m_lastPresentationTimer;
|
||||
bool m_ratsScheduled = false;
|
||||
CTimer m_lastPresentationTimer;
|
||||
std::optional<Time::steady_tp> m_estimatedNextVblank;
|
||||
|
||||
bool m_isBeingLeased = false;
|
||||
bool m_isBeingLeased = false;
|
||||
|
||||
Config::CMonitorRule m_activeMonitorRule;
|
||||
Config::CMonitorRule m_activeMonitorRule;
|
||||
|
||||
SP<Render::ITexture> m_splash;
|
||||
SP<Render::ITexture> m_background;
|
||||
SP<Render::ITexture> m_splash;
|
||||
SP<Render::ITexture> m_background;
|
||||
|
||||
// explicit sync
|
||||
Hyprutils::OS::CFileDescriptor m_inFence; // TODO: remove when aq uses CFileDescriptor
|
||||
|
|
|
|||
|
|
@ -1,21 +1,7 @@
|
|||
#include "SyncReleaser.hpp"
|
||||
#include "SyncTimeline.hpp"
|
||||
#include "../../render/OpenGL.hpp"
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/sync_file.h>
|
||||
#else
|
||||
struct sync_merge_data {
|
||||
char name[32];
|
||||
__s32 fd2;
|
||||
__s32 fence;
|
||||
__u32 flags;
|
||||
__u32 pad;
|
||||
};
|
||||
#define SYNC_IOC_MAGIC '>'
|
||||
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
|
||||
#endif
|
||||
#include "../../helpers/Drm.hpp"
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
|
|
@ -35,30 +21,11 @@ CSyncReleaser::~CSyncReleaser() {
|
|||
m_timeline->signal(m_point);
|
||||
}
|
||||
|
||||
static CFileDescriptor mergeSyncFds(const CFileDescriptor& fd1, const CFileDescriptor& fd2) {
|
||||
// combines the fences of both sync_fds into a dma_fence_array (https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_fence_array_create)
|
||||
// with the signal_on_any param set to false, so the new sync_fd will "signal when all fences in the array signal."
|
||||
|
||||
struct sync_merge_data data{
|
||||
.name = "merged release fence",
|
||||
.fd2 = fd2.get(),
|
||||
.fence = -1,
|
||||
};
|
||||
int err = -1;
|
||||
do {
|
||||
err = ioctl(fd1.get(), SYNC_IOC_MERGE, &data);
|
||||
} while (err == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
if (err < 0)
|
||||
return CFileDescriptor{};
|
||||
else
|
||||
return CFileDescriptor(data.fence);
|
||||
}
|
||||
|
||||
void CSyncReleaser::addSyncFileFd(const Hyprutils::OS::CFileDescriptor& syncFd) {
|
||||
if (m_fd.isValid())
|
||||
m_fd = mergeSyncFds(m_fd, syncFd);
|
||||
else
|
||||
if (!m_fd.isValid())
|
||||
m_fd = syncFd.duplicate();
|
||||
else
|
||||
m_fd = DRM::mergeFence(m_fd.take(), syncFd.duplicate().take());
|
||||
}
|
||||
|
||||
void CSyncReleaser::drop() {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "Subcompositor.hpp"
|
||||
#include "../Viewporter.hpp"
|
||||
#include "../../helpers/Monitor.hpp"
|
||||
#include "../../helpers/Drm.hpp"
|
||||
#include "../PresentationTime.hpp"
|
||||
#include "../DRMSyncobj.hpp"
|
||||
#include "../types/DMABuffer.hpp"
|
||||
|
|
@ -148,10 +149,28 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
|
|||
// fifo and fences first
|
||||
m_events.stateCommit.emit(state);
|
||||
|
||||
if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success && !state->updated.bits.acquire) {
|
||||
state->buffer->m_syncFd = dc<CDMABuffer*>(state->buffer.m_buffer.get())->exportSyncFile();
|
||||
if (state->buffer->m_syncFd.isValid())
|
||||
m_stateQueue.lock(state, LOCK_REASON_FENCE);
|
||||
if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success) {
|
||||
static const auto DEADLINE = CConfigValue<Config::INTEGER>("experimental:deadline_client_buffer");
|
||||
auto const WINDOW = m_hlSurface ? Desktop::View::CWindow::fromView(m_hlSurface->view()) : nullptr;
|
||||
if (g_pHyprRenderer->explicitSyncSupported()) {
|
||||
if (state->updated.bits.acquire && *DEADLINE && WINDOW && WINDOW->m_monitor && WINDOW->m_monitor->m_solitaryClient == WINDOW) {
|
||||
Time::steady_tp deadline = Time::steadyNow() + std::chrono::microseconds(100);
|
||||
DRM::setDeadline(deadline, state->acquire.exportAsFD());
|
||||
} else {
|
||||
state->buffer->m_syncFds = dc<CDMABuffer*>(state->buffer.m_buffer.get())->exportSyncFiles();
|
||||
if (!state->buffer->m_syncFds.empty()) {
|
||||
if (*DEADLINE && WINDOW && WINDOW->m_monitor && WINDOW->m_monitor->m_solitaryClient == WINDOW) {
|
||||
Time::steady_tp deadline = Time::steadyNow() + std::chrono::microseconds(100);
|
||||
for (auto& fence : state->buffer->m_syncFds) {
|
||||
if (fence.isValid())
|
||||
DRM::setDeadline(deadline, fence);
|
||||
}
|
||||
}
|
||||
|
||||
m_stateQueue.lock(state, LOCK_REASON_FENCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now for timer.
|
||||
|
|
@ -542,9 +561,30 @@ void CWLSurfaceResource::scheduleState(WP<SSurfaceState> state) {
|
|||
} else if (state->buffer && state->buffer->isSynchronous()) {
|
||||
// synchronous (shm) buffers can be read immediately
|
||||
m_stateQueue.unlock(state, LOCK_REASON_FENCE);
|
||||
} else if (state->buffer && state->buffer->m_syncFd.isValid()) {
|
||||
} else if (state->buffer && !state->buffer->m_syncFds.empty()) {
|
||||
// async buffer and is dmabuf, then we can wait on implicit fences
|
||||
g_pEventLoopManager->doOnReadable(std::move(state->buffer->m_syncFd), [state, whenReadable]() { whenReadable(state, LOCK_REASON_FENCE); });
|
||||
auto fence = std::ranges::find_if(state->buffer->m_syncFds, [](auto& f) { return !Hyprutils::OS::CFileDescriptor::isReadable(f.get()); });
|
||||
if (fence == state->buffer->m_syncFds.end())
|
||||
m_stateQueue.unlock(state, LOCK_REASON_FENCE);
|
||||
else {
|
||||
//#TODO: if multiple fences are not ready, wait for them..
|
||||
auto checkFences = [state, whenReadable](auto&& self) -> void {
|
||||
if (!state || !state->buffer.m_buffer)
|
||||
return;
|
||||
|
||||
auto fence = std::ranges::find_if(state->buffer->m_syncFds, [](auto& f) { return !Hyprutils::OS::CFileDescriptor::isReadable(f.get()); });
|
||||
|
||||
if (fence == state->buffer->m_syncFds.end()) {
|
||||
// All fences readable
|
||||
whenReadable(state, LOCK_REASON_FENCE);
|
||||
return;
|
||||
}
|
||||
|
||||
g_pEventLoopManager->doOnReadable(fence->duplicate(), [state, whenReadable, self]() mutable { self(self); });
|
||||
};
|
||||
|
||||
checkFences(checkFences);
|
||||
}
|
||||
} else {
|
||||
// state commit without a buffer.
|
||||
m_stateQueue.tryProcess();
|
||||
|
|
|
|||
|
|
@ -13,24 +13,24 @@ class CHLBufferReference;
|
|||
class IHLBuffer : public Aquamarine::IBuffer {
|
||||
public:
|
||||
virtual ~IHLBuffer();
|
||||
virtual Aquamarine::eBufferCapability caps() = 0;
|
||||
virtual Aquamarine::eBufferType type() = 0;
|
||||
virtual void update(const CRegion& damage) = 0;
|
||||
virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
|
||||
virtual bool good() = 0;
|
||||
virtual void sendRelease();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual bool locked();
|
||||
virtual Aquamarine::eBufferCapability caps() = 0;
|
||||
virtual Aquamarine::eBufferType type() = 0;
|
||||
virtual void update(const CRegion& damage) = 0;
|
||||
virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
|
||||
virtual bool good() = 0;
|
||||
virtual void sendRelease();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual bool locked();
|
||||
|
||||
void onBackendRelease(const std::function<void()>& fn);
|
||||
void addReleasePoint(CDRMSyncPointState& point);
|
||||
void onBackendRelease(const std::function<void()>& fn);
|
||||
void addReleasePoint(CDRMSyncPointState& point);
|
||||
|
||||
SP<Render::ITexture> m_texture;
|
||||
bool m_opaque = false;
|
||||
SP<CWLBufferResource> m_resource;
|
||||
std::vector<UP<CSyncReleaser>> m_syncReleasers;
|
||||
Hyprutils::OS::CFileDescriptor m_syncFd;
|
||||
SP<Render::ITexture> m_texture;
|
||||
bool m_opaque = false;
|
||||
SP<CWLBufferResource> m_resource;
|
||||
std::vector<UP<CSyncReleaser>> m_syncReleasers;
|
||||
std::vector<Hyprutils::OS::CFileDescriptor> m_syncFds;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener backendRelease;
|
||||
|
|
|
|||
|
|
@ -4,12 +4,7 @@
|
|||
#include "../../render/Renderer.hpp"
|
||||
#include "../../helpers/Format.hpp"
|
||||
#include <hyprgraphics/egl/Egl.hpp>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/sync_file.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include "../../helpers/Drm.hpp"
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace Hyprgraphics::Egl;
|
||||
|
|
@ -92,18 +87,9 @@ void CDMABuffer::closeFDs() {
|
|||
m_attrs.planes = 0;
|
||||
}
|
||||
|
||||
static int doIoctl(int fd, unsigned long request, void* arg) {
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = ioctl(fd, request, arg);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_buf_export_sync_file
|
||||
// returns a sync file that will be signalled when dmabuf is ready to be read
|
||||
CFileDescriptor CDMABuffer::exportSyncFile() {
|
||||
std::vector<CFileDescriptor> CDMABuffer::exportSyncFiles() {
|
||||
if (!good())
|
||||
return {};
|
||||
|
||||
|
|
@ -113,7 +99,8 @@ CFileDescriptor CDMABuffer::exportSyncFile() {
|
|||
std::vector<CFileDescriptor> syncFds;
|
||||
syncFds.reserve(m_attrs.fds.size());
|
||||
|
||||
for (const auto& fd : m_attrs.fds) {
|
||||
for (auto i = 0ul; i < m_attrs.fds.size(); i++) {
|
||||
auto fd = m_attrs.fds[i];
|
||||
if (fd == -1)
|
||||
continue;
|
||||
|
||||
|
|
@ -124,40 +111,11 @@ CFileDescriptor CDMABuffer::exportSyncFile() {
|
|||
continue;
|
||||
}
|
||||
|
||||
dma_buf_export_sync_file request{
|
||||
.flags = DMA_BUF_SYNC_READ,
|
||||
.fd = -1,
|
||||
};
|
||||
|
||||
if (doIoctl(fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &request) == 0)
|
||||
syncFds.emplace_back(request.fd);
|
||||
auto fence = DRM::exportFence(fd);
|
||||
if (fence.isValid())
|
||||
syncFds.emplace_back(std::move(fence));
|
||||
}
|
||||
|
||||
if (syncFds.empty())
|
||||
return {};
|
||||
|
||||
CFileDescriptor syncFd;
|
||||
for (auto& fd : syncFds) {
|
||||
if (!syncFd.isValid()) {
|
||||
syncFd = std::move(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string name = "merged release fence";
|
||||
struct sync_merge_data data{
|
||||
.name = {}, // zero-initialize name[]
|
||||
.fd2 = fd.get(),
|
||||
.fence = -1,
|
||||
};
|
||||
|
||||
std::ranges::copy_n(name.c_str(), std::min(name.size() + 1, sizeof(data.name)), data.name);
|
||||
|
||||
if (doIoctl(syncFd.get(), SYNC_IOC_MERGE, &data) == 0)
|
||||
syncFd = CFileDescriptor(data.fence);
|
||||
else
|
||||
syncFd = {};
|
||||
}
|
||||
|
||||
return syncFd;
|
||||
return syncFds;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class CDMABuffer : public IHLBuffer {
|
|||
virtual void endDataPtr();
|
||||
bool good();
|
||||
void closeFDs();
|
||||
Hyprutils::OS::CFileDescriptor exportSyncFile();
|
||||
std::vector<Hyprutils::OS::CFileDescriptor> exportSyncFiles();
|
||||
bool m_success = false;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../debug/Overlay.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../helpers/Drm.hpp"
|
||||
#include "pass/TexPassElement.hpp"
|
||||
#include "pass/SurfacePassElement.hpp"
|
||||
#include "../debug/log/Logger.hpp"
|
||||
|
|
@ -71,7 +72,6 @@ bool CHyprGLRenderer::beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion&
|
|||
}
|
||||
|
||||
bool CHyprGLRenderer::beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple) {
|
||||
|
||||
m_currentRenderbuffer->bind();
|
||||
if (simple)
|
||||
g_pHyprOpenGL->beginSimple(pMonitor, damage, m_currentRenderbuffer);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "../helpers/CursorShapes.hpp"
|
||||
#include "../helpers/MainLoopExecutor.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../helpers/Drm.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "pass/TexPassElement.hpp"
|
||||
#include "pass/ClearPassElement.hpp"
|
||||
|
|
@ -1970,6 +1971,8 @@ void IHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
|
|||
|
||||
const float ZOOMFACTOR = pMonitor->m_cursorZoom->value();
|
||||
|
||||
auto cleanup = CScopeGuard([pMonitor]() { pMonitor->m_estimatedNextVblank = std::nullopt; });
|
||||
|
||||
if (pMonitor->m_pixelSize.x < 1 || pMonitor->m_pixelSize.y < 1) {
|
||||
Log::logger->log(Log::ERR, "Refusing to render a monitor because of an invalid pixel size: {}", pMonitor->m_pixelSize);
|
||||
return;
|
||||
|
|
@ -2404,6 +2407,16 @@ void IHyprRenderer::handleFullscreenSettings(PHLMONITOR pMonitor) {
|
|||
bool IHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
||||
handleFullscreenSettings(pMonitor);
|
||||
|
||||
static const auto DEADLINE = CConfigValue<Config::INTEGER>("experimental:deadline_main_buffer");
|
||||
if (*DEADLINE && m_currentBuffer) {
|
||||
auto deadline = pMonitor->isMultiGPU() || pMonitor->m_vrrActive || pMonitor->m_tearingState.activelyTearing || !pMonitor->m_estimatedNextVblank.has_value() ?
|
||||
Time::steadyNow() + std::chrono::microseconds(100) :
|
||||
pMonitor->m_estimatedNextVblank.value();
|
||||
auto fence = DRM::exportFence(m_currentBuffer->dmabuf().fds[0]);
|
||||
|
||||
DRM::setDeadline(deadline, fence);
|
||||
}
|
||||
|
||||
bool ok = pMonitor->m_state.commit();
|
||||
if (!ok) {
|
||||
if (pMonitor->m_inFence.isValid()) {
|
||||
|
|
|
|||
|
|
@ -271,12 +271,12 @@ namespace Render {
|
|||
bool m_cursorHidden = false;
|
||||
bool m_cursorHiddenByCondition = false;
|
||||
bool m_cursorHasSurface = false;
|
||||
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
|
||||
eRenderMode m_renderMode = RENDER_MODE_NORMAL;
|
||||
bool m_nvidia = false;
|
||||
bool m_intel = false;
|
||||
bool m_software = false;
|
||||
bool m_mgpu = false;
|
||||
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
|
||||
|
||||
struct {
|
||||
bool hiddenOnTouch = false;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue