aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/pugl_x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'pugl/pugl_x11.c')
-rw-r--r--pugl/pugl_x11.c225
1 files changed, 37 insertions, 188 deletions
diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c
index 5acd797..7a334e3 100644
--- a/pugl/pugl_x11.c
+++ b/pugl/pugl_x11.c
@@ -1,5 +1,5 @@
/*
- Copyright 2012-2016 David Robillard <http://drobilla.net>
+ Copyright 2012-2019 David Robillard <http://drobilla.net>
Copyright 2013 Robin Gareus <robin@gareus.org>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
@@ -29,18 +29,17 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#include "pugl/pugl_internal.h"
+#include "pugl/pugl_x11.h"
+
#ifdef PUGL_HAVE_GL
-#include <GL/gl.h>
-#include <GL/glx.h>
+#include "pugl/pugl_x11_gl.h"
#endif
#ifdef PUGL_HAVE_CAIRO
-#include <cairo/cairo-xlib.h>
-#include <cairo/cairo.h>
+#include "pugl/pugl_x11_cairo.h"
#endif
-#include "pugl/pugl_internal.h"
-
#ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
@@ -49,176 +48,22 @@
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
-#ifdef PUGL_HAVE_GL
-
-/** 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 };
-
-#endif // PUGL_HAVE_GL
-
-struct PuglInternalsImpl {
- Display* display;
- int screen;
- Window win;
- XIM xim;
- XIC xic;
-#ifdef PUGL_HAVE_CAIRO
- cairo_surface_t* surface;
- cairo_t* cr;
-#endif
-#ifdef PUGL_HAVE_GL
- GLXContext ctx;
- int doubleBuffered;
-#endif
-};
-
PuglInternals*
puglInitInternals(void)
{
return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}
-static XVisualInfo*
-getVisual(PuglView* view)
-{
- PuglInternals* const impl = view->impl;
- XVisualInfo* vi = NULL;
-
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type & PUGL_GL) {
- for (int* attr = *attrLists; !vi && *attr; ++attr) {
- vi = glXChooseVisual(impl->display, impl->screen, attr);
- }
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- XVisualInfo pat;
- int n;
- pat.screen = impl->screen;
- vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
- }
-#endif
-
- return vi;
-}
-
-#ifdef PUGL_HAVE_CAIRO
-static int
-createCairoContext(PuglView* view)
-{
- PuglInternals* const impl = view->impl;
-
- if (impl->cr) {
- cairo_destroy(impl->cr);
- }
-
- impl->cr = cairo_create(impl->surface);
- return cairo_status(impl->cr);
-}
-#endif
-
-static bool
-createContext(PuglView* view, XVisualInfo* vi)
-{
- PuglInternals* const impl = view->impl;
-
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type & PUGL_GL) {
- impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);
- glXGetConfig(impl->display, vi, GLX_DOUBLEBUFFER, &impl->doubleBuffered);
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- impl->surface = cairo_xlib_surface_create(
- impl->display, impl->win, vi->visual, view->width, view->height);
- }
-#endif
-
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- if (cairo_surface_status(impl->surface) != CAIRO_STATUS_SUCCESS) {
- fprintf(stderr, "error: failed to create cairo surface\n");
- return false;
- }
-
- if (createCairoContext(view) != CAIRO_STATUS_SUCCESS) {
- cairo_surface_destroy(impl->surface);
- fprintf(stderr, "error: failed to create cairo context\n");
- return false;
- }
- }
-#endif
-
- return true;
-}
-
-static void
-destroyContext(PuglView* view)
-{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type & PUGL_GL) {
- glXDestroyContext(view->impl->display, view->impl->ctx);
- }
-#endif
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- cairo_destroy(view->impl->cr);
- cairo_surface_destroy(view->impl->surface);
- }
-#endif
-}
-
void
puglEnterContext(PuglView* view)
{
-#ifdef PUGL_HAVE_GL
- if (view->ctx_type & PUGL_GL) {
- glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);
- }
-#endif
+ view->impl->ctx.enter(view);
}
void
puglLeaveContext(PuglView* view, bool flush)
{
-#ifdef PUGL_HAVE_GL
- if (flush && view->ctx_type & PUGL_GL) {
- glFlush();
- if (view->impl->doubleBuffered) {
- glXSwapBuffers(view->impl->display, view->impl->win);
- }
- }
-
- glXMakeCurrent(view->impl->display, None, NULL);
-#endif
+ view->impl->ctx.leave(view, flush);
}
int
@@ -229,17 +74,32 @@ puglCreateWindow(PuglView* view, const char* title)
impl->display = XOpenDisplay(0);
impl->screen = DefaultScreen(impl->display);
- XVisualInfo* const vi = getVisual(view);
- if (!vi) {
+ if (view->ctx_type == PUGL_GL) {
+#ifdef PUGL_HAVE_GL
+ impl->ctx = puglGetX11GlDrawContext();
+#endif
+ }
+ if (view->ctx_type == PUGL_CAIRO) {
+#ifdef PUGL_HAVE_CAIRO
+ impl->ctx = puglGetX11CairoDrawContext();
+#endif
+ }
+
+ if (!impl->ctx.configure) {
return 1;
}
+ impl->ctx.configure(view);
+ if (!impl->vi) {
+ return 2;
+ }
+
Window xParent = view->parent
? (Window)view->parent
: RootWindow(impl->display, impl->screen);
Colormap cmap = XCreateColormap(
- impl->display, xParent, vi->visual, AllocNone);
+ impl->display, xParent, impl->vi->visual, AllocNone);
XSetWindowAttributes attr;
memset(&attr, 0, sizeof(XSetWindowAttributes));
@@ -252,11 +112,11 @@ puglCreateWindow(PuglView* view, const char* title)
impl->win = XCreateWindow(
impl->display, xParent,
- 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual,
- CWColormap | CWEventMask, &attr);
+ 0, 0, view->width, view->height, 0, impl->vi->depth, InputOutput,
+ impl->vi->visual, CWColormap | CWEventMask, &attr);
- if (!createContext(view, vi)) {
- return 2;
+ if (impl->ctx.create(view)) {
+ return 3;
}
XSizeHints sizeHints;
@@ -316,8 +176,6 @@ puglCreateWindow(PuglView* view, const char* title)
fprintf(stderr, "warning: XCreateIC failed\n");
}
- XFree(vi);
-
return 0;
}
@@ -339,9 +197,10 @@ void
puglDestroy(PuglView* view)
{
if (view) {
- destroyContext(view);
+ view->impl->ctx.destroy(view);
XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display);
+ XFree(view->impl->vi);
free(view->windowClass);
free(view->impl);
free(view);
@@ -633,15 +492,10 @@ puglProcessEvents(PuglView* view)
}
if (config_event.type) {
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type == PUGL_CAIRO) {
- // Resize surfaces/contexts before dispatching
- view->redisplay = true;
- cairo_xlib_surface_set_size(view->impl->surface,
- config_event.configure.width,
- config_event.configure.height);
- }
-#endif
+ // Resize drawing context before dispatching
+ view->impl->ctx.resize(view,
+ config_event.configure.width,
+ config_event.configure.height);
puglDispatchEvent(view, (const PuglEvent*)&config_event);
}
@@ -677,10 +531,5 @@ puglGetNativeWindow(PuglView* view)
void*
puglGetContext(PuglView* view)
{
-#ifdef PUGL_HAVE_CAIRO
- if (view->ctx_type & PUGL_CAIRO) {
- return view->impl->cr;
- }
-#endif
- return NULL;
+ return view->impl->ctx.getHandle(view);
}