summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/EGLUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/EGLUtils.h')
-rw-r--r--xbmc/utils/EGLUtils.h232
1 files changed, 232 insertions, 0 deletions
diff --git a/xbmc/utils/EGLUtils.h b/xbmc/utils/EGLUtils.h
new file mode 100644
index 0000000..ad3b04d
--- /dev/null
+++ b/xbmc/utils/EGLUtils.h
@@ -0,0 +1,232 @@
1/*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#include <array>
12#include <set>
13#include <stdexcept>
14#include <string>
15#include <vector>
16
17#include <EGL/egl.h>
18
19class CEGLUtils
20{
21public:
22 static std::set<std::string> GetClientExtensions();
23 static std::set<std::string> GetExtensions(EGLDisplay eglDisplay);
24 static bool HasExtension(EGLDisplay eglDisplay, std::string const & name);
25 static bool HasClientExtension(std::string const& name);
26 static void Log(int logLevel, std::string const& what);
27 template<typename T>
28 static T GetRequiredProcAddress(const char * procname)
29 {
30 T p = reinterpret_cast<T>(eglGetProcAddress(procname));
31 if (!p)
32 {
33 throw std::runtime_error(std::string("Could not get EGL function \"") + procname + "\" - maybe a required extension is not supported?");
34 }
35 return p;
36 }
37
38private:
39 CEGLUtils();
40};
41
42/**
43 * Convenience wrapper for heap-allocated EGL attribute arrays
44 *
45 * The wrapper makes sure that the key/value pairs are always written in actual
46 * pairs and that the array is always terminated with EGL_NONE.
47 */
48class CEGLAttributesVec
49{
50public:
51 struct EGLAttribute
52 {
53 EGLint key;
54 EGLint value;
55 };
56
57 /**
58 * Add multiple attributes
59 *
60 * The array is automatically terminated with EGL_NONE
61 */
62 void Add(std::initializer_list<EGLAttribute> const& attributes)
63 {
64 for (auto const& attribute : attributes)
65 {
66 m_attributes.insert(m_attributes.begin(), attribute.value);
67 m_attributes.insert(m_attributes.begin(), attribute.key);
68 }
69 }
70
71 /**
72 * Add one attribute
73 *
74 * The array is automatically terminated with EGL_NONE
75 */
76 void Add(EGLAttribute const& attribute)
77 {
78 Add({attribute});
79 }
80
81 EGLint const * Get() const
82 {
83 return m_attributes.data();
84 }
85
86private:
87 std::vector<EGLint> m_attributes{EGL_NONE};
88};
89
90/**
91 * Convenience wrapper for stack-allocated EGL attribute arrays
92 *
93 * The wrapper makes sure that the key/value pairs are always written in actual
94 * pairs, that the array is always terminated with EGL_NONE, and that the bounds
95 * of the array are not exceeded (checked on runtime).
96 *
97 * \tparam AttributeCount maximum number of attributes that can be added.
98 * Determines the size of the storage array.
99 */
100template<std::size_t AttributeCount>
101class CEGLAttributes
102{
103public:
104 struct EGLAttribute
105 {
106 EGLint key;
107 EGLint value;
108 };
109
110 CEGLAttributes()
111 {
112 m_attributes[0] = EGL_NONE;
113 }
114
115 /**
116 * Add multiple attributes
117 *
118 * The array is automatically terminated with EGL_NONE
119 *
120 * \throws std::out_of_range if more than AttributeCount attributes are added
121 * in total
122 */
123 void Add(std::initializer_list<EGLAttribute> const& attributes)
124 {
125 if (m_writePosition + attributes.size() * 2 + 1 > m_attributes.size())
126 {
127 throw std::out_of_range("CEGLAttributes::Add");
128 }
129
130 for (auto const& attribute : attributes)
131 {
132 m_attributes[m_writePosition++] = attribute.key;
133 m_attributes[m_writePosition++] = attribute.value;
134 }
135 m_attributes[m_writePosition] = EGL_NONE;
136 }
137
138 /**
139 * Add one attribute
140 *
141 * The array is automatically terminated with EGL_NONE
142 *
143 * \throws std::out_of_range if more than AttributeCount attributes are added
144 * in total
145 */
146 void Add(EGLAttribute const& attribute)
147 {
148 Add({attribute});
149 }
150
151 EGLint const * Get() const
152 {
153 return m_attributes.data();
154 }
155
156 int Size() const
157 {
158 return m_writePosition;
159 }
160
161private:
162 std::array<EGLint, AttributeCount * 2 + 1> m_attributes;
163 int m_writePosition{};
164};
165
166class CEGLContextUtils final
167{
168public:
169 CEGLContextUtils() = default;
170 /**
171 * \param platform platform as constant from an extension building on EGL_EXT_platform_base
172 */
173 CEGLContextUtils(EGLenum platform, std::string const& platformExtension);
174 ~CEGLContextUtils();
175
176 bool CreateDisplay(EGLNativeDisplayType nativeDisplay);
177 /**
178 * Create EGLDisplay with EGL_EXT_platform_base
179 *
180 * Falls back to \ref CreateDisplay (with nativeDisplayLegacy) on failure.
181 * The native displays to use with the platform-based and the legacy approach
182 * may be defined to have different types and/or semantics, so this function takes
183 * both as separate parameters.
184 *
185 * \param nativeDisplay native display to use with eglGetPlatformDisplayEXT
186 * \param nativeDisplayLegacy native display to use with eglGetDisplay
187 */
188 bool CreatePlatformDisplay(void* nativeDisplay, EGLNativeDisplayType nativeDisplayLegacy);
189
190 void SurfaceAttrib(EGLint attribute, EGLint value);
191 bool CreateSurface(EGLNativeWindowType nativeWindow, EGLint HDRcolorSpace = EGL_NONE);
192 bool CreatePlatformSurface(void* nativeWindow, EGLNativeWindowType nativeWindowLegacy);
193 bool InitializeDisplay(EGLint renderingApi);
194 bool ChooseConfig(EGLint renderableType, EGLint visualId = 0, bool hdr = false);
195 bool CreateContext(CEGLAttributesVec contextAttribs);
196 bool BindContext();
197 void Destroy();
198 void DestroySurface();
199 void DestroyContext();
200 bool SetVSync(bool enable);
201 bool TrySwapBuffers();
202 bool IsPlatformSupported() const;
203 EGLint GetConfigAttrib(EGLint attribute) const;
204
205 EGLDisplay GetEGLDisplay() const
206 {
207 return m_eglDisplay;
208 }
209 EGLSurface GetEGLSurface() const
210 {
211 return m_eglSurface;
212 }
213 EGLContext GetEGLContext() const
214 {
215 return m_eglContext;
216 }
217 EGLConfig GetEGLConfig() const
218 {
219 return m_eglConfig;
220 }
221
222private:
223 void SurfaceAttrib();
224
225 EGLenum m_platform{EGL_NONE};
226 bool m_platformSupported{false};
227
228 EGLDisplay m_eglDisplay{EGL_NO_DISPLAY};
229 EGLSurface m_eglSurface{EGL_NO_SURFACE};
230 EGLContext m_eglContext{EGL_NO_CONTEXT};
231 EGLConfig m_eglConfig{}, m_eglHDRConfig{};
232};