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 "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