Mac: Fix performance issues with remote CoreAnimation
[chromium-blink-merge.git] / ui / gl / gl_context_glx.cc
blob9b6cfb452f8f1fa090cd312ec1856fda2a156ce0
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 "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"
19 namespace gfx {
21 GLContextGLX::GLContextGLX(GLShareGroup* share_group)
22 : GLContextReal(share_group),
23 context_(NULL),
24 display_(NULL) {
27 XDisplay* GLContextGLX::display() {
28 return display_;
31 bool GLContextGLX::Initialize(
32 GLSurface* compatible_surface, GpuPreference gpu_preference) {
33 display_ = static_cast<XDisplay*>(compatible_surface->GetDisplay());
35 GLXContext share_handle = static_cast<GLXContext>(
36 share_group() ? share_group()->GetHandle() : NULL);
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);
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;
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;
71 DCHECK(context_);
72 DVLOG(1) << " Successfully allocated "
73 << (compatible_surface->IsOffscreen() ?
74 "offscreen" : "onscreen")
75 << " GL context with LOSE_CONTEXT_ON_RESET_ARB";
77 DVLOG(1) << (compatible_surface->IsOffscreen() ? "Offscreen" : "Onscreen")
78 << " context was "
79 << (glXIsDirect(display_,
80 static_cast<GLXContext>(context_))
81 ? "direct" : "indirect")
82 << ".";
84 return true;
87 void GLContextGLX::Destroy() {
88 if (context_) {
89 glXDestroyContext(display_,
90 static_cast<GLXContext>(context_));
91 context_ = NULL;
95 bool GLContextGLX::MakeCurrent(GLSurface* surface) {
96 DCHECK(context_);
97 if (IsCurrent(surface))
98 return true;
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;
112 // Set this as soon as the context is current, since we might call into GL.
113 SetRealGLApi();
115 SetCurrent(surface);
116 if (!InitializeDynamicBindings()) {
117 Destroy();
118 return false;
121 if (!surface->OnMakeCurrent(this)) {
122 LOG(ERROR) << "Could not make current.";
123 Destroy();
124 return false;
127 release_current.Cancel();
128 return true;
131 void GLContextGLX::ReleaseCurrent(GLSurface* surface) {
132 if (!IsCurrent(surface))
133 return;
135 SetCurrent(NULL);
136 if (!glXMakeContextCurrent(display_, 0, 0, 0))
137 LOG(ERROR) << "glXMakeCurrent failed in ReleaseCurrent";
140 bool GLContextGLX::IsCurrent(GLSurface* surface) {
141 bool native_context_is_current =
142 glXGetCurrentContext() == static_cast<GLXContext>(context_);
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));
149 if (!native_context_is_current)
150 return false;
152 if (surface) {
153 if (glXGetCurrentDrawable() !=
154 reinterpret_cast<GLXDrawable>(surface->GetHandle())) {
155 return false;
159 return true;
162 void* GLContextGLX::GetHandle() {
163 return context_;
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";
185 std::string GLContextGLX::GetExtensions() {
186 DCHECK(IsCurrent(NULL));
187 const char* extensions = GLSurfaceGLX::GetGLXExtensions();
188 if (extensions) {
189 return GLContext::GetExtensions() + " " + extensions;
192 return GLContext::GetExtensions();
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;
204 return false;
207 bool GLContextGLX::WasAllocatedUsingRobustnessExtension() {
208 return GLSurfaceGLX::IsCreateContextRobustnessSupported();
211 GLContextGLX::~GLContextGLX() {
212 Destroy();
215 } // namespace gfx