protocols: Support content-type-v1 proto (#9226)

This commit is contained in:
UjinT34
2025-02-02 22:25:29 +03:00
committed by GitHub
parent 70d94fec13
commit 31431a9271
20 changed files with 386 additions and 94 deletions

View File

@@ -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; });
}

View File

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

View File

@@ -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();

View File

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

View File

@@ -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);
}