Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_context_glx.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 extern "C" {
6 #include <X11/Xlib.h>
7 }
8
9 #include "ui/gl/gl_context_glx.h"
10
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "third_party/mesa/src/include/GL/osmesa.h"
15 #include "ui/gl/GL/glextchromium.h"
16 #include "ui/gl/gl_bindings.h"
17 #include "ui/gl/gl_implementation.h"
18 #include "ui/gl/gl_surface_glx.h"
19
20 namespace gfx {
21
22 GLContextGLX::GLContextGLX(GLShareGroup* share_group)
23   : GLContextReal(share_group),
24     context_(NULL),
25     display_(NULL) {
26 }
27
28 XDisplay* GLContextGLX::display() {
29   return display_;
30 }
31
32 bool GLContextGLX::Initialize(
33     GLSurface* compatible_surface, GpuPreference gpu_preference) {
34   display_ = static_cast<XDisplay*>(compatible_surface->GetDisplay());
35
36   GLXContext share_handle = static_cast<GLXContext>(
37       share_group() ? share_group()->GetHandle() : NULL);
38
39   if (GLSurfaceGLX::IsCreateContextSupported()) {
40     DVLOG(1) << "GLX_ARB_create_context supported.";
41     std::vector<int> attribs;
42     if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) {
43       DVLOG(1) << "GLX_ARB_create_context_robustness supported.";
44       attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
45       attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
46     }
47     attribs.push_back(0);
48     context_ = glXCreateContextAttribsARB(
49         display_,
50         static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
51         share_handle,
52         True,
53         &attribs.front());
54     if (!context_) {
55       LOG(ERROR) << "Failed to create GL context with "
56                  << "glXCreateContextAttribsARB.";
57       return false;
58     }
59   } else {
60     DVLOG(1) << "GLX_ARB_create_context not supported.";
61     context_ = glXCreateNewContext(
62        display_,
63        static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
64        GLX_RGBA_TYPE,
65        share_handle,
66        True);
67     if (!context_) {
68       LOG(ERROR) << "Failed to create GL context with glXCreateNewContext.";
69       return false;
70     }
71   }
72   DCHECK(context_);
73   DVLOG(1) << "  Successfully allocated "
74            << (compatible_surface->IsOffscreen() ?
75                "offscreen" : "onscreen")
76            << " GL context with LOSE_CONTEXT_ON_RESET_ARB";
77
78   DVLOG(1) << (compatible_surface->IsOffscreen() ? "Offscreen" : "Onscreen")
79            << " context was "
80            << (glXIsDirect(display_,
81                            static_cast<GLXContext>(context_))
82                    ? "direct" : "indirect")
83            << ".";
84
85   return true;
86 }
87
88 void GLContextGLX::Destroy() {
89   if (context_) {
90     glXDestroyContext(display_,
91                       static_cast<GLXContext>(context_));
92     context_ = NULL;
93   }
94 }
95
96 bool GLContextGLX::MakeCurrent(GLSurface* surface) {
97   DCHECK(context_);
98   if (IsCurrent(surface))
99     return true;
100
101   ScopedReleaseCurrent release_current;
102   TRACE_EVENT0("gpu", "GLContextGLX::MakeCurrent");
103   if (!glXMakeContextCurrent(
104       display_,
105       reinterpret_cast<GLXDrawable>(surface->GetHandle()),
106       reinterpret_cast<GLXDrawable>(surface->GetHandle()),
107       static_cast<GLXContext>(context_))) {
108     LOG(ERROR) << "Couldn't make context current with X drawable.";
109     Destroy();
110     return false;
111   }
112
113   // Set this as soon as the context is current, since we might call into GL.
114   SetRealGLApi();
115
116   SetCurrent(surface);
117   if (!InitializeDynamicBindings()) {
118     Destroy();
119     return false;
120   }
121
122   if (!surface->OnMakeCurrent(this)) {
123     LOG(ERROR) << "Could not make current.";
124     Destroy();
125     return false;
126   }
127
128   release_current.Cancel();
129   return true;
130 }
131
132 void GLContextGLX::ReleaseCurrent(GLSurface* surface) {
133   if (!IsCurrent(surface))
134     return;
135
136   SetCurrent(NULL);
137   if (!glXMakeContextCurrent(display_, 0, 0, 0))
138     LOG(ERROR) << "glXMakeCurrent failed in ReleaseCurrent";
139 }
140
141 bool GLContextGLX::IsCurrent(GLSurface* surface) {
142   bool native_context_is_current =
143       glXGetCurrentContext() == static_cast<GLXContext>(context_);
144
145   // If our context is current then our notion of which GLContext is
146   // current must be correct. On the other hand, third-party code
147   // using OpenGL might change the current context.
148   DCHECK(!native_context_is_current || (GetRealCurrent() == this));
149
150   if (!native_context_is_current)
151     return false;
152
153   if (surface) {
154     if (glXGetCurrentDrawable() !=
155         reinterpret_cast<GLXDrawable>(surface->GetHandle())) {
156       return false;
157     }
158   }
159
160   return true;
161 }
162
163 void* GLContextGLX::GetHandle() {
164   return context_;
165 }
166
167 void GLContextGLX::SetSwapInterval(int interval) {
168   DCHECK(IsCurrent(NULL));
169   if (HasExtension("GLX_EXT_swap_control") &&
170       g_driver_glx.fn.glXSwapIntervalEXTFn) {
171     glXSwapIntervalEXT(
172         display_,
173         glXGetCurrentDrawable(),
174         interval);
175   } else if (HasExtension("GLX_MESA_swap_control") &&
176              g_driver_glx.fn.glXSwapIntervalMESAFn) {
177     glXSwapIntervalMESA(interval);
178   } else {
179     if(interval == 0)
180       LOG(WARNING) <<
181           "Could not disable vsync: driver does not "
182           "support GLX_EXT_swap_control";
183   }
184 }
185
186 std::string GLContextGLX::GetExtensions() {
187   DCHECK(IsCurrent(NULL));
188   const char* extensions = GLSurfaceGLX::GetGLXExtensions();
189   if (extensions) {
190     return GLContext::GetExtensions() + " " + extensions;
191   }
192
193   return GLContext::GetExtensions();
194 }
195
196 bool GLContextGLX::GetTotalGpuMemory(size_t* bytes) {
197   DCHECK(bytes);
198   *bytes = 0;
199   if (HasExtension("GL_NVX_gpu_memory_info")) {
200     GLint kbytes = 0;
201     glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &kbytes);
202     *bytes = 1024*kbytes;
203     return true;
204   }
205   return false;
206 }
207
208 bool GLContextGLX::WasAllocatedUsingRobustnessExtension() {
209   return GLSurfaceGLX::IsCreateContextRobustnessSupported();
210 }
211
212 GLContextGLX::~GLContextGLX() {
213   Destroy();
214 }
215
216 }  // namespace gfx