diff options
author | Vaxry <[email protected]> | 2024-09-30 00:57:51 +0100 |
---|---|---|
committer | Vaxry <[email protected]> | 2024-09-30 00:58:16 +0100 |
commit | 488efab63654a643d76df4997cd932d6fddd8faf (patch) | |
tree | 4e330456e26e6ba5e208424f292fc1d03e89f10b | |
parent | 6649255d54f45a7e2fedd9b4be85fe5d11229c04 (diff) | |
download | Hyprland-488efab63654a643d76df4997cd932d6fddd8faf.tar.gz Hyprland-488efab63654a643d76df4997cd932d6fddd8faf.zip |
single-pixel-buffer: new protocol impl
fixes #6624
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/helpers/Color.hpp | 3 | ||||
-rw-r--r-- | src/managers/ProtocolManager.cpp | 2 | ||||
-rw-r--r-- | src/protocols/SinglePixel.cpp | 125 | ||||
-rw-r--r-- | src/protocols/SinglePixel.hpp | 79 |
5 files changed, 209 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8115d01c..ee9cd2e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false) +protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false) protocolwayland() diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index 8abfe748..32ed39ee 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -8,8 +8,9 @@ class CColor { CColor(float r, float g, float b, float a); CColor(uint64_t); - float r = 0, g = 0, b = 0, a = 1.f; + float r = 0, g = 0, b = 0, a = 1.f; + // AR32 uint32_t getAsHex() const; CColor operator-(const CColor& c2) const { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 6b6d5acf..8bcc857a 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -44,6 +44,7 @@ #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/XDGDialog.hpp" +#include "../protocols/SinglePixel.hpp" #include "../protocols/core/Seat.hpp" #include "../protocols/core/DataDevice.hpp" @@ -152,6 +153,7 @@ CProtocolManager::CProtocolManager() { PROTO::toplevelExport = std::make_unique<CToplevelExportProtocol>(&hyprland_toplevel_export_manager_v1_interface, 2, "ToplevelExport"); PROTO::globalShortcuts = std::make_unique<CGlobalShortcutsProtocol>(&hyprland_global_shortcuts_manager_v1_interface, 1, "GlobalShortcuts"); PROTO::xdgDialog = std::make_unique<CXDGDialogProtocol>(&xdg_dialog_v1_interface, 1, "XDGDialog"); + PROTO::singlePixel = std::make_unique<CSinglePixelProtocol>(&wp_single_pixel_buffer_manager_v1_interface, 1, "SinglePixel"); for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { if (b->type() != Aquamarine::AQ_BACKEND_DRM) diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp new file mode 100644 index 00000000..7dd3748f --- /dev/null +++ b/src/protocols/SinglePixel.cpp @@ -0,0 +1,125 @@ +#include "SinglePixel.hpp" +#include <limits> + +CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col_) { + LOGM(LOG, "New single-pixel buffer with color 0x{:x}", col_.getAsHex()); + + color = col_.getAsHex(); + + g_pHyprRenderer->makeEGLCurrent(); + + opaque = col_.a >= 1.F; + + texture = makeShared<CTexture>(DRM_FORMAT_ARGB8888, (uint8_t*)&color, 4, Vector2D{1, 1}); + + resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id)); + + success = texture->m_iTexID; + + if (!success) + Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); +} + +CSinglePixelBuffer::~CSinglePixelBuffer() { + ; +} + +Aquamarine::eBufferCapability CSinglePixelBuffer::caps() { + return Aquamarine::eBufferCapability::BUFFER_CAPABILITY_DATAPTR; +} + +Aquamarine::eBufferType CSinglePixelBuffer::type() { + return Aquamarine::eBufferType::BUFFER_TYPE_SHM; +} + +bool CSinglePixelBuffer::isSynchronous() { + return true; +} + +void CSinglePixelBuffer::update(const CRegion& damage) { + ; +} + +Aquamarine::SDMABUFAttrs CSinglePixelBuffer::dmabuf() { + return {.success = false}; +} + +std::tuple<uint8_t*, uint32_t, size_t> CSinglePixelBuffer::beginDataPtr(uint32_t flags) { + return {(uint8_t*)&color, DRM_FORMAT_ARGB8888, 4}; +} + +void CSinglePixelBuffer::endDataPtr() { + ; +} + +bool CSinglePixelBuffer::good() { + return resource->good(); +} + +CSinglePixelBufferResource::CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color) { + buffer = makeShared<CSinglePixelBuffer>(id, client, color); + + if (!buffer->good()) + return; + + buffer->resource->buffer = buffer; + + listeners.bufferResourceDestroy = buffer->events.destroy.registerListener([this](std::any d) { + listeners.bufferResourceDestroy.reset(); + PROTO::singlePixel->destroyResource(this); + }); +} + +CSinglePixelBufferResource::~CSinglePixelBufferResource() { + ; +} + +bool CSinglePixelBufferResource::good() { + return buffer->good(); +} + +CSinglePixelBufferManagerResource::CSinglePixelBufferManagerResource(SP<CWpSinglePixelBufferManagerV1> resource_) : resource(resource_) { + if (!good()) + return; + + resource->setDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); + resource->setOnDestroy([this](CWpSinglePixelBufferManagerV1* r) { PROTO::singlePixel->destroyResource(this); }); + + resource->setCreateU32RgbaBuffer([this](CWpSinglePixelBufferManagerV1* res, uint32_t id, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { + CColor color{r / (float)std::numeric_limits<uint32_t>::max(), g / (float)std::numeric_limits<uint32_t>::max(), b / (float)std::numeric_limits<uint32_t>::max(), + a / (float)std::numeric_limits<uint32_t>::max()}; + const auto RESOURCE = PROTO::singlePixel->m_vBuffers.emplace_back(makeShared<CSinglePixelBufferResource>(id, resource->client(), color)); + + if (!RESOURCE->good()) { + res->noMemory(); + PROTO::singlePixel->m_vBuffers.pop_back(); + return; + } + }); +} + +bool CSinglePixelBufferManagerResource::good() { + return resource->resource(); +} + +CSinglePixelProtocol::CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CSinglePixelProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared<CSinglePixelBufferManagerResource>(makeShared<CWpSinglePixelBufferManagerV1>(client, ver, id))); + + if (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +void CSinglePixelProtocol::destroyResource(CSinglePixelBufferManagerResource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == res; }); +} + +void CSinglePixelProtocol::destroyResource(CSinglePixelBufferResource* surf) { + std::erase_if(m_vBuffers, [&](const auto& other) { return other.get() == surf; }); +} diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp new file mode 100644 index 00000000..ab74825c --- /dev/null +++ b/src/protocols/SinglePixel.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include <memory> +#include <vector> +#include <cstdint> +#include "WaylandProtocol.hpp" +#include "single-pixel-buffer-v1.hpp" +#include "types/Buffer.hpp" + +class CSinglePixelBuffer : public IHLBuffer { + public: + CSinglePixelBuffer(uint32_t id, wl_client* client, CColor col); + virtual ~CSinglePixelBuffer(); + + virtual Aquamarine::eBufferCapability caps(); + virtual Aquamarine::eBufferType type(); + virtual bool isSynchronous(); + virtual void update(const CRegion& damage); + virtual Aquamarine::SDMABUFAttrs dmabuf(); + virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags); + virtual void endDataPtr(); + // + bool good(); + bool success = false; + + private: + uint32_t color = 0x00000000; + + struct { + CHyprSignalListener resourceDestroy; + } listeners; +}; + +class CSinglePixelBufferResource { + public: + CSinglePixelBufferResource(uint32_t id, wl_client* client, CColor color); + ~CSinglePixelBufferResource(); + + bool good(); + + private: + SP<CSinglePixelBuffer> buffer; + + struct { + CHyprSignalListener bufferResourceDestroy; + } listeners; +}; + +class CSinglePixelBufferManagerResource { + public: + CSinglePixelBufferManagerResource(SP<CWpSinglePixelBufferManagerV1> resource_); + + bool good(); + + private: + SP<CWpSinglePixelBufferManagerV1> resource; +}; + +class CSinglePixelProtocol : public IWaylandProtocol { + public: + CSinglePixelProtocol(const wl_interface* iface, const int& ver, const std::string& name); + + virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); + + private: + void destroyResource(CSinglePixelBufferManagerResource* resource); + void destroyResource(CSinglePixelBufferResource* resource); + + // + std::vector<SP<CSinglePixelBufferManagerResource>> m_vManagers; + std::vector<SP<CSinglePixelBufferResource>> m_vBuffers; + + friend class CSinglePixelBufferManagerResource; + friend class CSinglePixelBufferResource; +}; + +namespace PROTO { + inline UP<CSinglePixelProtocol> singlePixel; +};
\ No newline at end of file |