From b4dbb3616865cd236cda4f2e4ac806b3b4840b29 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 27 Aug 2014 07:09:58 +0000 Subject: Cairo support on X11. --- pugl/gl.h | 32 ++++++++++ pugl/glu.h | 32 ++++++++++ pugl/pugl.h | 37 ++++++----- pugl/pugl_internal.h | 13 +++- pugl/pugl_x11.c | 173 ++++++++++++++++++++++++++++++++------------------- pugl_cairo_test.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++ pugl_test.c | 9 +-- wscript | 72 +++++++++++++++------ 8 files changed, 430 insertions(+), 105 deletions(-) create mode 100644 pugl/gl.h create mode 100644 pugl/glu.h create mode 100644 pugl_cairo_test.c 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 + + 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 /* 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 + + 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 /* 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 -/* - 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 /* Broken Windows GL headers require this */ -# endif -# include "GL/gl.h" -#endif - #ifdef PUGL_SHARED # ifdef _WIN32 # define PUGL_LIB_IMPORT __declspec(dllimport) @@ -87,6 +73,14 @@ typedef enum { PUGL_SUCCESS = 0 } PuglStatus; +/** + Drawing context type. +*/ +typedef enum { + PUGL_GL, + PUGL_CAIRO +} PuglContextType; + /** Convenience symbols for ASCII control characters. */ @@ -246,6 +240,12 @@ puglInitWindowSize(PuglView* view, int width, int height); 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. @@ -284,6 +284,15 @@ puglSetHandle(PuglView* view, PuglHandle handle); 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. */ 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; @@ -109,6 +112,12 @@ puglInitResizable(PuglView* view, bool resizable) view->resizable = resizable; } +void +puglInitContextType(PuglView* view, PuglContextType type) +{ + view->ctx_type = type; +} + void puglSetHandle(PuglView* view, PuglHandle 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 #include -#include -#include #include #include +#include #include +#ifdef PUGL_HAVE_GL +#include +#include +#endif + +#ifdef PUGL_HAVE_CAIRO +#include +#include +#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; +} diff --git a/pugl_cairo_test.c b/pugl_cairo_test.c new file mode 100644 index 0000000..6ff5bd5 --- /dev/null +++ b/pugl_cairo_test.c @@ -0,0 +1,167 @@ +/* + Copyright 2012-2014 David Robillard + + 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 pugl_cairo_test.c A simple Pugl test that creates a top-level window. +*/ + +#include +#include +#include + +#include + +#include "pugl/pugl.h" + +static int quit = 0; + +typedef struct { + int x; + int y; + int w; + int h; + bool pressed; + const char* label; +} Button; + +static Button toggle_button = { 16, 16, 128, 64, false, "Test" }; + +static void +roundedBox(cairo_t* cr, double x, double y, double w, double h) +{ + static const double radius = 10; + static const double degrees = 3.14159265 / 180.0; + + cairo_new_sub_path(cr); + cairo_arc(cr, + x + w - radius, + y + radius, + radius, -90 * degrees, 0 * degrees); + cairo_arc(cr, + x + w - radius, y + h - radius, + radius, 0 * degrees, 90 * degrees); + cairo_arc(cr, + x + radius, y + h - radius, + radius, 90 * degrees, 180 * degrees); + cairo_arc(cr, + x + radius, y + radius, + radius, 180 * degrees, 270 * degrees); + cairo_close_path(cr); +} + +static void +drawButton(cairo_t* cr, const Button* but) +{ + // Draw base + if (but->pressed) { + cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1); + } else { + cairo_set_source_rgba(cr, 0.3, 0.5, 0.1, 1); + } + roundedBox(cr, but->x, but->y, but->w, but->h); + cairo_fill_preserve(cr); + + // Draw border + cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1); + cairo_set_line_width(cr, 4.0); + cairo_stroke(cr); + + // Draw label + cairo_text_extents_t extents; + cairo_set_font_size(cr, 32.0); + cairo_text_extents(cr, but->label, &extents); + cairo_move_to(cr, + (but->x + but->w / 2) - extents.width / 2, + (but->y + but->h / 2) + extents.height / 2); + cairo_set_source_rgba(cr, 0, 0, 0, 1); + cairo_show_text(cr, but->label); +} + +static void +onDisplay(PuglView* view) +{ + cairo_t* cr = puglGetContext(view); + + drawButton(cr, &toggle_button); +} + +static void +onKeyboard(PuglView* view, bool press, uint32_t key) +{ + if (key == 'q' || key == 'Q' || key == PUGL_CHAR_ESCAPE) { + quit = 1; + } +} + +static void +onMouse(PuglView* view, int button, bool press, int x, int y) +{ + if (press && + x >= toggle_button.x && x <= toggle_button.x + toggle_button.w && + y >= toggle_button.y && y <= toggle_button.y + toggle_button.h) { + toggle_button.pressed = !toggle_button.pressed; + puglPostRedisplay(view); + } +} + +static void +onClose(PuglView* view) +{ + quit = 1; +} + +int +main(int argc, char** argv) +{ + bool ignoreKeyRepeat = false; + bool resizable = false; + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-h")) { + printf("USAGE: %s [OPTIONS]...\n\n" + " -h Display this help\n" + " -i Ignore key repeat\n" + " -r Resizable window\n", argv[0]); + return 0; + } else if (!strcmp(argv[i], "-i")) { + ignoreKeyRepeat = true; + } else if (!strcmp(argv[i], "-r")) { + resizable = true; + } else { + fprintf(stderr, "Unknown option: %s\n", argv[i]); + } + } + + PuglView* view = puglInit(NULL, NULL); + puglInitWindowSize(view, 512, 512); + puglInitResizable(view, resizable); + puglInitContextType(view, PUGL_CAIRO); + + puglIgnoreKeyRepeat(view, ignoreKeyRepeat); + puglSetKeyboardFunc(view, onKeyboard); + puglSetMouseFunc(view, onMouse); + puglSetDisplayFunc(view, onDisplay); + puglSetCloseFunc(view, onClose); + + puglCreateWindow(view, "Pugl Test"); + puglShowWindow(view); + + while (!quit) { + puglProcessEvents(view); + } + + puglDestroy(view); + return 0; +} diff --git a/pugl_test.c b/pugl_test.c index 9282420..aa7997d 100644 --- a/pugl_test.c +++ b/pugl_test.c @@ -22,13 +22,8 @@ #include #include "pugl/pugl.h" - -// Argh! -#ifdef __APPLE__ -# include -#else -# include -#endif +#include "pugl/gl.h" +#include "pugl/glu.h" static int quit = 0; static float xAngle = 0.0f; diff --git a/wscript b/wscript index 7da324d..cebf807 100644 --- a/wscript +++ b/wscript @@ -30,13 +30,17 @@ def options(opt): if Options.platform == 'win32': opt.load('compiler_cxx') autowaf.set_options(opt) + opt.add_option('--no-gl', action='store_true', default=False, dest='no_gl', + help='Do not build OpenGL support') + opt.add_option('--no-cairo', action='store_true', default=False, dest='no_cairo', + help='Do not build Cairo support') opt.add_option('--test', action='store_true', default=False, dest='build_tests', help='Build unit tests') opt.add_option('--static', action='store_true', default=False, dest='static', help='Build static library') opt.add_option('--shared', action='store_true', default=False, dest='shared', help='Build shared library') - opt.add_option('--verbose', action='store_true', default=False, dest='verbose', + opt.add_option('--log', action='store_true', default=False, dest='log', help='Print GL information to console') opt.add_option('--grab-focus', action='store_true', default=False, dest='grab_focus', help='Work around reparent keyboard issues by grabbing focus') @@ -46,15 +50,28 @@ def configure(conf): if Options.platform == 'win32': conf.load('compiler_cxx') autowaf.configure(conf) + autowaf.set_c99_mode(conf) autowaf.display_header('Pugl Configuration') - if conf.env['MSVC_COMPILER']: - conf.env.append_unique('CFLAGS', ['-TP', '-MD']) - else: - conf.env.append_unique('CFLAGS', '-std=c99') - - if Options.options.verbose: - autowaf.define(conf, 'PUGL_VERBOSE', PUGL_VERBOSE) + if not Options.options.no_gl: + conf.check(function_name = 'glLoadIdentity', + header_name = 'GL/gl.h', + define_name = 'HAVE_GL', + lib = ['GL'], + mandatory = False) + if conf.is_defined('HAVE_GL'): + autowaf.define(conf, 'PUGL_HAVE_GL', 1) + + if not Options.options.no_cairo: + autowaf.check_pkg(conf, 'cairo', + uselib_store = 'CAIRO', + atleast_version = '1.0.0', + mandatory = False) + if conf.is_defined('HAVE_CAIRO'): + autowaf.define(conf, 'PUGL_HAVE_CAIRO', 1) + + if Options.options.log: + autowaf.define(conf, 'PUGL_VERBOSE', 1) # Shared library building is broken on win32 for some reason conf.env['BUILD_TESTS'] = Options.options.build_tests @@ -71,6 +88,9 @@ def configure(conf): conf.env['LIBPATH_PUGL'] = [conf.env['LIBDIR']] conf.env['LIB_PUGL'] = ['pugl-%s' % PUGL_MAJOR_VERSION]; + autowaf.display_msg(conf, "OpenGL support", conf.is_defined('HAVE_GL')) + autowaf.display_msg(conf, "Cairo support", conf.is_defined('HAVE_CAIRO')) + autowaf.display_msg(conf, "Verbose console output", conf.is_defined('PUGL_VERBOSE')) autowaf.display_msg(conf, "Static library", str(conf.env['BUILD_STATIC'])) autowaf.display_msg(conf, "Unit tests", str(conf.env['BUILD_TESTS'])) print('') @@ -100,8 +120,10 @@ def build(bld): else: lang = 'c' lib_source = ['pugl/pugl_x11.c'] - libs = ['X11', 'GL', 'GLU'] + libs = ['X11'] defines = [] + if bld.is_defined('HAVE_GL'): + libs += ['GL', 'GLU'] if bld.env['MSVC_COMPILER']: libflags = [] @@ -112,6 +134,7 @@ def build(bld): source = lib_source, includes = ['.', './src'], lib = libs, + uselib = ['CAIRO'], framework = framework, name = 'libpugl', target = 'pugl-%s' % PUGL_MAJOR_VERSION, @@ -128,6 +151,7 @@ def build(bld): source = lib_source, includes = ['.', './src'], lib = libs, + uselib = ['CAIRO'], framework = framework, name = 'libpugl_static', target = 'pugl-%s' % PUGL_MAJOR_VERSION, @@ -140,17 +164,25 @@ def build(bld): test_libs = libs test_cflags = [''] - # Unit test program - obj = bld(features = 'c cprogram', - source = 'pugl_test.c', - includes = ['.', './src'], - use = 'libpugl_static', - lib = test_libs, - framework = framework, - target = 'pugl_test', - install_path = '', - defines = defines, - cflags = test_cflags) + # Test programs + progs = [] + if bld.is_defined('HAVE_GL'): + progs += ['pugl_test'] + if bld.is_defined('HAVE_CAIRO'): + progs += ['pugl_cairo_test'] + + for prog in progs: + obj = bld(features = 'c cprogram', + source = '%s.c' % prog, + includes = ['.', './src'], + use = 'libpugl_static', + lib = test_libs, + uselib = ['CAIRO'], + framework = framework, + target = prog, + install_path = '', + defines = defines, + cflags = test_cflags) def lint(ctx): subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-readability/todo,-build/include src/* pugl/*', shell=True) -- cgit v1.2.3