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