1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
* Copyright (C) 2017-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#include "EGLFence.h"
#include "EGLUtils.h"
#include "utils/log.h"
using namespace KODI::UTILS::EGL;
CEGLFence::CEGLFence(EGLDisplay display)
: m_display(display),
m_eglCreateSyncKHR(
CEGLUtils::GetRequiredProcAddress<PFNEGLCREATESYNCKHRPROC>("eglCreateSyncKHR")),
m_eglDestroySyncKHR(
CEGLUtils::GetRequiredProcAddress<PFNEGLDESTROYSYNCKHRPROC>("eglDestroySyncKHR")),
m_eglGetSyncAttribKHR(
CEGLUtils::GetRequiredProcAddress<PFNEGLGETSYNCATTRIBKHRPROC>("eglGetSyncAttribKHR"))
{
#if defined(EGL_ANDROID_native_fence_sync) && defined(EGL_KHR_fence_sync)
m_eglDupNativeFenceFDANDROID =
CEGLUtils::GetRequiredProcAddress<PFNEGLDUPNATIVEFENCEFDANDROIDPROC>(
"eglDupNativeFenceFDANDROID");
m_eglClientWaitSyncKHR =
CEGLUtils::GetRequiredProcAddress<PFNEGLCLIENTWAITSYNCKHRPROC>("eglClientWaitSyncKHR");
m_eglWaitSyncKHR = CEGLUtils::GetRequiredProcAddress<PFNEGLWAITSYNCKHRPROC>("eglWaitSyncKHR");
#endif
}
void CEGLFence::CreateFence()
{
m_fence = m_eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, nullptr);
if (m_fence == EGL_NO_SYNC_KHR)
{
CEGLUtils::Log(LOGERROR, "failed to create egl sync fence");
throw std::runtime_error("failed to create egl sync fence");
}
}
void CEGLFence::DestroyFence()
{
if (m_fence == EGL_NO_SYNC_KHR)
{
return;
}
if (m_eglDestroySyncKHR(m_display, m_fence) != EGL_TRUE)
{
CEGLUtils::Log(LOGERROR, "failed to destroy egl sync fence");
}
m_fence = EGL_NO_SYNC_KHR;
}
bool CEGLFence::IsSignaled()
{
// fence has been destroyed so return true immediately so buffer can be used
if (m_fence == EGL_NO_SYNC_KHR)
{
return true;
}
EGLint status = EGL_UNSIGNALED_KHR;
if (m_eglGetSyncAttribKHR(m_display, m_fence, EGL_SYNC_STATUS_KHR, &status) != EGL_TRUE)
{
CEGLUtils::Log(LOGERROR, "failed to query egl sync fence");
return false;
}
if (status == EGL_SIGNALED_KHR)
{
return true;
}
return false;
}
#if defined(EGL_ANDROID_native_fence_sync) && defined(EGL_KHR_fence_sync)
EGLSyncKHR CEGLFence::CreateFence(int fd)
{
CEGLAttributes<1> attributeList;
attributeList.Add({{EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd}});
EGLSyncKHR fence =
m_eglCreateSyncKHR(m_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attributeList.Get());
if (fence == EGL_NO_SYNC_KHR)
{
CEGLUtils::Log(LOGERROR, "failed to create EGL sync object");
return nullptr;
}
return fence;
}
void CEGLFence::CreateGPUFence()
{
m_gpuFence = CreateFence(EGL_NO_NATIVE_FENCE_FD_ANDROID);
}
void CEGLFence::CreateKMSFence(int fd)
{
m_kmsFence = CreateFence(fd);
}
EGLint CEGLFence::FlushFence()
{
EGLint fd = m_eglDupNativeFenceFDANDROID(m_display, m_gpuFence);
if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
CEGLUtils::Log(LOGERROR, "failed to duplicate EGL fence fd");
m_eglDestroySyncKHR(m_display, m_gpuFence);
return fd;
}
void CEGLFence::WaitSyncGPU()
{
if (!m_kmsFence)
return;
if (m_eglWaitSyncKHR(m_display, m_kmsFence, 0) != EGL_TRUE)
CEGLUtils::Log(LOGERROR, "failed to create EGL sync point");
}
void CEGLFence::WaitSyncCPU()
{
if (!m_kmsFence)
return;
if (m_eglClientWaitSyncKHR(m_display, m_kmsFence, 0, EGL_FOREVER_KHR) != EGL_FALSE)
m_eglDestroySyncKHR(m_display, m_kmsFence);
}
#endif
|