• 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 "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 std::unique_ptr<GLInterface> g_main_gl_interface;
27 
28 GLInterface* GLInterface::Create() {
29   return new GLXInterface;
30 }
31 
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)            \
51   fun = reinterpret_cast<type>( \
52       glXGetProcAddress(reinterpret_cast<const GLubyte*>(#fun)));
53   LIST_PROC_FUNCTIONS(F)
54 #undef F
55   _glXSwapIntervalMESA =
56       reinterpret_cast<PFNGLXSWAPINTERVALMESAPROC>(glXGetProcAddress(
57           reinterpret_cast<const GLubyte*>("glXSwapIntervalMESA")));
58 
59   return true;
60 }
61 
62 void GLXInterface::Cleanup() {
63   glXMakeCurrent(g_xlib_display, 0, NULL);
64   DeleteContext(context_);
65 }
66 
67 XVisualInfo* GLXInterface::GetXVisual() {
68   if (!fb_config_) {
69     int screen = DefaultScreen(g_xlib_display);
70     int attrib[] = {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     int nelements;
79     GLXFBConfig* fb_configs =
80         glXChooseFBConfig(g_xlib_display, screen, attrib, &nelements);
81     CHECK(nelements >= 1);
82     fb_config_ = fb_configs[0];
83     XFree(fb_configs);
84   }
85 
86   return glXGetVisualFromFBConfig(g_xlib_display, fb_config_);
87 }
88 
89 bool GLXInterface::MakeCurrent(const GLContext& context) {
90   return glXMakeCurrent(g_xlib_display, g_xlib_window, context);
91 }
92 
93 const GLContext GLXInterface::CreateContext() {
94   CHECK(g_xlib_display);
95   CHECK(fb_config_);
96   return glXCreateNewContext(g_xlib_display, fb_config_, GLX_RGBA_TYPE, 0,
97                              True);
98 }
99 
100 void GLXInterface::DeleteContext(const GLContext& context) {
101   glXDestroyContext(g_xlib_display, context);
102 }
103 
104 void GLXInterface::SwapBuffers() {
105   glXSwapBuffers(g_xlib_display, g_xlib_window);
106 }
107 
108 bool GLXInterface::SwapInterval(int interval) {
109   // Strictly, glXSwapIntervalSGI only allows interval > 0, whereas
110   // glXSwapIntervalMESA allow 0 with the same semantics as eglSwapInterval.
111   if (_glXSwapIntervalMESA) {
112     return _glXSwapIntervalMESA(interval) == 0;
113   } else {
114     return glXSwapIntervalSGI(interval) == 0;
115   }
116 }
117 
118 void GLXInterface::CheckError() {
119   CHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
120 };
121