aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/pugl_x11_gl.c
diff options
context:
space:
mode:
Diffstat (limited to 'pugl/pugl_x11_gl.c')
-rw-r--r--pugl/pugl_x11_gl.c143
1 files changed, 100 insertions, 43 deletions
diff --git a/pugl/pugl_x11_gl.c b/pugl/pugl_x11_gl.c
index d6242f2..6c007b1 100644
--- a/pugl/pugl_x11_gl.c
+++ b/pugl/pugl_x11_gl.c
@@ -22,62 +22,117 @@
#include <GL/glx.h>
#include <stdlib.h>
+#include <stdio.h>
typedef struct {
- GLXContext ctx;
- int doubleBuffered;
+ GLXFBConfig fb_config;
+ GLXContext ctx;
+ int double_buffered;
} PuglX11GlSurface;
static int
+puglX11GlHintValue(const int value)
+{
+ return value == PUGL_DONT_CARE ? (int)GLX_DONT_CARE : value;
+}
+
+static int
+puglX11GlGetAttrib(Display* const display,
+ const GLXFBConfig fb_config,
+ const int attrib)
+{
+ int value = 0;
+ glXGetFBConfigAttrib(display, fb_config, attrib, &value);
+ return value;
+}
+
+static int
puglX11GlConfigure(PuglView* view)
{
- PuglInternals* const impl = view->impl;
-
- /** Attributes for double-buffered RGBA. */
- static int attrListDbl[] = { GLX_RGBA,
- GLX_DOUBLEBUFFER, True,
- GLX_RED_SIZE, 4,
- GLX_GREEN_SIZE, 4,
- GLX_BLUE_SIZE, 4,
- GLX_DEPTH_SIZE, 16,
- /* GLX_SAMPLE_BUFFERS , 1, */
- /* GLX_SAMPLES , 4, */
- None };
-
- /** Attributes for single-buffered RGBA. */
- static int attrListSgl[] = { GLX_RGBA,
- GLX_DOUBLEBUFFER, False,
- GLX_RED_SIZE, 4,
- GLX_GREEN_SIZE, 4,
- GLX_BLUE_SIZE, 4,
- GLX_DEPTH_SIZE, 16,
- /* GLX_SAMPLE_BUFFERS , 1, */
- /* GLX_SAMPLES , 4, */
- None };
-
- /** Null-terminated list of attributes in order of preference. */
- static int* attrLists[] = { attrListDbl, attrListSgl, NULL };
-
- if (view->ctx_type & PUGL_GL) {
- for (int* attr = *attrLists; !impl->vi && *attr; ++attr) {
- impl->vi = glXChooseVisual(impl->display, impl->screen, attr);
- }
+ PuglInternals* const impl = view->impl;
+ const int screen = impl->screen;
+ Display* const display = impl->display;
+
+ PuglX11GlSurface* const surface =
+ (PuglX11GlSurface*)calloc(1, sizeof(PuglX11GlSurface));
+ impl->surface = surface;
+
+ const int attrs[] = {
+ GLX_X_RENDERABLE, True,
+ GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_SAMPLES, view->hints.samples,
+ GLX_RED_SIZE, puglX11GlHintValue(view->hints.red_bits),
+ GLX_GREEN_SIZE, puglX11GlHintValue(view->hints.green_bits),
+ GLX_BLUE_SIZE, puglX11GlHintValue(view->hints.blue_bits),
+ GLX_ALPHA_SIZE, puglX11GlHintValue(view->hints.alpha_bits),
+ GLX_DEPTH_SIZE, puglX11GlHintValue(view->hints.depth_bits),
+ GLX_STENCIL_SIZE, puglX11GlHintValue(view->hints.stencil_bits),
+ GLX_DOUBLEBUFFER, (view->hints.samples
+ ? GLX_DONT_CARE
+ : view->hints.double_buffer),
+ None
+ };
+
+ int n_fbc = 0;
+ GLXFBConfig* fbc = glXChooseFBConfig(display, screen, attrs, &n_fbc);
+ if (n_fbc <= 0) {
+ fprintf(stderr, "error: Failed to create GL context\n");
+ return 1;
}
+ surface->fb_config = fbc[0];
+ impl->vi = glXGetVisualFromFBConfig(impl->display, fbc[0]);
+
+ printf("Using visual 0x%lX: R=%d G=%d B=%d A=%d D=%d"
+ " DOUBLE=%d SAMPLES=%d\n",
+ impl->vi->visualid,
+ puglX11GlGetAttrib(display, fbc[0], GLX_RED_SIZE),
+ puglX11GlGetAttrib(display, fbc[0], GLX_GREEN_SIZE),
+ puglX11GlGetAttrib(display, fbc[0], GLX_BLUE_SIZE),
+ puglX11GlGetAttrib(display, fbc[0], GLX_ALPHA_SIZE),
+ puglX11GlGetAttrib(display, fbc[0], GLX_DEPTH_SIZE),
+ puglX11GlGetAttrib(display, fbc[0], GLX_DOUBLEBUFFER),
+ puglX11GlGetAttrib(display, fbc[0], GLX_SAMPLES));
+
return 0;
}
static int
puglX11GlCreate(PuglView* view)
{
- PuglInternals* const impl = view->impl;
-
- PuglX11GlSurface* surface = (PuglX11GlSurface*)calloc(1, sizeof(PuglX11GlSurface));
+ PuglInternals* const impl = view->impl;
+ PuglX11GlSurface* const surface = (PuglX11GlSurface*)impl->surface;
+ Display* const display = impl->display;
+ const GLXFBConfig fb_config = surface->fb_config;
+
+ const int ctx_attrs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, view->hints.context_version_major,
+ GLX_CONTEXT_MINOR_VERSION_ARB, view->hints.context_version_minor,
+ GLX_CONTEXT_PROFILE_MASK_ARB, (view->hints.use_compat_profile
+ ? GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
+ : GLX_CONTEXT_CORE_PROFILE_BIT_ARB),
+ 0};
+
+ typedef GLXContext (*CreateContextAttribs)(
+ Display*, GLXFBConfig, GLXContext, Bool, const int*);
+
+ CreateContextAttribs create_context =
+ (CreateContextAttribs)glXGetProcAddress(
+ (GLubyte*)"glXCreateContextAttribsARB");
impl->surface = surface;
- surface->ctx = glXCreateContext(impl->display, impl->vi, 0, GL_TRUE);
- glXGetConfig(
- impl->display, impl->vi, GLX_DOUBLEBUFFER, &surface->doubleBuffered);
+ surface->ctx = create_context(display, fb_config, 0, GL_TRUE, ctx_attrs);
+ if (!surface->ctx) {
+ surface->ctx =
+ glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True);
+ }
+
+ glXGetConfig(impl->display,
+ impl->vi,
+ GLX_DOUBLEBUFFER,
+ &surface->double_buffered);
return 0;
}
@@ -86,9 +141,11 @@ static int
puglX11GlDestroy(PuglView* view)
{
PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface;
- glXDestroyContext(view->impl->display, surface->ctx);
- free(surface);
- view->impl->surface = NULL;
+ if (surface) {
+ glXDestroyContext(view->impl->display, surface->ctx);
+ free(surface);
+ view->impl->surface = NULL;
+ }
return 0;
}
@@ -110,7 +167,7 @@ puglX11GlLeave(PuglView* view, bool flush)
}
glXMakeCurrent(view->impl->display, None, NULL);
- if (surface->doubleBuffered) {
+ if (surface->double_buffered) {
glXSwapBuffers(view->impl->display, view->impl->win);
}