diff options
| author | UjinT34 <41110182+UjinT34@users.noreply.github.com> | 2025-02-02 22:25:29 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-02 20:25:29 +0100 |
| commit | 31431a92714ab7f53c25d2ececb26c5b7264b7e3 (patch) | |
| tree | b5a9ff0e57493b503b09eb9f0e70e96075d70add /src/protocols | |
| parent | 70d94fec134c4b91916812901310e7765acf8405 (diff) | |
protocols: Support content-type-v1 proto (#9226)
Diffstat (limited to 'src/protocols')
| -rw-r--r-- | src/protocols/ContentType.cpp | 95 | ||||
| -rw-r--r-- | src/protocols/ContentType.hpp | 59 | ||||
| -rw-r--r-- | src/protocols/core/Compositor.hpp | 2 | ||||
| -rw-r--r-- | src/protocols/types/ContentType.cpp | 37 | ||||
| -rw-r--r-- | src/protocols/types/ContentType.hpp | 18 |
5 files changed, 211 insertions, 0 deletions
diff --git a/src/protocols/ContentType.cpp b/src/protocols/ContentType.cpp new file mode 100644 index 00000000..0dd5481a --- /dev/null +++ b/src/protocols/ContentType.cpp @@ -0,0 +1,95 @@ +#include "ContentType.hpp" +#include "content-type-v1.hpp" +#include "protocols/types/ContentType.hpp" + +CContentTypeManager::CContentTypeManager(SP<CWpContentTypeManagerV1> resource) : m_resource(resource) { + if UNLIKELY (!good()) + return; + + resource->setDestroy([](CWpContentTypeManagerV1* r) {}); + resource->setOnDestroy([this](CWpContentTypeManagerV1* r) { PROTO::contentType->destroyResource(this); }); + + resource->setGetSurfaceContentType([](CWpContentTypeManagerV1* r, uint32_t id, wl_resource* surface) { + LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface); + auto SURF = CWLSurfaceResource::fromResource(surface); + + if (!SURF) { + LOGM(ERR, "No surface for resource {}", (uintptr_t)surface); + r->error(-1, "Invalid surface (2)"); + return; + } + + if (SURF->colorManagement) { + r->error(WP_CONTENT_TYPE_MANAGER_V1_ERROR_ALREADY_CONSTRUCTED, "CT manager already exists"); + return; + } + + const auto RESOURCE = PROTO::contentType->m_vContentTypes.emplace_back(makeShared<CContentType>(makeShared<CWpContentTypeV1>(r->client(), r->version(), id))); + if UNLIKELY (!RESOURCE->good()) { + r->noMemory(); + PROTO::contentType->m_vContentTypes.pop_back(); + return; + } + + RESOURCE->self = RESOURCE; + + SURF->contentType = RESOURCE; + }); +} + +bool CContentTypeManager::good() { + return m_resource->resource(); +} + +CContentType::CContentType(WP<CWLSurfaceResource> surface) { + destroy = surface->events.destroy.registerListener([this](std::any d) { PROTO::contentType->destroyResource(this); }); +} + +CContentType::CContentType(SP<CWpContentTypeV1> resource) : m_resource(resource) { + if UNLIKELY (!good()) + return; + + m_pClient = resource->client(); + + resource->setDestroy([this](CWpContentTypeV1* r) { PROTO::contentType->destroyResource(this); }); + resource->setOnDestroy([this](CWpContentTypeV1* r) { PROTO::contentType->destroyResource(this); }); + + resource->setSetContentType([this](CWpContentTypeV1* r, wpContentTypeV1Type type) { value = NContentType::fromWP(type); }); +} + +bool CContentType::good() { + return m_resource && m_resource->resource(); +} + +wl_client* CContentType::client() { + return m_pClient; +} + +CContentTypeProtocol::CContentTypeProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CContentTypeProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(makeShared<CContentTypeManager>(makeShared<CWpContentTypeManagerV1>(client, ver, id))); + + if UNLIKELY (!RESOURCE->good()) { + wl_client_post_no_memory(client); + m_vManagers.pop_back(); + return; + } +} + +SP<CContentType> CContentTypeProtocol::getContentType(WP<CWLSurfaceResource> surface) { + if (surface->contentType.valid()) + return surface->contentType.lock(); + + return m_vContentTypes.emplace_back(makeShared<CContentType>(surface)); +} + +void CContentTypeProtocol::destroyResource(CContentTypeManager* resource) { + std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; }); +} + +void CContentTypeProtocol::destroyResource(CContentType* resource) { + std::erase_if(m_vContentTypes, [&](const auto& other) { return other.get() == resource; }); +} diff --git a/src/protocols/ContentType.hpp b/src/protocols/ContentType.hpp new file mode 100644 index 00000000..c0359bf1 --- /dev/null +++ b/src/protocols/ContentType.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "WaylandProtocol.hpp" +#include "core/Compositor.hpp" +#include "content-type-v1.hpp" +#include "protocols/types/ContentType.hpp" + +class CContentTypeManager { + public: + CContentTypeManager(SP<CWpContentTypeManagerV1> resource); + + bool good(); + + private: + SP<CWpContentTypeManagerV1> m_resource; +}; + +class CContentType { + public: + CContentType(SP<CWpContentTypeV1> resource); + CContentType(WP<CWLSurfaceResource> surface); + + bool good(); + wl_client* client(); + NContentType::eContentType value = NContentType::CONTENT_TYPE_NONE; + + WP<CContentType> self; + + private: + SP<CWpContentTypeV1> m_resource; + wl_client* m_pClient = nullptr; + + CHyprSignalListener destroy; + + friend class CContentTypeProtocol; +}; + +class CContentTypeProtocol : public IWaylandProtocol { + public: + CContentTypeProtocol(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); + + SP<CContentType> getContentType(WP<CWLSurfaceResource> surface); + + private: + void destroyResource(CContentTypeManager* resource); + void destroyResource(CContentType* resource); + + std::vector<SP<CContentTypeManager>> m_vManagers; + std::vector<SP<CContentType>> m_vContentTypes; + + friend class CContentTypeManager; + friend class CContentType; +}; + +namespace PROTO { + inline UP<CContentTypeProtocol> contentType; +}; diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index 20614813..aaaf9b1a 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -26,6 +26,7 @@ class CViewportResource; class CDRMSyncobjSurfaceResource; class CColorManagementSurface; class CFrogColorManagementSurface; +class CContentType; class CWLCallbackResource { public: @@ -123,6 +124,7 @@ class CWLSurfaceResource { WP<CViewportResource> viewportResource; WP<CDRMSyncobjSurfaceResource> syncobj; // may not be present WP<CColorManagementSurface> colorManagement; + WP<CContentType> contentType; void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data); CRegion accumulateCurrentBufferDamage(); diff --git a/src/protocols/types/ContentType.cpp b/src/protocols/types/ContentType.cpp new file mode 100644 index 00000000..c0a3d30f --- /dev/null +++ b/src/protocols/types/ContentType.cpp @@ -0,0 +1,37 @@ +#include "ContentType.hpp" +#include <drm_mode.h> +#include <stdexcept> +#include <format> + +namespace NContentType { + static std::unordered_map<std::string, eContentType> const table = { + {"none", CONTENT_TYPE_NONE}, {"photo", CONTENT_TYPE_PHOTO}, {"video", CONTENT_TYPE_VIDEO}, {"game", CONTENT_TYPE_GAME}}; + + eContentType fromString(const std::string name) { + auto it = table.find(name); + if (it != table.end()) + return it->second; + else + throw std::invalid_argument(std::format("Unknown content type {}", name)); + } + + eContentType fromWP(wpContentTypeV1Type contentType) { + switch (contentType) { + case WP_CONTENT_TYPE_V1_TYPE_NONE: return CONTENT_TYPE_NONE; + case WP_CONTENT_TYPE_V1_TYPE_PHOTO: return CONTENT_TYPE_PHOTO; + case WP_CONTENT_TYPE_V1_TYPE_VIDEO: return CONTENT_TYPE_VIDEO; + case WP_CONTENT_TYPE_V1_TYPE_GAME: return CONTENT_TYPE_GAME; + default: return CONTENT_TYPE_NONE; + } + } + + uint16_t toDRM(eContentType contentType) { + switch (contentType) { + case CONTENT_TYPE_NONE: return DRM_MODE_CONTENT_TYPE_GRAPHICS; + case CONTENT_TYPE_PHOTO: return DRM_MODE_CONTENT_TYPE_PHOTO; + case CONTENT_TYPE_VIDEO: return DRM_MODE_CONTENT_TYPE_CINEMA; + case CONTENT_TYPE_GAME: return DRM_MODE_CONTENT_TYPE_GAME; + default: return DRM_MODE_CONTENT_TYPE_NO_DATA; + } + } +}
\ No newline at end of file diff --git a/src/protocols/types/ContentType.hpp b/src/protocols/types/ContentType.hpp new file mode 100644 index 00000000..66fcbca7 --- /dev/null +++ b/src/protocols/types/ContentType.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "content-type-v1.hpp" +#include <cstdint> + +namespace NContentType { + + enum eContentType : uint8_t { + CONTENT_TYPE_NONE = 0, + CONTENT_TYPE_PHOTO = 1, + CONTENT_TYPE_VIDEO = 2, + CONTENT_TYPE_GAME = 3, + }; + + eContentType fromString(const std::string name); + eContentType fromWP(wpContentTypeV1Type contentType); + uint16_t toDRM(eContentType contentType); +}
\ No newline at end of file |
