Update To 11.40.268.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 #if defined(USE_OZONE)
116   eglSwapInterval(display_, 0);
117 #endif
118
119   // Set this as soon as the context is current, since we might call into GL.
120   SetRealGLApi();
121
122   SetCurrent(surface);
123   if (!InitializeDynamicBindings()) {
124     return false;
125   }
126
127   if (!surface->OnMakeCurrent(this)) {
128     LOG(ERROR) << "Could not make current.";
129     return false;
130   }
131
132   release_current.Cancel();
133   return true;
134 }
135
136 void GLContextEGL::SetUnbindFboOnMakeCurrent() {
137   unbind_fbo_on_makecurrent_ = true;
138 }
139
140 void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
141   if (!IsCurrent(surface))
142     return;
143
144   if (unbind_fbo_on_makecurrent_)
145     glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
146
147   SetCurrent(NULL);
148   eglMakeCurrent(display_,
149                  EGL_NO_SURFACE,
150                  EGL_NO_SURFACE,
151                  EGL_NO_CONTEXT);
152 }
153
154 bool GLContextEGL::IsCurrent(GLSurface* surface) {
155   DCHECK(context_);
156
157   bool native_context_is_current = context_ == eglGetCurrentContext();
158
159   // If our context is current then our notion of which GLContext is
160   // current must be correct. On the other hand, third-party code
161   // using OpenGL might change the current context.
162   DCHECK(!native_context_is_current || (GetRealCurrent() == this));
163
164   if (!native_context_is_current)
165     return false;
166
167   if (surface) {
168     if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW))
169       return false;
170   }
171
172   return true;
173 }
174
175 void* GLContextEGL::GetHandle() {
176   return context_;
177 }
178
179 void GLContextEGL::SetSwapInterval(int interval) {
180   DCHECK(IsCurrent(NULL) && GLSurface::GetCurrent());
181
182   // This is a surfaceless context. eglSwapInterval doesn't take any effect in
183   // this case and will just return EGL_BAD_SURFACE.
184   if (GLSurface::GetCurrent()->IsSurfaceless())
185     return;
186
187   if (!eglSwapInterval(display_, interval)) {
188     LOG(ERROR) << "eglSwapInterval failed with error "
189                << GetLastEGLErrorString();
190   } else {
191     GLSurface::GetCurrent()->SetSwapInterval(interval);
192   }
193 }
194
195 std::string GLContextEGL::GetExtensions() {
196   const char* extensions = eglQueryString(display_,
197                                           EGL_EXTENSIONS);
198   if (!extensions)
199     return GLContext::GetExtensions();
200
201   return GLContext::GetExtensions() + " " + extensions;
202 }
203
204 bool GLContextEGL::WasAllocatedUsingRobustnessExtension() {
205   return GLSurfaceEGL::IsCreateContextRobustnessSupported();
206 }
207
208 GLContextEGL::~GLContextEGL() {
209   Destroy();
210 }
211
212 #if !defined(OS_ANDROID)
213 bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) {
214   DCHECK(bytes);
215   *bytes = 0;
216   return false;
217 }
218 #endif
219
220 }  // namespace gfx