initial version
This commit is contained in:
176
gl3.c
Normal file
176
gl3.c
Normal file
@@ -0,0 +1,176 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "gl3.h"
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, bool, const int*);
|
||||
|
||||
#define ERROR(condition, msg, ...) if(condition){fprintf(stderr, msg, ##__VA_ARGS__); return false;}
|
||||
|
||||
bool initGL(int screen, int mask, GLInfo *glinfo)
|
||||
{
|
||||
glinfo->display = XOpenDisplay(NULL);
|
||||
ERROR(!glinfo->display, "Failed to open X display\n");
|
||||
|
||||
// check GLX version >= 1.3
|
||||
int glx_major, glx_minor;
|
||||
ERROR(!glXQueryVersion(glinfo->display, &glx_major, &glx_minor), "Could not query GLX version\n");
|
||||
ERROR(glx_major == 1 && glx_minor < 3 || glx_major < 1, "Invalid GLX version\n");
|
||||
|
||||
// Let GLX suggest a frame buffer config with a minimum feature set
|
||||
static int visual_attribs[] = {
|
||||
GLX_X_RENDERABLE , True,
|
||||
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
|
||||
GLX_RENDER_TYPE , GLX_RGBA_BIT,
|
||||
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE , 8,
|
||||
GLX_GREEN_SIZE , 8,
|
||||
GLX_BLUE_SIZE , 8,
|
||||
GLX_ALPHA_SIZE , 8,
|
||||
GLX_DEPTH_SIZE , 24,
|
||||
GLX_STENCIL_SIZE , 8,
|
||||
GLX_DOUBLEBUFFER , True,
|
||||
None
|
||||
};
|
||||
int fbcount;
|
||||
GLXFBConfig *fbclist = glXChooseFBConfig(glinfo->display, screen, visual_attribs, &fbcount);
|
||||
ERROR(!fbclist, "Failed to retrieve a framebuffer config\n");
|
||||
GLXFBConfig fbc = fbclist[0];
|
||||
XFree(fbclist);
|
||||
|
||||
// Create X Window
|
||||
XVisualInfo *vi = glXGetVisualFromFBConfig(glinfo->display, fbc);
|
||||
ERROR(!vi, "Failed to get visual from framebuffer config\n");
|
||||
XSetWindowAttributes swa;
|
||||
glinfo->cmap = XCreateColormap(glinfo->display, RootWindow(glinfo->display, vi->screen), vi->visual, AllocNone);
|
||||
swa.colormap = glinfo->cmap;
|
||||
swa.background_pixmap = None;
|
||||
swa.border_pixel = 0;
|
||||
swa.event_mask = mask;
|
||||
glinfo->win = XCreateWindow(glinfo->display, RootWindow(glinfo->display, vi->screen), 0, 0, 100, 100, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
|
||||
ERROR(!glinfo->win, "Failed to create window.\n");
|
||||
XFree(vi);
|
||||
|
||||
// Print GLX Extensions
|
||||
// const char *glxExts = glXQueryExtensionsString(glinfo->display, screen);
|
||||
// printf("%s\n", glxExts);
|
||||
|
||||
// Create GLX context
|
||||
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
|
||||
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB");
|
||||
ERROR(!glXCreateContextAttribsARB, "GLX_ARB_create_context is not supported\n");
|
||||
int context_attribs[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
None
|
||||
};
|
||||
glinfo->ctx = glXCreateContextAttribsARB(glinfo->display, fbc, 0, True, context_attribs);
|
||||
ERROR(!glXIsDirect(glinfo->display, glinfo->ctx), "GLX context is not direct\n");
|
||||
|
||||
XMapWindow(glinfo->display, glinfo->win);
|
||||
glXMakeCurrent(glinfo->display, glinfo->win, glinfo->ctx);
|
||||
|
||||
GLenum result = glewInit();
|
||||
ERROR(result != GLEW_OK, "Failed to initialize GLEW: %s\n", glewGetErrorString(result));
|
||||
|
||||
char name[] = "Billiards";
|
||||
XClassHint *classHint = XAllocClassHint();
|
||||
classHint->res_name = classHint->res_class = name;
|
||||
XSetClassHint(glinfo->display, glinfo->win, classHint);
|
||||
XStoreName(glinfo->display, glinfo->win, name);
|
||||
XFree(classHint);
|
||||
|
||||
glinfo->wm_delete_window = XInternAtom(glinfo->display, "WM_DELETE_WINDOW", false);
|
||||
glinfo->wm_protocols = XInternAtom(glinfo->display, "WM_PROTOCOLS", false);
|
||||
XSetWMProtocols(glinfo->display, glinfo->win, &glinfo->wm_delete_window, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void destroyGL(GLInfo *glinfo)
|
||||
{
|
||||
glXMakeCurrent(glinfo->display, None, 0);
|
||||
glXDestroyContext(glinfo->display, glinfo->ctx);
|
||||
XDestroyWindow(glinfo->display, glinfo->win);
|
||||
XFreeColormap(glinfo->display, glinfo->cmap);
|
||||
XCloseDisplay(glinfo->display);
|
||||
}
|
||||
|
||||
bool initShaders(const char *vertexShaderPath, const char *fragmentShaderPath, GLuint *program)
|
||||
{
|
||||
GLuint vertexShader, fragmentShader;
|
||||
GLint result;
|
||||
int infoLogLength;
|
||||
char *infoLog;
|
||||
FILE *file;
|
||||
struct stat filestat;
|
||||
char *vertexShaderSrc, *fragmentShaderSrc;
|
||||
|
||||
// load vertex shader
|
||||
file = fopen(vertexShaderPath, "r");
|
||||
ERROR(!file, "Could not open file %s\n", vertexShaderPath);
|
||||
fstat(fileno(file), &filestat);
|
||||
ERROR(filestat.st_size > 10000000, "Unreasonably large shader file\n");
|
||||
vertexShaderSrc = (char*)malloc(filestat.st_size + 1);
|
||||
vertexShaderSrc[filestat.st_size] = 0; // just for safety
|
||||
fread(vertexShaderSrc, 1, filestat.st_size, file);
|
||||
fclose(file);
|
||||
|
||||
// load framgent shader
|
||||
file = fopen(fragmentShaderPath, "r");
|
||||
ERROR(!file, "Could not open file %s\n", fragmentShaderPath);
|
||||
fstat(fileno(file), &filestat);
|
||||
ERROR(filestat.st_size > 10000000, "Unreasonably large shader file\n");
|
||||
fragmentShaderSrc = (char*)malloc(filestat.st_size + 1);
|
||||
fragmentShaderSrc[filestat.st_size] = 0; // just for safety
|
||||
fread(fragmentShaderSrc, 1, filestat.st_size, file);
|
||||
fclose(file);
|
||||
|
||||
// compile vertex shader
|
||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSrc, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &result);
|
||||
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
infoLog = (char*)malloc(infoLogLength+1);
|
||||
glGetShaderInfoLog(vertexShader, infoLogLength, NULL, infoLog);
|
||||
ERROR(!result, "Vertex shader compile error: %s\n", infoLog);
|
||||
free(infoLog);
|
||||
|
||||
// compile fragment shader
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSrc, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &result);
|
||||
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
infoLog = (char*)malloc(infoLogLength+1);
|
||||
glGetShaderInfoLog(fragmentShader, infoLogLength, NULL, infoLog);
|
||||
ERROR(!result, "Fragment shader compile error: %s\n", infoLog);
|
||||
free(infoLog);
|
||||
|
||||
// link program
|
||||
*program = glCreateProgram();
|
||||
glAttachShader(*program, vertexShader);
|
||||
glAttachShader(*program, fragmentShader);
|
||||
glLinkProgram(*program);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSrc, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
glGetShaderiv(*program, GL_LINK_STATUS, &result);
|
||||
glGetShaderiv(*program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
infoLog = (char*)malloc(infoLogLength+1);
|
||||
glGetProgramInfoLog(*program, infoLogLength, NULL, infoLog);
|
||||
ERROR(!result, "Shader linking error: %s\n", infoLog);
|
||||
free(infoLog);
|
||||
|
||||
glDetachShader(*program, vertexShader);
|
||||
glDetachShader(*program, fragmentShader);
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
free(vertexShaderSrc);
|
||||
free(fragmentShaderSrc);
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user