Core: More work to get Hyprland working

This commit is contained in:
Vaxry 2024-06-20 19:24:43 +02:00
parent a13f03d718
commit a7a8840400
7 changed files with 247 additions and 91 deletions

View File

@ -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<int> 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;

View File

@ -26,7 +26,7 @@ namespace Aquamarine {
private:
struct {
Hyprutils::Memory::CSharedPointer<CWlBuffer> buffer;
Hyprutils::Memory::CSharedPointer<CCWlBuffer> buffer;
} waylandState;
Hyprutils::Memory::CWeakPointer<IBuffer> 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<IBackendImplementation> getBackend();
virtual bool setCursor(Hyprutils::Memory::CSharedPointer<IBuffer> buffer, const Hyprutils::Math::Vector2D& hotspot);
virtual void moveCursor(const Hyprutils::Math::Vector2D& coord);
virtual void scheduleFrame();
Hyprutils::Memory::CWeakPointer<CWaylandOutput> self;
private:
CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
std::string name;
Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend;
Hyprutils::Memory::CSharedPointer<CWaylandBuffer> wlBufferFromBuffer(Hyprutils::Memory::CSharedPointer<IBuffer> buffer);
@ -55,10 +61,10 @@ namespace Aquamarine {
} backendState;
struct {
Hyprutils::Memory::CSharedPointer<CWlSurface> surface;
Hyprutils::Memory::CSharedPointer<CXdgSurface> xdgSurface;
Hyprutils::Memory::CSharedPointer<CXdgToplevel> xdgToplevel;
Hyprutils::Memory::CSharedPointer<CWlCallback> frameCallback;
Hyprutils::Memory::CSharedPointer<CCWlSurface> surface;
Hyprutils::Memory::CSharedPointer<CCXdgSurface> xdgSurface;
Hyprutils::Memory::CSharedPointer<CCXdgToplevel> xdgToplevel;
Hyprutils::Memory::CSharedPointer<CCWlCallback> frameCallback;
} waylandState;
friend class CWaylandBackend;
@ -67,12 +73,12 @@ namespace Aquamarine {
class CWaylandKeyboard : public IKeyboard {
public:
CWaylandKeyboard(Hyprutils::Memory::CSharedPointer<CWlKeyboard> keyboard_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
CWaylandKeyboard(Hyprutils::Memory::CSharedPointer<CCWlKeyboard> keyboard_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
virtual ~CWaylandKeyboard();
virtual const std::string& getName();
Hyprutils::Memory::CSharedPointer<CWlKeyboard> keyboard;
Hyprutils::Memory::CSharedPointer<CCWlKeyboard> keyboard;
Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend;
private:
@ -81,12 +87,12 @@ namespace Aquamarine {
class CWaylandPointer : public IPointer {
public:
CWaylandPointer(Hyprutils::Memory::CSharedPointer<CWlPointer> pointer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
CWaylandPointer(Hyprutils::Memory::CSharedPointer<CCWlPointer> pointer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
virtual ~CWaylandPointer();
virtual const std::string& getName();
Hyprutils::Memory::CSharedPointer<CWlPointer> pointer;
Hyprutils::Memory::CSharedPointer<CCWlPointer> pointer;
Hyprutils::Memory::CWeakPointer<CWaylandBackend> 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<IBuffer> buffer, const Hyprutils::Math::Vector2D& hotspot);
virtual void onReady();
Hyprutils::Memory::CWeakPointer<CWaylandBackend> self;
@ -114,7 +123,7 @@ namespace Aquamarine {
//
Hyprutils::Memory::CWeakPointer<CBackend> backend;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandOutput>> outputs;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandOutput>> outputs, scheduledFrames;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandKeyboard>> keyboards;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandPointer>> pointers;
@ -126,12 +135,12 @@ namespace Aquamarine {
wl_display* display = nullptr;
// hw-s types
Hyprutils::Memory::CSharedPointer<CWlRegistry> registry;
Hyprutils::Memory::CSharedPointer<CWlSeat> seat;
Hyprutils::Memory::CSharedPointer<CXdgWmBase> xdg;
Hyprutils::Memory::CSharedPointer<CWlCompositor> compositor;
Hyprutils::Memory::CSharedPointer<CZwpLinuxDmabufV1> dmabuf;
Hyprutils::Memory::CSharedPointer<CZwpLinuxDmabufFeedbackV1> dmabufFeedback;
Hyprutils::Memory::CSharedPointer<CCWlRegistry> registry;
Hyprutils::Memory::CSharedPointer<CCWlSeat> seat;
Hyprutils::Memory::CSharedPointer<CCXdgWmBase> xdg;
Hyprutils::Memory::CSharedPointer<CCWlCompositor> compositor;
Hyprutils::Memory::CSharedPointer<CCZwpLinuxDmabufV1> dmabuf;
Hyprutils::Memory::CSharedPointer<CCZwpLinuxDmabufFeedbackV1> dmabufFeedback;
// control
bool dmabufFailed = false;

View File

@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <optional>
#include <hyprutils/signal/Signal.hpp>
#include <hyprutils/memory/SharedPtr.hpp>
#include <hyprutils/math/Region.hpp>
@ -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<uint16_t> gammaLut;
Hyprutils::Math::Vector2D lastModeSize;
Hyprutils::Memory::CWeakPointer<SOutputMode> mode;
std::optional<SOutputMode> customMode;
uint32_t drmFormat = DRM_FORMAT_INVALID;
Hyprutils::Memory::CSharedPointer<IBuffer> 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<uint16_t> gammaLut;
Hyprutils::Math::Vector2D lastModeSize;
Hyprutils::Memory::CWeakPointer<SOutputMode> mode;
Hyprutils::Memory::CSharedPointer<SOutputMode> customMode;
uint32_t drmFormat = DRM_FORMAT_INVALID;
Hyprutils::Memory::CSharedPointer<IBuffer> 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<IBackendImplementation> getBackend() = 0;
virtual Hyprutils::Memory::CSharedPointer<SOutputMode> preferredMode();
virtual bool setCursor(Hyprutils::Memory::CSharedPointer<IBuffer> 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<Hyprutils::Memory::CSharedPointer<SOutputMode>> modes;

View File

@ -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<std::mutex> lg(m_sEventLoopInternals.eventLock);
for (size_t i = 0; i < pollFDs.size(); ++i) {
implementations.at(i)->dispatchEvents();
}
dispatchEventsAsync();
}
}
std::vector<int> Aquamarine::CBackend::getPollFDs() {
std::vector<int> 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;
}

View File

@ -35,37 +35,37 @@ bool Aquamarine::CWaylandBackend::start() {
return false;
}
waylandState.registry = makeShared<CWlRegistry>((wl_proxy*)wl_display_get_registry(waylandState.display));
waylandState.registry = makeShared<CCWlRegistry>((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<CWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &wl_seat_interface, 9));
waylandState.seat = makeShared<CCWlSeat>((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<CXdgWmBase>((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &xdg_wm_base_interface, 6));
waylandState.xdg = makeShared<CCXdgWmBase>((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<CWlCompositor>((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &wl_compositor_interface, 6));
waylandState.compositor = makeShared<CCWlCompositor>((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<CZwpLinuxDmabufV1>((wl_proxy*)wl_registry_bind((wl_registry*)waylandState.registry->resource(), id, &zwp_linux_dmabuf_v1_interface, 5));
makeShared<CCZwpLinuxDmabufV1>((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<CWaylandOutput>(new CWaylandOutput(szName, self)));
auto o = outputs.emplace_back(SP<CWaylandOutput>(new CWaylandOutput(szName, self)));
o->self = o;
backend->events.newOutput.emit(SP<IOutput>(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<CWlKeyboard> keyboard_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_) : keyboard(keyboard_), backend(backend_) {
uint32_t Aquamarine::CWaylandBackend::capabilities() {
return AQ_BACKEND_CAPABILITY_POINTER;
}
bool Aquamarine::CWaylandBackend::setCursor(Hyprutils::Memory::CSharedPointer<IBuffer> buffer, const Hyprutils::Math::Vector2D& hotspot) {
// TODO:
return true;
}
void Aquamarine::CWaylandBackend::onReady() {
for (auto& o : outputs) {
o->swapchain = makeShared<CSwapchain>(backend->allocator);
if (!o->swapchain) {
backend->log(AQ_LOG_ERROR, std::format("Output {} failed: swapchain creation failed", o->name));
continue;
}
}
}
Aquamarine::CWaylandKeyboard::CWaylandKeyboard(SP<CCWlKeyboard> keyboard_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> 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<CWlKeyboard> 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<CWlPointer> pointer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_) : pointer(pointer_), backend(backend_) {
Aquamarine::CWaylandPointer::CWaylandPointer(SP<CCWlPointer> pointer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> 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<CWlPointer> 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<CWlPointer> 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<CWlPointer> 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<CWaylandKeyboard>(makeShared<CWlKeyboard>(waylandState.seat->sendGetKeyboard()), self));
auto k = keyboards.emplace_back(makeShared<CWaylandKeyboard>(makeShared<CCWlKeyboard>(waylandState.seat->sendGetKeyboard()), self));
backend->events.newKeyboard.emit(SP<IKeyboard>(k));
} else if (!HAS_KEYBOARD && !keyboards.empty())
keyboards.clear();
if (HAS_POINTER && pointers.empty()) {
auto p = pointers.emplace_back(makeShared<CWaylandPointer>(makeShared<CWlPointer>(waylandState.seat->sendGetPointer()), self));
auto p = pointers.emplace_back(makeShared<CWaylandPointer>(makeShared<CCWlPointer>(waylandState.seat->sendGetPointer()), self));
backend->events.newPointer.emit(SP<IPointer>(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<CZwpLinuxDmabufFeedbackV1>(waylandState.dmabuf->sendGetDefaultFeedback());
waylandState.dmabufFeedback = makeShared<CCZwpLinuxDmabufFeedbackV1>(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<CWaylandBackend> backend_) : name(name_), backend(backend_) {
errno = 0;
Aquamarine::CWaylandOutput::CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_) : backend(backend_) {
name = name_;
waylandState.surface = makeShared<CWlSurface>(backend->waylandState.compositor->sendCreateSurface());
waylandState.surface = makeShared<CCWlSurface>(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<CXdgSurface>(backend->waylandState.xdg->sendGetXdgSurface(waylandState.surface->resource()));
waylandState.xdgSurface = makeShared<CCXdgSurface>(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<CXdgToplevel>(waylandState.xdgSurface->sendGetToplevel());
waylandState.xdgToplevel = makeShared<CCXdgToplevel>(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<CSwapchain>(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<CWlRegion>(backend->waylandState.compositor->sendCreateRegion());
auto inputRegion = makeShared<CCWlRegion>(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<IBackendImplementation> Aquamarine::CWaylandOutput::getBackend() {
return SP<IBackendImplementation>(backend.lock());
}
SP<CWaylandBuffer> Aquamarine::CWaylandOutput::wlBufferFromBuffer(SP<IBuffer> 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<CWlCallback>(waylandState.surface->sendFrame());
waylandState.frameCallback->setDone([this](CWlCallback* r, uint32_t ms) {
waylandState.frameCallback = makeShared<CCWlCallback>(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<IBuffer> 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<IBuffer> buffer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_) : buffer(buffer_), backend(backend_) {
auto params = makeShared<CZwpLinuxBufferParamsV1>(backend->waylandState.dmabuf->sendCreateParams());
auto params = makeShared<CCZwpLinuxBufferParamsV1>(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<IBuffer> 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<CWlBuffer>(params->sendCreateImmed(attrs.size.x, attrs.size.y, attrs.format, (zwpLinuxBufferParamsV1Flags)0));
waylandState.buffer = makeShared<CCWlBuffer>(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();
}

24
src/output/Output.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <aquamarine/output/Output.hpp>
using namespace Aquamarine;
Hyprutils::Memory::CSharedPointer<SOutputMode> 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<IBuffer> buffer, const Hyprutils::Math::Vector2D& hotspot) {
return false;
}
void Aquamarine::IOutput::scheduleFrame() {
;
}

View File

@ -2,6 +2,7 @@
#include <aquamarine/output/Output.hpp>
#include <aquamarine/input/Input.hpp>
#include <iostream>
#include <wayland-server.h>
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>(Aquamarine::SOutputMode{.pixelSize = event.size});
output->state->drmFormat = DRM_FORMAT_XRGB8888;
output->commit();