backends/drm: Import gbm bos using dmabuf
It appears that importing gbm_bo's using eglCreateImageKHR() doesn't work on nvidia. Another issue is that Platform::createDmaBufTexture() uses gbm_bo_create(). The nvidia driver doesn't like that, it's preferred to use gbm_bo_create_with_modifiers(). In order to address those issues, this change refactors how gbm_bo objects are imported and how gbm_bo's are allocated for dmabuf textures, so the same code can be reused in EglGbmBackend::textureForOutput() and Platform::createDmaBufTexture().
This commit is contained in:
parent
db2af5500f
commit
d7ec51998b
19 changed files with 204 additions and 150 deletions
|
@ -24,7 +24,6 @@ set(DRM_SOURCES
|
|||
egl_gbm_layer.cpp
|
||||
drm_buffer_gbm.cpp
|
||||
gbm_surface.cpp
|
||||
gbm_dmabuf.cpp
|
||||
placeholderinputeventfilter.cpp
|
||||
virtual_egl_gbm_layer.cpp
|
||||
drm_lease_egl_gbm_layer.cpp
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "backends/libinput/libinputbackend.h"
|
||||
#include "composite.h"
|
||||
#include "cursor.h"
|
||||
#include "drm_fourcc.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "drm_object_connector.h"
|
||||
#include "drm_object_crtc.h"
|
||||
|
@ -623,11 +624,37 @@ void DrmBackend::removeVirtualOutput(Output *output)
|
|||
primaryGpu()->removeVirtualOutput(virtualOutput);
|
||||
}
|
||||
|
||||
DmaBufTexture *DrmBackend::createDmaBufTexture(const QSize &size)
|
||||
QSharedPointer<DmaBufTexture> DrmBackend::createDmaBufTexture(const QSize &size)
|
||||
{
|
||||
if (const auto eglBackend = dynamic_cast<EglGbmBackend *>(m_renderBackend); eglBackend && primaryGpu()->gbmDevice()) {
|
||||
eglBackend->makeCurrent();
|
||||
return GbmDmaBuf::createBuffer(size, primaryGpu()->gbmDevice());
|
||||
|
||||
const int format = GBM_FORMAT_ARGB8888;
|
||||
const uint64_t modifiers[] = {DRM_FORMAT_MOD_LINEAR};
|
||||
|
||||
gbm_bo *bo = gbm_bo_create_with_modifiers(primaryGpu()->gbmDevice(),
|
||||
size.width(),
|
||||
size.height(),
|
||||
format,
|
||||
modifiers, 1);
|
||||
|
||||
// If modifiers are not supported fallback to gbm_bo_create().
|
||||
if (!bo && errno == ENOSYS) {
|
||||
bo = gbm_bo_create(primaryGpu()->gbmDevice(),
|
||||
size.width(),
|
||||
size.height(),
|
||||
format,
|
||||
GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
|
||||
}
|
||||
if (!bo) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The bo will be kept around until the last fd is closed.
|
||||
const DmaBufAttributes attributes = dmaBufAttributesForBo(bo);
|
||||
gbm_bo_destroy(bo);
|
||||
|
||||
return QSharedPointer<DmaBufTexture>::create(eglBackend->importDmaBufAsTexture(attributes), attributes);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
InputBackend *createInputBackend() override;
|
||||
QPainterBackend *createQPainterBackend() override;
|
||||
OpenGLBackend *createOpenGLBackend() override;
|
||||
DmaBufTexture *createDmaBufTexture(const QSize &size) override;
|
||||
QSharedPointer<DmaBufTexture> createDmaBufTexture(const QSize &size) override;
|
||||
Session *session() const override;
|
||||
bool initialize() override;
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "config-kwin.h"
|
||||
#include "drm_gpu.h"
|
||||
#include "kwineglimagetexture.h"
|
||||
#include "kwineglutils_p.h"
|
||||
#include "logging.h"
|
||||
#include "wayland/clientbuffer.h"
|
||||
|
@ -129,17 +128,6 @@ bool GbmBuffer::map(uint32_t flags)
|
|||
return m_data;
|
||||
}
|
||||
|
||||
QSharedPointer<GLTexture> GbmBuffer::createTexture(EGLDisplay eglDisplay) const
|
||||
{
|
||||
EGLImageKHR image = eglCreateImageKHR(eglDisplay, nullptr, EGL_NATIVE_PIXMAP_KHR, m_bo, nullptr);
|
||||
if (image != EGL_NO_IMAGE_KHR) {
|
||||
return QSharedPointer<EGLImageTexture>::create(eglDisplay, image, GL_RGBA8, QSize(gbm_bo_get_width(m_bo), gbm_bo_get_height(m_bo)));
|
||||
} else {
|
||||
qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GbmBuffer::createFds()
|
||||
{
|
||||
#if HAVE_GBM_BO_GET_FD_FOR_PLANE
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "egl_dmabuf.h"
|
||||
#include "egl_gbm_cursor_layer.h"
|
||||
#include "egl_gbm_layer.h"
|
||||
#include "gbm_dmabuf.h"
|
||||
#include "gbm_surface.h"
|
||||
#include "kwineglutils_p.h"
|
||||
#include "linux_dmabuf.h"
|
||||
|
@ -267,4 +268,99 @@ bool operator==(const GbmFormat &lhs, const GbmFormat &rhs)
|
|||
return lhs.drmFormat == rhs.drmFormat;
|
||||
}
|
||||
|
||||
EGLImageKHR EglGbmBackend::importDmaBufAsImage(const DmaBufAttributes &dmabuf)
|
||||
{
|
||||
QVector<EGLint> attribs;
|
||||
attribs.reserve(6 + dmabuf.planeCount * 10 + 1);
|
||||
|
||||
attribs
|
||||
<< EGL_WIDTH << dmabuf.width
|
||||
<< EGL_HEIGHT << dmabuf.height
|
||||
<< EGL_LINUX_DRM_FOURCC_EXT << dmabuf.format;
|
||||
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE0_FD_EXT << dmabuf.fd[0]
|
||||
<< EGL_DMA_BUF_PLANE0_OFFSET_EXT << dmabuf.offset[0]
|
||||
<< EGL_DMA_BUF_PLANE0_PITCH_EXT << dmabuf.pitch[0];
|
||||
if (dmabuf.modifier[0] != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[0] & 0xffffffff)
|
||||
<< EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[0] >> 32);
|
||||
}
|
||||
|
||||
if (dmabuf.planeCount > 1) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE1_FD_EXT << dmabuf.fd[1]
|
||||
<< EGL_DMA_BUF_PLANE1_OFFSET_EXT << dmabuf.offset[1]
|
||||
<< EGL_DMA_BUF_PLANE1_PITCH_EXT << dmabuf.pitch[1];
|
||||
if (dmabuf.modifier[1] != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[1] & 0xffffffff)
|
||||
<< EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[1] >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (dmabuf.planeCount > 2) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE2_FD_EXT << dmabuf.fd[2]
|
||||
<< EGL_DMA_BUF_PLANE2_OFFSET_EXT << dmabuf.offset[2]
|
||||
<< EGL_DMA_BUF_PLANE2_PITCH_EXT << dmabuf.pitch[2];
|
||||
if (dmabuf.modifier[2] != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[2] & 0xffffffff)
|
||||
<< EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[2] >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (dmabuf.planeCount > 3) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE3_FD_EXT << dmabuf.fd[3]
|
||||
<< EGL_DMA_BUF_PLANE3_OFFSET_EXT << dmabuf.offset[3]
|
||||
<< EGL_DMA_BUF_PLANE3_PITCH_EXT << dmabuf.pitch[3];
|
||||
if (dmabuf.modifier[3] != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs
|
||||
<< EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[3] & 0xffffffff)
|
||||
<< EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[3] >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
attribs << EGL_NONE;
|
||||
|
||||
return eglCreateImageKHR(eglDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
|
||||
}
|
||||
|
||||
EGLImageKHR EglGbmBackend::importDmaBufAsImage(gbm_bo *bo)
|
||||
{
|
||||
const DmaBufAttributes dmabuf = dmaBufAttributesForBo(bo);
|
||||
EGLImage image = importDmaBufAsImage(dmabuf);
|
||||
|
||||
for (int i = 0; i < dmabuf.planeCount; ++i) {
|
||||
close(dmabuf.fd[i]);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
QSharedPointer<GLTexture> EglGbmBackend::importDmaBufAsTexture(const DmaBufAttributes &attributes)
|
||||
{
|
||||
EGLImageKHR image = importDmaBufAsImage(attributes);
|
||||
if (image != EGL_NO_IMAGE_KHR) {
|
||||
return QSharedPointer<EGLImageTexture>::create(eglDisplay(), image, GL_RGBA8, QSize(attributes.width, attributes.height));
|
||||
} else {
|
||||
qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<GLTexture> EglGbmBackend::importDmaBufAsTexture(gbm_bo *bo)
|
||||
{
|
||||
EGLImageKHR image = importDmaBufAsImage(bo);
|
||||
if (image != EGL_NO_IMAGE_KHR) {
|
||||
return QSharedPointer<EGLImageTexture>::create(eglDisplay(), image, GL_RGBA8, QSize(gbm_bo_get_width(bo), gbm_bo_get_height(bo)));
|
||||
} else {
|
||||
qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -27,6 +27,8 @@ class SurfaceInterface;
|
|||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
struct DmaBufAttributes;
|
||||
class Output;
|
||||
class DrmAbstractOutput;
|
||||
class DrmBuffer;
|
||||
|
@ -79,6 +81,11 @@ public:
|
|||
std::optional<GbmFormat> gbmFormatForDrmFormat(uint32_t format) const;
|
||||
DrmGpu *gpu() const;
|
||||
|
||||
EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &attributes);
|
||||
EGLImageKHR importDmaBufAsImage(gbm_bo *bo);
|
||||
QSharedPointer<GLTexture> importDmaBufAsTexture(const DmaBufAttributes &attributes);
|
||||
QSharedPointer<GLTexture> importDmaBufAsTexture(gbm_bo *bo);
|
||||
|
||||
private:
|
||||
bool initializeEgl();
|
||||
bool initBufferConfigs();
|
||||
|
|
|
@ -79,7 +79,7 @@ bool EglGbmLayer::checkTestBuffer()
|
|||
QSharedPointer<GLTexture> EglGbmLayer::texture() const
|
||||
{
|
||||
if (m_scanoutBuffer) {
|
||||
return static_cast<GbmBuffer *>(m_scanoutBuffer->buffer())->createTexture(m_surface.eglBackend()->eglDisplay());
|
||||
return m_surface.eglBackend()->importDmaBufAsTexture(static_cast<GbmBuffer *>(m_scanoutBuffer->buffer())->bo());
|
||||
} else {
|
||||
return m_surface.texture();
|
||||
}
|
||||
|
|
|
@ -336,7 +336,7 @@ QSharedPointer<GLTexture> EglGbmLayerSurface::texture() const
|
|||
qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!";
|
||||
return nullptr;
|
||||
}
|
||||
return m_currentBuffer->createTexture(m_eglBackend->eglDisplay());
|
||||
return m_eglBackend->importDmaBufAsTexture(m_currentBuffer->bo());
|
||||
}
|
||||
|
||||
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats, uint32_t additionalFlags)
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "gbm_dmabuf.h"
|
||||
#include "drm_fourcc.h"
|
||||
#include "kwineglimagetexture.h"
|
||||
#include "main.h"
|
||||
#include "platform.h"
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
GbmDmaBuf::GbmDmaBuf(GLTexture *texture, gbm_bo *bo, int fd)
|
||||
: DmaBufTexture(texture)
|
||||
, m_bo(bo)
|
||||
, m_fd(fd)
|
||||
{
|
||||
}
|
||||
|
||||
GbmDmaBuf::~GbmDmaBuf()
|
||||
{
|
||||
m_texture.reset(nullptr);
|
||||
|
||||
close(m_fd);
|
||||
gbm_bo_destroy(m_bo);
|
||||
}
|
||||
|
||||
int GbmDmaBuf::fd() const
|
||||
{
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
quint32 GbmDmaBuf::stride() const
|
||||
{
|
||||
return gbm_bo_get_stride(m_bo);
|
||||
}
|
||||
|
||||
GbmDmaBuf *GbmDmaBuf::createBuffer(const QSize &size, gbm_device *device)
|
||||
{
|
||||
if (!device) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto bo = gbm_bo_create(device, size.width(), size.height(), GBM_FORMAT_ARGB8888, GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
|
||||
|
||||
if (!bo) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int fd = gbm_bo_get_fd(bo);
|
||||
if (fd < 0) {
|
||||
gbm_bo_destroy(bo);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EGLint importAttributes[] = {
|
||||
EGL_WIDTH, EGLint(gbm_bo_get_width(bo)),
|
||||
EGL_HEIGHT, EGLint(gbm_bo_get_height(bo)),
|
||||
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, fd,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGLint(gbm_bo_get_offset(bo, 0)),
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, EGLint(gbm_bo_get_stride(bo)),
|
||||
EGL_NONE};
|
||||
|
||||
EGLDisplay display = kwinApp()->platform()->sceneEglDisplay();
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
return nullptr;
|
||||
}
|
||||
EGLImageKHR destinationImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, importAttributes);
|
||||
if (destinationImage == EGL_NO_IMAGE_KHR) {
|
||||
close(fd);
|
||||
gbm_bo_destroy(bo);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new GbmDmaBuf(new KWin::EGLImageTexture(display, destinationImage, GL_RGBA8, size), bo, fd);
|
||||
}
|
||||
|
||||
}
|
|
@ -7,27 +7,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "dmabuftexture.h"
|
||||
#include <QSize>
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
#include <gbm.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class GbmDmaBuf : public DmaBufTexture
|
||||
inline DmaBufAttributes dmaBufAttributesForBo(gbm_bo *bo)
|
||||
{
|
||||
public:
|
||||
~GbmDmaBuf();
|
||||
DmaBufAttributes attributes;
|
||||
attributes.planeCount = gbm_bo_get_plane_count(bo);
|
||||
attributes.width = gbm_bo_get_width(bo);
|
||||
attributes.height = gbm_bo_get_height(bo);
|
||||
attributes.format = gbm_bo_get_format(bo);
|
||||
|
||||
int fd() const override;
|
||||
quint32 stride() const override;
|
||||
|
||||
static GbmDmaBuf *createBuffer(const QSize &size, gbm_device *device);
|
||||
|
||||
private:
|
||||
GbmDmaBuf(GLTexture *texture, gbm_bo *bo, int fd);
|
||||
struct gbm_bo *const m_bo;
|
||||
const int m_fd;
|
||||
};
|
||||
for (int i = 0; i < attributes.planeCount; ++i) {
|
||||
attributes.fd[i] = gbm_bo_get_fd_for_plane(bo, i);
|
||||
attributes.offset[i] = gbm_bo_get_offset(bo, i);
|
||||
attributes.pitch[i] = gbm_bo_get_stride_for_plane(bo, i);
|
||||
attributes.modifier[i] = gbm_bo_get_modifier(bo);
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "egl_dmabuf.h"
|
||||
#include "egl_gbm_backend.h"
|
||||
#include "gbm_surface.h"
|
||||
#include "kwineglimagetexture.h"
|
||||
#include "kwineglutils_p.h"
|
||||
#include "logging.h"
|
||||
#include "shadowbuffer.h"
|
||||
|
@ -139,7 +138,7 @@ QSharedPointer<GLTexture> VirtualEglGbmLayer::texture() const
|
|||
qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!";
|
||||
return nullptr;
|
||||
}
|
||||
return m_currentBuffer->createTexture(m_eglBackend->eglDisplay());
|
||||
return m_eglBackend->importDmaBufAsTexture(m_currentBuffer->bo());
|
||||
}
|
||||
|
||||
bool VirtualEglGbmLayer::scanout(SurfaceItem *surfaceItem)
|
||||
|
|
|
@ -6,7 +6,7 @@ set(WAYLAND_BACKEND_SOURCES
|
|||
)
|
||||
|
||||
if (HAVE_WAYLAND_EGL)
|
||||
set(WAYLAND_BACKEND_SOURCES egl_wayland_backend.cpp ${WAYLAND_BACKEND_SOURCES} ../drm/gbm_dmabuf.cpp)
|
||||
set(WAYLAND_BACKEND_SOURCES egl_wayland_backend.cpp ${WAYLAND_BACKEND_SOURCES})
|
||||
endif()
|
||||
|
||||
add_library(KWinWaylandWaylandBackend MODULE ${WAYLAND_BACKEND_SOURCES})
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "wayland_backend.h"
|
||||
|
||||
#if HAVE_WAYLAND_EGL
|
||||
#include "../drm/gbm_dmabuf.h"
|
||||
#include "egl_wayland_backend.h"
|
||||
#include <gbm.h>
|
||||
#endif
|
||||
|
@ -991,15 +990,6 @@ void WaylandBackend::addConfiguredOutput(WaylandOutput *output)
|
|||
}
|
||||
}
|
||||
|
||||
DmaBufTexture *WaylandBackend::createDmaBufTexture(const QSize &size)
|
||||
{
|
||||
#if HAVE_WAYLAND_EGL
|
||||
return GbmDmaBuf::createBuffer(size, m_gbmDevice);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void WaylandBackend::createDpmsFilter()
|
||||
{
|
||||
if (m_dpmsFilter) {
|
||||
|
|
|
@ -260,7 +260,6 @@ public:
|
|||
InputBackend *createInputBackend() override;
|
||||
OpenGLBackend *createOpenGLBackend() override;
|
||||
QPainterBackend *createQPainterBackend() override;
|
||||
DmaBufTexture *createDmaBufTexture(const QSize &size) override;
|
||||
|
||||
void flush();
|
||||
|
||||
|
|
|
@ -6,19 +6,31 @@
|
|||
|
||||
#include "dmabuftexture.h"
|
||||
|
||||
#include "kwineglimagetexture.h"
|
||||
#include "kwinglutils.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
DmaBufTexture::DmaBufTexture(KWin::GLTexture *texture)
|
||||
DmaBufTexture::DmaBufTexture(QSharedPointer<GLTexture> texture, const DmaBufAttributes &attributes)
|
||||
: m_texture(texture)
|
||||
, m_framebuffer(new KWin::GLFramebuffer(texture))
|
||||
, m_framebuffer(new GLFramebuffer(texture.data()))
|
||||
, m_attributes(attributes)
|
||||
{
|
||||
}
|
||||
|
||||
DmaBufTexture::~DmaBufTexture() = default;
|
||||
DmaBufTexture::~DmaBufTexture()
|
||||
{
|
||||
for (int i = 0; i < m_attributes.planeCount; ++i) {
|
||||
::close(m_attributes.fd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
DmaBufAttributes DmaBufTexture::attributes() const
|
||||
{
|
||||
return m_attributes;
|
||||
}
|
||||
|
||||
KWin::GLTexture *DmaBufTexture::texture() const
|
||||
{
|
||||
|
|
|
@ -6,27 +6,42 @@
|
|||
|
||||
#pragma once
|
||||
#include "kwin_export.h"
|
||||
|
||||
#include <QScopedPointer>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class GLFramebuffer;
|
||||
class GLTexture;
|
||||
|
||||
struct DmaBufAttributes
|
||||
{
|
||||
int planeCount;
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
|
||||
int fd[4];
|
||||
int offset[4];
|
||||
int pitch[4];
|
||||
uint64_t modifier[4];
|
||||
};
|
||||
|
||||
class KWIN_EXPORT DmaBufTexture
|
||||
{
|
||||
public:
|
||||
explicit DmaBufTexture(KWin::GLTexture *texture);
|
||||
explicit DmaBufTexture(QSharedPointer<GLTexture> texture, const DmaBufAttributes &attributes);
|
||||
virtual ~DmaBufTexture();
|
||||
|
||||
virtual quint32 stride() const = 0;
|
||||
virtual int fd() const = 0;
|
||||
KWin::GLTexture *texture() const;
|
||||
KWin::GLFramebuffer *framebuffer() const;
|
||||
DmaBufAttributes attributes() const;
|
||||
GLTexture *texture() const;
|
||||
GLFramebuffer *framebuffer() const;
|
||||
|
||||
protected:
|
||||
QScopedPointer<KWin::GLTexture> m_texture;
|
||||
QScopedPointer<KWin::GLFramebuffer> m_framebuffer;
|
||||
QSharedPointer<GLTexture> m_texture;
|
||||
QScopedPointer<GLFramebuffer> m_framebuffer;
|
||||
DmaBufAttributes m_attributes;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -80,6 +80,12 @@ QPainterBackend *Platform::createQPainterBackend()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
QSharedPointer<DmaBufTexture> Platform::createDmaBufTexture(const QSize &size)
|
||||
{
|
||||
Q_UNUSED(size)
|
||||
return {};
|
||||
}
|
||||
|
||||
Edge *Platform::createScreenEdge(ScreenEdges *edges)
|
||||
{
|
||||
return new Edge(edges);
|
||||
|
|
|
@ -66,11 +66,7 @@ public:
|
|||
virtual InputBackend *createInputBackend();
|
||||
virtual OpenGLBackend *createOpenGLBackend();
|
||||
virtual QPainterBackend *createQPainterBackend();
|
||||
virtual DmaBufTexture *createDmaBufTexture(const QSize &size)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
return nullptr;
|
||||
}
|
||||
virtual QSharedPointer<DmaBufTexture> createDmaBufTexture(const QSize &size);
|
||||
|
||||
/**
|
||||
* Allows the platform to create a platform specific screen edge.
|
||||
|
|
|
@ -142,14 +142,16 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer)
|
|||
spa_data->flags = SPA_DATA_FLAG_READWRITE;
|
||||
|
||||
if (spa_data[0].type != SPA_ID_INVALID && spa_data[0].type & (1 << SPA_DATA_DmaBuf)) {
|
||||
dmabuf.reset(kwinApp()->platform()->createDmaBufTexture(stream->m_resolution));
|
||||
dmabuf = kwinApp()->platform()->createDmaBufTexture(stream->m_resolution);
|
||||
}
|
||||
|
||||
if (dmabuf) {
|
||||
const DmaBufAttributes dmabufAttribs = dmabuf->attributes();
|
||||
|
||||
spa_data->type = SPA_DATA_DmaBuf;
|
||||
spa_data->fd = dmabuf->fd();
|
||||
spa_data->fd = dmabufAttribs.fd[0];
|
||||
spa_data->data = nullptr;
|
||||
spa_data->maxsize = dmabuf->stride() * stream->m_resolution.height();
|
||||
spa_data->maxsize = dmabufAttribs.pitch[0] * stream->m_resolution.height();
|
||||
|
||||
stream->m_dmabufDataForPwBuffer.insert(buffer, dmabuf);
|
||||
#ifdef F_SEAL_SEAL // Disable memfd on systems that don't have it, like BSD < 12
|
||||
|
@ -399,7 +401,7 @@ void ScreenCastStream::recordFrame(const QRegion &damagedRegion)
|
|||
} else {
|
||||
auto &buf = m_dmabufDataForPwBuffer[buffer];
|
||||
|
||||
spa_data->chunk->stride = buf->stride();
|
||||
spa_data->chunk->stride = buf->attributes().pitch[0];
|
||||
spa_data->chunk->size = spa_data->maxsize;
|
||||
|
||||
m_source->render(buf->framebuffer());
|
||||
|
|
Loading…
Reference in a new issue