From a7a88404008cea489b59b432fc2f38a5f926231f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 20 Jun 2024 19:24:43 +0200 Subject: [PATCH] Core: More work to get Hyprland working --- include/aquamarine/backend/Backend.hpp | 21 +++- include/aquamarine/backend/Wayland.hpp | 45 +++++--- include/aquamarine/output/Output.hpp | 53 ++++++--- src/backend/Backend.cpp | 43 ++++++- src/backend/Wayland.cpp | 149 ++++++++++++++++--------- src/output/Output.cpp | 24 ++++ tests/SimpleWindow.cpp | 3 +- 7 files changed, 247 insertions(+), 91 deletions(-) create mode 100644 src/output/Output.cpp diff --git a/include/aquamarine/backend/Backend.hpp b/include/aquamarine/backend/Backend.hpp index 574ef2c..836d0c6 100644 --- a/include/aquamarine/backend/Backend.hpp +++ b/include/aquamarine/backend/Backend.hpp @@ -54,11 +54,18 @@ namespace Aquamarine { virtual ~IBackendImplementation() { ; } + + enum eBackendCapabilities : uint32_t { + AQ_BACKEND_CAPABILITY_POINTER = (1 << 0), + }; + virtual eBackendType type() = 0; virtual bool start() = 0; virtual int pollFD() = 0; virtual int drmFD() = 0; virtual bool dispatchEvents() = 0; + virtual uint32_t capabilities() = 0; + virtual void onReady() = 0; }; class CBackend { @@ -74,9 +81,21 @@ namespace Aquamarine { void log(eBackendLogLevel level, const std::string& msg); /* Enters the event loop synchronously. For simple clients, this is probably what you want. For more complex ones, - see async methods further below */ + see the async methods further below */ void enterLoop(); + /* Gets all the FDs you have to poll. When any single one fires, call dispatchEventsAsync */ + std::vector getPollFDs(); + + /* Dispatches all pending events on all queues then returns */ + void dispatchEventsAsync(); + + /* Checks if the backend has a session - iow if it's a DRM backend */ + bool hasSession(); + + /* Get the primary DRM FD */ + int drmFD(); + struct { Hyprutils::Signal::CSignal newOutput; Hyprutils::Signal::CSignal newPointer; diff --git a/include/aquamarine/backend/Wayland.hpp b/include/aquamarine/backend/Wayland.hpp index b8a5621..f2342af 100644 --- a/include/aquamarine/backend/Wayland.hpp +++ b/include/aquamarine/backend/Wayland.hpp @@ -26,7 +26,7 @@ namespace Aquamarine { private: struct { - Hyprutils::Memory::CSharedPointer buffer; + Hyprutils::Memory::CSharedPointer buffer; } waylandState; Hyprutils::Memory::CWeakPointer buffer; @@ -38,12 +38,18 @@ namespace Aquamarine { class CWaylandOutput : public IOutput { public: virtual ~CWaylandOutput(); - virtual bool commit(); + virtual bool commit(); + virtual bool test(); + virtual Hyprutils::Memory::CSharedPointer getBackend(); + virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); + virtual void moveCursor(const Hyprutils::Math::Vector2D& coord); + virtual void scheduleFrame(); + + Hyprutils::Memory::CWeakPointer self; private: CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer backend_); - std::string name; Hyprutils::Memory::CWeakPointer backend; Hyprutils::Memory::CSharedPointer wlBufferFromBuffer(Hyprutils::Memory::CSharedPointer buffer); @@ -55,10 +61,10 @@ namespace Aquamarine { } backendState; struct { - Hyprutils::Memory::CSharedPointer surface; - Hyprutils::Memory::CSharedPointer xdgSurface; - Hyprutils::Memory::CSharedPointer xdgToplevel; - Hyprutils::Memory::CSharedPointer frameCallback; + Hyprutils::Memory::CSharedPointer surface; + Hyprutils::Memory::CSharedPointer xdgSurface; + Hyprutils::Memory::CSharedPointer xdgToplevel; + Hyprutils::Memory::CSharedPointer frameCallback; } waylandState; friend class CWaylandBackend; @@ -67,12 +73,12 @@ namespace Aquamarine { class CWaylandKeyboard : public IKeyboard { public: - CWaylandKeyboard(Hyprutils::Memory::CSharedPointer keyboard_, Hyprutils::Memory::CWeakPointer backend_); + CWaylandKeyboard(Hyprutils::Memory::CSharedPointer keyboard_, Hyprutils::Memory::CWeakPointer backend_); virtual ~CWaylandKeyboard(); virtual const std::string& getName(); - Hyprutils::Memory::CSharedPointer keyboard; + Hyprutils::Memory::CSharedPointer keyboard; Hyprutils::Memory::CWeakPointer backend; private: @@ -81,12 +87,12 @@ namespace Aquamarine { class CWaylandPointer : public IPointer { public: - CWaylandPointer(Hyprutils::Memory::CSharedPointer pointer_, Hyprutils::Memory::CWeakPointer backend_); + CWaylandPointer(Hyprutils::Memory::CSharedPointer pointer_, Hyprutils::Memory::CWeakPointer backend_); virtual ~CWaylandPointer(); virtual const std::string& getName(); - Hyprutils::Memory::CSharedPointer pointer; + Hyprutils::Memory::CSharedPointer pointer; Hyprutils::Memory::CWeakPointer backend; private: @@ -101,6 +107,9 @@ namespace Aquamarine { virtual int pollFD(); virtual int drmFD(); virtual bool dispatchEvents(); + virtual uint32_t capabilities(); + virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); + virtual void onReady(); Hyprutils::Memory::CWeakPointer self; @@ -114,7 +123,7 @@ namespace Aquamarine { // Hyprutils::Memory::CWeakPointer backend; - std::vector> outputs; + std::vector> outputs, scheduledFrames; std::vector> keyboards; std::vector> pointers; @@ -126,12 +135,12 @@ namespace Aquamarine { wl_display* display = nullptr; // hw-s types - Hyprutils::Memory::CSharedPointer registry; - Hyprutils::Memory::CSharedPointer seat; - Hyprutils::Memory::CSharedPointer xdg; - Hyprutils::Memory::CSharedPointer compositor; - Hyprutils::Memory::CSharedPointer dmabuf; - Hyprutils::Memory::CSharedPointer dmabufFeedback; + Hyprutils::Memory::CSharedPointer registry; + Hyprutils::Memory::CSharedPointer seat; + Hyprutils::Memory::CSharedPointer xdg; + Hyprutils::Memory::CSharedPointer compositor; + Hyprutils::Memory::CSharedPointer dmabuf; + Hyprutils::Memory::CSharedPointer dmabufFeedback; // control bool dmabufFailed = false; diff --git a/include/aquamarine/output/Output.hpp b/include/aquamarine/output/Output.hpp index cc9cc38..121860a 100644 --- a/include/aquamarine/output/Output.hpp +++ b/include/aquamarine/output/Output.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -9,6 +10,9 @@ #include "../buffer/Buffer.hpp" namespace Aquamarine { + + class IBackendImplementation; + struct SOutputMode { Hyprutils::Math::Vector2D pixelSize; unsigned int refreshRate = 0 /* in mHz */; @@ -20,20 +24,30 @@ namespace Aquamarine { AQ_OUTPUT_PRESENTATION_IMMEDIATE, // likely tearing }; + enum eSubpixelMode { + AQ_SUBPIXEL_UNKNOWN = 0, + AQ_SUBPIXEL_NONE, + AQ_SUBPIXEL_HORIZONTAL_RGB, + AQ_SUBPIXEL_HORIZONTAL_BGR, + AQ_SUBPIXEL_VERTICAL_RGB, + AQ_SUBPIXEL_VERTICAL_BGR, + }; + class IOutput; class COutputState { public: - Hyprutils::Math::CRegion damage; - bool enabled = false; - bool adaptiveSync = false; - eOutputPresentationMode presentationMode = AQ_OUTPUT_PRESENTATION_VSYNC; - std::vector gammaLut; - Hyprutils::Math::Vector2D lastModeSize; - Hyprutils::Memory::CWeakPointer mode; - std::optional customMode; - uint32_t drmFormat = DRM_FORMAT_INVALID; - Hyprutils::Memory::CSharedPointer buffer; + // TODO: make this state private, this sucks + Hyprutils::Math::CRegion damage; + bool enabled = false; + bool adaptiveSync = false; + eOutputPresentationMode presentationMode = AQ_OUTPUT_PRESENTATION_VSYNC; + std::vector gammaLut; + Hyprutils::Math::Vector2D lastModeSize; + Hyprutils::Memory::CWeakPointer mode; + Hyprutils::Memory::CSharedPointer customMode; + uint32_t drmFormat = DRM_FORMAT_INVALID; + Hyprutils::Memory::CSharedPointer buffer; }; class IOutput { @@ -42,13 +56,20 @@ namespace Aquamarine { ; } - virtual bool commit() = 0; + virtual bool commit() = 0; + virtual bool test() = 0; + virtual Hyprutils::Memory::CSharedPointer getBackend() = 0; + virtual Hyprutils::Memory::CSharedPointer preferredMode(); + virtual bool setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot); + virtual void moveCursor(const Hyprutils::Math::Vector2D& coord); // includes the hotspot + virtual void scheduleFrame(); - std::string name, description, make, model, serial; - Hyprutils::Math::Vector2D physicalSize; - bool enabled = false; - bool adaptiveSync = false; - bool nonDesktop = false; + std::string name, description, make, model, serial; + Hyprutils::Math::Vector2D physicalSize; + bool enabled = false; + bool adaptiveSync = false; + bool nonDesktop = false; + eSubpixelMode subpixel = AQ_SUBPIXEL_NONE; // std::vector> modes; diff --git a/src/backend/Backend.cpp b/src/backend/Backend.cpp index 47d2b72..3aa009e 100644 --- a/src/backend/Backend.cpp +++ b/src/backend/Backend.cpp @@ -103,6 +103,10 @@ bool Aquamarine::CBackend::start() { if (!allocator) return false; + for (auto& b : implementations) { + b->onReady(); + } + return true; } @@ -167,8 +171,41 @@ void Aquamarine::CBackend::enterLoop() { std::lock_guard lg(m_sEventLoopInternals.eventLock); - for (size_t i = 0; i < pollFDs.size(); ++i) { - implementations.at(i)->dispatchEvents(); - } + dispatchEventsAsync(); } } + +std::vector Aquamarine::CBackend::getPollFDs() { + std::vector result; + for (auto& i : implementations) { + int fd = i->pollFD(); + if (fd < 0) + continue; + + result.push_back(fd); + } + + return result; +} + +int Aquamarine::CBackend::drmFD() { + for (auto& i : implementations) { + int fd = i->drmFD(); + if (fd < 0) + continue; + + return fd; + } + return -1; +} + +void Aquamarine::CBackend::dispatchEventsAsync() { + for (auto& i : implementations) { + i->dispatchEvents(); + } +} + +bool Aquamarine::CBackend::hasSession() { + // TODO: + return false; +} diff --git a/src/backend/Wayland.cpp b/src/backend/Wayland.cpp index 8c278d6..e228289 100644 --- a/src/backend/Wayland.cpp +++ b/src/backend/Wayland.cpp @@ -35,37 +35,37 @@ bool Aquamarine::CWaylandBackend::start() { return false; } - waylandState.registry = makeShared((wl_proxy*)wl_display_get_registry(waylandState.display)); + waylandState.registry = makeShared((wl_proxy*)wl_display_get_registry(waylandState.display)); backend->log(AQ_LOG_DEBUG, std::format("Got registry at 0x{:x}", (uintptr_t)waylandState.registry->resource())); - waylandState.registry->setGlobal([this](CWlRegistry* r, uint32_t id, const char* name, uint32_t version) { + waylandState.registry->setGlobal([this](CCWlRegistry* r, uint32_t id, const char* name, uint32_t version) { backend->log(AQ_LOG_TRACE, std::format(" | received global: {} (version {}) with id {}", name, version, id)); const std::string NAME = name; if (NAME == "wl_seat") { backend->log(AQ_LOG_TRACE, std::format(" > binding to global: {} (version {}) with id {}", name, 9, id)); - waylandState.seat = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &wl_seat_interface, 9)); + waylandState.seat = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &wl_seat_interface, 9)); initSeat(); } else if (NAME == "xdg_wm_base") { backend->log(AQ_LOG_TRACE, std::format(" > binding to global: {} (version {}) with id {}", name, 6, id)); - waylandState.xdg = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &xdg_wm_base_interface, 6)); + waylandState.xdg = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &xdg_wm_base_interface, 6)); initShell(); } else if (NAME == "wl_compositor") { backend->log(AQ_LOG_TRACE, std::format(" > binding to global: {} (version {}) with id {}", name, 6, id)); - waylandState.compositor = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &wl_compositor_interface, 6)); + waylandState.compositor = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &wl_compositor_interface, 6)); } else if (NAME == "zwp_linux_dmabuf_v1") { backend->log(AQ_LOG_TRACE, std::format(" > binding to global: {} (version {}) with id {}", name, 5, id)); waylandState.dmabuf = - makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &zwp_linux_dmabuf_v1_interface, 5)); + makeShared((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &zwp_linux_dmabuf_v1_interface, 5)); if (!initDmabuf()) { backend->log(AQ_LOG_ERROR, "Wayland backend cannot start: zwp_linux_dmabuf_v1 init failed"); waylandState.dmabufFailed = true; } } }); - waylandState.registry->setGlobalRemove([this](CWlRegistry* r, uint32_t id) { ; }); + waylandState.registry->setGlobalRemove([this](CCWlRegistry* r, uint32_t id) { backend->log(AQ_LOG_DEBUG, std::format("Global {} removed", id)); }); wl_display_roundtrip(waylandState.display); @@ -86,7 +86,8 @@ int Aquamarine::CWaylandBackend::drmFD() { } void Aquamarine::CWaylandBackend::createOutput(const std::string& szName) { - auto o = outputs.emplace_back(SP(new CWaylandOutput(szName, self))); + auto o = outputs.emplace_back(SP(new CWaylandOutput(szName, self))); + o->self = o; backend->events.newOutput.emit(SP(o)); } @@ -112,16 +113,42 @@ bool Aquamarine::CWaylandBackend::dispatchEvents() { wl_display_flush(waylandState.display); } while (ret > 0); + // dispatch frames + for (auto& f : scheduledFrames) { + f->events.frame.emit(); + } + + scheduledFrames.clear(); + return true; } -Aquamarine::CWaylandKeyboard::CWaylandKeyboard(SP keyboard_, Hyprutils::Memory::CWeakPointer backend_) : keyboard(keyboard_), backend(backend_) { +uint32_t Aquamarine::CWaylandBackend::capabilities() { + return AQ_BACKEND_CAPABILITY_POINTER; +} + +bool Aquamarine::CWaylandBackend::setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot) { + // TODO: + return true; +} + +void Aquamarine::CWaylandBackend::onReady() { + for (auto& o : outputs) { + o->swapchain = makeShared(backend->allocator); + if (!o->swapchain) { + backend->log(AQ_LOG_ERROR, std::format("Output {} failed: swapchain creation failed", o->name)); + continue; + } + } +} + +Aquamarine::CWaylandKeyboard::CWaylandKeyboard(SP keyboard_, Hyprutils::Memory::CWeakPointer backend_) : keyboard(keyboard_), backend(backend_) { if (!keyboard->resource()) return; backend->backend->log(AQ_LOG_DEBUG, "New wayland keyboard wl_keyboard"); - keyboard->setKey([this](CWlKeyboard* r, uint32_t serial, uint32_t timeMs, uint32_t key, wl_keyboard_key_state state) { + keyboard->setKey([this](CCWlKeyboard* r, uint32_t serial, uint32_t timeMs, uint32_t key, wl_keyboard_key_state state) { events.key.emit(SKeyEvent{ .timeMs = timeMs, .key = key, @@ -129,7 +156,7 @@ Aquamarine::CWaylandKeyboard::CWaylandKeyboard(SP keyboard_, Hyprut }); }); - keyboard->setModifiers([this](CWlKeyboard* r, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { + keyboard->setModifiers([this](CCWlKeyboard* r, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { events.modifiers.emit(SModifiersEvent{ .depressed = depressed, .latched = latched, @@ -147,28 +174,27 @@ const std::string& Aquamarine::CWaylandKeyboard::getName() { return name; } -Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils::Memory::CWeakPointer backend_) : pointer(pointer_), backend(backend_) { +Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils::Memory::CWeakPointer backend_) : pointer(pointer_), backend(backend_) { if (!pointer->resource()) return; backend->backend->log(AQ_LOG_DEBUG, "New wayland pointer wl_pointer"); - pointer->setMotion([this](CWlPointer* r, uint32_t serial, wl_fixed_t x, wl_fixed_t y) { - if (!backend->focusedOutput || (!backend->focusedOutput->state->mode && !backend->focusedOutput->state->customMode.has_value())) + pointer->setMotion([this](CCWlPointer* r, uint32_t serial, wl_fixed_t x, wl_fixed_t y) { + if (!backend->focusedOutput || (!backend->focusedOutput->state->mode && !backend->focusedOutput->state->customMode)) return; - const Vector2D size = - backend->focusedOutput->state->customMode.has_value() ? backend->focusedOutput->state->customMode->pixelSize : backend->focusedOutput->state->mode->pixelSize; + const Vector2D size = backend->focusedOutput->state->customMode ? backend->focusedOutput->state->customMode->pixelSize : backend->focusedOutput->state->mode->pixelSize; - Vector2D local = {wl_fixed_to_double(x), wl_fixed_to_double(y)}; - local = local / size; + Vector2D local = {wl_fixed_to_double(x), wl_fixed_to_double(y)}; + local = local / size; events.warp.emit(SWarpEvent{ .absolute = local, }); }); - pointer->setEnter([this](CWlPointer* r, uint32_t serial, wl_proxy* surface, wl_fixed_t x, wl_fixed_t y) { + pointer->setEnter([this](CCWlPointer* r, uint32_t serial, wl_proxy* surface, wl_fixed_t x, wl_fixed_t y) { backend->lastEnterSerial = serial; for (auto& o : backend->outputs) { @@ -181,7 +207,7 @@ Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils: } }); - pointer->setButton([this](CWlPointer* r, uint32_t serial, uint32_t timeMs, uint32_t button, wl_pointer_button_state state) { + pointer->setButton([this](CCWlPointer* r, uint32_t serial, uint32_t timeMs, uint32_t button, wl_pointer_button_state state) { events.button.emit(SButtonEvent{ .timeMs = timeMs, .button = button, @@ -189,7 +215,7 @@ Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils: }); }); - pointer->setAxis([this](CWlPointer* r, uint32_t timeMs, wl_pointer_axis axis, wl_fixed_t value) { + pointer->setAxis([this](CCWlPointer* r, uint32_t timeMs, wl_pointer_axis axis, wl_fixed_t value) { events.axis.emit(SAxisEvent{ .timeMs = timeMs, .axis = axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ? AQ_POINTER_AXIS_HORIZONTAL : AQ_POINTER_AXIS_VERTICAL, @@ -197,7 +223,7 @@ Aquamarine::CWaylandPointer::CWaylandPointer(SP pointer_, Hyprutils: }); }); - pointer->setFrame([this](CWlPointer* r) { events.frame.emit(); }); + pointer->setFrame([this](CCWlPointer* r) { events.frame.emit(); }); } Aquamarine::CWaylandPointer::~CWaylandPointer() { @@ -209,18 +235,18 @@ const std::string& Aquamarine::CWaylandPointer::getName() { } void Aquamarine::CWaylandBackend::initSeat() { - waylandState.seat->setCapabilities([this](CWlSeat* r, wl_seat_capability cap) { + waylandState.seat->setCapabilities([this](CCWlSeat* r, wl_seat_capability cap) { const bool HAS_KEYBOARD = ((uint32_t)cap) & WL_SEAT_CAPABILITY_KEYBOARD; const bool HAS_POINTER = ((uint32_t)cap) & WL_SEAT_CAPABILITY_POINTER; if (HAS_KEYBOARD && keyboards.empty()) { - auto k = keyboards.emplace_back(makeShared(makeShared(waylandState.seat->sendGetKeyboard()), self)); + auto k = keyboards.emplace_back(makeShared(makeShared(waylandState.seat->sendGetKeyboard()), self)); backend->events.newKeyboard.emit(SP(k)); } else if (!HAS_KEYBOARD && !keyboards.empty()) keyboards.clear(); if (HAS_POINTER && pointers.empty()) { - auto p = pointers.emplace_back(makeShared(makeShared(waylandState.seat->sendGetPointer()), self)); + auto p = pointers.emplace_back(makeShared(makeShared(waylandState.seat->sendGetPointer()), self)); backend->events.newPointer.emit(SP(p)); } else if (!HAS_POINTER && !pointers.empty()) pointers.clear(); @@ -228,22 +254,22 @@ void Aquamarine::CWaylandBackend::initSeat() { } void Aquamarine::CWaylandBackend::initShell() { - waylandState.xdg->setPing([](CXdgWmBase* r, uint32_t serial) { r->sendPong(serial); }); + waylandState.xdg->setPing([](CCXdgWmBase* r, uint32_t serial) { r->sendPong(serial); }); } bool Aquamarine::CWaylandBackend::initDmabuf() { - waylandState.dmabufFeedback = makeShared(waylandState.dmabuf->sendGetDefaultFeedback()); + waylandState.dmabufFeedback = makeShared(waylandState.dmabuf->sendGetDefaultFeedback()); if (!waylandState.dmabufFeedback) { backend->log(AQ_LOG_ERROR, "initDmabuf: failed to get default feedback"); return false; } - waylandState.dmabufFeedback->setDone([this](CZwpLinuxDmabufFeedbackV1* r) { + waylandState.dmabufFeedback->setDone([this](CCZwpLinuxDmabufFeedbackV1* r) { // no-op backend->log(AQ_LOG_DEBUG, "zwp_linux_dmabuf_v1: Got done"); }); - waylandState.dmabufFeedback->setMainDevice([this](CZwpLinuxDmabufFeedbackV1* r, wl_array* deviceArr) { + waylandState.dmabufFeedback->setMainDevice([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* deviceArr) { backend->log(AQ_LOG_DEBUG, "zwp_linux_dmabuf_v1: Got main device"); dev_t device; @@ -296,29 +322,29 @@ bool Aquamarine::CWaylandBackend::initDmabuf() { return true; } -Aquamarine::CWaylandOutput::CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer backend_) : name(name_), backend(backend_) { - errno = 0; +Aquamarine::CWaylandOutput::CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer backend_) : backend(backend_) { + name = name_; - waylandState.surface = makeShared(backend->waylandState.compositor->sendCreateSurface()); + waylandState.surface = makeShared(backend->waylandState.compositor->sendCreateSurface()); if (!waylandState.surface->resource()) { backend->backend->log(AQ_LOG_ERROR, std::format("Output {} failed: no surface given. Errno: {}", name, errno)); return; } - waylandState.xdgSurface = makeShared(backend->waylandState.xdg->sendGetXdgSurface(waylandState.surface->resource())); + waylandState.xdgSurface = makeShared(backend->waylandState.xdg->sendGetXdgSurface(waylandState.surface->resource())); if (!waylandState.xdgSurface->resource()) { backend->backend->log(AQ_LOG_ERROR, std::format("Output {} failed: no xdgSurface given. Errno: {}", name, errno)); return; } - waylandState.xdgSurface->setConfigure([this](CXdgSurface* r, uint32_t serial) { + waylandState.xdgSurface->setConfigure([this](CCXdgSurface* r, uint32_t serial) { backend->backend->log(AQ_LOG_DEBUG, std::format("Output {}: configure surface with {}", name, serial)); r->sendAckConfigure(serial); }); - waylandState.xdgToplevel = makeShared(waylandState.xdgSurface->sendGetToplevel()); + waylandState.xdgToplevel = makeShared(waylandState.xdgSurface->sendGetToplevel()); if (!waylandState.xdgToplevel->resource()) { backend->backend->log(AQ_LOG_ERROR, std::format("Output {} failed: no xdgToplevel given. Errno: {}", name, errno)); @@ -326,24 +352,15 @@ Aquamarine::CWaylandOutput::CWaylandOutput(const std::string& name_, Hyprutils:: } waylandState.xdgToplevel->setWmCapabilities( - [this](CXdgToplevel* r, wl_array* arr) { backend->backend->log(AQ_LOG_DEBUG, std::format("Output {}: wm_capabilities received", name)); }); - - waylandState.xdgToplevel->setConfigure([this](CXdgToplevel* r, int32_t w, int32_t h, wl_array* arr) { - // we only create the swapchain here because in the main func we still don't have an allocator - if (!swapchain) { - swapchain = makeShared(backend->backend->allocator); - if (!swapchain) { - backend->backend->log(AQ_LOG_ERROR, std::format("Output {} failed: swapchain creation failed", name)); - return; - } - } + [this](CCXdgToplevel* r, wl_array* arr) { backend->backend->log(AQ_LOG_DEBUG, std::format("Output {}: wm_capabilities received", name)); }); + waylandState.xdgToplevel->setConfigure([this](CCXdgToplevel* r, int32_t w, int32_t h, wl_array* arr) { backend->backend->log(AQ_LOG_DEBUG, std::format("Output {}: configure toplevel with {}x{}", name, w, h)); events.state.emit(SStateEvent{.size = {w, h}}); sendFrameAndSetCallback(); }); - auto inputRegion = makeShared(backend->waylandState.compositor->sendCreateRegion()); + auto inputRegion = makeShared(backend->waylandState.compositor->sendCreateRegion()); inputRegion->sendAdd(0, 0, INT32_MAX, INT32_MAX); waylandState.surface->sendSetInputRegion(inputRegion.get()); @@ -364,6 +381,10 @@ Aquamarine::CWaylandOutput::~CWaylandOutput() { waylandState.surface->sendDestroy(); } +bool Aquamarine::CWaylandOutput::test() { + return true; // TODO: +} + bool Aquamarine::CWaylandOutput::commit() { Vector2D pixelSize = {}; uint32_t refreshRate = 0; @@ -384,6 +405,11 @@ bool Aquamarine::CWaylandOutput::commit() { return false; } + if (!swapchain) { + backend->backend->log(AQ_LOG_ERROR, std::format("Output {}: no swapchain, lying because it will soon be here", name)); + return true; + } + if (!swapchain->reconfigure(SSwapchainOptions{.length = 2, .size = pixelSize, .format = format})) { backend->backend->log(AQ_LOG_ERROR, std::format("Output {}: pending state rejected: swapchain failed reconfiguring", name)); return false; @@ -413,6 +439,10 @@ bool Aquamarine::CWaylandOutput::commit() { return true; } +SP Aquamarine::CWaylandOutput::getBackend() { + return SP(backend.lock()); +} + SP Aquamarine::CWaylandOutput::wlBufferFromBuffer(SP buffer) { std::erase_if(backendState.buffers, [this](const auto& el) { return el.first.expired() || !swapchain->contains(el.first.lock()); }); @@ -439,15 +469,30 @@ void Aquamarine::CWaylandOutput::sendFrameAndSetCallback() { if (waylandState.frameCallback) return; - waylandState.frameCallback = makeShared(waylandState.surface->sendFrame()); - waylandState.frameCallback->setDone([this](CWlCallback* r, uint32_t ms) { + waylandState.frameCallback = makeShared(waylandState.surface->sendFrame()); + waylandState.frameCallback->setDone([this](CCWlCallback* r, uint32_t ms) { events.frame.emit(); waylandState.frameCallback.reset(); }); } +bool Aquamarine::CWaylandOutput::setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot) { + return true; +} + +void Aquamarine::CWaylandOutput::moveCursor(const Hyprutils::Math::Vector2D& coord) { + return; +} + +void Aquamarine::CWaylandOutput::scheduleFrame() { + if (std::find(backend->scheduledFrames.begin(), backend->scheduledFrames.end(), self.lock()) != backend->scheduledFrames.end()) + return; + + backend->scheduledFrames.emplace_back(self.lock()); +} + Aquamarine::CWaylandBuffer::CWaylandBuffer(SP buffer_, Hyprutils::Memory::CWeakPointer backend_) : buffer(buffer_), backend(backend_) { - auto params = makeShared(backend->waylandState.dmabuf->sendCreateParams()); + auto params = makeShared(backend->waylandState.dmabuf->sendCreateParams()); if (!params) { backend->backend->log(AQ_LOG_ERROR, "WaylandBuffer: failed to query params"); @@ -460,9 +505,9 @@ Aquamarine::CWaylandBuffer::CWaylandBuffer(SP buffer_, Hyprutils::Memor params->sendAdd(attrs.fds.at(i), i, attrs.offsets.at(i), attrs.strides.at(i), attrs.modifier >> 32, attrs.modifier & 0xFFFFFFFF); } - waylandState.buffer = makeShared(params->sendCreateImmed(attrs.size.x, attrs.size.y, attrs.format, (zwpLinuxBufferParamsV1Flags)0)); + waylandState.buffer = makeShared(params->sendCreateImmed(attrs.size.x, attrs.size.y, attrs.format, (zwpLinuxBufferParamsV1Flags)0)); - waylandState.buffer->setRelease([this](CWlBuffer* r) { pendingRelease = false; }); + waylandState.buffer->setRelease([this](CCWlBuffer* r) { pendingRelease = false; }); params->sendDestroy(); } diff --git a/src/output/Output.cpp b/src/output/Output.cpp new file mode 100644 index 0000000..a490d8a --- /dev/null +++ b/src/output/Output.cpp @@ -0,0 +1,24 @@ +#include + +using namespace Aquamarine; + +Hyprutils::Memory::CSharedPointer Aquamarine::IOutput::preferredMode() { + for (auto& m : modes) { + if (m->preferred) + return m; + } + + return nullptr; +} + +void Aquamarine::IOutput::moveCursor(const Hyprutils::Math::Vector2D& coord) { + ; +} + +bool Aquamarine::IOutput::setCursor(Hyprutils::Memory::CSharedPointer buffer, const Hyprutils::Math::Vector2D& hotspot) { + return false; +} + +void Aquamarine::IOutput::scheduleFrame() { + ; +} diff --git a/tests/SimpleWindow.cpp b/tests/SimpleWindow.cpp index a09b856..b0a3a9d 100644 --- a/tests/SimpleWindow.cpp +++ b/tests/SimpleWindow.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace Hyprutils::Signal; using namespace Hyprutils::Memory; @@ -41,7 +42,7 @@ void onState(const Aquamarine::IOutput::SStateEvent& event) { std::cout << "[Client] onState with size " << std::format("{}", event.size) << "\n"; output->state->enabled = true; - output->state->customMode = {.pixelSize = event.size}; + output->state->customMode = makeShared(Aquamarine::SOutputMode{.pixelSize = event.size}); output->state->drmFormat = DRM_FORMAT_XRGB8888; output->commit();