123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/gl/gl_context_egl.h"
- #include <memory>
- #include "base/command_line.h"
- #include "base/logging.h"
- #include "base/trace_event/trace_event.h"
- #include "build/build_config.h"
- #include "third_party/khronos/EGL/egl.h"
- #include "third_party/khronos/EGL/eglext.h"
- #include "ui/gl/egl_util.h"
- #include "ui/gl/gl_bindings.h"
- #include "ui/gl/gl_display.h"
- #include "ui/gl/gl_fence.h"
- #include "ui/gl/gl_gl_api_implementation.h"
- #include "ui/gl/gl_surface_egl.h"
- #include "ui/gl/yuv_to_rgb_converter.h"
- #ifndef EGL_CHROMIUM_create_context_bind_generates_resource
- #define EGL_CHROMIUM_create_context_bind_generates_resource 1
- #define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x33AD
- #endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
- #ifndef EGL_ANGLE_create_context_webgl_compatibility
- #define EGL_ANGLE_create_context_webgl_compatibility 1
- #define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC
- #endif /* EGL_ANGLE_create_context_webgl_compatibility */
- #ifndef EGL_ANGLE_display_texture_share_group
- #define EGL_ANGLE_display_texture_share_group 1
- #define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF
- #endif /* EGL_ANGLE_display_texture_share_group */
- #ifndef EGL_ANGLE_display_semaphore_share_group
- #define EGL_ANGLE_display_semaphore_share_group 1
- #define EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE 0x348D
- #endif /* EGL_ANGLE_display_semaphore_share_group */
- #ifndef EGL_ANGLE_external_context_and_surface
- #define EGL_ANGLE_external_context_and_surface 1
- #define EGL_EXTERNAL_CONTEXT_ANGLE 0x348E
- #define EGL_EXTERNAL_SURFACE_ANGLE 0x348F
- #define EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE 0x3490
- #endif /* EGL_ANGLE_external_context_and_surface */
- #ifndef EGL_ANGLE_create_context_client_arrays
- #define EGL_ANGLE_create_context_client_arrays 1
- #define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
- #endif /* EGL_ANGLE_create_context_client_arrays */
- #ifndef EGL_ANGLE_robust_resource_initialization
- #define EGL_ANGLE_robust_resource_initialization 1
- #define EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453
- #endif /* EGL_ANGLE_display_robust_resource_initialization */
- #ifndef EGL_ANGLE_create_context_backwards_compatible
- #define EGL_ANGLE_create_context_backwards_compatible 1
- #define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
- #endif /* EGL_ANGLE_create_context_backwards_compatible */
- #ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG
- #define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
- #define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
- #define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
- #define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
- #endif /* EGL_CONTEXT_PRIORITY_LEVEL */
- #ifndef EGL_ANGLE_power_preference
- #define EGL_ANGLE_power_preference 1
- #define EGL_POWER_PREFERENCE_ANGLE 0x3482
- #define EGL_LOW_POWER_ANGLE 0x0001
- #define EGL_HIGH_POWER_ANGLE 0x0002
- #endif /* EGL_ANGLE_power_preference */
- #ifndef EGL_NV_robustness_video_memory_purge
- #define EGL_NV_robustness_video_memory_purge 1
- #define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
- #endif /*EGL_NV_robustness_video_memory_purge */
- #ifndef EGL_ANGLE_context_virtualization
- #define EGL_ANGLE_context_virtualization 1
- #define EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE 0x3481
- #endif /* EGL_ANGLE_context_virtualization */
- #ifndef EGL_ANGLE_program_cache_control
- #define EGL_ANGLE_program_cache_control 1
- #define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459
- #endif /* EGL_ANGLE_program_cache_control */
- using ui::GetLastEGLErrorString;
- namespace gl {
- namespace {
- // Change the specified attribute in context_attributes. This fails if
- // the attribute is not already present. Returns true on success, false
- // otherwise.
- bool ChangeContextAttributes(std::vector<EGLint>& context_attributes,
- EGLint attribute,
- EGLint value) {
- auto iter = std::find(context_attributes.begin(), context_attributes.end(),
- attribute);
- if (iter != context_attributes.end()) {
- ++iter;
- if (iter != context_attributes.end()) {
- *iter = value;
- return true;
- }
- }
- return false;
- }
- } // namespace
- GLContextEGL::GLContextEGL(GLShareGroup* share_group)
- : GLContextReal(share_group) {}
- bool GLContextEGL::Initialize(GLSurface* compatible_surface,
- const GLContextAttribs& attribs) {
- DCHECK(compatible_surface);
- DCHECK(!context_);
- gl_display_ = static_cast<GLDisplayEGL*>(compatible_surface->GetGLDisplay());
- DCHECK(gl_display_);
- EGLint context_client_major_version = attribs.client_major_es_version;
- EGLint context_client_minor_version = attribs.client_minor_es_version;
- // Always prefer to use EGL_KHR_no_config_context so that all surfaces and
- // contexts are compatible
- if (!gl_display_->ext->b_EGL_KHR_no_config_context) {
- config_ = compatible_surface->GetConfig();
- EGLint config_renderable_type = 0;
- if (!eglGetConfigAttrib(gl_display_->GetDisplay(), config_,
- EGL_RENDERABLE_TYPE, &config_renderable_type)) {
- LOG(ERROR) << "eglGetConfigAttrib failed with error "
- << GetLastEGLErrorString();
- return false;
- }
- // If the requested context is ES3 but the config cannot support ES3,
- // request ES2 instead.
- if ((config_renderable_type & EGL_OPENGL_ES3_BIT) == 0 &&
- context_client_major_version >= 3) {
- context_client_major_version = 2;
- context_client_minor_version = 0;
- }
- }
- std::vector<EGLint> context_attributes;
- if (attribs.can_skip_validation &&
- GetGLImplementation() == kGLImplementationEGLANGLE) {
- context_attributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
- context_attributes.push_back(EGL_TRUE);
- }
- // EGL_KHR_create_context allows requesting both a major and minor context
- // version
- if (gl_display_->ext->b_EGL_KHR_create_context) {
- context_attributes.push_back(EGL_CONTEXT_MAJOR_VERSION);
- context_attributes.push_back(context_client_major_version);
- context_attributes.push_back(EGL_CONTEXT_MINOR_VERSION);
- context_attributes.push_back(context_client_minor_version);
- } else {
- context_attributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
- context_attributes.push_back(context_client_major_version);
- // Can only request 2.0 or 3.0 contexts without the EGL_KHR_create_context
- // extension, DCHECK to make sure we update the code to support devices
- // without this extension
- DCHECK(context_client_minor_version == 0);
- }
- bool is_swangle = IsSoftwareGLImplementation(GetGLImplementationParts());
- if (gl_display_->ext->b_EGL_EXT_create_context_robustness || is_swangle) {
- DVLOG(1) << "EGL_EXT_create_context_robustness supported.";
- context_attributes.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
- context_attributes.push_back(
- (attribs.robust_buffer_access || is_swangle) ? EGL_TRUE : EGL_FALSE);
- if (attribs.lose_context_on_reset) {
- context_attributes.push_back(
- EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
- context_attributes.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT);
- if (gl_display_->ext->b_EGL_NV_robustness_video_memory_purge) {
- context_attributes.push_back(
- EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV);
- context_attributes.push_back(EGL_TRUE);
- }
- }
- } else {
- // At some point we should require the presence of the robustness
- // extension and remove this code path.
- DVLOG(1) << "EGL_EXT_create_context_robustness NOT supported.";
- }
- if (!eglBindAPI(EGL_OPENGL_ES_API)) {
- LOG(ERROR) << "eglBindApi failed with error "
- << GetLastEGLErrorString();
- return false;
- }
- if (gl_display_->ext->b_EGL_CHROMIUM_create_context_bind_generates_resource) {
- context_attributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
- context_attributes.push_back(attribs.bind_generates_resource ? EGL_TRUE
- : EGL_FALSE);
- } else {
- DCHECK(attribs.bind_generates_resource);
- }
- if (gl_display_->ext->b_EGL_ANGLE_create_context_webgl_compatibility) {
- context_attributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
- context_attributes.push_back(
- attribs.webgl_compatibility_context ? EGL_TRUE : EGL_FALSE);
- } else {
- DCHECK(!attribs.webgl_compatibility_context);
- }
- if (gl_display_->IsEGLContextPrioritySupported()) {
- // Medium priority is the default, only set the attribute if
- // a different priority is requested.
- if (attribs.context_priority == ContextPriorityLow) {
- DVLOG(1) << __FUNCTION__ << ": setting ContextPriorityLow";
- context_attributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
- context_attributes.push_back(EGL_CONTEXT_PRIORITY_LOW_IMG);
- } else if (attribs.context_priority == ContextPriorityHigh) {
- DVLOG(1) << __FUNCTION__ << ": setting ContextPriorityHigh";
- context_attributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
- context_attributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
- }
- }
- if (gl_display_->ext->b_EGL_ANGLE_display_texture_share_group) {
- context_attributes.push_back(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE);
- context_attributes.push_back(
- attribs.global_texture_share_group ? EGL_TRUE : EGL_FALSE);
- } else {
- DCHECK(!attribs.global_texture_share_group);
- }
- if (gl_display_->ext->b_EGL_ANGLE_display_semaphore_share_group) {
- context_attributes.push_back(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE);
- context_attributes.push_back(
- attribs.global_semaphore_share_group ? EGL_TRUE : EGL_FALSE);
- } else {
- DCHECK(!attribs.global_semaphore_share_group);
- }
- if (gl_display_->ext->b_EGL_ANGLE_create_context_client_arrays) {
- // Disable client arrays if the context supports it
- context_attributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
- context_attributes.push_back(EGL_FALSE);
- }
- if (gl_display_->ext->b_EGL_ANGLE_robust_resource_initialization ||
- is_swangle) {
- context_attributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
- context_attributes.push_back(
- (attribs.robust_resource_initialization || is_swangle) ? EGL_TRUE
- : EGL_FALSE);
- } else {
- DCHECK(!attribs.robust_resource_initialization);
- }
- if (gl_display_->ext->b_EGL_ANGLE_create_context_backwards_compatible) {
- // Request a specific context version. The Passthrough command decoder
- // relies on the returned context being the exact version it requested.
- context_attributes.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
- context_attributes.push_back(EGL_FALSE);
- }
- if (gl_display_->ext->b_EGL_ANGLE_power_preference) {
- GpuPreference pref = attribs.gpu_preference;
- pref = GLSurface::AdjustGpuPreference(pref);
- switch (pref) {
- case GpuPreference::kDefault:
- // Don't request any GPU, let ANGLE and the native driver decide.
- break;
- case GpuPreference::kLowPower:
- context_attributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
- context_attributes.push_back(EGL_LOW_POWER_ANGLE);
- break;
- case GpuPreference::kHighPerformance:
- context_attributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
- context_attributes.push_back(EGL_HIGH_POWER_ANGLE);
- break;
- default:
- NOTREACHED();
- }
- }
- if (gl_display_->ext->b_EGL_ANGLE_external_context_and_surface) {
- if (attribs.angle_create_from_external_context) {
- context_attributes.push_back(EGL_EXTERNAL_CONTEXT_ANGLE);
- context_attributes.push_back(EGL_TRUE);
- }
- if (attribs.angle_restore_external_context_state) {
- context_attributes.push_back(EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE);
- context_attributes.push_back(EGL_TRUE);
- }
- }
- if (gl_display_->ext->b_EGL_ANGLE_context_virtualization) {
- context_attributes.push_back(EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE);
- context_attributes.push_back(
- static_cast<EGLint>(attribs.angle_context_virtualization_group_number));
- }
- // Skia manages program cache by itself.
- // For WebGL program, it should manage program by itself too.
- if (gl_display_->ext->b_EGL_ANGLE_program_cache_control) {
- context_attributes.push_back(
- EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
- context_attributes.push_back(EGL_FALSE);
- }
- // Append final EGL_NONE to signal the context attributes are finished
- context_attributes.push_back(EGL_NONE);
- context_attributes.push_back(EGL_NONE);
- context_ =
- eglCreateContext(gl_display_->GetDisplay(), config_,
- share_group() ? share_group()->GetHandle() : nullptr,
- context_attributes.data());
- // If EGL_KHR_no_config_context is in use and context creation failed,
- // it might indicate that an unsupported ES version was requested. Try
- // falling back to a lower version.
- if (!context_ && gl_display_->ext->b_EGL_KHR_no_config_context &&
- eglGetError() == EGL_BAD_MATCH) {
- // Set up the list of versions to try: 3.1 -> 3.0 -> 2.0
- std::vector<std::pair<EGLint, EGLint>> candidate_versions;
- if (context_client_major_version == 3 &&
- context_client_minor_version == 1) {
- candidate_versions.emplace_back(3, 0);
- candidate_versions.emplace_back(2, 0);
- } else if (context_client_major_version == 3 &&
- context_client_minor_version == 0) {
- candidate_versions.emplace_back(2, 0);
- }
- for (const auto& version : candidate_versions) {
- if (!ChangeContextAttributes(context_attributes,
- EGL_CONTEXT_MAJOR_VERSION, version.first) ||
- !ChangeContextAttributes(context_attributes,
- EGL_CONTEXT_MINOR_VERSION, version.second)) {
- break;
- }
- context_ =
- eglCreateContext(gl_display_->GetDisplay(), config_,
- share_group() ? share_group()->GetHandle() : nullptr,
- context_attributes.data());
- // Stop searching as soon as a context is successfully created.
- if (context_) {
- break;
- }
- }
- }
- if (!context_) {
- LOG(ERROR) << "eglCreateContext failed with error "
- << GetLastEGLErrorString();
- return false;
- }
- return true;
- }
- void GLContextEGL::Destroy() {
- ReleaseYUVToRGBConvertersAndBackpressureFences();
- if (context_) {
- if (!eglDestroyContext(gl_display_->GetDisplay(), context_)) {
- LOG(ERROR) << "eglDestroyContext failed with error "
- << GetLastEGLErrorString();
- }
- context_ = nullptr;
- }
- }
- YUVToRGBConverter* GLContextEGL::GetYUVToRGBConverter(
- const gfx::ColorSpace& color_space) {
- // Make sure YUVToRGBConverter objects never get created when surfaceless EGL
- // contexts aren't supported since support for surfaceless EGL contexts is
- // required in order to properly release YUVToRGBConverter objects (see
- // GLContextEGL::ReleaseYUVToRGBConvertersAndBackpressureFences())
- if (!gl_display_->IsEGLSurfacelessContextSupported()) {
- return nullptr;
- }
- std::unique_ptr<YUVToRGBConverter>& yuv_to_rgb_converter =
- yuv_to_rgb_converters_[color_space];
- if (!yuv_to_rgb_converter) {
- yuv_to_rgb_converter =
- std::make_unique<YUVToRGBConverter>(*GetVersionInfo(), color_space);
- }
- return yuv_to_rgb_converter.get();
- }
- void GLContextEGL::SetVisibility(bool visibility) {
- if (gl_display_->ext->b_EGL_ANGLE_power_preference) {
- // It doesn't matter whether this context was explicitly allocated
- // with a power preference - ANGLE will take care of any default behavior.
- if (visibility) {
- eglReacquireHighPowerGPUANGLE(gl_display_->GetDisplay(), context_);
- } else {
- eglReleaseHighPowerGPUANGLE(gl_display_->GetDisplay(), context_);
- }
- }
- }
- GLDisplayEGL* GLContextEGL::GetGLDisplayEGL() {
- return gl_display_;
- }
- void GLContextEGL::ReleaseYUVToRGBConvertersAndBackpressureFences() {
- #if BUILDFLAG(IS_APPLE)
- bool has_backpressure_fences = HasBackpressureFences();
- #else
- bool has_backpressure_fences = false;
- #endif
- if (!yuv_to_rgb_converters_.empty() || has_backpressure_fences) {
- // If this context is not current, bind this context's API so that the YUV
- // converter can safely destruct
- GLContext* current_context = GetRealCurrent();
- if (current_context != this) {
- SetCurrentGL(GetCurrentGL());
- }
- EGLContext current_egl_context = eglGetCurrentContext();
- EGLSurface current_draw_surface = EGL_NO_SURFACE;
- EGLSurface current_read_surface = EGL_NO_SURFACE;
- if (context_ != current_egl_context) {
- current_draw_surface = eglGetCurrentSurface(EGL_DRAW);
- current_read_surface = eglGetCurrentSurface(EGL_READ);
- // This call relies on the fact that yuv_to_rgb_converters_ are only ever
- // allocated in GLImageIOSurfaceEGL::CopyTexImage, which is only on
- // MacOS, where surfaceless EGL contexts are always supported.
- if (!eglMakeCurrent(gl_display_->GetDisplay(), EGL_NO_SURFACE,
- EGL_NO_SURFACE, context_)) {
- LOG(ERROR) << "eglMakeCurrent failed with error "
- << GetLastEGLErrorString();
- }
- }
- yuv_to_rgb_converters_.clear();
- #if BUILDFLAG(IS_APPLE)
- DestroyBackpressureFences();
- #endif
- // Rebind the current context's API if needed.
- if (current_context && current_context != this) {
- SetCurrentGL(current_context->GetCurrentGL());
- }
- if (context_ != current_egl_context) {
- if (!eglMakeCurrent(gl_display_->GetDisplay(), current_draw_surface,
- current_read_surface, current_egl_context)) {
- LOG(ERROR) << "eglMakeCurrent failed with error "
- << GetLastEGLErrorString();
- }
- }
- }
- }
- bool GLContextEGL::MakeCurrentImpl(GLSurface* surface) {
- DCHECK(context_);
- if (lost_) {
- LOG(ERROR) << "Failed to make context current since it is marked as lost";
- return false;
- }
- if (IsCurrent(surface))
- return true;
- ScopedReleaseCurrent release_current;
- TRACE_EVENT2("gpu", "GLContextEGL::MakeCurrent", "context",
- static_cast<void*>(context_), "surface",
- static_cast<void*>(surface));
- if (unbind_fbo_on_makecurrent_ && GetCurrent()) {
- glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
- }
- if (!eglMakeCurrent(gl_display_->GetDisplay(), surface->GetHandle(),
- surface->GetHandle(), context_)) {
- LOG(ERROR) << "eglMakeCurrent failed with error "
- << GetLastEGLErrorString();
- return false;
- }
- // Set this as soon as the context is current, since we might call into GL.
- BindGLApi();
- SetCurrent(surface);
- InitializeDynamicBindings();
- if (!surface->OnMakeCurrent(this)) {
- LOG(ERROR) << "Could not make current.";
- return false;
- }
- release_current.Cancel();
- return true;
- }
- void GLContextEGL::SetUnbindFboOnMakeCurrent() {
- unbind_fbo_on_makecurrent_ = true;
- }
- void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
- if (!IsCurrent(surface))
- return;
- if (unbind_fbo_on_makecurrent_)
- glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
- SetCurrent(nullptr);
- if (!eglMakeCurrent(gl_display_->GetDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT)) {
- LOG(ERROR) << "eglMakeCurrent failed to release current with error "
- << GetLastEGLErrorString();
- lost_ = true;
- }
- DCHECK(!IsCurrent(nullptr));
- }
- bool GLContextEGL::IsCurrent(GLSurface* surface) {
- DCHECK(context_);
- if (lost_)
- return false;
- bool native_context_is_current = context_ == eglGetCurrentContext();
- // If our context is current then our notion of which GLContext is
- // current must be correct. On the other hand, third-party code
- // using OpenGL might change the current context.
- DCHECK(!native_context_is_current || (GetRealCurrent() == this));
- if (!native_context_is_current)
- return false;
- if (surface) {
- if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW))
- return false;
- }
- return true;
- }
- void* GLContextEGL::GetHandle() {
- return context_;
- }
- unsigned int GLContextEGL::CheckStickyGraphicsResetStatusImpl() {
- DCHECK(IsCurrent(nullptr));
- DCHECK(g_current_gl_driver);
- const ExtensionsGL& ext = g_current_gl_driver->ext;
- if ((graphics_reset_status_ == GL_NO_ERROR) &&
- gl_display_->ext->b_EGL_EXT_create_context_robustness &&
- (ext.b_GL_KHR_robustness || ext.b_GL_EXT_robustness ||
- ext.b_GL_ARB_robustness)) {
- graphics_reset_status_ = glGetGraphicsResetStatusARB();
- }
- return graphics_reset_status_;
- }
- GLContextEGL::~GLContextEGL() {
- Destroy();
- }
- } // namespace gl
|