Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_context_egl.cc
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
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
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
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
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
132 void GLContextEGL::SetUnbindFboOnMakeCurrent() {
133   unbind_fbo_on_makecurrent_ = true;
134 }
135
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
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
171 void* GLContextEGL::GetHandle() {
172   return context_;
173 }
174
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
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
192 bool GLContextEGL::WasAllocatedUsingRobustnessExtension() {
193   return GLSurfaceEGL::IsCreateContextRobustnessSupported();
194 }
195
196 GLContextEGL::~GLContextEGL() {
197   Destroy();
198 }
199
200 #if !defined(OS_ANDROID)
201 bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
202   DCHECK(bytes);
203   *bytes = 0;
204   return false;
205 }
206 #endif
207
208 }  // namespace gfx