[DevTools] Move DispatchOnDevToolsFrontend to embedder.
[chromium-blink-merge.git] / ui / gl / gl_context_glx.cc
blobd5ab073e40daf4c48411c10556e030fb469d2361
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.
5 extern "C" {
6 #include <X11/Xlib.h>
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"
20 namespace gfx {
22 GLContextGLX::GLContextGLX(GLShareGroup* share_group)
23 : GLContextReal(share_group),
24 context_(NULL),
25 display_(NULL) {
28 XDisplay* GLContextGLX::display() {
29 return display_;
32 bool GLContextGLX::Initialize(
33 GLSurface* compatible_surface, GpuPreference gpu_preference) {
34 display_ = static_cast<XDisplay*>(compatible_surface->GetDisplay());
36 GLXContext share_handle = static_cast<GLXContext>(
37 share_group() ? share_group()->GetHandle() : NULL);
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);
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;
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;
72 DCHECK(context_);
73 DVLOG(1) << " Successfully allocated "
74 << (compatible_surface->IsOffscreen() ?
75 "offscreen" : "onscreen")
76 << " GL context with LOSE_CONTEXT_ON_RESET_ARB";
78 DVLOG(1) << (compatible_surface->IsOffscreen() ? "Offscreen" : "Onscreen")
79 << " context was "
80 << (glXIsDirect(display_,
81 static_cast<GLXContext>(context_))
82 ? "direct" : "indirect")
83 << ".";
85 return true;
88 void GLContextGLX::Destroy() {
89 if (context_) {
90 glXDestroyContext(display_,
91 static_cast<GLXContext>(context_));
92 context_ = NULL;
96 bool GLContextGLX::MakeCurrent(GLSurface* surface) {
97 DCHECK(context_);
98 if (IsCurrent(surface))
99 return true;
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;
113 // Set this as soon as the context is current, since we might call into GL.
114 SetRealGLApi();
116 SetCurrent(surface);
117 if (!InitializeDynamicBindings()) {
118 Destroy();
119 return false;
122 if (!surface->OnMakeCurrent(this)) {
123 LOG(ERROR) << "Could not make current.";
124 Destroy();
125 return false;
128 release_current.Cancel();
129 return true;
132 void GLContextGLX::ReleaseCurrent(GLSurface* surface) {
133 if (!IsCurrent(surface))
134 return;
136 SetCurrent(NULL);
137 if (!glXMakeContextCurrent(display_, 0, 0, 0))
138 LOG(ERROR) << "glXMakeCurrent failed in ReleaseCurrent";
141 bool GLContextGLX::IsCurrent(GLSurface* surface) {
142 bool native_context_is_current =
143 glXGetCurrentContext() == static_cast<GLXContext>(context_);
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));
150 if (!native_context_is_current)
151 return false;
153 if (surface) {
154 if (glXGetCurrentDrawable() !=
155 reinterpret_cast<GLXDrawable>(surface->GetHandle())) {
156 return false;
160 return true;
163 void* GLContextGLX::GetHandle() {
164 return context_;
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";
186 std::string GLContextGLX::GetExtensions() {
187 DCHECK(IsCurrent(NULL));
188 const char* extensions = GLSurfaceGLX::GetGLXExtensions();
189 if (extensions) {
190 return GLContext::GetExtensions() + " " + extensions;
193 return GLContext::GetExtensions();
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;
205 return false;
208 bool GLContextGLX::WasAllocatedUsingRobustnessExtension() {
209 return GLSurfaceGLX::IsCreateContextRobustnessSupported();
212 GLContextGLX::~GLContextGLX() {
213 Destroy();
216 } // namespace gfx