aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-09-30 00:57:51 +0100
committerVaxry <[email protected]>2024-09-30 00:58:16 +0100
commit488efab63654a643d76df4997cd932d6fddd8faf (patch)
tree4e330456e26e6ba5e208424f292fc1d03e89f10b
parent6649255d54f45a7e2fedd9b4be85fe5d11229c04 (diff)
downloadHyprland-488efab63654a643d76df4997cd932d6fddd8faf.tar.gz
Hyprland-488efab63654a643d76df4997cd932d6fddd8faf.zip
single-pixel-buffer: new protocol impl
fixes #6624
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/helpers/Color.hpp3
-rw-r--r--src/managers/ProtocolManager.cpp2
-rw-r--r--src/protocols/SinglePixel.cpp125
-rw-r--r--src/protocols/SinglePixel.hpp79
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