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 "system_egl.h" 18 19 class CEGLUtils 20 { 21 public: 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> GetRequiredProcAddress(const char * procname)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 38 private: 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 */ 48 class CEGLAttributesVec 49 { 50 public: 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 */ Add(std::initializer_list<EGLAttribute> const & attributes)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 */ Add(EGLAttribute const & attribute)76 void Add(EGLAttribute const& attribute) 77 { 78 Add({attribute}); 79 } 80 Get()81 EGLint const * Get() const 82 { 83 return m_attributes.data(); 84 } 85 86 private: 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 */ 100 template<std::size_t AttributeCount> 101 class CEGLAttributes 102 { 103 public: 104 struct EGLAttribute 105 { 106 EGLint key; 107 EGLint value; 108 }; 109 CEGLAttributes()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 */ Add(std::initializer_list<EGLAttribute> const & attributes)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 */ Add(EGLAttribute const & attribute)146 void Add(EGLAttribute const& attribute) 147 { 148 Add({attribute}); 149 } 150 Get()151 EGLint const * Get() const 152 { 153 return m_attributes.data(); 154 } 155 Size()156 int Size() const 157 { 158 return m_writePosition; 159 } 160 161 private: 162 std::array<EGLint, AttributeCount * 2 + 1> m_attributes; 163 int m_writePosition{}; 164 }; 165 166 class CEGLContextUtils final 167 { 168 public: 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 GetEGLDisplay()205 EGLDisplay GetEGLDisplay() const 206 { 207 return m_eglDisplay; 208 } GetEGLSurface()209 EGLSurface GetEGLSurface() const 210 { 211 return m_eglSurface; 212 } GetEGLContext()213 EGLContext GetEGLContext() const 214 { 215 return m_eglContext; 216 } GetEGLConfig()217 EGLConfig GetEGLConfig() const 218 { 219 return m_eglConfig; 220 } 221 222 private: 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 }; 233