[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / ui / gl / gl_context_egl.cc
blobed83b85ebd3cae5032592896753d9159a1435e55
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/gl/gl_context_egl.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/trace_event/trace_event.h"
11 #include "build/build_config.h"
12 #include "third_party/khronos/EGL/egl.h"
13 #include "third_party/khronos/EGL/eglext.h"
14 #include "ui/gl/egl_util.h"
15 #include "ui/gl/gl_bindings.h"
16 #include "ui/gl/gl_surface_egl.h"
18 #if defined(USE_X11)
19 extern "C" {
20 #include <X11/Xlib.h>
22 #endif
24 using ui::GetLastEGLErrorString;
26 namespace gfx {
28 GLContextEGL::GLContextEGL(GLShareGroup* share_group)
29 : GLContextReal(share_group),
30 context_(nullptr),
31 display_(nullptr),
32 config_(nullptr),
33 unbind_fbo_on_makecurrent_(false),
34 swap_interval_(1) {
37 bool GLContextEGL::Initialize(
38 GLSurface* compatible_surface, GpuPreference gpu_preference) {
39 DCHECK(compatible_surface);
40 DCHECK(!context_);
42 EGLint context_client_version = 2;
43 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
44 switches::kEnableUnsafeES3APIs)) {
45 context_client_version = 3;
48 const EGLint kContextAttributes[] = {
49 EGL_CONTEXT_CLIENT_VERSION, context_client_version,
50 EGL_NONE
52 const EGLint kContextRobustnessAttributes[] = {
53 EGL_CONTEXT_CLIENT_VERSION, context_client_version,
54 EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
55 EGL_LOSE_CONTEXT_ON_RESET_EXT,
56 EGL_NONE
59 display_ = compatible_surface->GetDisplay();
60 config_ = compatible_surface->GetConfig();
62 const EGLint* context_attributes = nullptr;
63 if (GLSurfaceEGL::IsCreateContextRobustnessSupported()) {
64 DVLOG(1) << "EGL_EXT_create_context_robustness supported.";
65 context_attributes = kContextRobustnessAttributes;
66 } else {
67 // At some point we should require the presence of the robustness
68 // extension and remove this code path.
69 DVLOG(1) << "EGL_EXT_create_context_robustness NOT supported.";
70 context_attributes = kContextAttributes;
73 context_ = eglCreateContext(
74 display_,
75 config_,
76 share_group() ? share_group()->GetHandle() : nullptr,
77 context_attributes);
79 if (!context_) {
80 LOG(ERROR) << "eglCreateContext failed with error "
81 << GetLastEGLErrorString();
82 return false;
85 return true;
88 void GLContextEGL::Destroy() {
89 if (context_) {
90 if (!eglDestroyContext(display_, context_)) {
91 LOG(ERROR) << "eglDestroyContext failed with error "
92 << GetLastEGLErrorString();
95 context_ = nullptr;
99 bool GLContextEGL::MakeCurrent(GLSurface* surface) {
100 DCHECK(context_);
101 if (IsCurrent(surface))
102 return true;
104 ScopedReleaseCurrent release_current;
105 TRACE_EVENT2("gpu", "GLContextEGL::MakeCurrent",
106 "context", context_,
107 "surface", surface);
109 if (unbind_fbo_on_makecurrent_ &&
110 eglGetCurrentContext() != EGL_NO_CONTEXT) {
111 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
114 if (!eglMakeCurrent(display_,
115 surface->GetHandle(),
116 surface->GetHandle(),
117 context_)) {
118 DVLOG(1) << "eglMakeCurrent failed with error "
119 << GetLastEGLErrorString();
120 return false;
123 // Set this as soon as the context is current, since we might call into GL.
124 SetRealGLApi();
126 SetCurrent(surface);
127 if (!InitializeDynamicBindings()) {
128 return false;
131 if (!surface->OnMakeCurrent(this)) {
132 LOG(ERROR) << "Could not make current.";
133 return false;
136 surface->OnSetSwapInterval(swap_interval_);
138 release_current.Cancel();
139 return true;
142 void GLContextEGL::SetUnbindFboOnMakeCurrent() {
143 unbind_fbo_on_makecurrent_ = true;
146 void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
147 if (!IsCurrent(surface))
148 return;
150 if (unbind_fbo_on_makecurrent_)
151 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
153 SetCurrent(nullptr);
154 eglMakeCurrent(display_,
155 EGL_NO_SURFACE,
156 EGL_NO_SURFACE,
157 EGL_NO_CONTEXT);
160 bool GLContextEGL::IsCurrent(GLSurface* surface) {
161 DCHECK(context_);
163 bool native_context_is_current = context_ == eglGetCurrentContext();
165 // If our context is current then our notion of which GLContext is
166 // current must be correct. On the other hand, third-party code
167 // using OpenGL might change the current context.
168 DCHECK(!native_context_is_current || (GetRealCurrent() == this));
170 if (!native_context_is_current)
171 return false;
173 if (surface) {
174 if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW))
175 return false;
178 return true;
181 void* GLContextEGL::GetHandle() {
182 return context_;
185 void GLContextEGL::OnSetSwapInterval(int interval) {
186 DCHECK(IsCurrent(nullptr) && GLSurface::GetCurrent());
188 // This is a surfaceless context. eglSwapInterval doesn't take any effect in
189 // this case and will just return EGL_BAD_SURFACE.
190 if (GLSurface::GetCurrent()->IsSurfaceless())
191 return;
193 if (!eglSwapInterval(display_, interval)) {
194 LOG(ERROR) << "eglSwapInterval failed with error "
195 << GetLastEGLErrorString();
196 } else {
197 swap_interval_ = interval;
198 GLSurface::GetCurrent()->OnSetSwapInterval(interval);
202 std::string GLContextEGL::GetExtensions() {
203 const char* extensions = eglQueryString(display_,
204 EGL_EXTENSIONS);
205 if (!extensions)
206 return GLContext::GetExtensions();
208 return GLContext::GetExtensions() + " " + extensions;
211 bool GLContextEGL::WasAllocatedUsingRobustnessExtension() {
212 return GLSurfaceEGL::IsCreateContextRobustnessSupported();
215 GLContextEGL::~GLContextEGL() {
216 Destroy();
219 #if !defined(OS_ANDROID)
220 bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
221 DCHECK(bytes);
222 *bytes = 0;
223 return false;
225 #endif
227 } // namespace gfx