Compare commits

...

3 Commits

Author SHA1 Message Date
414630ecfd Better framebuffer config selection with sRGB. 2022-12-29 19:15:27 +01:00
ed6c852102 Rework GL framebuffer config selection. 2022-12-29 16:24:37 +01:00
919ba9291f Cleanup GL/GLX extensions. 2022-12-29 16:20:42 +01:00
3 changed files with 143 additions and 98 deletions

View File

@ -17,6 +17,7 @@
#include "../display.hpp" #include "../display.hpp"
#include "display_glx.hpp" #include "display_glx.hpp"
#include "../events/events_x11.hpp"
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -26,24 +27,6 @@ static bool rk_error_occured = false;
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*rk_CreateContextAttribsFunc)(Display *, GLXFBConfig, GLXContext, Bool, int const *); typedef GLXContext (*rk_CreateContextAttribsFunc)(Display *, GLXFBConfig, GLXContext, Bool, int const *);
rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance = nullptr;
rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect = nullptr;
static int const rk_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
};
static int const rk_context_attribs[] = { static int const rk_context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 2,
@ -51,19 +34,24 @@ static int const rk_context_attribs[] = {
None None
}; };
static void rk_x11_printf(
char const * messsage) {
printf("[X11] %s\n", messsage);
}
static void rk_glx_printf( static void rk_glx_printf(
char const * messsage) { char const * messsage) {
printf("[GLX] %s\n", messsage); printf("[GLX] %s\n", messsage);
} }
static bool rk_extension_supported( bool rk_extension_supported(
char const * extlist, char const * extensions,
char const * extension) { char const * extension) {
char const * where = strchr(extension, ' '); char const * where = strchr(extension, ' ');
if (where || *extension == '\0') { if (where || *extension == '\0') {
return false; return false;
} }
for (char const * start = extlist;;) { for (char const * start = extensions;;) {
where = strstr(start, extension); where = strstr(start, extension);
if (!where) { if (!where) {
break; break;
@ -77,6 +65,24 @@ static bool rk_extension_supported(
return false; return false;
} }
rk_func_ptr rk_resolve_extension(
char const * extensions,
char const * extension,
char const * fn) {
if (!extensions || !extension || !fn) {
return nullptr;
}
if (!rk_extension_supported(extensions, extension)) {
printf("[GLX] Extension %s not supported\n", extension);
return nullptr;
}
rk_func_ptr const ptr = glXGetProcAddressARB(reinterpret_cast<GLubyte const *>(fn));
if (!ptr) {
printf("[GLX] Function %s::%s not found\n", extension, fn);
}
return ptr;
}
static int rk_error_handler( static int rk_error_handler(
Display * display, Display * display,
XErrorEvent * event) { XErrorEvent * event) {
@ -97,7 +103,7 @@ rk_display_t rk_create_display(
display->colormap = 0; display->colormap = 0;
display->context = nullptr; display->context = nullptr;
if (!display->display) { if (!display->display) {
rk_glx_printf("Failed to open X display."); rk_x11_printf("Failed to open X display.");
rk_destroy_display(reinterpret_cast<rk_display_t>(display)); rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr; return nullptr;
} }
@ -109,103 +115,115 @@ rk_display_t rk_create_display(
rk_destroy_display(reinterpret_cast<rk_display_t>(display)); rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr; return nullptr;
} }
char const * const glx_exts = glXQueryExtensionsString(display->display, DefaultScreen(display->display)); char const * const glx_exts = glXQueryExtensionsString(display->display, DefaultScreen(display->display));
// rk_glx_printf(glx_exts); // rk_glx_printf(glx_exts);
rk_CreateContextAttribsFunc const glXCreateContextAttribs = reinterpret_cast<rk_CreateContextAttribsFunc>(
rk_resolve_extension(glx_exts, "GLX_ARB_create_context", "glXCreateContextAttribsARB"));
if (!glXCreateContextAttribs) {
rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr;
}
int fbcount; int fb_count = 0;
GLXFBConfig * const fbc = glXChooseFBConfig( GLXFBConfig * fb_configs;
display->display, DefaultScreen(display->display), rk_visual_attribs, &fbcount); bool const srgb_ext = rk_extension_supported(glx_exts, "GLX_EXT_framebuffer_sRGB");
if (!fbc) { if (srgb_ext) {
rk_glx_printf("GLX_EXT_framebuffer_sRGB extension supported.");
int const visual_attribs[] = { GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, True, GLX_DOUBLEBUFFER, True, None };
fb_configs = glXChooseFBConfig(display->display, DefaultScreen(display->display), visual_attribs, &fb_count);
} else {
int const visual_attribs[] = { GLX_DOUBLEBUFFER, True, None };
fb_configs = glXChooseFBConfig(display->display, DefaultScreen(display->display), visual_attribs, &fb_count);
}
printf("[GLX] Found %d framebuffer configs.\n", fb_count);
if (!fb_configs || !fb_count) {
rk_glx_printf("Failed to retrieve framebuffer configs."); rk_glx_printf("Failed to retrieve framebuffer configs.");
rk_destroy_display(reinterpret_cast<rk_display_t>(display)); rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr; return nullptr;
} }
printf("[GLX] Found %d framebuffer configs.\n", fbcount); GLXFBConfig fb_config;
int rs = 0;
int best_fbc = -1; int gs = 0;
int best_num_samp = -1; int bs = 0;
for (int i = 0; i < fbcount; ++i) { int as = 0;
XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, fbc[i]); int ds = 0;
if (vi) { int ss = 0;
int samp_buf, samples; for (int fb_index = 0; fb_index < fb_count; ++fb_index) {
glXGetFBConfigAttrib(display->display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); GLXFBConfig _config = fb_configs[fb_index];
glXGetFBConfigAttrib(display->display, fbc[i], GLX_SAMPLES, &samples); int _rs = 0;
if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) { int _gs = 0;
best_fbc = i; int _bs = 0;
best_num_samp = samples; int _as = 0;
int _ds = 0;
int _ss = 0;
glXGetFBConfigAttrib(display->display, _config, GLX_RED_SIZE, &_rs);
glXGetFBConfigAttrib(display->display, _config, GLX_GREEN_SIZE, &_gs);
glXGetFBConfigAttrib(display->display, _config, GLX_BLUE_SIZE, &_bs);
glXGetFBConfigAttrib(display->display, _config, GLX_ALPHA_SIZE, &_as);
glXGetFBConfigAttrib(display->display, _config, GLX_DEPTH_SIZE, &_ds);
glXGetFBConfigAttrib(display->display, _config, GLX_STENCIL_SIZE, &_ss);
if ((_rs >= rs && _gs >= gs && _bs >= bs && _as >= as && _ds >= ds && _ss >= ss) &&
(_rs > rs || _gs > gs || _bs > bs || _as > as || _ds > ds || _ss > ss)) {
XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, _config);
if (vi) {
XFree(vi);
rs = _rs;
gs = _gs;
bs = _bs;
as = _as;
ds = _ds;
ss = _ss;
fb_config = _config;
} }
XFree(vi);
} }
} }
if (best_fbc == -1) { printf("[RK] Select framebuffer config R%dG%dB%dA%d D%dS%d.\n", rs, gs, bs, as, ds, ss);
XFree(fbc); if (srgb_ext) {
rk_glx_printf("Failed to find a suitable framebuffer config."); int srgb = 0;
rk_destroy_display(reinterpret_cast<rk_display_t>(display)); glXGetFBConfigAttrib(display->display, fb_config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb);
return nullptr; if (srgb) {
rk_glx_printf("sRGB framebuffer selected.");
}
} }
GLXFBConfig const bestFbc = fbc[best_fbc];
XFree(fbc);
printf("[GLX] Select framebuffer config with %d samples.\n", best_num_samp);
XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, bestFbc); XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, fb_config);
display->colormap = XCreateColormap( Window root = RootWindow(display->display, vi->screen);
display->display, RootWindow(display->display, vi->screen), vi->visual, AllocNone); display->colormap = XCreateColormap(display->display, root, vi->visual, AllocNone);
XSetWindowAttributes swa; XSetWindowAttributes win_attributes;
swa.colormap = display->colormap; win_attributes.colormap = display->colormap;
swa.event_mask = RK_EVENTS_MASK; win_attributes.event_mask = RK_EVENTS_MASK;
display->window = XCreateWindow(display->display, RootWindow(display->display, vi->screen), display->window = XCreateWindow(display->display, root,
0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &win_attributes);
XFree(vi); XFree(vi);
XFree(fb_configs);
if (!display->window) { if (!display->window) {
rk_glx_printf("Failed to create window."); rk_x11_printf("Failed to create window.");
rk_destroy_display(reinterpret_cast<rk_display_t>(display)); rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr; return nullptr;
} }
XStoreName(display->display, display->window, name); XStoreName(display->display, display->window, name);
XMapWindow(display->display, display->window); XMapWindow(display->display, display->window);
rk_CreateContextAttribsFunc const glXCreateContextAttribs = rk_error_occured = false;
reinterpret_cast<rk_CreateContextAttribsFunc>( int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&rk_error_handler);
glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("glXCreateContextAttribsARB"))); display->context = glXCreateContextAttribs(display->display, fb_config, 0, True, rk_context_attribs);
XSync(display->display, False);
if (!rk_extension_supported(glx_exts, "GLX_ARB_create_context") || !glXCreateContextAttribs) { XSetErrorHandler(oldHandler);
rk_glx_printf("glXCreateContextAttribsARB extension not found."); if (rk_error_occured || !display->context) {
rk_glx_printf("Failed to create context.");
rk_destroy_display(reinterpret_cast<rk_display_t>(display)); rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr; return nullptr;
} else {
rk_error_occured = false;
int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&rk_error_handler);
display->context = glXCreateContextAttribs(display->display, bestFbc, 0, True, rk_context_attribs);
XSync(display->display, False);
XSetErrorHandler(oldHandler);
if (rk_error_occured || !display->context) {
rk_glx_printf("Failed to create context.");
rk_destroy_display(reinterpret_cast<rk_display_t>(display));
return nullptr;
}
} }
if (!glXIsDirect(display->display, display->context)) { if (!glXIsDirect(display->display, display->context)) {
rk_glx_printf("Warning: Rendering context is indirect."); rk_glx_printf("Warning: Rendering context is indirect.");
} }
glXMakeCurrent(display->display, display->window, display->context); glXMakeCurrent(display->display, display->window, display->context);
if (srgb_ext) {
char const * const gl_exts = reinterpret_cast<char const *>(glGetString(GL_EXTENSIONS)); glEnable(GL_FRAMEBUFFER_SRGB_EXT);
// printf("[GL] %s\n", gl_exts); if (glIsEnabled(GL_FRAMEBUFFER_SRGB_EXT)) {
if (rk_extension_supported(gl_exts, "GL_EXT_base_instance")) { rk_glx_printf("sRGB framebuffer enabled.");
rk_DrawElementsInstancedBaseInstance =
reinterpret_cast<rk_DrawElementsInstancedBaseInstanceFunc>(
glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("DrawElementsInstancedBaseInstance")));
if (rk_DrawElementsInstancedBaseInstance) {
rk_glx_printf("Using extension GL_EXT_base_instance::DrawElementsInstancedBaseInstance.");
if (rk_extension_supported(gl_exts, "GL_EXT_multi_draw_indirect")) {
rk_MultiDrawElementsIndirect =
reinterpret_cast<rk_MultiDrawElementsIndirectFunc>(
glXGetProcAddressARB(reinterpret_cast<GLubyte const *>("MultiDrawElementsIndirectEXT")));
if (rk_MultiDrawElementsIndirect) {
rk_glx_printf("Using extension GL_EXT_multi_draw_indirect::MultiDrawElementsIndirectEXT.");
}
}
} }
} }

View File

@ -18,17 +18,21 @@
#include "../types.hpp" #include "../types.hpp"
#include "display_x11.hpp" #include "display_x11.hpp"
#include "../events/events_x11.hpp"
#include <GL/glx.h> #include <GL/glx.h>
struct rk_display_glx : public rk_display_x11 { struct rk_display_glx : public rk_display_x11 {
GLXContext context; GLXContext context;
}; };
typedef void (*rk_DrawElementsInstancedBaseInstanceFunc)(rk_uint, rk_uint, rk_uint, const void *, rk_uint, rk_uint); typedef void (*rk_func_ptr)();
typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, rk_uint, rk_uint);
extern rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance; extern bool rk_extension_supported(
extern rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect; char const * extensions,
char const * extension);
extern rk_func_ptr rk_resolve_extension(
char const * extensions,
char const * extension,
char const * fn);
#endif // _RK_ENGINE_DISPLAY_GLX_H #endif // _RK_ENGINE_DISPLAY_GLX_H

View File

@ -19,9 +19,19 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
typedef void (*rk_DrawElementsInstancedBaseInstanceFunc)(rk_uint, rk_uint, rk_uint, const void *, rk_uint, rk_uint);
typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, rk_uint, rk_uint);
static rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance = nullptr;
static rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect = nullptr;
static rk_shader const * rk_current_shader = nullptr; static rk_shader const * rk_current_shader = nullptr;
static rk_vertices const * rk_current_vertices = nullptr; static rk_vertices const * rk_current_vertices = nullptr;
static void rk_gl_printf(char const * message) {
printf("[GL] %s\n", message);
}
static void rk_printf(char const * message) { static void rk_printf(char const * message) {
printf("[RK] %s\n", message); printf("[RK] %s\n", message);
} }
@ -42,14 +52,27 @@ static void rk_debug_message_callback(
void rk_render_initialize() { void rk_render_initialize() {
GLubyte const * const vendor = glGetString(GL_VENDOR); GLubyte const * const vendor = glGetString(GL_VENDOR);
GLubyte const * const renderer = glGetString(GL_RENDERER); GLubyte const * const renderer = glGetString(GL_RENDERER);
printf("[RK] vendor: %s, renderer: %s\n", vendor, renderer); printf("[GL] vendor: %s, renderer: %s\n", vendor, renderer);
GLubyte const * const version = glGetString(GL_VERSION); GLubyte const * const version = glGetString(GL_VERSION);
GLubyte const * const language = glGetString(GL_SHADING_LANGUAGE_VERSION); GLubyte const * const language = glGetString(GL_SHADING_LANGUAGE_VERSION);
printf("[RK] version: %s, language: %s\n", version, language); printf("[GL] version: %s, language: %s\n", version, language);
glDebugMessageCallback(rk_debug_message_callback, nullptr); glDebugMessageCallback(rk_debug_message_callback, nullptr);
glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT);
char const * const gl_exts = reinterpret_cast<char const *>(glGetString(GL_EXTENSIONS));
// printf("[GL] %s\n", gl_exts);
rk_DrawElementsInstancedBaseInstance = reinterpret_cast<rk_DrawElementsInstancedBaseInstanceFunc>(
rk_resolve_extension(gl_exts, "GL_EXT_base_instance", "DrawElementsInstancedBaseInstance"));
if (rk_DrawElementsInstancedBaseInstance) {
rk_gl_printf("Using extension GL_EXT_base_instance::DrawElementsInstancedBaseInstance.");
rk_MultiDrawElementsIndirect = reinterpret_cast<rk_MultiDrawElementsIndirectFunc>(
rk_resolve_extension(gl_exts, "GL_EXT_multi_draw_indirect", "MultiDrawElementsIndirectEXT"));
if (rk_MultiDrawElementsIndirect) {
rk_gl_printf("Using extension GL_EXT_multi_draw_indirect::MultiDrawElementsIndirectEXT.");
}
}
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_DITHER); glEnable(GL_DITHER);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);