switched from egl to glx and wgl

This commit is contained in:
Maciej Samborski 2025-06-12 17:34:58 +02:00
parent c28c07dad4
commit 98af446a2f
18 changed files with 1012 additions and 71 deletions

View File

@ -1,13 +1,29 @@
FLAGS=-fPIC --shared
LIBS=-lX11 -lGL
FILES=src/openwindow.c deps/lib/glad.a
libopenwindow.so: glad.a
gcc ${FLAGS} -o libopenwindow.so ${FILES}
LINUX_FILES=src/openwindow.c deps/lib/glad_linux.a
WINDOWS_LIBS=-lopengl32 -lgdi32
WINDOWS_FILES=src/openwindow.c deps/lib/glad_windows.a
OUTPUT=lib/
all: libopenwindow.so libopenwindow.dll
libopenwindow.so: glad_linux.a
mkdir -p ${OUTPUT}
gcc ${FLAGS} -o ${OUTPUT}libopenwindow.so ${LINUX_FILES}
libopenwindow.dll: glad_windows.a
mkdir -p ${OUTPUT}
x86_64-w64-mingw32-gcc ${FLAGS} -o ${OUTPUT}libopenwindow.dll ${WINDOWS_FILES} ${WINDOWS_LIBS}
GLAD_FLAGS=-fPIC -c
GLAD_FILES=deps/src/glad.c
glad.a: deps/src/glad.o
gcc ${GLAD_FLAGS} -o deps/src/glad.o ${GLAD_FILES}
ar rcs deps/lib/glad.a deps/src/glad.o
glad_linux.a: deps/src/glad.c
gcc ${GLAD_FLAGS} -o deps/src/glad_linux.o ${GLAD_FILES}
ar rcs deps/lib/glad_linux.a deps/src/glad_linux.o
glad_windows.a: deps/src/glad.c
x86_64-w64-mingw32-gcc ${GLAD_FLAGS} -o deps/src/glad_windows.o ${GLAD_FILES}
ar rcs deps/lib/glad_windows.a deps/src/glad_windows.o

24
main.c
View File

@ -1,6 +1,9 @@
#include <stdio.h>
#include <stdbool.h>
#include "deps/include/glad/glad.h"
#include "src/openwindow.h"
#ifndef _WIN32
#include <X11/keysym.h>
@ -9,8 +12,6 @@
#include <X11/Xlib.h>
#undef Window
#include "src/openwindow.h"
void xevent(Window * w, XEvent xev) {
switch (xev.type)
{
@ -37,6 +38,10 @@ void xevent(Window * w, XEvent xev) {
}
}
#else
#include <windows.h>
#endif // _WIN32
const char * fss =
@ -52,22 +57,25 @@ int main(void)
{
Window w = openWindow("Window", 800, 600);
// TODO: do this
#ifndef _WIN32
windowSetEventHandler(&w, xevent);
#endif // _WIN32
while (!w.close) {
while (!w.close)
{
windowHandleEvents(&w);
glClearColor(1, 1, 1, 1);
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, 800, 600);
glColor3f(1.0, 0, 0);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-0.5, -0.5);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.5, -0.5);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(0.0, 0.5);
glEnd();
glFlush();
windowDraw(w);
}

13
other/deltatime.c Normal file
View File

@ -0,0 +1,13 @@
#include "deltatime.h"
struct timespec deltaTimeX1, deltaTimeX2;
#include <time.h>
double getDeltaTime() {
clock_gettime(CLOCK_MONOTONIC, &deltaTimeX2);
double dt = (deltaTimeX2.tv_sec - deltaTimeX1.tv_sec) + (deltaTimeX2.tv_nsec - deltaTimeX1.tv_nsec) / 1e9;
deltaTimeX1 = deltaTimeX2;
return dt;
}

8
other/deltatime.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef DELTA_TIME_H_
#define DELTA_TIME_H_
extern struct timespec deltaTimeX1, deltaTimeX2;
double getDeltaTime();
#endif // DELTA_TIME_H_

87
other/graphics.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdlib.h>
#include "graphics.h"
#include "../deps/include/glad/glad.h"
const char * defaultVertexShader =
"#version 330 core\n"
"precision mediump float;"
"void main()\n"
"{\n"
"}";
const char * defaultFragmentShader =
"#version 330 core\n"
"precision mediump float;"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}";
void compileShader(GLuint program, const char * source, GLenum type) {
GLint status = 0;
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
fprintf(stderr, "Failed to compile %s shader!\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment");
GLint len;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
char * infolog = (char*) malloc(len * sizeof(char));
glGetShaderInfoLog(shader, len, NULL, infolog);
fprintf(stderr, "Shader compilation error: %s\n", infolog);
free(infolog);
exit(1);
}
glAttachShader(program, shader);
}
void linkProgram(GLuint program) {
int status = 0;
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
fprintf(stderr, "Failed to link program!\n");
GLint len;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
char * infolog = (char*) malloc(len * sizeof(char));
glGetProgramInfoLog(program, len, NULL, infolog);
fprintf(stderr, "Program linking error: %s", infolog);
free(infolog);
exit(1);
}
}
Graphics createGraphics(const char * vss, const char * fss) {
GLuint program = glCreateProgram();
if (vss == NULL) vss = defaultVertexShader;
if (fss == NULL) fss = defaultFragmentShader;
compileShader(program, vss, GL_VERTEX_SHADER);
compileShader(program, fss, GL_FRAGMENT_SHADER);
linkProgram(program);
GLuint vao;
glGenVertexArrays(1, &vao);
return (Graphics) {
.program = program,
.vao = vao,
};
}

15
other/graphics.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef GRAPHICS_H_
#define GRAPHICS_H_
#include "../deps/include/glad/glad.h"
extern const char * defaultVertexShader, * defaultFragmentShader;
typedef struct {
GLuint program;
GLuint vao;
} Graphics;
Graphics createGraphics(const char * vss, const char * fss);
#endif // GRAPHICS_H_

82
sample/lis.c Normal file
View File

@ -0,0 +1,82 @@
#include <windows.h>
#include "../deps/include/glad/glad.h"
#include <stdio.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HGLRC CreateOpenGLContext(HWND hwnd, HDC hdc) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 8, 0,
PFD_MAIN_PLANE, 0, 0, 0, 0
};
int pf = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, pf, &pfd);
return wglCreateContext(hdc);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
const char CLASS_NAME[] = "WGLSampleWindow";
WNDCLASS wc = {0};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, "OpenGL with WGL and GLAD", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
if (!hwnd) return -1;
HDC hdc = GetDC(hwnd);
HGLRC hglrc = CreateOpenGLContext(hwnd, hdc);
wglMakeCurrent(hdc, hglrc);
// Load OpenGL functions using GLAD
if (!gladLoadGL()) {
MessageBoxA(NULL, "Failed to initialize GLAD", "Error", MB_OK | MB_ICONERROR);
return -1;
}
ShowWindow(hwnd, nCmdShow);
// Main loop
MSG msg;
while (1) {
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) goto cleanup;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// OpenGL rendering
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(hdc);
}
cleanup:
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_DESTROY:
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}

BIN
sample/lis.exe Executable file

Binary file not shown.

106
sample/test.c Normal file
View File

@ -0,0 +1,106 @@
#include <windows.h>
#include "../deps/include/glad/glad.h"
LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int main() {
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_CLASSDC;
wcex.lpfnWndProc = wndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetModuleHandle(NULL);
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = 0;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "OpenGL";
wcex.hIconSm = NULL;
if (!RegisterClassEx(&wcex)) {
MessageBox(NULL, "Failed to register window class", "Error", MB_ICONERROR);
return -1;
}
HWND hwnd = CreateWindow("OpenGL", "OpenGL", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, GetModuleHandle(NULL), NULL);
if (hwnd == NULL) {
MessageBox(NULL, "Failed to create window", "Error", MB_ICONERROR);
return -1;
}
HDC hdc = GetDC(hwnd);
if (hdc == NULL) {
MessageBox(NULL, "Failed to get device context", "Error", MB_ICONERROR);
return -1;
}
PIXELFORMATDESCRIPTOR pfd = {0};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
int format = ChoosePixelFormat(hdc, &pfd);
if (format == 0) {
MessageBox(NULL, "Failed to choose pixel format", "Error", MB_ICONERROR);
return -1;
}
if (!SetPixelFormat(hdc, format, &pfd)) {
MessageBox(NULL, "Failed to set pixel format", "Error", MB_ICONERROR);
return -1;
}
HGLRC hrc = wglCreateContext(hdc);
if (hrc == NULL) {
MessageBox(NULL, "Failed to create OpenGL context", "Error", MB_ICONERROR);
return -1;
}
if (!wglMakeCurrent(hdc, hrc)) {
MessageBox(NULL, "Failed to make OpenGL context current", "Error", MB_ICONERROR);
return -1;
}
if (!gladLoadGLLoader((GLADloadproc)wglGetProcAddress)) {
MessageBox(NULL, "Failed to load OpenGL functions", "Error", MB_ICONERROR);
return -1;
}
MSG msg;
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT) {
break;
}
} else {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
SwapBuffers(hdc);
}
}
wglDeleteContext(hrc);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
UnregisterClass("OpenGL", GetModuleHandle(NULL));
return 0;
}

BIN
sample/test.exe Executable file

Binary file not shown.

107
sample/w.c Normal file
View File

@ -0,0 +1,107 @@
#include <windows.h>
#include <stdio.h>
#include "../deps/include/glad/glad.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
printf("AAA\n");
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int main()
{
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "GLSample", NULL };
RegisterClassEx(&wc);
// Create the window
HWND hWnd = CreateWindowEx(
0,
"GLSample",
"OpenGL Sample",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
256,
256,
NULL,
NULL,
GetModuleHandle(NULL),
NULL
);
// Enable OpenGL
HDC hDC = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
int iFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, iFormat, &pfd);
// Create the OpenGL context
HGLRC hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
gladLoadGLLoader((GLADloadproc)wglGetProcAddress);
// Main loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
// Clear the screen
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a triangle
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-0.5f, -0.5f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.5f, -0.5f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(0.0f, 0.5f);
glEnd();
// Swap buffers
SwapBuffers(hDC);
}
// Disable OpenGL
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
// Clean up
UnregisterClass("GLSample", GetModuleHandle(NULL));
return msg.wParam;
}

BIN
sample/w.exe Executable file

Binary file not shown.

152
sample/win.c Normal file
View File

@ -0,0 +1,152 @@
#include <windows.h>
#include <GL/gl.h>
// Global variables
HINSTANCE hInstance;
HWND hWnd;
HDC hDC;
HGLRC hRC;
// Forward declarations
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void EnableOpenGL(HWND, HDC*, HGLRC*);
void DisableOpenGL(HWND, HDC, HGLRC);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Register the window class
WNDCLASSEX wc = {
sizeof(WNDCLASSEX),
CS_CLASSDC,
WndProc,
0L,
0L,
hInst,
NULL,
NULL,
NULL,
NULL,
"GLSample",
NULL
};
RegisterClassEx(&wc);
// Create the window
hWnd = CreateWindowEx(
0,
"GLSample",
"OpenGL Sample",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
256,
256,
NULL,
NULL,
hInst,
NULL
);
// Enable OpenGL
EnableOpenGL(hWnd, &hDC, &hRC);
// Show the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Disable OpenGL
DisableOpenGL(hWnd, hDC, hRC);
// Clean up
UnregisterClass("GLSample", hInstance);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_SIZE:
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
// Clear the screen
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a triangle
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-0.5f, -0.5f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.5f, -0.5f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(0.0f, 0.5f);
glEnd();
// Swap buffers
SwapBuffers(hDC);
EndPaint(hWnd, &ps);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void EnableOpenGL(HWND hWnd, HDC* hDC, HGLRC* hRC)
{
*hDC = GetDC(hWnd);
// Set the pixel format
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
int iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
// Create the OpenGL context
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}

BIN
sample/win.exe Executable file

Binary file not shown.

BIN
sample/x11 Executable file

Binary file not shown.

256
sample/x11.c Normal file
View File

@ -0,0 +1,256 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
// Helper to check for extension string presence. Adapted from:
// http://www.opengl.org/resources/features/OGLextensions/
static bool isExtensionSupported(const char *extList, const char *extension)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = strchr(extension, ' ');
if (where || *extension == '\0')
return false;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
for (start=extList;;) {
where = strstr(start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if ( where == start || *(where - 1) == ' ' )
if ( *terminator == ' ' || *terminator == '\0' )
return true;
start = terminator;
}
return false;
}
int main(int argc, char* argv[])
{
Display *display = XOpenDisplay(NULL);
if (!display)
{
printf("Failed to open X display\n");
exit(1);
}
// Get a matching FB config
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,
//GLX_SAMPLE_BUFFERS , 1,
//GLX_SAMPLES , 4,
None
};
int glx_major, glx_minor;
// FBConfigs were added in GLX version 1.3.
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
{
printf("Invalid GLX version");
exit(1);
}
printf( "Getting matching framebuffer configs\n" );
int fbcount;
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
if (!fbc)
{
printf( "Failed to retrieve a framebuffer config\n" );
exit(1);
}
printf( "Found %d matching FB configs.\n", fbcount );
// Pick the FB config/visual with the most samples per pixel
printf( "Getting XVisualInfos\n" );
int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
int i;
for (i=0; i<fbcount; ++i)
{
XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
if ( vi )
{
int samp_buf, samples;
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
" SAMPLES = %d\n",
i, vi -> visualid, samp_buf, samples );
if ( best_fbc < 0 || samp_buf && samples > best_num_samp )
best_fbc = i, best_num_samp = samples;
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
worst_fbc = i, worst_num_samp = samples;
}
XFree( vi );
}
GLXFBConfig bestFbc = fbc[ best_fbc ];
// Be sure to free the FBConfig list allocated by glXChooseFBConfig()
XFree( fbc );
// Get a visual
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
printf( "Chosen visual ID = 0x%x\n", vi->visualid );
printf( "Creating colormap\n" );
XSetWindowAttributes swa;
Colormap cmap;
swa.colormap = cmap = XCreateColormap( display,
RootWindow( display, vi->screen ),
vi->visual, AllocNone );
swa.background_pixmap = None ;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
printf( "Creating window\n" );
Window win = XCreateWindow( display, RootWindow( display, vi->screen ),
0, 0, 100, 100, 0, vi->depth, InputOutput,
vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa );
if ( !win )
{
printf( "Failed to create window.\n" );
exit(1);
}
// Done with the visual info data
XFree( vi );
XStoreName( display, win, "GL 3.0 Window" );
printf( "Mapping window\n" );
XMapWindow( display, win );
// Get the default screen's GLX extension list
//const char *glxExts = glXQueryExtensionsString( display,
// DefaultScreen( display ) );
// NOTE: It is not necessary to create or make current to a context before
// calling glXGetProcAddressARB
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
GLXContext ctx = 0;
// Install an X error handler so the application won't exit if GL 3.0
// context allocation fails.
//
// Note this error handler is global. All display connections in all threads
// of a process use the same error handler, so be sure to guard against other
// threads issuing X commands while this code is running.
//ctxErrorOccurred = false;
//int (*oldHandler)(Display*, XErrorEvent*) =
// XSetErrorHandler(&ctxErrorHandler);
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
//if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
// !glXCreateContextAttribsARB )
//{
// printf( "glXCreateContextAttribsARB() not found"
// " ... using old-style GLX context\n" );
// ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
//} else
//{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
printf( "Creating context\n" );
ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
True, context_attribs );
// Sync to ensure any errors generated are processed.
//XSync( display, False );
//if (ctxErrorOccurred && !ctx)
//{
// context_attribs[1] = 1;
// context_attribs[3] = 0;
// ctxErrorOccurred = false;
// printf( "Failed to create GL 3.0 context"
// " ... using old-style GLX context\n" );
// ctx = glXCreateContextAttribsARB( display, bestFbc, 0,
// True, context_attribs );
//}
//}
//XSync( display, False );
//XSetErrorHandler( oldHandler );
//if ( ctxErrorOccurred || !ctx )
//{
// printf( "Failed to create an OpenGL context\n" );
// exit(1);
//}
printf( "Making context current\n" );
glXMakeCurrent( display, win, ctx );
const GLubyte * v = glGetString(GL_VERSION);
printf("%s\n", v);
glClearColor( 0, 0.5, 1, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glXSwapBuffers ( display, win );
sleep( 1 );
glClearColor ( 1, 0.5, 0, 1 );
glClear ( GL_COLOR_BUFFER_BIT );
glXSwapBuffers ( display, win );
sleep( 1 );
glXMakeCurrent( display, 0, 0 );
glXDestroyContext( display, ctx );
XDestroyWindow( display, win );
XFreeColormap( display, cmap );
XCloseDisplay( display );
return 0;
}

View File

@ -12,8 +12,6 @@ int initOpenGL() {
#ifndef _WIN32
#define GLLOADER glXGetProcAddress
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
bool checkGLXVersion(Window window) {
@ -87,9 +85,9 @@ int initGLX(Window * window)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
int context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
GLX_CONTEXT_MINOR_VERSION_ARB, 6,
GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
window->glx.context = glXCreateContextAttribsARB(window->x.display, window->glx.config, 0, True, context_attribs);
@ -206,51 +204,122 @@ void closeWindow(Window window) {
#else
#include <windows.h>
#include <GL/wgl.h>
#define GLLOADER wglGetProcAddress
#define WND_CLASS_NAME "OpenWindowWndClass"
LRESULT CALLBACK wndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
Window * window = (Window *)GetWindowLong(hwnd, GWLP_USERDATA);
Window * window = (Window *)(LONG_PTR)GetWindowLong(hwnd, GWLP_USERDATA);
switch (msg)
{
case WM_CLOSE: {
window->close = true;
return 0;
case WM_KEYDOWN:
{
if (wParam == VK_ESCAPE) window->close = true;
break;
}
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
int initWGL(Window * window, const char * title, size_t width, size_t height) {
HINSTANCE hInstance = GetModuleHandle(NULL);
int init(Window * window, const char * title, size_t width, size_t height) {
window->wgl.instance = GetModuleHandle(NULL);
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = &DefWindowProc;
wcex.style = CS_CLASSDC;
wcex.lpfnWndProc = wndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hInstance = window->wgl.instance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = 0;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = title;
wcex.lpszClassName = WND_CLASS_NAME;
wcex.hIconSm = NULL;
wcex.lpfnWndProc = wndProc;
RegisterClassEx(&wcex);
RECT rect = { 0, 0, width, height };
int style = WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
AdjustWindowRect(&rect, style, FALSE);
window->w.window = CreateWindow(title, "example", style, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, GetModuleHandle(NULL), window);
ShowWindow(window->w.window, SW_SHOW);
window->wgl.window = CreateWindow(
WND_CLASS_NAME,
title,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
width,
height,
NULL,
NULL,
window->wgl.instance,
window
);
SetWindowLong(window->w.window, GWLP_USERDATA, (LONG)window);
if (window->wgl.window == NULL) return -1;
ShowWindow(window->wgl.window, SW_SHOW);
SetWindowLong(window->wgl.window, GWLP_USERDATA, (LONG_PTR)window);
window->wgl.display = GetDC(window->wgl.window);
PIXELFORMATDESCRIPTOR pfd = {0};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cRedBits = 0;
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 0;
pfd.cAccumRedBits = 0;
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
int format = ChoosePixelFormat(window->wgl.display, &pfd);
SetPixelFormat(window->wgl.display, format, &pfd);
HGLRC tempContext = wglCreateContext(window->wgl.display);
if (tempContext == NULL) return -1;
if (!wglMakeCurrent(window->wgl.display, tempContext)) return -1;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if (wglCreateContextAttribsARB == NULL) return -1;
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 6,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
window->wgl.context = wglCreateContextAttribsARB(window->wgl.display, 0, attribs);
if (window->wgl.context == NULL) {
fprintf(stderr, "Failed to create wgl context!\n");
return -1;
}
wglMakeCurrent(window->wgl.display, NULL);
wglDeleteContext(tempContext);
wglMakeCurrent(window->wgl.display, window->wgl.context);
return 0;
}
@ -258,24 +327,41 @@ int initWGL(Window * window, const char * title, size_t width, size_t height) {
Window openWindow(const char * name, size_t width, size_t height) {
Window w = {0};
if (initWGL(&w, name, width, height) < 0) {
fprintf(stderr, "Failed to initialize egl!\n");
if (init(&w, name, width, height) < 0) {
fprintf(stderr, "Failed to initialize wgl!\n");
exit(1);
}
initOpenGL();
eglMakeCurrent(w.egl.display, w.egl.surface, w.egl.surface, w.egl.context);
if (initOpenGL() < 0) {
fprintf(stderr, "Failed to initialize window: GLAD/OPENGL error!\n");
exit(1);
}
return w;
}
void windowDraw(Window window) {
SwapBuffers(window.wgl.display);
}
void windowHandleEvents(Window * window) {
MSG msg;
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
void closeWindow(Window window) {
DestroyWindow(window.w.window);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(window.wgl.context);
ReleaseDC(window.wgl.window, window.wgl.display);
DestroyWindow(window.wgl.window);
UnregisterClass(WND_CLASS_NAME, window.wgl.instance);
}
#endif // _WIN32
int getOpenGLProcs(void) {
return gladLoadGLLoader((GLADloadproc)GLLOADER);
return gladLoadGL();
}

View File

@ -38,36 +38,41 @@ typedef struct Window {
bool close;
} Window;
#else
typedef struct {
} WGL;
typedef struct {
HDC display;
HWND window;
} Windows;
typedef struct Window Window;
typedef struct Window {
WGL wgl;
Windows x;
WindowEventHandler eventHandler;
bool close;
} Window;
#endif // _WIN32
// depends on glad
int getOpenGLProcs(void);
Window openWindow(const char * name, size_t width, size_t height);
void windowDraw(Window window);
void windowSetEventHandler(Window * window, WindowEventHandler handler);
void windowHandleEvents(Window * window);
void closeWindow(Window w);
#else
#include <windows.h>
typedef struct {
HINSTANCE instance;
HDC display;
HWND window;
HGLRC context;
} WGL;
typedef struct Window Window;
typedef struct Window {
WGL wgl;
//WindowEventHandler eventHandler;
bool close;
} Window;
Window openWindow(const char * name, size_t width, size_t height);
void windowDraw(Window window);
void windowHandleEvents(Window * window);
void closeWindow(Window w);
#endif // _WIN32
// depends on glad
int getOpenGLProcs(void);
#endif // _OPEN_WINDOW_H_
// TODO: Add all the error handling to the glx