2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2017-10-05 16:58:57 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org>
|
2017-10-05 16:58:57 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2017-10-05 16:58:57 +00:00
|
|
|
#include "gbm_surface.h"
|
|
|
|
|
|
|
|
#include <gbm.h>
|
2021-05-25 17:25:55 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
2021-05-25 22:05:17 +00:00
|
|
|
#include "abstract_egl_drm_backend.h"
|
2021-05-25 17:25:55 +00:00
|
|
|
#include "drm_gpu.h"
|
|
|
|
#include "logging.h"
|
2021-08-01 21:26:49 +00:00
|
|
|
#include "kwineglutils_p.h"
|
2017-10-05 16:58:57 +00:00
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2021-05-25 17:25:55 +00:00
|
|
|
GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, uint32_t flags)
|
|
|
|
: m_surface(gbm_surface_create(gpu->gbmDevice(), size.width(), size.height(), format, flags))
|
|
|
|
, m_gpu(gpu)
|
2021-05-25 22:05:17 +00:00
|
|
|
, m_size(size)
|
2017-10-05 16:58:57 +00:00
|
|
|
{
|
2021-05-25 17:25:55 +00:00
|
|
|
if (!m_surface) {
|
|
|
|
qCCritical(KWIN_DRM) << "Could not create gbm surface!" << strerror(errno);
|
|
|
|
return;
|
|
|
|
}
|
2021-07-31 13:32:50 +00:00
|
|
|
m_eglSurface = eglCreatePlatformWindowSurfaceEXT(m_gpu->eglDisplay(), m_gpu->eglBackend()->config(), m_surface, nullptr);
|
|
|
|
if (m_eglSurface == EGL_NO_SURFACE) {
|
|
|
|
qCCritical(KWIN_DRM) << "Creating EGL surface failed!" << getEglErrorString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GbmSurface::GbmSurface(DrmGpu *gpu, const QSize &size, uint32_t format, QVector<uint64_t> modifiers)
|
|
|
|
: m_surface(gbm_surface_create_with_modifiers(gpu->gbmDevice(), size.width(), size.height(), format, modifiers.isEmpty() ? nullptr : modifiers.constData(), modifiers.count()))
|
|
|
|
, m_gpu(gpu)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
if (!m_surface) {
|
|
|
|
qCCritical(KWIN_DRM) << "Could not create gbm surface!" << strerror(errno);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_eglSurface = eglCreatePlatformWindowSurfaceEXT(m_gpu->eglDisplay(), m_gpu->eglBackend()->config(), m_surface, nullptr);
|
2021-05-25 17:25:55 +00:00
|
|
|
if (m_eglSurface == EGL_NO_SURFACE) {
|
2021-08-01 21:26:49 +00:00
|
|
|
qCCritical(KWIN_DRM) << "Creating EGL surface failed!" << getEglErrorString();
|
2021-05-25 17:25:55 +00:00
|
|
|
}
|
2017-10-05 16:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GbmSurface::~GbmSurface()
|
|
|
|
{
|
2021-05-25 17:25:55 +00:00
|
|
|
auto buffers = m_lockedBuffers;
|
|
|
|
for (auto buffer : buffers) {
|
|
|
|
buffer->releaseBuffer();
|
|
|
|
}
|
|
|
|
if (m_eglSurface != EGL_NO_SURFACE) {
|
|
|
|
eglDestroySurface(m_gpu->eglDisplay(), m_eglSurface);
|
|
|
|
}
|
2017-10-05 16:58:57 +00:00
|
|
|
if (m_surface) {
|
|
|
|
gbm_surface_destroy(m_surface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 17:25:55 +00:00
|
|
|
QSharedPointer<DrmGbmBuffer> GbmSurface::swapBuffersForDrm()
|
2017-10-05 16:58:57 +00:00
|
|
|
{
|
2021-05-25 17:25:55 +00:00
|
|
|
auto error = eglSwapBuffers(m_gpu->eglDisplay(), m_eglSurface);
|
|
|
|
if (error != EGL_TRUE) {
|
2021-08-01 21:26:49 +00:00
|
|
|
qCCritical(KWIN_DRM) << "an error occurred while swapping buffers" << getEglErrorString();
|
2021-05-25 17:25:55 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto bo = gbm_surface_lock_front_buffer(m_surface);
|
|
|
|
if (!bo) {
|
2017-10-05 16:58:57 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2021-05-25 17:25:55 +00:00
|
|
|
auto buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, this, bo);
|
|
|
|
m_currentBuffer = buffer;
|
|
|
|
m_lockedBuffers << m_currentBuffer.get();
|
|
|
|
if (!buffer->bufferId()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
m_currentDrmBuffer = buffer;
|
|
|
|
return buffer;
|
2017-10-05 16:58:57 +00:00
|
|
|
}
|
|
|
|
|
2021-05-25 17:25:55 +00:00
|
|
|
QSharedPointer<GbmBuffer> GbmSurface::swapBuffers()
|
2017-10-05 16:58:57 +00:00
|
|
|
{
|
2021-05-25 17:25:55 +00:00
|
|
|
auto error = eglSwapBuffers(m_gpu->eglDisplay(), m_eglSurface);
|
|
|
|
if (error != EGL_TRUE) {
|
2021-08-01 21:26:49 +00:00
|
|
|
qCCritical(KWIN_DRM) << "an error occurred while swapping buffers" << getEglErrorString();
|
2021-05-25 17:25:55 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto bo = gbm_surface_lock_front_buffer(m_surface);
|
|
|
|
if (!bo) {
|
|
|
|
return nullptr;
|
2017-10-05 16:58:57 +00:00
|
|
|
}
|
2021-05-25 17:25:55 +00:00
|
|
|
m_currentBuffer = QSharedPointer<GbmBuffer>::create(this, bo);
|
|
|
|
m_lockedBuffers << m_currentBuffer.get();
|
|
|
|
return m_currentBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GbmSurface::releaseBuffer(GbmBuffer *buffer)
|
|
|
|
{
|
|
|
|
gbm_surface_release_buffer(m_surface, buffer->getBo());
|
|
|
|
m_lockedBuffers.removeOne(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
QSharedPointer<GbmBuffer> GbmSurface::currentBuffer() const
|
|
|
|
{
|
|
|
|
return m_currentBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSharedPointer<DrmGbmBuffer> GbmSurface::currentDrmBuffer() const
|
|
|
|
{
|
|
|
|
return m_currentDrmBuffer;
|
2017-10-05 16:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|