diff options
Diffstat (limited to 'pugl')
-rw-r--r-- | pugl/gl.h | 32 | ||||
-rw-r--r-- | pugl/glu.h | 32 | ||||
-rw-r--r-- | pugl/pugl.h | 37 | ||||
-rw-r--r-- | pugl/pugl_internal.h | 13 | ||||
-rw-r--r-- | pugl/pugl_x11.c | 173 |
5 files changed, 209 insertions, 78 deletions
diff --git a/pugl/gl.h b/pugl/gl.h new file mode 100644 index 0000000..9a6aeef --- /dev/null +++ b/pugl/gl.h @@ -0,0 +1,32 @@ +/* + Copyright 2012-2014 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file gl.h Portable header wrapper for gl.h. + + Unfortunately, GL includes vary across platforms so this header allows for + pure portable programs. +*/ + +#ifdef __APPLE__ +# include "OpenGL/gl.h" +#else +# ifdef _WIN32 +# include <windows.h> /* Broken Windows GL headers require this */ +# endif +# include "GL/gl.h" +#endif + diff --git a/pugl/glu.h b/pugl/glu.h new file mode 100644 index 0000000..0ed0055 --- /dev/null +++ b/pugl/glu.h @@ -0,0 +1,32 @@ +/* + Copyright 2012-2014 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file gl.h Portable header wrapper for glu.h. + + Unfortunately, GL includes vary across platforms so this header allows for + pure portable programs. +*/ + +#ifdef __APPLE__ +# include "OpenGL/glu.h" +#else +# ifdef _WIN32 +# include <windows.h> /* Broken Windows GL headers require this */ +# endif +# include "GL/glu.h" +#endif + diff --git a/pugl/pugl.h b/pugl/pugl.h index 360f8e8..8cd8afb 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -23,20 +23,6 @@ #include <stdint.h> -/* - This API is pure portable C and contains no platform specific elements, or - even a GL dependency. However, unfortunately GL includes vary across - platforms so they are included here to allow for pure portable programs. -*/ -#ifdef __APPLE__ -# include "OpenGL/gl.h" -#else -# ifdef _WIN32 -# include <windows.h> /* Broken Windows GL headers require this */ -# endif -# include "GL/gl.h" -#endif - #ifdef PUGL_SHARED # ifdef _WIN32 # define PUGL_LIB_IMPORT __declspec(dllimport) @@ -88,6 +74,14 @@ typedef enum { } PuglStatus; /** + Drawing context type. +*/ +typedef enum { + PUGL_GL, + PUGL_CAIRO +} PuglContextType; + +/** Convenience symbols for ASCII control characters. */ typedef enum { @@ -247,6 +241,12 @@ PUGL_API void puglInitResizable(PuglView* view, bool resizable); /** + Set the context type before creating a window. +*/ +PUGL_API void +puglInitContextType(PuglView* view, PuglContextType type); + +/** Create a window with the settings given by the various puglInit functions. @return 1 (pugl does not currently support multiple windows). @@ -285,6 +285,15 @@ PUGL_API PuglHandle puglGetHandle(PuglView* view); /** + Get the drawing context. + + For PUGL_GL contexts, this is unused and returns NULL. + For PUGL_CAIRO contexts, this returns a pointer to a cairo_t. +*/ +PUGL_API void* +puglGetContext(PuglView* view); + +/** Return the timestamp (if any) of the currently-processing event. */ PUGL_API uint32_t diff --git a/pugl/pugl_internal.h b/pugl/pugl_internal.h index b86533a..3db08f7 100644 --- a/pugl/pugl_internal.h +++ b/pugl/pugl_internal.h @@ -25,7 +25,9 @@ symbols can be defined to tweak pugl behaviour: PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus. - PUGL_VERBOSE: Print GL information to console. + PUGL_VERBOSE: Print graphics information to console. + PUGL_HAVE_CAIRO: Include Cairo support code. + PUGL_HAVE_GL: Include OpenGL support code. */ #include "pugl.h" @@ -55,6 +57,7 @@ struct PuglViewImpl { PuglInternals* impl; PuglNativeWindow parent; + PuglContextType ctx_type; int width; int height; @@ -110,6 +113,12 @@ puglInitResizable(PuglView* view, bool resizable) } void +puglInitContextType(PuglView* view, PuglContextType type) +{ + view->ctx_type = type; +} + +void puglSetHandle(PuglView* view, PuglHandle handle) { view->handle = handle; @@ -136,6 +145,7 @@ puglGetModifiers(PuglView* view) void puglDefaultReshape(PuglView* view, int width, int height) { +#ifdef PUGL_HAVE_GL glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, height, 0, 0, 1); @@ -143,6 +153,7 @@ puglDefaultReshape(PuglView* view, int width, int height) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); +#endif return; // unused diff --git a/pugl/pugl_x11.c b/pugl/pugl_x11.c index e29e3bd..509e527 100644 --- a/pugl/pugl_x11.c +++ b/pugl/pugl_x11.c @@ -24,46 +24,34 @@ #include <stdlib.h> #include <string.h> -#include <GL/gl.h> -#include <GL/glx.h> #include <X11/Xatom.h> #include <X11/Xlib.h> +#include <X11/Xutil.h> #include <X11/keysym.h> +#ifdef PUGL_HAVE_GL +#include <GL/gl.h> +#include <GL/glx.h> +#endif + +#ifdef PUGL_HAVE_CAIRO +#include <cairo/cairo.h> +#include <cairo/cairo-xlib.h> +#endif + #include "pugl_internal.h" struct PuglInternalsImpl { Display* display; int screen; Window win; +#ifdef PUGL_HAVE_CAIRO + cairo_t* cr; +#endif +#ifdef PUGL_HAVE_GL GLXContext ctx; Bool doubleBuffered; -}; - -/** - Attributes for single-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. -*/ -static int attrListSgl[] = { - GLX_RGBA, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - None -}; - -/** - Attributes for double-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. -*/ -static int attrListDbl[] = { - GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - None +#endif }; PuglInternals* @@ -80,21 +68,49 @@ puglCreateWindow(PuglView* view, const char* title) impl->display = XOpenDisplay(0); impl->screen = DefaultScreen(impl->display); - XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); - if (!vi) { - vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); - impl->doubleBuffered = False; - PUGL_LOG("no double-buffering available, using single-buffering\n"); - } else { - impl->doubleBuffered = True; - PUGL_LOG("using double-buffered rendering\n"); + XVisualInfo* vi = NULL; + +#ifdef PUGL_HAVE_GL + if (view->ctx_type == PUGL_GL) { + // Try to create double-buffered visual + int double_attrs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + None }; + vi = glXChooseVisual(impl->display, impl->screen, double_attrs); + if (!vi) { + // Failed, create single-buffered visual + int single_attrs[] = { GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + None }; + vi = glXChooseVisual(impl->display, impl->screen, single_attrs); + impl->doubleBuffered = False; + } else { + impl->doubleBuffered = True; + } + + impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); + PUGL_LOGF("GLX depth %d, %s-buffered, %s\n", + vi->depth, + impl->doubleBuffered ? "double" : "single", + (glXIsDirect(impl->display, impl->ctx) + ? "direct (set LIBGL_ALWAYS_INDIRECT=1 to disable)" + : "indirect")); } - - int glxMajor, glxMinor; - glXQueryVersion(impl->display, &glxMajor, &glxMinor); - PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor); - - impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); +#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 Window xParent = view->parent ? (Window)view->parent @@ -105,10 +121,10 @@ puglCreateWindow(PuglView* view, const char* title) XSetWindowAttributes attr; memset(&attr, 0, sizeof(XSetWindowAttributes)); - attr.colormap = cmap; - attr.border_pixel = 0; - - attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask + attr.background_pixel = BlackPixel(impl->display, impl->screen); + attr.border_pixel = BlackPixel(impl->display, impl->screen); + attr.colormap = cmap; + attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask #ifdef PUGL_GRAB_FOCUS | EnterWindowMask @@ -118,7 +134,17 @@ puglCreateWindow(PuglView* view, const char* title) impl->win = XCreateWindow( impl->display, xParent, 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &attr); + CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr); + +#ifdef PUGL_HAVE_CAIRO + if (view->ctx_type == PUGL_CAIRO) { + cairo_surface_t* surface = cairo_xlib_surface_create( + impl->display, impl->win, vi->visual, view->width, view->height); + if (!(impl->cr = cairo_create(surface))) { + fprintf(stderr, "failed to create cairo context\n"); + } + } +#endif XSizeHints sizeHints; memset(&sizeHints, 0, sizeof(sizeHints)); @@ -140,12 +166,6 @@ puglCreateWindow(PuglView* view, const char* title) XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); } - if (glXIsDirect(impl->display, impl->ctx)) { - PUGL_LOG("DRI enabled (set LIBGL_ALWAYS_INDIRECT=1 to disable)\n"); - } else { - PUGL_LOG("no DRI available\n"); - } - XFree(vi); return 0; @@ -174,7 +194,12 @@ puglDestroy(PuglView* view) return; } - glXDestroyContext(view->impl->display, view->impl->ctx); +#ifdef PUGL_HAVE_GL + if (view->ctx_type == PUGL_GL) { + glXDestroyContext(view->impl->display, view->impl->ctx); + } +#endif + XDestroyWindow(view->impl->display, view->impl->win); XCloseDisplay(view->impl->display); free(view->impl); @@ -184,7 +209,11 @@ puglDestroy(PuglView* view) static void puglReshape(PuglView* view, int width, int height) { - glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); +#ifdef PUGL_HAVE_GL + if (view->ctx_type == PUGL_GL) { + glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); + } +#endif if (view->reshapeFunc) { view->reshapeFunc(view, width, height); @@ -199,20 +228,27 @@ puglReshape(PuglView* view, int width, int height) static void puglDisplay(PuglView* view) { - glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); +#ifdef PUGL_HAVE_GL + if (view->ctx_type == PUGL_GL) { + glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + } +#endif if (view->displayFunc) { view->displayFunc(view); } + view->redisplay = false; - glFlush(); - if (view->impl->doubleBuffered) { - glXSwapBuffers(view->impl->display, view->impl->win); +#ifdef PUGL_HAVE_GL + if (view->ctx_type == PUGL_GL) { + glFlush(); + if (view->impl->doubleBuffered) { + glXSwapBuffers(view->impl->display, view->impl->win); + } } - - view->redisplay = false; +#endif } static PuglKey @@ -402,3 +438,14 @@ puglGetNativeWindow(PuglView* view) { return view->impl->win; } + +void* +puglGetContext(PuglView* view) +{ +#ifdef PUGL_HAVE_CAIRO + if (view->ctx_type == PUGL_CAIRO) { + return view->impl->cr; + } +#endif + return NULL; +} |