diff options
Diffstat (limited to 'ui/gl/gl_context_egl.cc')
-rw-r--r-- | ui/gl/gl_context_egl.cc | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc new file mode 100644 index 0000000..fa655a0 --- /dev/null +++ b/ui/gl/gl_context_egl.cc @@ -0,0 +1,160 @@ +// 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 "base/debug/trace_event.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "build/build_config.h" +#include "third_party/angle/include/EGL/egl.h" +#include "ui/gl/egl_util.h" +#include "ui/gl/gl_surface.h" + +// This header must come after the above third-party include, as +// it brings in #defines that cause conflicts. +#include "ui/gl/gl_bindings.h" + +#if defined(USE_X11) +extern "C" { +#include <X11/Xlib.h> +} +#endif + +namespace gfx { + +std::string GLContextEGL::GetExtensions() { + const char* extensions = eglQueryString(display_, + EGL_EXTENSIONS); + if (!extensions) + return GLContext::GetExtensions(); + + return GLContext::GetExtensions() + " " + extensions; +} + +GLContextEGL::GLContextEGL(GLShareGroup* share_group) + : GLContext(share_group), + context_(NULL), + display_(NULL), + config_(NULL) { +} + +GLContextEGL::~GLContextEGL() { + Destroy(); +} + +bool GLContextEGL::Initialize( + GLSurface* compatible_surface, GpuPreference gpu_preference) { + DCHECK(compatible_surface); + DCHECK(!context_); + + static const EGLint kContextAttributes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + display_ = compatible_surface->GetDisplay(); + config_ = compatible_surface->GetConfig(); + + context_ = eglCreateContext( + display_, + config_, + share_group() ? share_group()->GetHandle() : NULL, + kContextAttributes); + if (!context_) { + LOG(ERROR) << "eglCreateContext failed with error " + << GetLastEGLErrorString(); + Destroy(); + return false; + } + + return true; +} + +void GLContextEGL::Destroy() { + if (context_) { + if (!eglDestroyContext(display_, context_)) { + LOG(ERROR) << "eglDestroyContext failed with error " + << GetLastEGLErrorString(); + } + + context_ = NULL; + } +} + +bool GLContextEGL::MakeCurrent(GLSurface* surface) { + DCHECK(context_); + if (IsCurrent(surface)) + return true; + + TRACE_EVENT0("gpu", "GLContextEGL::MakeCurrent"); + + if (!eglMakeCurrent(display_, + surface->GetHandle(), + surface->GetHandle(), + context_)) { + DVLOG(1) << "eglMakeCurrent failed with error " + << GetLastEGLErrorString(); + return false; + } + + SetCurrent(this, surface); + if (!InitializeExtensionBindings()) { + ReleaseCurrent(surface); + return false; + } + + if (!surface->OnMakeCurrent(this)) { + LOG(ERROR) << "Could not make current."; + return false; + } + + return true; +} + +void GLContextEGL::ReleaseCurrent(GLSurface* surface) { + if (!IsCurrent(surface)) + return; + + SetCurrent(NULL, NULL); + eglMakeCurrent(display_, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); +} + +bool GLContextEGL::IsCurrent(GLSurface* surface) { + DCHECK(context_); + + 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 || (GetCurrent() == 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_; +} + +void GLContextEGL::SetSwapInterval(int interval) { + DCHECK(IsCurrent(NULL)); + if (!eglSwapInterval(display_, interval)) { + LOG(ERROR) << "eglSwapInterval failed with error " + << GetLastEGLErrorString(); + } +} + +} // namespace gfx |