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.
9 #include "ui/gl/gl_context_glx.h"
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"
24 // scoped_ptr functor for XFree(). Use as follows:
25 // scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
26 // where "XVisualInfo" is any X type that is freed with XFree.
27 class ScopedPtrXFree
{
29 void operator()(void* x
) const {
36 GLContextGLX::GLContextGLX(GLShareGroup
* share_group
)
37 : GLContextReal(share_group
),
42 Display
* GLContextGLX::display() {
46 bool GLContextGLX::Initialize(
47 GLSurface
* compatible_surface
, GpuPreference gpu_preference
) {
48 display_
= static_cast<Display
*>(compatible_surface
->GetDisplay());
50 GLXContext share_handle
= static_cast<GLXContext
>(
51 share_group() ? share_group()->GetHandle() : NULL
);
53 if (GLSurfaceGLX::IsCreateContextSupported()) {
54 DVLOG(1) << "GLX_ARB_create_context supported.";
55 std::vector
<int> attribs
;
56 if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) {
57 DVLOG(1) << "GLX_ARB_create_context_robustness supported.";
58 attribs
.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
);
59 attribs
.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB
);
62 context_
= glXCreateContextAttribsARB(
64 static_cast<GLXFBConfig
>(compatible_surface
->GetConfig()),
69 LOG(ERROR
) << "Failed to create GL context with "
70 << "glXCreateContextAttribsARB.";
74 DVLOG(1) << "GLX_ARB_create_context not supported.";
75 context_
= glXCreateNewContext(
77 static_cast<GLXFBConfig
>(compatible_surface
->GetConfig()),
82 LOG(ERROR
) << "Failed to create GL context with glXCreateNewContext.";
87 DVLOG(1) << " Successfully allocated "
88 << (compatible_surface
->IsOffscreen() ?
89 "offscreen" : "onscreen")
90 << " GL context with LOSE_CONTEXT_ON_RESET_ARB";
92 DVLOG(1) << (compatible_surface
->IsOffscreen() ? "Offscreen" : "Onscreen")
94 << (glXIsDirect(display_
,
95 static_cast<GLXContext
>(context_
))
96 ? "direct" : "indirect")
102 void GLContextGLX::Destroy() {
104 glXDestroyContext(display_
,
105 static_cast<GLXContext
>(context_
));
110 bool GLContextGLX::MakeCurrent(GLSurface
* surface
) {
112 if (IsCurrent(surface
))
115 TRACE_EVENT0("gpu", "GLContextGLX::MakeCurrent");
116 if (!glXMakeContextCurrent(
118 reinterpret_cast<GLXDrawable
>(surface
->GetHandle()),
119 reinterpret_cast<GLXDrawable
>(surface
->GetHandle()),
120 static_cast<GLXContext
>(context_
))) {
121 LOG(ERROR
) << "Couldn't make context current with X drawable.";
126 // Set this as soon as the context is current, since we might call into GL.
130 if (!InitializeExtensionBindings()) {
131 ReleaseCurrent(surface
);
136 if (!surface
->OnMakeCurrent(this)) {
137 LOG(ERROR
) << "Could not make current.";
138 ReleaseCurrent(surface
);
146 void GLContextGLX::ReleaseCurrent(GLSurface
* surface
) {
147 if (!IsCurrent(surface
))
151 if (!glXMakeContextCurrent(display_
, 0, 0, 0))
152 LOG(ERROR
) << "glXMakeCurrent failed in ReleaseCurrent";
155 bool GLContextGLX::IsCurrent(GLSurface
* surface
) {
156 bool native_context_is_current
=
157 glXGetCurrentContext() == static_cast<GLXContext
>(context_
);
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));
164 if (!native_context_is_current
)
168 if (glXGetCurrentDrawable() !=
169 reinterpret_cast<GLXDrawable
>(surface
->GetHandle())) {
177 void* GLContextGLX::GetHandle() {
181 void GLContextGLX::SetSwapInterval(int interval
) {
182 DCHECK(IsCurrent(NULL
));
183 if (HasExtension("GLX_EXT_swap_control") &&
184 g_driver_glx
.fn
.glXSwapIntervalEXTFn
) {
187 glXGetCurrentDrawable(),
189 } else if (HasExtension("GLX_MESA_swap_control") &&
190 g_driver_glx
.fn
.glXSwapIntervalMESAFn
) {
191 glXSwapIntervalMESA(interval
);
195 "Could not disable vsync: driver does not "
196 "support GLX_EXT_swap_control";
200 std::string
GLContextGLX::GetExtensions() {
201 DCHECK(IsCurrent(NULL
));
202 const char* extensions
= GLSurfaceGLX::GetGLXExtensions();
204 return GLContext::GetExtensions() + " " + extensions
;
207 return GLContext::GetExtensions();
210 bool GLContextGLX::GetTotalGpuMemory(size_t* bytes
) {
213 if (HasExtension("GL_NVX_gpu_memory_info")) {
215 glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
, &kbytes
);
216 *bytes
= 1024*kbytes
;
222 bool GLContextGLX::WasAllocatedUsingRobustnessExtension() {
223 return GLSurfaceGLX::IsCreateContextRobustnessSupported();
226 GLContextGLX::~GLContextGLX() {