25static const int s_version = 4;
28 : QtWaylandServer::zwp_linux_dmabuf_v1(*display, s_version)
36 if (resource->version() < ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) {
38 const uint32_t &
format = it.key();
39 const auto &modifiers = it.value();
40 for (
const uint64_t &modifier : std::as_const(modifiers)) {
41 if (resource->version() >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
42 const uint32_t modifier_lo = modifier & 0xffffffff;
43 const uint32_t modifier_hi = modifier >> 32;
44 send_modifier(resource->handle,
format, modifier_hi, modifier_lo);
45 }
else if (modifier == DRM_FORMAT_MOD_LINEAR || modifier == DRM_FORMAT_MOD_INVALID) {
46 send_format(resource->handle,
format);
62 qCWarning(KWIN_CORE) <<
"requested surface feedback for nonexistant surface!";
66 if (!surfacePrivate->dmabufFeedbackV1) {
74 wl_resource_destroy(resource->handle);
79 wl_resource *paramsResource = wl_resource_create(resource->client(), &zwp_linux_buffer_params_v1_interface, resource->version(), params_id);
80 if (!paramsResource) {
81 wl_resource_post_no_memory(resource->handle);
88 : QtWaylandServer::zwp_linux_buffer_params_v1(resource)
89 , m_integration(integration)
100 wl_resource_destroy(resource->handle);
108 uint32_t modifier_hi,
109 uint32_t modifier_lo)
111 if (Q_UNLIKELY(m_isUsed)) {
112 wl_resource_post_error(resource->handle, error_already_used,
"the params object has already been used to create a wl_buffer");
117 if (Q_UNLIKELY(plane_idx >= 4)) {
118 wl_resource_post_error(resource->handle, error_plane_idx,
"plane index %d is out of bounds", plane_idx);
123 if (Q_UNLIKELY(m_attrs.
fd[plane_idx].isValid())) {
124 wl_resource_post_error(resource->handle, error_plane_set,
"the plane index %d was already set", plane_idx);
129 m_attrs.
offset[plane_idx] = offset;
130 m_attrs.
pitch[plane_idx] = stride;
131 m_attrs.
modifier = (quint64(modifier_hi) << 32) | modifier_lo;
137 if (Q_UNLIKELY(m_isUsed)) {
138 wl_resource_post_error(resource->handle, error_already_used,
"the params object has already been used to create a wl_buffer");
142 if (Q_UNLIKELY(!test(resource, width, height))) {
147 if (Q_UNLIKELY(!renderBackend)) {
148 send_failed(resource->handle);
153 send_failed(resource->handle);
159 m_attrs.
width = width;
165 send_failed(resource->handle);
170 wl_resource *bufferResource = wl_resource_create(resource->client(), &wl_buffer_interface, 1, 0);
171 if (!bufferResource) {
172 wl_resource_post_no_memory(resource->handle);
177 clientBuffer->initialize(bufferResource);
178 send_created(resource->handle, bufferResource);
188 if (Q_UNLIKELY(m_isUsed)) {
189 wl_resource_post_error(resource->handle, error_already_used,
"the params object has already been used to create a wl_buffer");
193 if (Q_UNLIKELY(!test(resource, width, height))) {
198 if (Q_UNLIKELY(!renderBackend)) {
199 wl_resource_post_error(resource->handle, error_invalid_wl_buffer,
"importing the supplied dmabufs failed");
204 wl_resource_post_error(resource->handle, error_invalid_wl_buffer,
"dma-buf flags are not supported");
210 m_attrs.
width = width;
216 wl_resource_post_error(resource->handle, error_invalid_wl_buffer,
"importing the supplied dmabufs failed");
221 wl_resource *bufferResource = wl_resource_create(resource->client(), &wl_buffer_interface, 1, buffer_id);
222 if (!bufferResource) {
223 wl_resource_post_no_memory(resource->handle);
228 clientBuffer->initialize(bufferResource);
231bool LinuxDmaBufParamsV1::test(Resource *resource, uint32_t width, uint32_t height)
234 wl_resource_post_error(resource->handle, error_incomplete,
"no planes have been specified");
239 for (
int i = 0; i < m_attrs.
planeCount; ++i) {
240 if (!m_attrs.
fd[i].isValid()) {
241 wl_resource_post_error(resource->handle, error_incomplete,
"no dmabuf has been added for plane %d", i);
246 if (Q_UNLIKELY(width == 0 || height == 0)) {
247 wl_resource_post_error(resource->handle, error_invalid_dimensions,
"invalid width %d or height %d", width, height);
251 for (
int i = 0; i < m_attrs.
planeCount; ++i) {
253 if (Q_UNLIKELY(uint64_t(m_attrs.
offset[i]) + m_attrs.
pitch[i] > UINT32_MAX)) {
254 wl_resource_post_error(resource->handle, error_out_of_bounds,
"size overflow for plane %d", i);
258 if (Q_UNLIKELY(i == 0 && uint64_t(m_attrs.
offset[i]) + uint64_t(m_attrs.
pitch[i]) * height > UINT32_MAX)) {
259 wl_resource_post_error(resource->handle, error_out_of_bounds,
"size overflow for plane %d", i);
265 const off_t size = lseek(m_attrs.
fd[i].get(), 0, SEEK_END);
270 if (Q_UNLIKELY(m_attrs.
offset[i] >= size)) {
271 wl_resource_post_error(resource->handle, error_out_of_bounds,
"invalid offset %i for plane %d", m_attrs.
offset[i], i);
275 if (Q_UNLIKELY(m_attrs.
offset[i] + m_attrs.
pitch[i] > size)) {
276 wl_resource_post_error(resource->handle, error_out_of_bounds,
"invalid stride %i for plane %d", m_attrs.
pitch[i], i);
282 if (Q_UNLIKELY(i == 0 && m_attrs.
offset[i] + m_attrs.
pitch[i] * height > size)) {
283 wl_resource_post_error(resource->handle, error_out_of_bounds,
"invalid buffer stride of height for plane %d", i);
308 return d->renderBackend;
319 QHash<uint32_t, QList<uint64_t>> set;
320 for (
const auto &tranche : tranches) {
321 set.insert(tranche.formatTable);
323 d->supportedModifiers = set;
324 d->mainDevice = tranches.first().device;
325 d->table = std::make_unique<LinuxDmaBufV1FormatTable>(set);
326 d->defaultFeedback->setTranches(tranches);
330void LinuxDmaBufV1ClientBuffer::buffer_destroy_resource(wl_resource *resource)
333 buffer->m_resource =
nullptr;
338void LinuxDmaBufV1ClientBuffer::buffer_destroy(wl_client *client, wl_resource *resource)
340 wl_resource_destroy(resource);
349 m_attrs = std::move(attrs);
353void LinuxDmaBufV1ClientBuffer::initialize(wl_resource *resource)
355 m_resource = resource;
356 wl_resource_set_implementation(resource, &implementation,
this, buffer_destroy_resource);
359 wl_buffer_send_release(m_resource);
375 return m_hasAlphaChannel;
380 if (wl_resource_instance_of(resource, &wl_buffer_interface, &implementation)) {
395 if (d->m_tranches != tranches) {
396 d->m_tranches = tranches;
397 const auto &map = d->resourceMap();
398 for (
const auto &resource : map) {
410 : m_bufferintegration(bufferintegration)
419 send_main_device(resource->handle, bytes);
421 QByteArray targetDevice;
422 targetDevice.append(
reinterpret_cast<const char *
>(&tranche.device),
sizeof(dev_t));
424 for (
auto it = tranche.formatTable.begin(); it != tranche.formatTable.end(); it++) {
425 const uint32_t
format = it.key();
426 for (
const auto &mod : std::as_const(it.value())) {
428 indices.append(
reinterpret_cast<const char *
>(&index), 2);
431 send_tranche_target_device(resource->handle, targetDevice);
432 send_tranche_formats(resource->handle, indices);
433 send_tranche_flags(resource->handle,
static_cast<uint32_t
>(tranche.flags));
434 send_tranche_done(resource->handle);
436 for (
const auto &tranche : std::as_const(
m_tranches)) {
437 sendTranche(tranche);
441 if (
this != defaultFeedbackPrivate) {
442 for (
const auto &tranche : std::as_const(defaultFeedbackPrivate->m_tranches)) {
443 sendTranche(tranche);
446 send_done(resource->handle);
456 wl_resource_destroy(resource->handle);
468 QList<linux_dmabuf_feedback_v1_table_entry> data;
469 for (
auto it = supportedModifiers.begin(); it != supportedModifiers.end(); it++) {
470 const uint32_t
format = it.key();
471 for (
const uint64_t &mod : *it) {
473 data.append({
format, 0, mod});
480 qCCritical(KWIN_CORE) <<
"Failed to create RamFile for LinuxDmaBufV1FormatTable";
487#include "moc_linuxdmabufv1clientbuffer_p.cpp"
489#include "moc_linuxdmabufv1clientbuffer.cpp"
Class holding the Wayland server display loop.
static bool alphaChannelFromDrmFormat(uint32_t format)
LinuxDmaBufParamsV1(LinuxDmaBufV1ClientBufferIntegration *integration, ::wl_resource *resource)
void zwp_linux_buffer_params_v1_destroy(Resource *resource) override
void zwp_linux_buffer_params_v1_add(Resource *resource, int32_t fd, uint32_t plane_idx, uint32_t offset, uint32_t stride, uint32_t modifier_hi, uint32_t modifier_lo) override
void zwp_linux_buffer_params_v1_create_immed(Resource *resource, uint32_t buffer_id, int32_t width, int32_t height, uint32_t format, uint32_t flags) override
void zwp_linux_buffer_params_v1_destroy_resource(Resource *resource) override
void zwp_linux_buffer_params_v1_create(Resource *resource, int32_t width, int32_t height, uint32_t format, uint32_t flags) override
void setSupportedFormatsWithModifiers(const QList< LinuxDmaBufV1Feedback::Tranche > &tranches)
LinuxDmaBufV1ClientBufferIntegration(Display *display)
RenderBackend * renderBackend() const
void setRenderBackend(RenderBackend *renderBackend)
~LinuxDmaBufV1ClientBufferIntegration() override
LinuxDmaBufV1ClientBufferIntegration * q
void zwp_linux_dmabuf_v1_destroy(Resource *resource) override
std::unique_ptr< LinuxDmaBufV1FormatTable > table
void zwp_linux_dmabuf_v1_bind_resource(Resource *resource) override
void zwp_linux_dmabuf_v1_get_default_feedback(Resource *resource, uint32_t id) override
QHash< uint32_t, QList< uint64_t > > supportedModifiers
std::unique_ptr< LinuxDmaBufV1Feedback > defaultFeedback
void zwp_linux_dmabuf_v1_get_surface_feedback(Resource *resource, uint32_t id, wl_resource *surface) override
LinuxDmaBufV1ClientBufferIntegrationPrivate(LinuxDmaBufV1ClientBufferIntegration *q, Display *display)
void zwp_linux_dmabuf_v1_create_params(Resource *resource, uint32_t params_id) override
void setTranches(const QList< Tranche > &tranches)
~LinuxDmaBufV1Feedback() override
void send(Resource *resource)
LinuxDmaBufV1FeedbackPrivate(LinuxDmaBufV1ClientBufferIntegrationPrivate *bufferintegration)
static LinuxDmaBufV1FeedbackPrivate * get(LinuxDmaBufV1Feedback *q)
QList< LinuxDmaBufV1Feedback::Tranche > m_tranches
void zwp_linux_dmabuf_feedback_v1_bind_resource(Resource *resource) override
LinuxDmaBufV1ClientBufferIntegrationPrivate * m_bufferintegration
void zwp_linux_dmabuf_feedback_v1_destroy(Resource *resource) override
Creates a file in memory.
@ SealWrite
Seal the file descriptor for writing.
virtual bool testImportBuffer(GraphicsBuffer *buffer)
static SurfaceInterface * get(wl_resource *native)
static SurfaceInterfacePrivate * get(SurfaceInterface *surface)
bool operator==(const LinuxDmaBufV1Feedback::Tranche &t1, const LinuxDmaBufV1Feedback::Tranche &t2)
std::array< uint32_t, 4 > offset
std::array< uint32_t, 4 > pitch
std::array< FileDescriptor, 4 > fd
static LinuxDmaBufV1ClientBuffer * get(wl_resource *resource)
const DmaBufAttributes * dmabufAttributes() const override
LinuxDmaBufV1ClientBuffer(DmaBufAttributes &&attrs)
bool hasAlphaChannel() const override
QSize size() const override
QHash< uint32_t, QList< uint64_t > > formatTable