• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 The Chromium OS 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 #include <GL/gl.h>
6 #include <string.h>
7 
8 #include "base/logging.h"
9 
10 #include "glx_stuff.h"
11 #include "main.h"
12 #include "xlib_window.h"
13 
14 namespace gl {
15 #define F(fun, type) type fun = NULL;
16 LIST_PROC_FUNCTIONS(F)
17 #undef F
18 };
19 
20 #ifndef GLX_MESA_swap_control
21 typedef GLint (* PFNGLXSWAPINTERVALMESAPROC) (unsigned interval);
22 typedef GLint (* PFNGLXGETSWAPINTERVALMESAPROC) (void);
23 #endif
24 PFNGLXSWAPINTERVALMESAPROC _glXSwapIntervalMESA = NULL;
25 
26 scoped_ptr<GLInterface> g_main_gl_interface;
27 
Create()28 GLInterface* GLInterface::Create() {
29   return new GLXInterface;
30 }
31 
Init()32 bool GLXInterface::Init() {
33   if (!XlibInit())
34     return false;
35 
36   context_ = CreateContext();
37   if (!context_)
38     return false;
39 
40   if (!glXMakeCurrent(g_xlib_display, g_xlib_window, context_)) {
41     glXDestroyContext(g_xlib_display, context_);
42     return false;
43   }
44 
45   const GLubyte *str = glGetString(GL_EXTENSIONS);
46   if (!str || !strstr(reinterpret_cast<const char *>(str),
47                       "GL_ARB_vertex_buffer_object"))
48     return false;
49 
50 #define F(fun, type) fun = reinterpret_cast<type>( \
51     glXGetProcAddress(reinterpret_cast<const GLubyte *>(#fun)));
52   LIST_PROC_FUNCTIONS(F)
53 #undef F
54   _glXSwapIntervalMESA = reinterpret_cast<PFNGLXSWAPINTERVALMESAPROC>(
55     glXGetProcAddress(reinterpret_cast<const GLubyte *>(
56         "glXSwapIntervalMESA")));
57 
58   return true;
59 }
60 
Cleanup()61 void GLXInterface::Cleanup() {
62   glXMakeCurrent(g_xlib_display, 0, NULL);
63   DeleteContext(context_);
64 }
65 
GetXVisual()66 XVisualInfo* GLXInterface::GetXVisual() {
67   if (!fb_config_) {
68     int screen = DefaultScreen(g_xlib_display);
69     int attrib[] = {
70       GLX_DOUBLEBUFFER, True,
71       GLX_RED_SIZE, 1,
72       GLX_GREEN_SIZE, 1,
73       GLX_BLUE_SIZE, 1,
74       GLX_DEPTH_SIZE, 1,
75       GLX_STENCIL_SIZE, 1,
76       GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
77       None
78     };
79     int nelements;
80     GLXFBConfig *fb_configs = glXChooseFBConfig(g_xlib_display, screen,
81                                                 attrib, &nelements);
82     CHECK(nelements >= 1);
83     fb_config_ = fb_configs[0];
84     XFree(fb_configs);
85   }
86 
87   return glXGetVisualFromFBConfig(g_xlib_display, fb_config_);
88 }
89 
MakeCurrent(const GLContext & context)90 bool GLXInterface::MakeCurrent(const GLContext& context) {
91   return glXMakeCurrent(g_xlib_display, g_xlib_window, context);
92 }
93 
CreateContext()94 const GLContext GLXInterface::CreateContext() {
95   CHECK(g_xlib_display);
96   CHECK(fb_config_);
97   return glXCreateNewContext(g_xlib_display, fb_config_, GLX_RGBA_TYPE, 0,
98                              True);
99 }
100 
DeleteContext(const GLContext & context)101 void GLXInterface::DeleteContext(const GLContext& context) {
102   glXDestroyContext(g_xlib_display, context);
103 }
104 
SwapBuffers()105 void GLXInterface::SwapBuffers() {
106   glXSwapBuffers(g_xlib_display, g_xlib_window);
107 }
108 
SwapInterval(int interval)109 bool GLXInterface::SwapInterval(int interval) {
110   // Strictly, glXSwapIntervalSGI only allows interval > 0, whereas
111   // glXSwapIntervalMESA allow 0 with the same semantics as eglSwapInterval.
112   if (_glXSwapIntervalMESA) {
113     return _glXSwapIntervalMESA(interval) == 0;
114   } else {
115     return glXSwapIntervalSGI(interval) == 0;
116   }
117 }
118 
CheckError()119 void GLXInterface::CheckError() {
120   CHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
121 };
122