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