• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ui/gl/gl_context_egl.h"
6 
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "build/build_config.h"
11 #include "third_party/khronos/EGL/egl.h"
12 #include "third_party/khronos/EGL/eglext.h"
13 #include "ui/gl/egl_util.h"
14 #include "ui/gl/gl_bindings.h"
15 #include "ui/gl/gl_surface_egl.h"
16 
17 #if defined(USE_X11)
18 extern "C" {
19 #include <X11/Xlib.h>
20 }
21 #endif
22 
23 using ui::GetLastEGLErrorString;
24 
25 namespace gfx {
26 
GLContextEGL(GLShareGroup * share_group)27 GLContextEGL::GLContextEGL(GLShareGroup* share_group)
28     : GLContextReal(share_group),
29       context_(NULL),
30       display_(NULL),
31       config_(NULL),
32       unbind_fbo_on_makecurrent_(false) {
33 }
34 
Initialize(GLSurface * compatible_surface,GpuPreference gpu_preference)35 bool GLContextEGL::Initialize(
36     GLSurface* compatible_surface, GpuPreference gpu_preference) {
37   DCHECK(compatible_surface);
38   DCHECK(!context_);
39 
40   static const EGLint kContextAttributes[] = {
41     EGL_CONTEXT_CLIENT_VERSION, 2,
42     EGL_NONE
43   };
44   static const EGLint kContextRobustnessAttributes[] = {
45     EGL_CONTEXT_CLIENT_VERSION, 2,
46     EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
47     EGL_LOSE_CONTEXT_ON_RESET_EXT,
48     EGL_NONE
49   };
50 
51   display_ = compatible_surface->GetDisplay();
52   config_ = compatible_surface->GetConfig();
53 
54   const EGLint* context_attributes = NULL;
55   if (GLSurfaceEGL::IsCreateContextRobustnessSupported()) {
56     DVLOG(1) << "EGL_EXT_create_context_robustness supported.";
57     context_attributes = kContextRobustnessAttributes;
58   } else {
59     // At some point we should require the presence of the robustness
60     // extension and remove this code path.
61     DVLOG(1) << "EGL_EXT_create_context_robustness NOT supported.";
62     context_attributes = kContextAttributes;
63   }
64 
65   context_ = eglCreateContext(
66       display_,
67       config_,
68       share_group() ? share_group()->GetHandle() : NULL,
69       context_attributes);
70 
71   if (!context_) {
72     LOG(ERROR) << "eglCreateContext failed with error "
73                << GetLastEGLErrorString();
74     return false;
75   }
76 
77   return true;
78 }
79 
Destroy()80 void GLContextEGL::Destroy() {
81   if (context_) {
82     if (!eglDestroyContext(display_, context_)) {
83       LOG(ERROR) << "eglDestroyContext failed with error "
84                  << GetLastEGLErrorString();
85     }
86 
87     context_ = NULL;
88   }
89 }
90 
MakeCurrent(GLSurface * surface)91 bool GLContextEGL::MakeCurrent(GLSurface* surface) {
92   DCHECK(context_);
93   if (IsCurrent(surface))
94       return true;
95 
96   ScopedReleaseCurrent release_current;
97   TRACE_EVENT2("gpu", "GLContextEGL::MakeCurrent",
98                "context", context_,
99                "surface", surface);
100 
101   if (unbind_fbo_on_makecurrent_ &&
102       eglGetCurrentContext() != EGL_NO_CONTEXT) {
103     glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
104   }
105 
106   if (!eglMakeCurrent(display_,
107                       surface->GetHandle(),
108                       surface->GetHandle(),
109                       context_)) {
110     DVLOG(1) << "eglMakeCurrent failed with error "
111              << GetLastEGLErrorString();
112     return false;
113   }
114 
115   // Set this as soon as the context is current, since we might call into GL.
116   SetRealGLApi();
117 
118   SetCurrent(surface);
119   if (!InitializeDynamicBindings()) {
120     return false;
121   }
122 
123   if (!surface->OnMakeCurrent(this)) {
124     LOG(ERROR) << "Could not make current.";
125     return false;
126   }
127 
128   release_current.Cancel();
129   return true;
130 }
131 
SetUnbindFboOnMakeCurrent()132 void GLContextEGL::SetUnbindFboOnMakeCurrent() {
133   unbind_fbo_on_makecurrent_ = true;
134 }
135 
ReleaseCurrent(GLSurface * surface)136 void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
137   if (!IsCurrent(surface))
138     return;
139 
140   if (unbind_fbo_on_makecurrent_)
141     glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
142 
143   SetCurrent(NULL);
144   eglMakeCurrent(display_,
145                  EGL_NO_SURFACE,
146                  EGL_NO_SURFACE,
147                  EGL_NO_CONTEXT);
148 }
149 
IsCurrent(GLSurface * surface)150 bool GLContextEGL::IsCurrent(GLSurface* surface) {
151   DCHECK(context_);
152 
153   bool native_context_is_current = context_ == eglGetCurrentContext();
154 
155   // If our context is current then our notion of which GLContext is
156   // current must be correct. On the other hand, third-party code
157   // using OpenGL might change the current context.
158   DCHECK(!native_context_is_current || (GetRealCurrent() == this));
159 
160   if (!native_context_is_current)
161     return false;
162 
163   if (surface) {
164     if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW))
165       return false;
166   }
167 
168   return true;
169 }
170 
GetHandle()171 void* GLContextEGL::GetHandle() {
172   return context_;
173 }
174 
SetSwapInterval(int interval)175 void GLContextEGL::SetSwapInterval(int interval) {
176   DCHECK(IsCurrent(NULL));
177   if (!eglSwapInterval(display_, interval)) {
178     LOG(ERROR) << "eglSwapInterval failed with error "
179                << GetLastEGLErrorString();
180   }
181 }
182 
GetExtensions()183 std::string GLContextEGL::GetExtensions() {
184   const char* extensions = eglQueryString(display_,
185                                           EGL_EXTENSIONS);
186   if (!extensions)
187     return GLContext::GetExtensions();
188 
189   return GLContext::GetExtensions() + " " + extensions;
190 }
191 
WasAllocatedUsingRobustnessExtension()192 bool GLContextEGL::WasAllocatedUsingRobustnessExtension() {
193   return GLSurfaceEGL::IsCreateContextRobustnessSupported();
194 }
195 
~GLContextEGL()196 GLContextEGL::~GLContextEGL() {
197   Destroy();
198 }
199 
200 #if !defined(OS_ANDROID)
GetTotalGpuMemory(size_t * bytes)201 bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
202   DCHECK(bytes);
203   *bytes = 0;
204   return false;
205 }
206 #endif
207 
208 }  // namespace gfx
209