kwin/screencast/eglnativefence.cpp
Vlad Zahorodnii 9c20df5030 screencast: Use fences to avoid stalling the graphics pipeline
Currently, we use glFinish() to ensure that stream consumers don't see
corrupted or rather incomplete buffers. This is a serious issue because
glFinish() not only prevents the gpu from processing new GL commands,
but it also blocks the compositor.

This change addresses the blocking issue by using native fences. With
the proposed change, after finishing recording a frame, a fence is
inserted in the command stream. When the native fence is signaled, the
pending pipewire buffer will be enqueued.

If the EGL_ANDROID_native_fence_sync extension is not supported, we'll
fall back to using glFinish().
2020-10-19 14:23:06 +00:00

50 lines
1.2 KiB
C++

/*
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "eglnativefence.h"
#include <unistd.h>
namespace KWin
{
#ifndef EGL_ANDROID_native_fence_sync
#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
#endif // EGL_ANDROID_native_fence_sync
EGLNativeFence::EGLNativeFence(EGLDisplay display)
: m_display(display)
{
m_sync = eglCreateSyncKHR(m_display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
if (m_sync != EGL_NO_SYNC_KHR) {
// The native fence will get a valid sync file fd only after a flush.
glFlush();
m_fileDescriptor = eglDupNativeFenceFDANDROID(m_display, m_sync);
}
}
EGLNativeFence::~EGLNativeFence()
{
if (m_fileDescriptor != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
close(m_fileDescriptor);
}
if (m_sync != EGL_NO_SYNC_KHR) {
eglDestroySyncKHR(m_display, m_sync);
}
}
bool EGLNativeFence::isValid() const
{
return m_sync != EGL_NO_SYNC_KHR && m_fileDescriptor != EGL_NO_NATIVE_FENCE_FD_ANDROID;
}
int EGLNativeFence::fileDescriptor() const
{
return m_fileDescriptor;
}
} // namespace KWin