kwin/src/wayland/drmclientbuffer.cpp
Vlad Zahorodnii 0d2879c62d Split BufferInterface
Currently, the BufferInterface encapsulates all the kinds of client
buffers. This has become a somewhat annoying issue as we want to
reference the shm pool if a shm buffer is destroyed, or have custom
buffer readiness logic for linux dma-buf client buffers.

Implementing all of that with the current abstractions will be
challenging as there's no good separation between different client
buffer types.

This change splits the BufferInterface class in three sub-classes -
DrmClientBuffer, LinuxDmaBufV1ClientBuffer, and ShmClientBuffer.

In addition to that, this change fixes the broken buffer ref'ing api.
2021-07-22 11:41:06 +03:00

96 lines
2.7 KiB
C++

/*
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "drmclientbuffer.h"
#include "clientbuffer_p.h"
#include "display.h"
#include <EGL/egl.h>
#include <QtGui/qopengl.h>
#ifndef EGL_WL_bind_wayland_display
#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB
#endif
namespace KWaylandServer
{
typedef GLboolean(*eglQueryWaylandBufferWL_func)(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
static eglQueryWaylandBufferWL_func eglQueryWaylandBufferWL = nullptr;
class DrmClientBufferPrivate : public ClientBufferPrivate
{
public:
int textureFormat = 0;
int width = 0;
int height = 0;
int yInverted = 0;
bool hasAlphaChannel = false;
};
DrmClientBuffer::DrmClientBuffer(wl_resource *resource, DrmClientBufferIntegration *integration)
: ClientBuffer(resource, *new DrmClientBufferPrivate)
{
Q_D(DrmClientBuffer);
EGLDisplay eglDisplay = integration->display()->eglDisplay();
eglQueryWaylandBufferWL(eglDisplay, resource, EGL_TEXTURE_FORMAT, &d->textureFormat);
eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WIDTH, &d->width);
eglQueryWaylandBufferWL(eglDisplay, resource, EGL_HEIGHT, &d->height);
bool ok = eglQueryWaylandBufferWL(eglDisplay, resource, EGL_WAYLAND_Y_INVERTED_WL, &d->yInverted);
if (!ok) {
// If EGL_WAYLAND_Y_INVERTED_WL is unsupported, we must assume that the buffer is inverted.
d->yInverted = true;
}
}
int DrmClientBuffer::textureFormat() const
{
Q_D(const DrmClientBuffer);
return d->textureFormat;
}
QSize DrmClientBuffer::size() const
{
Q_D(const DrmClientBuffer);
return QSize(d->width, d->height);
}
bool DrmClientBuffer::hasAlphaChannel() const
{
Q_D(const DrmClientBuffer);
return d->textureFormat == EGL_TEXTURE_RGBA;
}
ClientBuffer::Origin DrmClientBuffer::origin() const
{
Q_D(const DrmClientBuffer);
return d->yInverted ? Origin::TopLeft : Origin::BottomLeft;
}
DrmClientBufferIntegration::DrmClientBufferIntegration(Display *display)
: ClientBufferIntegration(display)
{
}
ClientBuffer *DrmClientBufferIntegration::createBuffer(::wl_resource *resource)
{
EGLDisplay eglDisplay = display()->eglDisplay();
static bool resolved = false;
if (!resolved && eglDisplay != EGL_NO_DISPLAY) {
eglQueryWaylandBufferWL = (eglQueryWaylandBufferWL_func)eglGetProcAddress("eglQueryWaylandBufferWL");
resolved = true;
}
EGLint format;
if (eglQueryWaylandBufferWL(eglDisplay, resource, EGL_TEXTURE_FORMAT, &format)) {
return new DrmClientBuffer(resource, this);
}
return nullptr;
}
} // namespace KWaylandServer