blob: c2909dba3b88a04b3160656e21ada146a3e67e67 [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <GL/gl.h>
#include <string.h>
#include <memory>
#include "glx_stuff.h"
#include "main.h"
#include "xlib_window.h"
namespace gl {
#define F(fun, type) type fun = NULL;
LIST_PROC_FUNCTIONS(F)
#undef F
}; // namespace gl
#ifndef GLX_MESA_swap_control
typedef GLint (*PFNGLXSWAPINTERVALMESAPROC)(unsigned interval);
typedef GLint (*PFNGLXGETSWAPINTERVALMESAPROC)(void);
#endif
PFNGLXSWAPINTERVALMESAPROC _glXSwapIntervalMESA = NULL;
std::unique_ptr<GLInterface> g_main_gl_interface;
GLInterface* GLInterface::Create() {
return new GLXInterface;
}
bool GLXInterface::Init() {
if (!XlibInit())
return false;
context_ = CreateContext();
if (!context_)
return false;
if (!glXMakeCurrent(g_xlib_display, g_xlib_window, context_)) {
glXDestroyContext(g_xlib_display, context_);
return false;
}
const GLubyte* str = glGetString(GL_EXTENSIONS);
if (!str || !strstr(reinterpret_cast<const char*>(str),
"GL_ARB_vertex_buffer_object"))
return false;
#define F(fun, type) \
fun = reinterpret_cast<type>( \
glXGetProcAddress(reinterpret_cast<const GLubyte*>(#fun)));
LIST_PROC_FUNCTIONS(F)
#undef F
_glXSwapIntervalMESA =
reinterpret_cast<PFNGLXSWAPINTERVALMESAPROC>(glXGetProcAddress(
reinterpret_cast<const GLubyte*>("glXSwapIntervalMESA")));
return true;
}
void GLXInterface::Cleanup() {
glXMakeCurrent(g_xlib_display, 0, NULL);
DeleteContext(context_);
}
XVisualInfo* GLXInterface::GetXVisual() {
if (!fb_config_) {
int screen = DefaultScreen(g_xlib_display);
int attrib[] = {GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_STENCIL_SIZE, 1,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
None};
int nelements;
GLXFBConfig* fb_configs =
glXChooseFBConfig(g_xlib_display, screen, attrib, &nelements);
CHECK(nelements >= 1);
fb_config_ = fb_configs[0];
XFree(fb_configs);
}
return glXGetVisualFromFBConfig(g_xlib_display, fb_config_);
}
bool GLXInterface::MakeCurrent(const GLContext& context) {
return glXMakeCurrent(g_xlib_display, g_xlib_window, context);
}
const GLContext GLXInterface::CreateContext() {
CHECK(g_xlib_display);
CHECK(fb_config_);
return glXCreateNewContext(g_xlib_display, fb_config_, GLX_RGBA_TYPE, 0,
True);
}
void GLXInterface::DeleteContext(const GLContext& context) {
glXDestroyContext(g_xlib_display, context);
}
void GLXInterface::SwapBuffers() {
glXSwapBuffers(g_xlib_display, g_xlib_window);
}
bool GLXInterface::SwapInterval(int interval) {
// Strictly, glXSwapIntervalSGI only allows interval > 0, whereas
// glXSwapIntervalMESA allow 0 with the same semantics as eglSwapInterval.
if (_glXSwapIntervalMESA) {
return _glXSwapIntervalMESA(interval) == 0;
} else {
return glXSwapIntervalSGI(interval) == 0;
}
}
void GLXInterface::CheckError() {
CHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
};