9c20df5030
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().
50 lines
1.2 KiB
C++
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
|