File: EGLFence.cpp

package info (click to toggle)
kodi 2%3A21.2%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 143,076 kB
  • sloc: cpp: 694,471; xml: 52,618; ansic: 38,300; python: 7,161; sh: 4,289; javascript: 2,325; makefile: 1,791; perl: 969; java: 513; cs: 390; objc: 340
file content (139 lines) | stat: -rw-r--r-- 3,490 bytes parent folder | download | duplicates (2)
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