20#include <drm_fourcc.h>
30 , m_eglBackend(eglBackend)
39 if (doesGbmSwapchainFit(m_gbmSwapchain.get())) {
40 m_oldGbmSwapchain.reset();
41 m_oldDamageJournal.
clear();
43 if (doesGbmSwapchainFit(m_oldGbmSwapchain.get())) {
44 m_gbmSwapchain = m_oldGbmSwapchain;
45 m_damageJournal = m_oldDamageJournal;
47 if (
const auto swapchain = createGbmSwapchain()) {
48 m_oldGbmSwapchain = m_gbmSwapchain;
49 m_oldDamageJournal = m_damageJournal;
50 m_gbmSwapchain = swapchain;
62 auto slot = m_gbmSwapchain->acquire();
68 m_scanoutSurface.clear();
69 if (m_scanoutBuffer) {
70 m_scanoutBuffer->unref();
71 m_scanoutBuffer =
nullptr;
75 m_query = std::make_unique<GLRenderTimeQuery>();
90 m_currentDamage = damagedRegion;
91 m_damageJournal.
add(damagedRegion);
92 m_gbmSwapchain->release(m_currentSlot);
98 return m_currentDamage;
101std::shared_ptr<EglSwapchain> VirtualEglGbmLayer::createGbmSwapchain()
const
103 static bool modifiersEnvSet =
false;
104 static const bool modifiersEnv = qEnvironmentVariableIntValue(
"KWIN_DRM_USE_MODIFIERS", &modifiersEnvSet) != 0;
105 const bool allowModifiers = !modifiersEnvSet || modifiersEnv;
107 const auto tranches = m_eglBackend->
tranches();
108 for (
const auto &tranche : tranches) {
109 for (
auto it = tranche.formatTable.constBegin(); it != tranche.formatTable.constEnd(); it++) {
111 const auto format = it.key();
112 const auto modifiers = it.value();
114 if (allowModifiers && !modifiers.isEmpty()) {
120 static const QList<uint64_t> implicitModifier{DRM_FORMAT_MOD_INVALID};
126 qCWarning(KWIN_DRM) <<
"couldn't create a gbm swapchain for a virtual output!";
130bool VirtualEglGbmLayer::doesGbmSwapchainFit(EglSwapchain *swapchain)
const
132 return swapchain && swapchain->size() == m_output->
modeSize();
137 if (m_scanoutSurface) {
139 }
else if (m_currentSlot) {
140 return m_currentSlot->texture();
148 static const bool directScanoutDisabled = qEnvironmentVariableIntValue(
"KWIN_DRM_NO_DIRECT_SCANOUT", &valid) == 1 && valid;
149 if (directScanoutDisabled) {
154 if (!item || !item->
surface()) {
158 if (!buffer || !buffer->dmabufAttributes() || buffer->size() != m_output->
modeSize()) {
162 if (m_scanoutBuffer) {
163 m_scanoutBuffer->unref();
165 m_scanoutBuffer = buffer;
171 m_scanoutSurface = item->
surface();
178 m_gbmSwapchain.reset();
179 m_oldGbmSwapchain.reset();
180 m_currentSlot.reset();
181 if (m_scanoutBuffer) {
182 m_scanoutBuffer->unref();
183 m_scanoutBuffer =
nullptr;
190 return m_query->result();
bool makeCurrent() override
QList< LinuxDmaBufV1Feedback::Tranche > tranches() const
std::shared_ptr< GLTexture > importDmaBufAsTexture(const DmaBufAttributes &attributes) const
EglContext * contextObject()
void add(const QRegion ®ion)
QRegion accumulate(int bufferAge, const QRegion &fallback=QRegion()) const
GraphicsBufferAllocator * graphicsBufferAllocator() const
bool makeCurrent(EGLSurface surface=EGL_NO_SURFACE) const
OpenGL Backend using Egl on a GBM surface.
static std::shared_ptr< EglSwapchain > create(GraphicsBufferAllocator *allocator, EglContext *context, const QSize &size, uint32_t format, const QList< uint64_t > &modifiers)
GraphicsBuffer * buffer() const
QRegion mapFromBuffer(const QRegion ®ion) const
SurfaceInterface * surface() const
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
void releaseBuffers() override
QRegion currentDamage() const override
~VirtualEglGbmLayer() override
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
std::shared_ptr< GLTexture > texture() const override
std::chrono::nanoseconds queryRenderTime() const override
bool scanout(SurfaceItem *surfaceItem) override
VirtualEglGbmLayer(EglGbmBackend *eglBackend, DrmVirtualOutput *output)
KWIN_EXPORT QRect infiniteRegion()
RenderTarget renderTarget