Home | History | Annotate | Download | only in src
      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