Merge pull request #26166 from ksooo/improve-plugin-ctx-menus
[xbmc.git] / xbmc / utils / EGLUtils.cpp
blob01867354cf363350047c53fb8ca011235eec8e33
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "EGLUtils.h"
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 #include "utils/Geometry.h"
19 #include <map>
21 #include <EGL/egl.h>
22 #include <EGL/eglext.h>
23 #include <EGL/eglplatform.h>
25 namespace
28 #define X(VAL) std::make_pair(VAL, #VAL)
29 std::map<EGLint, const char*> eglAttributes =
31 // please keep attributes in accordance to:
32 // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetConfigAttrib.xhtml
33 X(EGL_ALPHA_SIZE),
34 X(EGL_ALPHA_MASK_SIZE),
35 X(EGL_BIND_TO_TEXTURE_RGB),
36 X(EGL_BIND_TO_TEXTURE_RGBA),
37 X(EGL_BLUE_SIZE),
38 X(EGL_BUFFER_SIZE),
39 X(EGL_COLOR_BUFFER_TYPE),
40 X(EGL_CONFIG_CAVEAT),
41 X(EGL_CONFIG_ID),
42 X(EGL_CONFORMANT),
43 X(EGL_DEPTH_SIZE),
44 X(EGL_GREEN_SIZE),
45 X(EGL_LEVEL),
46 X(EGL_LUMINANCE_SIZE),
47 X(EGL_MAX_PBUFFER_WIDTH),
48 X(EGL_MAX_PBUFFER_HEIGHT),
49 X(EGL_MAX_PBUFFER_PIXELS),
50 X(EGL_MAX_SWAP_INTERVAL),
51 X(EGL_MIN_SWAP_INTERVAL),
52 X(EGL_NATIVE_RENDERABLE),
53 X(EGL_NATIVE_VISUAL_ID),
54 X(EGL_NATIVE_VISUAL_TYPE),
55 X(EGL_RED_SIZE),
56 X(EGL_RENDERABLE_TYPE),
57 X(EGL_SAMPLE_BUFFERS),
58 X(EGL_SAMPLES),
59 X(EGL_STENCIL_SIZE),
60 X(EGL_SURFACE_TYPE),
61 X(EGL_TRANSPARENT_TYPE),
62 X(EGL_TRANSPARENT_RED_VALUE),
63 X(EGL_TRANSPARENT_GREEN_VALUE),
64 X(EGL_TRANSPARENT_BLUE_VALUE)
67 std::map<EGLenum, const char*> eglErrors =
69 // please keep errors in accordance to:
70 // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetError.xhtml
71 X(EGL_SUCCESS),
72 X(EGL_NOT_INITIALIZED),
73 X(EGL_BAD_ACCESS),
74 X(EGL_BAD_ALLOC),
75 X(EGL_BAD_ATTRIBUTE),
76 X(EGL_BAD_CONFIG),
77 X(EGL_BAD_CONTEXT),
78 X(EGL_BAD_CURRENT_SURFACE),
79 X(EGL_BAD_DISPLAY),
80 X(EGL_BAD_MATCH),
81 X(EGL_BAD_NATIVE_PIXMAP),
82 X(EGL_BAD_NATIVE_WINDOW),
83 X(EGL_BAD_PARAMETER),
84 X(EGL_BAD_SURFACE),
85 X(EGL_CONTEXT_LOST),
88 std::map<EGLint, const char*> eglErrorType =
90 X(EGL_DEBUG_MSG_CRITICAL_KHR),
91 X(EGL_DEBUG_MSG_ERROR_KHR),
92 X(EGL_DEBUG_MSG_WARN_KHR),
93 X(EGL_DEBUG_MSG_INFO_KHR),
95 #undef X
97 } // namespace
99 void EglErrorCallback(EGLenum error,
100 const char* command,
101 EGLint messageType,
102 EGLLabelKHR threadLabel,
103 EGLLabelKHR objectLabel,
104 const char* message)
106 std::string errorStr;
107 std::string typeStr;
109 auto eglError = eglErrors.find(error);
110 if (eglError != eglErrors.end())
112 errorStr = eglError->second;
115 auto eglType = eglErrorType.find(messageType);
116 if (eglType != eglErrorType.end())
118 typeStr = eglType->second;
121 CLog::Log(LOGDEBUG, "EGL Debugging:\nError: {}\nCommand: {}\nType: {}\nMessage: {}", errorStr,
122 command, typeStr, message ? message : "");
125 std::set<std::string> CEGLUtils::GetClientExtensions()
127 const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
128 if (!extensions)
130 return {};
132 std::set<std::string> result;
133 StringUtils::SplitTo(std::inserter(result, result.begin()), extensions, " ");
134 return result;
137 std::set<std::string> CEGLUtils::GetExtensions(EGLDisplay eglDisplay)
139 const char* extensions = eglQueryString(eglDisplay, EGL_EXTENSIONS);
140 if (!extensions)
142 throw std::runtime_error("Could not query EGL for extensions");
144 std::set<std::string> result;
145 StringUtils::SplitTo(std::inserter(result, result.begin()), extensions, " ");
146 return result;
149 bool CEGLUtils::HasExtension(EGLDisplay eglDisplay, const std::string& name)
151 auto exts = GetExtensions(eglDisplay);
152 return (exts.find(name) != exts.end());
155 bool CEGLUtils::HasClientExtension(const std::string& name)
157 auto exts = GetClientExtensions();
158 return (exts.find(name) != exts.end());
161 void CEGLUtils::Log(int logLevel, const std::string& what)
163 EGLenum error = eglGetError();
164 std::string errorStr = StringUtils::Format("{:#04X}", error);
166 auto eglError = eglErrors.find(error);
167 if (eglError != eglErrors.end())
169 errorStr = eglError->second;
172 CLog::Log(logLevel, "{} ({})", what, errorStr);
175 CEGLContextUtils::CEGLContextUtils(EGLenum platform, std::string const& platformExtension)
176 : m_platform{platform}
178 if (CEGLUtils::HasClientExtension("EGL_KHR_debug"))
180 auto eglDebugMessageControl = CEGLUtils::GetRequiredProcAddress<PFNEGLDEBUGMESSAGECONTROLKHRPROC>("eglDebugMessageControlKHR");
182 EGLAttrib eglDebugAttribs[] = {EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE,
183 EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE,
184 EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE,
185 EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE,
186 EGL_NONE};
188 eglDebugMessageControl(EglErrorCallback, eglDebugAttribs);
191 m_platformSupported = CEGLUtils::HasClientExtension("EGL_EXT_platform_base") &&
192 CEGLUtils::HasClientExtension(platformExtension);
195 bool CEGLContextUtils::IsPlatformSupported() const
197 return m_platformSupported;
200 CEGLContextUtils::~CEGLContextUtils()
202 Destroy();
205 bool CEGLContextUtils::CreateDisplay(EGLNativeDisplayType nativeDisplay)
207 if (m_eglDisplay != EGL_NO_DISPLAY)
209 throw std::logic_error("Do not call CreateDisplay when display has already been created");
212 m_eglDisplay = eglGetDisplay(nativeDisplay);
213 if (m_eglDisplay == EGL_NO_DISPLAY)
215 CEGLUtils::Log(LOGERROR, "failed to get EGL display");
216 return false;
219 return true;
222 bool CEGLContextUtils::CreatePlatformDisplay(void* nativeDisplay, EGLNativeDisplayType nativeDisplayLegacy)
224 if (m_eglDisplay != EGL_NO_DISPLAY)
226 throw std::logic_error("Do not call CreateDisplay when display has already been created");
229 #if defined(EGL_EXT_platform_base)
230 if (IsPlatformSupported())
232 // Theoretically it is possible to use eglGetDisplay() and eglCreateWindowSurface,
233 // but then the EGL library basically has to guess which platform we want
234 // if it supports multiple which is usually the case -
235 // it's better and safer to make it explicit
237 auto getPlatformDisplayEXT = CEGLUtils::GetRequiredProcAddress<PFNEGLGETPLATFORMDISPLAYEXTPROC>("eglGetPlatformDisplayEXT");
238 m_eglDisplay = getPlatformDisplayEXT(m_platform, nativeDisplay, nullptr);
240 if (m_eglDisplay == EGL_NO_DISPLAY)
242 CEGLUtils::Log(LOGERROR, "failed to get platform display");
243 return false;
246 #endif
248 if (m_eglDisplay == EGL_NO_DISPLAY)
250 return CreateDisplay(nativeDisplayLegacy);
253 return true;
256 bool CEGLContextUtils::InitializeDisplay(EGLint renderingApi)
258 if (!eglInitialize(m_eglDisplay, nullptr, nullptr))
260 CEGLUtils::Log(LOGERROR, "failed to initialize EGL display");
261 Destroy();
262 return false;
265 const char* value;
266 value = eglQueryString(m_eglDisplay, EGL_VERSION);
267 CLog::Log(LOGINFO, "EGL_VERSION = {}", value ? value : "NULL");
269 value = eglQueryString(m_eglDisplay, EGL_VENDOR);
270 CLog::Log(LOGINFO, "EGL_VENDOR = {}", value ? value : "NULL");
272 value = eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
273 CLog::Log(LOGINFO, "EGL_EXTENSIONS = {}", value ? value : "NULL");
275 value = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
276 CLog::Log(LOGINFO, "EGL_CLIENT_EXTENSIONS = {}", value ? value : "NULL");
278 if (eglBindAPI(renderingApi) != EGL_TRUE)
280 CEGLUtils::Log(LOGERROR, "failed to bind EGL API");
281 Destroy();
282 return false;
285 return true;
288 bool CEGLContextUtils::ChooseConfig(EGLint renderableType, EGLint visualId, bool hdr)
290 EGLint numMatched{0};
292 if (m_eglDisplay == EGL_NO_DISPLAY)
294 throw std::logic_error("Choosing an EGLConfig requires an EGL display");
297 EGLint surfaceType = EGL_WINDOW_BIT;
299 CEGLAttributesVec attribs;
300 attribs.Add({{EGL_RED_SIZE, 8},
301 {EGL_GREEN_SIZE, 8},
302 {EGL_BLUE_SIZE, 8},
303 {EGL_ALPHA_SIZE, 2},
304 {EGL_DEPTH_SIZE, 16},
305 {EGL_STENCIL_SIZE, 0},
306 {EGL_SAMPLE_BUFFERS, 0},
307 {EGL_SAMPLES, 0},
308 {EGL_SURFACE_TYPE, surfaceType},
309 {EGL_RENDERABLE_TYPE, renderableType}});
311 EGLConfig* currentConfig(hdr ? &m_eglHDRConfig : &m_eglConfig);
313 if (hdr)
314 #if EGL_EXT_pixel_format_float
315 attribs.Add({{EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT}});
316 #else
317 return false;
318 #endif
320 const char* errorMsg = nullptr;
322 if (eglChooseConfig(m_eglDisplay, attribs.Get(), nullptr, 0, &numMatched) != EGL_TRUE)
323 errorMsg = "failed to query number of EGL configs";
325 std::vector<EGLConfig> eglConfigs(numMatched);
326 if (eglChooseConfig(m_eglDisplay, attribs.Get(), eglConfigs.data(), numMatched, &numMatched) != EGL_TRUE)
327 errorMsg = "failed to find EGL configs with appropriate attributes";
329 if (errorMsg)
331 if (!hdr)
333 CEGLUtils::Log(LOGERROR, errorMsg);
334 Destroy();
336 else
337 CEGLUtils::Log(LOGINFO, errorMsg);
338 return false;
341 EGLint id{0};
342 for (const auto &eglConfig: eglConfigs)
344 *currentConfig = eglConfig;
346 if (visualId == 0)
347 break;
349 if (eglGetConfigAttrib(m_eglDisplay, *currentConfig, EGL_NATIVE_VISUAL_ID, &id) != EGL_TRUE)
350 CEGLUtils::Log(LOGERROR, "failed to query EGL attribute EGL_NATIVE_VISUAL_ID");
352 if (visualId == id)
353 break;
356 if (visualId != 0 && visualId != id)
358 CLog::Log(LOGDEBUG, "failed to find EGL config with EGL_NATIVE_VISUAL_ID={}", visualId);
359 return false;
362 CLog::Log(LOGDEBUG, "EGL {}Config Attributes:", hdr ? "HDR " : "");
364 for (const auto &eglAttribute : eglAttributes)
366 EGLint value{0};
367 if (eglGetConfigAttrib(m_eglDisplay, *currentConfig, eglAttribute.first, &value) != EGL_TRUE)
368 CEGLUtils::Log(LOGERROR,
369 StringUtils::Format("failed to query EGL attribute {}", eglAttribute.second));
371 // we only need to print the hex value if it's an actual EGL define
372 CLog::Log(LOGDEBUG, " {}: {}", eglAttribute.second,
373 (value >= 0x3000 && value <= 0x3200) ? StringUtils::Format("{:#04x}", value)
374 : std::to_string(value));
377 return true;
380 EGLint CEGLContextUtils::GetConfigAttrib(EGLint attribute) const
382 EGLint value{0};
383 if (eglGetConfigAttrib(m_eglDisplay, m_eglConfig, attribute, &value) != EGL_TRUE)
384 CEGLUtils::Log(LOGERROR, "failed to query EGL attribute");
385 return value;
388 bool CEGLContextUtils::CreateContext(CEGLAttributesVec contextAttribs)
390 if (m_eglContext != EGL_NO_CONTEXT)
392 throw std::logic_error("Do not call CreateContext when context has already been created");
395 EGLConfig eglConfig{m_eglConfig};
397 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_no_config_context"))
398 eglConfig = EGL_NO_CONFIG_KHR;
400 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority"))
401 contextAttribs.Add({{EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG}});
403 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_create_context") &&
404 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_openGlDebugging)
406 contextAttribs.Add({{EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR}});
409 m_eglContext = eglCreateContext(m_eglDisplay, eglConfig,
410 EGL_NO_CONTEXT, contextAttribs.Get());
412 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority"))
414 EGLint value{EGL_CONTEXT_PRIORITY_MEDIUM_IMG};
416 if (eglQueryContext(m_eglDisplay, m_eglContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value) != EGL_TRUE)
417 CEGLUtils::Log(LOGERROR, "failed to query EGL context attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG");
419 if (value != EGL_CONTEXT_PRIORITY_HIGH_IMG)
420 CLog::Log(LOGDEBUG, "Failed to obtain a high priority EGL context");
423 if (m_eglContext == EGL_NO_CONTEXT)
425 // This is expected to fail under some circumstances, so log as debug
426 CLog::Log(LOGDEBUG, "Failed to create EGL context (EGL error {})", eglGetError());
427 return false;
430 m_eglUploadContext =
431 eglCreateContext(m_eglDisplay, m_eglConfig, m_eglContext, contextAttribs.Get());
433 if (m_eglUploadContext == EGL_NO_CONTEXT)
434 CLog::Log(LOGWARNING, "Failed to create EGL upload context");
436 m_bufferAgeSupport = CEGLUtils::HasExtension(m_eglDisplay, "EGL_EXT_buffer_age");
438 if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_partial_update"))
440 m_partialUpdateSupport = true;
441 m_eglSetDamageRegionKHR =
442 reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
445 return true;
448 bool CEGLContextUtils::BindContext()
450 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglSurface == EGL_NO_SURFACE || m_eglContext == EGL_NO_CONTEXT)
452 throw std::logic_error("Activating an EGLContext requires display, surface, and context");
455 if (eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext) != EGL_TRUE)
457 CLog::Log(LOGERROR, "Failed to make context current {} {} {}", fmt::ptr(m_eglDisplay),
458 fmt::ptr(m_eglSurface), fmt::ptr(m_eglContext));
459 return false;
462 return true;
465 void CEGLContextUtils::SurfaceAttrib()
467 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglSurface == EGL_NO_SURFACE)
469 throw std::logic_error("Setting surface attributes requires a surface");
473 void CEGLContextUtils::SurfaceAttrib(EGLint attribute, EGLint value)
475 if (eglSurfaceAttrib(m_eglDisplay, m_eglSurface, attribute, value) != EGL_TRUE)
477 CEGLUtils::Log(LOGERROR, "failed to set EGL_BUFFER_PRESERVED swap behavior");
481 bool CEGLContextUtils::CreateSurface(EGLNativeWindowType nativeWindow, EGLint HDRcolorSpace /* = EGL_NONE */)
483 if (m_eglDisplay == EGL_NO_DISPLAY)
485 throw std::logic_error("Creating a surface requires a display");
487 if (m_eglSurface != EGL_NO_SURFACE)
489 throw std::logic_error("Do not call CreateSurface when surface has already been created");
492 CEGLAttributesVec attribs;
493 EGLConfig config = m_eglConfig;
495 #ifdef EGL_GL_COLORSPACE
496 if (HDRcolorSpace != EGL_NONE)
498 attribs.Add({{EGL_GL_COLORSPACE, HDRcolorSpace}});
499 config = m_eglHDRConfig;
501 #endif
503 m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, nativeWindow, attribs.Get());
505 if (m_eglSurface == EGL_NO_SURFACE)
507 CEGLUtils::Log(LOGERROR, "failed to create window surface");
508 return false;
511 SurfaceAttrib();
513 return true;
516 bool CEGLContextUtils::CreatePlatformSurface(void* nativeWindow, EGLNativeWindowType nativeWindowLegacy)
518 if (m_eglDisplay == EGL_NO_DISPLAY)
520 throw std::logic_error("Creating a surface requires a display");
522 if (m_eglSurface != EGL_NO_SURFACE)
524 throw std::logic_error("Do not call CreateSurface when surface has already been created");
527 #if defined(EGL_EXT_platform_base)
528 if (IsPlatformSupported())
530 auto createPlatformWindowSurfaceEXT = CEGLUtils::GetRequiredProcAddress<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>("eglCreatePlatformWindowSurfaceEXT");
531 m_eglSurface = createPlatformWindowSurfaceEXT(m_eglDisplay, m_eglConfig, nativeWindow, nullptr);
533 if (m_eglSurface == EGL_NO_SURFACE)
535 CEGLUtils::Log(LOGERROR, "failed to create platform window surface");
536 return false;
539 #endif
541 if (m_eglSurface == EGL_NO_SURFACE)
543 return CreateSurface(nativeWindowLegacy);
546 SurfaceAttrib();
548 return true;
551 void CEGLContextUtils::Destroy()
553 DestroyContext();
554 DestroySurface();
556 if (m_eglDisplay != EGL_NO_DISPLAY)
558 eglTerminate(m_eglDisplay);
559 m_eglDisplay = EGL_NO_DISPLAY;
563 void CEGLContextUtils::DestroyContext()
565 if (m_eglContext != EGL_NO_CONTEXT)
567 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
568 eglDestroyContext(m_eglDisplay, m_eglContext);
569 m_eglContext = EGL_NO_CONTEXT;
572 if (m_eglUploadContext)
574 eglDestroyContext(m_eglDisplay, m_eglUploadContext);
575 m_eglUploadContext = EGL_NO_CONTEXT;
579 void CEGLContextUtils::DestroySurface()
581 if (m_eglSurface != EGL_NO_SURFACE)
583 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
584 eglDestroySurface(m_eglDisplay, m_eglSurface);
585 m_eglSurface = EGL_NO_SURFACE;
590 bool CEGLContextUtils::SetVSync(bool enable)
592 if (m_eglDisplay == EGL_NO_DISPLAY)
594 return false;
597 return (eglSwapInterval(m_eglDisplay, enable) == EGL_TRUE);
600 bool CEGLContextUtils::TrySwapBuffers()
602 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglSurface == EGL_NO_SURFACE)
604 return false;
607 return (eglSwapBuffers(m_eglDisplay, m_eglSurface) == EGL_TRUE);
610 bool CEGLContextUtils::BindTextureUploadContext()
612 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglUploadContext == EGL_NO_CONTEXT)
614 CLog::LogF(LOGERROR, "No texture upload context found.");
615 return false;
618 m_textureUploadLock.lock();
620 if (!eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_eglUploadContext))
622 m_textureUploadLock.unlock();
623 CLog::LogF(LOGERROR, "Couldn't bind texture upload context.");
624 return false;
627 return true;
630 bool CEGLContextUtils::UnbindTextureUploadContext()
632 if (m_eglDisplay == EGL_NO_DISPLAY || m_eglUploadContext == EGL_NO_CONTEXT)
634 CLog::LogF(LOGERROR, "No texture upload context found.");
635 m_textureUploadLock.unlock();
636 return false;
639 if (!eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
641 CLog::LogF(LOGERROR, "Couldn't release texture upload context");
642 m_textureUploadLock.unlock();
643 return false;
646 m_textureUploadLock.unlock();
648 return true;
651 bool CEGLContextUtils::HasContext()
653 return eglGetCurrentContext() != EGL_NO_CONTEXT;
656 void CEGLContextUtils::SetDamagedRegions(const CDirtyRegionList& dirtyRegions)
658 if (!m_partialUpdateSupport)
659 return;
661 using Rect = std::array<EGLint, 4>;
662 if (dirtyRegions.empty())
664 // add a single (empty) entry, otherwise the whole frame gets rendered
665 static Rect zeroRect{};
666 m_eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, zeroRect.data(), 1);
668 else
670 EGLint height = eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height);
671 std::vector<Rect> rects;
672 rects.reserve(dirtyRegions.size());
673 for (const auto& region : dirtyRegions)
675 rects.push_back({static_cast<EGLint>(region.x1), static_cast<EGLint>(height - region.y2),
676 static_cast<EGLint>(region.Width()), static_cast<EGLint>(region.Height())});
678 m_eglSetDamageRegionKHR(m_eglDisplay, m_eglSurface, reinterpret_cast<EGLint*>(rects.data()),
679 rects.size());
683 int CEGLContextUtils::GetBufferAge()
685 #ifdef EGL_BUFFER_AGE_KHR
686 if (m_partialUpdateSupport)
688 EGLint age;
689 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_KHR, &age);
690 return static_cast<int>(age);
692 #endif
693 #ifdef EGL_BUFFER_AGE_EXT
694 if (m_bufferAgeSupport)
696 EGLint age;
697 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, &age);
698 return static_cast<int>(age);
700 #endif
701 return 2;