summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/EGLUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/EGLUtils.cpp')
-rw-r--r--xbmc/utils/EGLUtils.cpp615
1 files changed, 615 insertions, 0 deletions
diff --git a/xbmc/utils/EGLUtils.cpp b/xbmc/utils/EGLUtils.cpp
new file mode 100644
index 0000000..01df4ba
--- /dev/null
+++ b/xbmc/utils/EGLUtils.cpp
@@ -0,0 +1,615 @@
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#include "EGLUtils.h"
10
11#include "ServiceBroker.h"
12#include "StringUtils.h"
13#include "guilib/IDirtyRegionSolver.h"
14#include "log.h"
15#include "settings/AdvancedSettings.h"
16#include "settings/SettingsComponent.h"
17
18#include <map>
19
20#include <EGL/eglext.h>
21
22namespace
23{
24//! @todo remove when Raspberry Pi updates their EGL headers
25#ifndef EGL_NO_CONFIG_KHR
26#define EGL_NO_CONFIG_KHR static_cast<EGLConfig>(0)
27#endif
28#ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG
29#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
30#endif
31#ifndef EGL_CONTEXT_PRIORITY_HIGH_IMG
32#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
33#endif
34#ifndef EGL_CONTEXT_PRIORITY_MEDIUM_IMG
35#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
36#endif
37
38#define X(VAL) std::make_pair(VAL, #VAL)
39std::map<EGLint, const char*> eglAttributes =
40{
41 // please keep attributes in accordance to:
42 // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetConfigAttrib.xhtml
43 X(EGL_ALPHA_SIZE),
44 X(EGL_ALPHA_MASK_SIZE),
45 X(EGL_BIND_TO_TEXTURE_RGB),
46 X(EGL_BIND_TO_TEXTURE_RGBA),
47 X(EGL_BLUE_SIZE),
48 X(EGL_BUFFER_SIZE),
49 X(EGL_COLOR_BUFFER_TYPE),
50 X(EGL_CONFIG_CAVEAT),
51 X(EGL_CONFIG_ID),
52 X(EGL_CONFORMANT),
53 X(EGL_DEPTH_SIZE),
54 X(EGL_GREEN_SIZE),
55 X(EGL_LEVEL),
56 X(EGL_LUMINANCE_SIZE),
57 X(EGL_MAX_PBUFFER_WIDTH),
58 X(EGL_MAX_PBUFFER_HEIGHT),
59 X(EGL_MAX_PBUFFER_PIXELS),
60 X(EGL_MAX_SWAP_INTERVAL),
61 X(EGL_MIN_SWAP_INTERVAL),
62 X(EGL_NATIVE_RENDERABLE),
63 X(EGL_NATIVE_VISUAL_ID),
64 X(EGL_NATIVE_VISUAL_TYPE),
65 X(EGL_RED_SIZE),
66 X(EGL_RENDERABLE_TYPE),
67 X(EGL_SAMPLE_BUFFERS),
68 X(EGL_SAMPLES),
69 X(EGL_STENCIL_SIZE),
70 X(EGL_SURFACE_TYPE),
71 X(EGL_TRANSPARENT_TYPE),
72 X(EGL_TRANSPARENT_RED_VALUE),
73 X(EGL_TRANSPARENT_GREEN_VALUE),
74 X(EGL_TRANSPARENT_BLUE_VALUE)
75};
76
77std::map<EGLenum, const char*> eglErrors =
78{
79 // please keep errors in accordance to:
80 // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetError.xhtml
81 X(EGL_SUCCESS),
82 X(EGL_NOT_INITIALIZED),
83 X(EGL_BAD_ACCESS),
84 X(EGL_BAD_ALLOC),
85 X(EGL_BAD_ATTRIBUTE),
86 X(EGL_BAD_CONFIG),
87 X(EGL_BAD_CONTEXT),
88 X(EGL_BAD_CURRENT_SURFACE),
89 X(EGL_BAD_DISPLAY),
90 X(EGL_BAD_MATCH),
91 X(EGL_BAD_NATIVE_PIXMAP),
92 X(EGL_BAD_NATIVE_WINDOW),
93 X(EGL_BAD_PARAMETER),
94 X(EGL_BAD_SURFACE),
95 X(EGL_CONTEXT_LOST),
96};
97
98std::map<EGLint, const char*> eglErrorType =
99{
100//! @todo remove when Raspberry Pi updates their EGL headers
101#if !defined(TARGET_RASPBERRY_PI)
102 X(EGL_DEBUG_MSG_CRITICAL_KHR),
103 X(EGL_DEBUG_MSG_ERROR_KHR),
104 X(EGL_DEBUG_MSG_WARN_KHR),
105 X(EGL_DEBUG_MSG_INFO_KHR),
106#endif
107};
108#undef X
109
110} // namespace
111
112//! @todo remove when Raspberry Pi updates their EGL headers
113#if !defined(TARGET_RASPBERRY_PI)
114void EglErrorCallback(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message)
115{
116 std::string errorStr;
117 std::string typeStr;
118
119 auto eglError = eglErrors.find(error);
120 if (eglError != eglErrors.end())
121 {
122 errorStr = eglError->second;
123 }
124
125 auto eglType = eglErrorType.find(messageType);
126 if (eglType != eglErrorType.end())
127 {
128 typeStr = eglType->second;
129 }
130
131 CLog::Log(LOGDEBUG, "EGL Debugging:\nError: {}\nCommand: {}\nType: {}\nMessage: {}", errorStr, command, typeStr, message);
132}
133#endif
134
135std::set<std::string> CEGLUtils::GetClientExtensions()
136{
137 const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
138 if (!extensions)
139 {
140 return {};
141 }
142 std::set<std::string> result;
143 StringUtils::SplitTo(std::inserter(result, result.begin()), extensions, " ");
144 return result;
145}
146
147std::set<std::string> CEGLUtils::GetExtensions(EGLDisplay eglDisplay)
148{
149 const char* extensions = eglQueryString(eglDisplay, EGL_EXTENSIONS);
150 if (!extensions)
151 {
152 throw std::runtime_error("Could not query EGL for extensions");
153 }
154 std::set<std::string> result;
155 StringUtils::SplitTo(std::inserter(result, result.begin()), extensions, " ");
156 return result;
157}
158
159bool CEGLUtils::HasExtension(EGLDisplay eglDisplay, const std::string& name)
160{
161 auto exts = GetExtensions(eglDisplay);
162 return (exts.find(name) != exts.end());
163}
164
165bool CEGLUtils::HasClientExtension(const std::string& name)
166{
167 auto exts = GetClientExtensions();
168 return (exts.find(name) != exts.end());
169}
170
171void CEGLUtils::Log(int logLevel, const std::string& what)
172{
173 EGLenum error = eglGetError();
174 std::string errorStr = StringUtils::Format("0x%04X", error);
175
176 auto eglError = eglErrors.find(error);
177 if (eglError != eglErrors.end())
178 {
179 errorStr = eglError->second;
180 }
181
182 CLog::Log(logLevel, "{} ({})", what.c_str(), errorStr);
183}
184
185CEGLContextUtils::CEGLContextUtils(EGLenum platform, std::string const& platformExtension)
186: m_platform{platform}
187{
188//! @todo remove when Raspberry Pi updates their EGL headers
189#if !defined(TARGET_RASPBERRY_PI)
190 if (CEGLUtils::HasClientExtension("EGL_KHR_debug"))
191 {
192 auto eglDebugMessageControl = CEGLUtils::GetRequiredProcAddress<PFNEGLDEBUGMESSAGECONTROLKHRPROC>("eglDebugMessageControlKHR");
193
194 EGLAttrib eglDebugAttribs[] = {EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE,
195 EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE,
196 EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE,
197 EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE,
198 EGL_NONE};
199
200 eglDebugMessageControl(EglErrorCallback, eglDebugAttribs);
201 }
202#endif
203
204 m_platformSupported = CEGLUtils::HasClientExtension("EGL_EXT_platform_base") && CEGLUtils::HasClientExtension(platformExtension);
205}
206
207bool CEGLContextUtils::IsPlatformSupported() const
208{
209 return m_platformSupported;
210}
211
212CEGLContextUtils::~CEGLContextUtils()
213{
214 Destroy();
215}
216
217bool CEGLContextUtils::CreateDisplay(EGLNativeDisplayType nativeDisplay)
218{
219 if (m_eglDisplay != EGL_NO_DISPLAY)
220 {
221 throw std::logic_error("Do not call CreateDisplay when display has already been created");
222 }
223
224 m_eglDisplay = eglGetDisplay(nativeDisplay);
225 if (m_eglDisplay == EGL_NO_DISPLAY)
226 {
227 CEGLUtils::Log(LOGERROR, "failed to get EGL display");
228 return false;
229 }
230
231 return true;
232}
233
234bool CEGLContextUtils::CreatePlatformDisplay(void* nativeDisplay, EGLNativeDisplayType nativeDisplayLegacy)
235{
236 if (m_eglDisplay != EGL_NO_DISPLAY)
237 {
238 throw std::logic_error("Do not call CreateDisplay when display has already been created");
239 }
240
241#if defined(EGL_EXT_platform_base)
242 if (IsPlatformSupported())
243 {
244 // Theoretically it is possible to use eglGetDisplay() and eglCreateWindowSurface,
245 // but then the EGL library basically has to guess which platform we want
246 // if it supports multiple which is usually the case -
247 // it's better and safer to make it explicit
248
249 auto getPlatformDisplayEXT = CEGLUtils::GetRequiredProcAddress<PFNEGLGETPLATFORMDISPLAYEXTPROC>("eglGetPlatformDisplayEXT");
250 m_eglDisplay = getPlatformDisplayEXT(m_platform, nativeDisplay, nullptr);
251
252 if (m_eglDisplay == EGL_NO_DISPLAY)
253 {
254 CEGLUtils::Log(LOGERROR, "failed to get platform display");
255 return false;
256 }
257 }
258#endif
259
260 if (m_eglDisplay == EGL_NO_DISPLAY)
261 {
262 return CreateDisplay(nativeDisplayLegacy);
263 }
264
265 return true;
266}
267
268bool CEGLContextUtils::InitializeDisplay(EGLint renderingApi)
269{
270 if (!eglInitialize(m_eglDisplay, nullptr, nullptr))
271 {
272 CEGLUtils::Log(LOGERROR, "failed to initialize EGL display");
273 Destroy();
274 return false;
275 }
276
277 const char* value;
278 value = eglQueryString(m_eglDisplay, EGL_VERSION);
279 CLog::Log(LOGINFO, "EGL_VERSION = %s", value ? value : "NULL");
280
281 value = eglQueryString(m_eglDisplay, EGL_VENDOR);
282 CLog::Log(LOGINFO, "EGL_VENDOR = %s", value ? value : "NULL");
283
284 value = eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
285 CLog::Log(LOGINFO, "EGL_EXTENSIONS = %s", value ? value : "NULL");
286
287 value = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
288 CLog::Log(LOGINFO, "EGL_CLIENT_EXTENSIONS = %s", value ? value : "NULL");
289
290 if (eglBindAPI(renderingApi) != EGL_TRUE)
291 {
292 CEGLUtils::Log(LOGERROR, "failed to bind EGL API");
293 Destroy();
294 return false;
295 }
296
297 return true;
298}
299
300bool CEGLContextUtils::ChooseConfig(EGLint renderableType, EGLint visualId, bool hdr)
301{
302 EGLint numMatched{0};
303
304 if (m_eglDisplay == EGL_NO_DISPLAY)
305 {
306 throw std::logic_error("Choosing an EGLConfig requires an EGL display");
307 }
308
309 EGLint surfaceType = EGL_WINDOW_BIT;
310 // for the non-trivial dirty region modes, we need the EGL buffer to be preserved across updates
311 int guiAlgorithmDirtyRegions = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAlgorithmDirtyRegions;
312 if (guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_COST_REDUCTION ||
313 guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_UNION)
314 surfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
315
316 CEGLAttributesVec attribs;
317 attribs.Add({{EGL_RED_SIZE, 8},
318 {EGL_GREEN_SIZE, 8},
319 {EGL_BLUE_SIZE, 8},
320 {EGL_ALPHA_SIZE, 2},
321 {EGL_DEPTH_SIZE, 16},
322 {EGL_STENCIL_SIZE, 0},
323 {EGL_SAMPLE_BUFFERS, 0},
324 {EGL_SAMPLES, 0},
325 {EGL_SURFACE_TYPE, surfaceType},
326 {EGL_RENDERABLE_TYPE, renderableType}});
327
328 EGLConfig* currentConfig(hdr ? &m_eglHDRConfig : &m_eglConfig);
329
330 if (hdr)
331#if EGL_EXT_pixel_format_float
332 attribs.Add({{EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT}});
333#else
334 return false;
335#endif
336
337 const char* errorMsg = nullptr;
338
339 if (eglChooseConfig(m_eglDisplay, attribs.Get(), nullptr, 0, &numMatched) != EGL_TRUE)
340 errorMsg = "failed to query number of EGL configs";
341
342 std::vector<EGLConfig> eglConfigs(numMatched);
343 if (eglChooseConfig(m_eglDisplay, attribs.Get(), eglConfigs.data(), numMatched, &numMatched) != EGL_TRUE)
344 errorMsg = "failed to find EGL configs with appropriate attributes";
345
346 if (errorMsg)
347 {
348 if (!hdr)
349 {
350 CEGLUtils::Log(LOGERROR, errorMsg);
351 Destroy();
352 }
353 else
354 CEGLUtils::Log(LOGINFO, errorMsg);
355 return false;
356 }
357
358 EGLint id{0};
359 for (const auto &eglConfig: eglConfigs)
360 {
361 *currentConfig = eglConfig;
362
363 if (visualId == 0)
364 break;
365
366 if (eglGetConfigAttrib(m_eglDisplay, *currentConfig, EGL_NATIVE_VISUAL_ID, &id) != EGL_TRUE)
367 CEGLUtils::Log(LOGERROR, "failed to query EGL attribute EGL_NATIVE_VISUAL_ID");
368
369 if (visualId == id)
370 break;
371 }
372
373 if (visualId != 0 && visualId != id)
374 {
375 CLog::Log(LOGDEBUG, "failed to find EGL config with EGL_NATIVE_VISUAL_ID={}", visualId);
376 return false;
377 }
378
379 CLog::Log(LOGDEBUG, "EGL %sConfig Attributes:", hdr ? "HDR " : "");
380
381 for (const auto &eglAttribute : eglAttributes)
382 {
383 EGLint value{0};
384 if (eglGetConfigAttrib(m_eglDisplay, *currentConfig, eglAttribute.first, &value) != EGL_TRUE)
385 CEGLUtils::Log(LOGERROR, StringUtils::Format("failed to query EGL attribute %s", eglAttribute.second));
386
387 // we only need to print the hex value if it's an actual EGL define
388 CLog::Log(LOGDEBUG, " %s: %s", eglAttribute.second, (value >= 0x3000 && value <= 0x3200) ? StringUtils::Format("0x%04x", value) : StringUtils::Format("%d", value));
389 }
390
391 return true;
392}
393
394EGLint CEGLContextUtils::GetConfigAttrib(EGLint attribute) const
395{
396 EGLint value{0};
397 if (eglGetConfigAttrib(m_eglDisplay, m_eglConfig, attribute, &value) != EGL_TRUE)
398 CEGLUtils::Log(LOGERROR, "failed to query EGL attribute");
399 return value;
400}
401
402bool CEGLContextUtils::CreateContext(CEGLAttributesVec contextAttribs)
403{
404 if (m_eglContext != EGL_NO_CONTEXT)
405 {
406 throw std::logic_error("Do not call CreateContext when context has already been created");
407 }
408
409 EGLConfig eglConfig{m_eglConfig};
410
411 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_no_config_context"))
412 eglConfig = EGL_NO_CONFIG_KHR;
413
414 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority"))
415 contextAttribs.Add({{EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG}});
416
417//! @todo remove when Raspberry Pi updates their EGL headers
418#if !defined(TARGET_RASPBERRY_PI)
419 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_create_context") &&
420 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging)
421 {
422 contextAttribs.Add({{EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR}});
423 }
424#endif
425
426 m_eglContext = eglCreateContext(m_eglDisplay, eglConfig,
427 EGL_NO_CONTEXT, contextAttribs.Get());
428
429 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority"))
430 {
431 EGLint value{EGL_CONTEXT_PRIORITY_MEDIUM_IMG};
432
433 if (eglQueryContext(m_eglDisplay, m_eglContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value) != EGL_TRUE)
434 CEGLUtils::Log(LOGERROR, "failed to query EGL context attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG");
435
436 if (value != EGL_CONTEXT_PRIORITY_HIGH_IMG)
437 CLog::Log(LOGDEBUG, "Failed to obtain a high priority EGL context");
438 }
439
440 if (m_eglContext == EGL_NO_CONTEXT)
441 {
442 // This is expected to fail under some circumstances, so log as debug
443 CLog::Log(LOGDEBUG, "Failed to create EGL context (EGL error %d)", eglGetError());
444 return false;
445 }
446
447 return true;
448}
449
450bool CEGLContextUtils::BindContext()
451{
452 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglSurface == EGL_NO_SURFACE || m_eglContext == EGL_NO_CONTEXT)
453 {
454 throw std::logic_error("Activating an EGLContext requires display, surface, and context");
455 }
456
457 if (eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext) != EGL_TRUE)
458 {
459 CLog::Log(LOGERROR, "Failed to make context current %p %p %p",
460 m_eglDisplay, m_eglSurface, m_eglContext);
461 return false;
462 }
463
464 return true;
465}
466
467void CEGLContextUtils::SurfaceAttrib()
468{
469 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglSurface == EGL_NO_SURFACE)
470 {
471 throw std::logic_error("Setting surface attributes requires a surface");
472 }
473
474 // for the non-trivial dirty region modes, we need the EGL buffer to be preserved across updates
475 int guiAlgorithmDirtyRegions = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAlgorithmDirtyRegions;
476 if (guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_COST_REDUCTION ||
477 guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_UNION)
478 {
479 if (eglSurfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED) != EGL_TRUE)
480 {
481 CEGLUtils::Log(LOGERROR, "failed to set EGL_BUFFER_PRESERVED swap behavior");
482 }
483 }
484}
485
486void CEGLContextUtils::SurfaceAttrib(EGLint attribute, EGLint value)
487{
488 if (eglSurfaceAttrib(m_eglDisplay, m_eglSurface, attribute, value) != EGL_TRUE)
489 {
490 CEGLUtils::Log(LOGERROR, "failed to set EGL_BUFFER_PRESERVED swap behavior");
491 }
492}
493
494bool CEGLContextUtils::CreateSurface(EGLNativeWindowType nativeWindow, EGLint HDRcolorSpace /* = EGL_NONE */)
495{
496 if (m_eglDisplay == EGL_NO_DISPLAY)
497 {
498 throw std::logic_error("Creating a surface requires a display");
499 }
500 if (m_eglSurface != EGL_NO_SURFACE)
501 {
502 throw std::logic_error("Do not call CreateSurface when surface has already been created");
503 }
504
505 CEGLAttributesVec attribs;
506 EGLConfig config = m_eglConfig;
507
508#ifdef EGL_GL_COLORSPACE
509 if (HDRcolorSpace != EGL_NONE)
510 {
511 attribs.Add({{EGL_GL_COLORSPACE, HDRcolorSpace}});
512 config = m_eglHDRConfig;
513 }
514#endif
515
516 m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, nativeWindow, attribs.Get());
517
518 if (m_eglSurface == EGL_NO_SURFACE)
519 {
520 CEGLUtils::Log(LOGERROR, "failed to create window surface");
521 return false;
522 }
523
524 SurfaceAttrib();
525
526 return true;
527}
528
529bool CEGLContextUtils::CreatePlatformSurface(void* nativeWindow, EGLNativeWindowType nativeWindowLegacy)
530{
531 if (m_eglDisplay == EGL_NO_DISPLAY)
532 {
533 throw std::logic_error("Creating a surface requires a display");
534 }
535 if (m_eglSurface != EGL_NO_SURFACE)
536 {
537 throw std::logic_error("Do not call CreateSurface when surface has already been created");
538 }
539
540#if defined(EGL_EXT_platform_base)
541 if (IsPlatformSupported())
542 {
543 auto createPlatformWindowSurfaceEXT = CEGLUtils::GetRequiredProcAddress<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>("eglCreatePlatformWindowSurfaceEXT");
544 m_eglSurface = createPlatformWindowSurfaceEXT(m_eglDisplay, m_eglConfig, nativeWindow, nullptr);
545
546 if (m_eglSurface == EGL_NO_SURFACE)
547 {
548 CEGLUtils::Log(LOGERROR, "failed to create platform window surface");
549 return false;
550 }
551 }
552#endif
553
554 if (m_eglSurface == EGL_NO_SURFACE)
555 {
556 return CreateSurface(nativeWindowLegacy);
557 }
558
559 SurfaceAttrib();
560
561 return true;
562}
563
564void CEGLContextUtils::Destroy()
565{
566 DestroyContext();
567 DestroySurface();
568
569 if (m_eglDisplay != EGL_NO_DISPLAY)
570 {
571 eglTerminate(m_eglDisplay);
572 m_eglDisplay = EGL_NO_DISPLAY;
573 }
574}
575
576void CEGLContextUtils::DestroyContext()
577{
578 if (m_eglContext != EGL_NO_CONTEXT)
579 {
580 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
581 eglDestroyContext(m_eglDisplay, m_eglContext);
582 m_eglContext = EGL_NO_CONTEXT;
583 }
584}
585
586void CEGLContextUtils::DestroySurface()
587{
588 if (m_eglSurface != EGL_NO_SURFACE)
589 {
590 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
591 eglDestroySurface(m_eglDisplay, m_eglSurface);
592 m_eglSurface = EGL_NO_SURFACE;
593 }
594}
595
596
597bool CEGLContextUtils::SetVSync(bool enable)
598{
599 if (m_eglDisplay == EGL_NO_DISPLAY)
600 {
601 return false;
602 }
603
604 return (eglSwapInterval(m_eglDisplay, enable) == EGL_TRUE);
605}
606
607bool CEGLContextUtils::TrySwapBuffers()
608{
609 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglSurface == EGL_NO_SURFACE)
610 {
611 return false;
612 }
613
614 return (eglSwapBuffers(m_eglDisplay, m_eglSurface) == EGL_TRUE);
615}