Browse Source

Start updating to latest pugl, again

gh-pages
falkTX 10 years ago
parent
commit
d9b8366a0d
8 changed files with 691 additions and 195 deletions
  1. +7
    -1
      dgl/src/Window.cpp
  2. +121
    -0
      dgl/src/pugl/common.h
  3. +41
    -0
      dgl/src/pugl/event.h
  4. +32
    -0
      dgl/src/pugl/gl.h
  5. +32
    -0
      dgl/src/pugl/glu.h
  6. +71
    -92
      dgl/src/pugl/pugl.h
  7. +160
    -19
      dgl/src/pugl/pugl_internal.h
  8. +227
    -83
      dgl/src/pugl/pugl_x11.c

+ 7
- 1
dgl/src/Window.cpp View File

@@ -22,6 +22,10 @@
#include "../Window.hpp" #include "../Window.hpp"
#include "../../distrho/extra/d_string.hpp" #include "../../distrho/extra/d_string.hpp"


#undef PUGL_HAVE_CAIRO
#undef PUGL_HAVE_GL
#define PUGL_HAVE_GL 1

#include "pugl/pugl.h" #include "pugl/pugl.h"


#if defined(DISTRHO_OS_WINDOWS) #if defined(DISTRHO_OS_WINDOWS)
@@ -182,7 +186,8 @@ struct Window::PrivateData {
return; return;
} }


puglInitResizable(fView, fResizable);
puglInitContextType(fView, PUGL_GL);
puglInitUserResizable(fView, fResizable);
puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight)); puglInitWindowSize(fView, static_cast<int>(fWidth), static_cast<int>(fHeight));


puglSetHandle(fView, this); puglSetHandle(fView, this);
@@ -223,6 +228,7 @@ struct Window::PrivateData {
XChangeProperty(xDisplay, xWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1); XChangeProperty(xDisplay, xWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);
} }
#endif #endif
puglEnterContext(fView);


fApp.pData->windows.push_back(fSelf); fApp.pData->windows.push_back(fSelf);




+ 121
- 0
dgl/src/pugl/common.h View File

@@ -0,0 +1,121 @@
/*
Copyright 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.
*/

#ifndef PUGL_COMMON_H_INCLUDED
#define PUGL_COMMON_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

/**
@addtogroup pugl
@{
*/

/**
A Pugl view.
*/
typedef struct PuglViewImpl PuglView;

/**
A native window handle.

On X11, this is a Window.
On OSX, this is an NSView*.
On Windows, this is a HWND.
*/
typedef intptr_t PuglNativeWindow;

/**
Handle for opaque user data.
*/
typedef void* PuglHandle;

/**
Return status code.
*/
typedef enum {
PUGL_SUCCESS = 0
} PuglStatus;

/**
Drawing context type.
*/
typedef enum {
PUGL_GL,
PUGL_CAIRO
} PuglContextType;

/**
Convenience symbols for ASCII control characters.
*/
typedef enum {
PUGL_CHAR_BACKSPACE = 0x08,
PUGL_CHAR_ESCAPE = 0x1B,
PUGL_CHAR_DELETE = 0x7F
} PuglChar;

/**
Keyboard modifier flags.
*/
typedef enum {
PUGL_MOD_SHIFT = 1 << 0, /**< Shift key */
PUGL_MOD_CTRL = 1 << 1, /**< Control key */
PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */
PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */
} PuglMod;

/**
Special (non-Unicode) keyboard keys.
*/
typedef enum {
PUGL_KEY_F1 = 1,
PUGL_KEY_F2,
PUGL_KEY_F3,
PUGL_KEY_F4,
PUGL_KEY_F5,
PUGL_KEY_F6,
PUGL_KEY_F7,
PUGL_KEY_F8,
PUGL_KEY_F9,
PUGL_KEY_F10,
PUGL_KEY_F11,
PUGL_KEY_F12,
PUGL_KEY_LEFT,
PUGL_KEY_UP,
PUGL_KEY_RIGHT,
PUGL_KEY_DOWN,
PUGL_KEY_PAGE_UP,
PUGL_KEY_PAGE_DOWN,
PUGL_KEY_HOME,
PUGL_KEY_END,
PUGL_KEY_INSERT,
PUGL_KEY_SHIFT,
PUGL_KEY_CTRL,
PUGL_KEY_ALT,
PUGL_KEY_SUPER
} PuglKey;

/**
@}
*/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* PUGL_COMMON_H_INCLUDED */

+ 41
- 0
dgl/src/pugl/event.h View File

@@ -0,0 +1,41 @@
/*
Copyright 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.
*/

#ifndef PUGL_EVENT_H_INCLUDED
#define PUGL_EVENT_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#else
# include <stdbool.h>
#endif

#include "pugl/common.h"

/**
@addtogroup pugl
@{
*/

/**
@}
*/

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* PUGL_EVENT_H_INCLUDED */

+ 32
- 0
dgl/src/pugl/gl.h View File

@@ -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


+ 32
- 0
dgl/src/pugl/glu.h View File

@@ -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 glu.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


+ 71
- 92
dgl/src/pugl/pugl.h View File

@@ -23,19 +23,8 @@


#include <stdint.h> #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
#include "pugl/common.h"
#include "pugl/event.h"


#ifdef PUGL_SHARED #ifdef PUGL_SHARED
# ifdef _WIN32 # ifdef _WIN32
@@ -70,82 +59,6 @@ extern "C" {
@{ @{
*/ */


/**
An OpenGL view.
*/
typedef struct PuglViewImpl PuglView;

/**
A native window handle.

On X11, this is a Window.
On OSX, this is an NSView*.
On Windows, this is a HWND.
*/
typedef intptr_t PuglNativeWindow;

/**
Return status code.
*/
typedef enum {
PUGL_SUCCESS = 0
} PuglStatus;

/**
Convenience symbols for ASCII control characters.
*/
typedef enum {
PUGL_CHAR_BACKSPACE = 0x08,
PUGL_CHAR_ESCAPE = 0x1B,
PUGL_CHAR_DELETE = 0x7F
} PuglChar;

/**
Special (non-Unicode) keyboard keys.
*/
typedef enum {
PUGL_KEY_F1 = 1,
PUGL_KEY_F2,
PUGL_KEY_F3,
PUGL_KEY_F4,
PUGL_KEY_F5,
PUGL_KEY_F6,
PUGL_KEY_F7,
PUGL_KEY_F8,
PUGL_KEY_F9,
PUGL_KEY_F10,
PUGL_KEY_F11,
PUGL_KEY_F12,
PUGL_KEY_LEFT,
PUGL_KEY_UP,
PUGL_KEY_RIGHT,
PUGL_KEY_DOWN,
PUGL_KEY_PAGE_UP,
PUGL_KEY_PAGE_DOWN,
PUGL_KEY_HOME,
PUGL_KEY_END,
PUGL_KEY_INSERT,
PUGL_KEY_SHIFT,
PUGL_KEY_CTRL,
PUGL_KEY_ALT,
PUGL_KEY_SUPER
} PuglKey;

/**
Keyboard modifier flags.
*/
typedef enum {
PUGL_MOD_SHIFT = 1, /**< Shift key */
PUGL_MOD_CTRL = 1 << 1, /**< Control key */
PUGL_MOD_ALT = 1 << 2, /**< Alt/Option key */
PUGL_MOD_SUPER = 1 << 3 /**< Mod4/Command/Windows key */
} PuglMod;

/**
Handle for opaque user data.
*/
typedef void* PuglHandle;

/** /**
A function called when the window is closed. A function called when the window is closed.
*/ */
@@ -227,6 +140,12 @@ typedef void (*PuglSpecialFunc)(PuglView* view, bool press, PuglKey key);
*/ */
typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename); typedef void (*PuglFileSelectedFunc)(PuglView* view, const char* filename);


/**
@name Initialization
Configuration functions which must be called before creating a window.
@{
*/

/** /**
Create a Pugl context. Create a Pugl context.


@@ -248,12 +167,43 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent);
PUGL_API void PUGL_API void
puglInitWindowSize(PuglView* view, int width, int height); puglInitWindowSize(PuglView* view, int width, int height);


/**
Set the minimum window size before creating a window.
*/
PUGL_API void
puglInitWindowMinSize(PuglView* view, int width, int height);

/** /**
Enable or disable resizing before creating a window. Enable or disable resizing before creating a window.
*/ */
PUGL_API void PUGL_API void
puglInitUserResizable(PuglView* view, bool resizable); puglInitUserResizable(PuglView* view, bool resizable);


/**
Set transient parent before creating a window.

On X11, parent_id must be a Window.
On OSX, parent_id must be an NSView*.
*/
PUGL_API void
puglInitTransientFor(PuglView* view, uintptr_t parent);

/**
Set the context type before creating a window.
*/
PUGL_API void
puglInitContextType(PuglView* view, PuglContextType type);

/**
@}
*/

/**
@name Windows
Window management functions.
@{
*/

/** /**
Create a window with the settings given by the various puglInit functions. Create a window with the settings given by the various puglInit functions.


@@ -274,6 +224,16 @@ puglShowWindow(PuglView* view);
PUGL_API void PUGL_API void
puglHideWindow(PuglView* view); puglHideWindow(PuglView* view);


/**
Return the native window handle.
*/
PUGL_API PuglNativeWindow
puglGetNativeWindow(PuglView* view);

/**
@}
*/

/** /**
Set the handle to be passed to all callbacks. Set the handle to be passed to all callbacks.


@@ -292,6 +252,15 @@ puglSetHandle(PuglView* view, PuglHandle handle);
PUGL_API PuglHandle PUGL_API PuglHandle
puglGetHandle(PuglView* view); 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. Return the timestamp (if any) of the currently-processing event.
*/ */
@@ -312,6 +281,12 @@ puglGetModifiers(PuglView* view);
PUGL_API void PUGL_API void
puglIgnoreKeyRepeat(PuglView* view, bool ignore); puglIgnoreKeyRepeat(PuglView* view, bool ignore);


/**
@name Event Callbacks
Functions to set event callbacks for handling user input.
@{
*/

/** /**
Set the function to call when the window is closed. Set the function to call when the window is closed.
*/ */
@@ -367,10 +342,14 @@ PUGL_API void
puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc);


/** /**
Return the native window handle.
@}
*/ */
PUGL_API PuglNativeWindow
puglGetNativeWindow(PuglView* view);

/**
Grab the input focus.
*/
PUGL_API void
puglGrabFocus(PuglView* view);


/** /**
Process all pending window events. Process all pending window events.


+ 160
- 19
dgl/src/pugl/pugl_internal.h View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012 David Robillard <http://drobilla.net>
Copyright 2012-2014 David Robillard <http://drobilla.net>


Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@@ -24,11 +24,14 @@
If you are copying the pugl code into your source tree, the following If you are copying the pugl code into your source tree, the following
symbols can be defined to tweak pugl behaviour: symbols can be defined to tweak pugl behaviour:


PUGL_HAVE_CAIRO: Include Cairo support code.
PUGL_HAVE_GL: Include OpenGL support code.
PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus. PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus.
PUGL_VERBOSE: Print GL information to console. PUGL_VERBOSE: Print GL information to console.
*/ */


#include "pugl.h"
#include "pugl/pugl.h"
#include "pugl/event.h"


#ifdef PUGL_VERBOSE #ifdef PUGL_VERBOSE
# include <stdio.h> # include <stdio.h>
@@ -54,10 +57,15 @@ struct PuglViewImpl {
PuglFileSelectedFunc fileSelectedFunc; PuglFileSelectedFunc fileSelectedFunc;


PuglInternals* impl; PuglInternals* impl;

PuglNativeWindow parent; PuglNativeWindow parent;
PuglContextType ctx_type;
uintptr_t transient_parent;


int width; int width;
int height; int height;
int min_width;
int min_height;
int mods; int mods;
bool mouse_in_view; bool mouse_in_view;
bool ignoreKeyRepeat; bool ignoreKeyRepeat;
@@ -96,6 +104,13 @@ puglInitWindowSize(PuglView* view, int width, int height)
view->height = height; view->height = height;
} }


void
puglInitWindowMinSize(PuglView* view, int width, int height)
{
view->min_width = width;
view->min_height = height;
}

void void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent) puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
{ {
@@ -103,11 +118,23 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
} }


void void
puglInitResizable(PuglView* view, bool resizable)
puglInitUserResizable(PuglView* view, bool resizable)
{ {
view->resizable = resizable; view->resizable = resizable;
} }


void
puglInitTransientFor(PuglView* view, uintptr_t parent)
{
view->transient_parent = parent;
}

void
puglInitContextType(PuglView* view, PuglContextType type)
{
view->ctx_type = type;
}

void void
puglSetHandle(PuglView* view, PuglHandle handle) puglSetHandle(PuglView* view, PuglHandle handle)
{ {
@@ -132,22 +159,6 @@ puglGetModifiers(PuglView* view)
return view->mods; return view->mods;
} }


static void
puglDefaultReshape(PuglView* view, int width, int height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glViewport(0, 0, width, height);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return;

// unused
(void)view;
}

void void
puglIgnoreKeyRepeat(PuglView* view, bool ignore) puglIgnoreKeyRepeat(PuglView* view, bool ignore)
{ {
@@ -207,3 +218,133 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc)
{ {
view->fileSelectedFunc = fileSelectedFunc; view->fileSelectedFunc = fileSelectedFunc;
} }

void
puglEnterContext(PuglView* view);

void
puglLeaveContext(PuglView* view, bool flush);

/** Return the code point for buf, or the replacement character on error. */
static uint32_t
puglDecodeUTF8(const uint8_t* buf)
{
#define FAIL_IF(cond) { if (cond) return 0xFFFD; }

/* http://en.wikipedia.org/wiki/UTF-8 */

if (buf[0] < 0x80) {
return buf[0];
} else if (buf[0] < 0xC2) {
return 0xFFFD;
} else if (buf[0] < 0xE0) {
FAIL_IF((buf[1] & 0xC0) != 0x80);
return (buf[0] << 6) + buf[1] - 0x3080;
} else if (buf[0] < 0xF0) {
FAIL_IF((buf[1] & 0xC0) != 0x80);
FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0);
FAIL_IF((buf[2] & 0xC0) != 0x80);
return (buf[0] << 12) + (buf[1] << 6) + buf[2] - 0xE2080;
} else if (buf[0] < 0xF5) {
FAIL_IF((buf[1] & 0xC0) != 0x80);
FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90);
FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90);
FAIL_IF((buf[2] & 0xC0) != 0x80);
FAIL_IF((buf[3] & 0xC0) != 0x80);
return ((buf[0] << 18) +
(buf[1] << 12) +
(buf[2] << 6) +
buf[3] - 0x3C82080);
}
return 0xFFFD;
}

static void
puglDefaultReshape(PuglView* view, int width, int height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glViewport(0, 0, width, height);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return;

// unused
(void)view;
}

#if 0
static void
puglDispatchEvent(PuglView* view, const PuglEvent* event)
{
if (view->eventFunc) {
view->eventFunc(view, event);
}

switch (event->type) {
case PUGL_CONFIGURE:
puglEnterContext(view);
view->width = event->configure.width;
view->height = event->configure.height;
if (view->reshapeFunc) {
view->reshapeFunc(view, view->width, view->height);
}
puglLeaveContext(view, false);
break;
case PUGL_EXPOSE:
if (event->expose.count == 0) {
puglEnterContext(view);
if (view->displayFunc) {
view->displayFunc(view);
}
view->redisplay = false;
puglLeaveContext(view, true);
}
break;
case PUGL_MOTION_NOTIFY:
view->event_timestamp_ms = event->motion.time;
view->mods = event->motion.state;
if (view->motionFunc) {
view->motionFunc(view, event->motion.x, event->motion.y);
}
break;
case PUGL_SCROLL:
if (view->scrollFunc) {
view->scrollFunc(view,
event->scroll.x, event->scroll.y,
event->scroll.dx, event->scroll.dy);
}
break;
case PUGL_BUTTON_PRESS:
case PUGL_BUTTON_RELEASE:
view->event_timestamp_ms = event->button.time;
view->mods = event->button.state;
if (view->mouseFunc) {
view->mouseFunc(view,
event->button.button,
event->type == PUGL_BUTTON_PRESS,
event->button.x,
event->button.y);
}
break;
case PUGL_KEY_PRESS:
case PUGL_KEY_RELEASE:
view->event_timestamp_ms = event->key.time;
view->mods = event->key.state;
if (event->key.special && view->specialFunc) {
view->specialFunc(view,
event->type == PUGL_KEY_PRESS,
event->key.special);
} else if (event->key.character && view->keyboardFunc) {
view->keyboardFunc(view,
event->type == PUGL_KEY_PRESS,
event->key.character);
}
break;
default:
break;
}
}
#endif

+ 227
- 83
dgl/src/pugl/pugl_x11.c View File

@@ -1,7 +1,7 @@
/* /*
Copyright 2012-2014 David Robillard <http://drobilla.net> Copyright 2012-2014 David Robillard <http://drobilla.net>
Copyright 2011-2012 Ben Loftis, Harrison Consoles
Copyright 2013 Robin Gareus <robin@gareus.org> Copyright 2013 Robin Gareus <robin@gareus.org>
Copyright 2011-2012 Ben Loftis, Harrison Consoles


Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@@ -24,13 +24,22 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>


#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h> #include <X11/keysym.h>


#include "pugl_internal.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/pugl_internal.h"


#define SOFD_HAVE_X11 #define SOFD_HAVE_X11
#include "../sofd/libsofd.h" #include "../sofd/libsofd.h"
@@ -40,53 +49,16 @@ struct PuglInternalsImpl {
Display* display; Display* display;
int screen; int screen;
Window win; Window win;
XIM xim;
XIC xic;
#ifdef PUGL_HAVE_CAIRO
cairo_t* cr;
cairo_surface_t* surface;
#endif
#ifdef PUGL_HAVE_GL
GLXContext ctx; GLXContext ctx;
Bool doubleBuffered; 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,
GLX_ARB_multisample, 1,
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,
GLX_ARB_multisample, 1,
None
};

/**
Attributes for double-buffered RGBA with multi-sampling
(antialiasing)
*/
static int attrListDblMS[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER , True,
GLX_RED_SIZE , 4,
GLX_GREEN_SIZE , 4,
GLX_BLUE_SIZE , 4,
GLX_ALPHA_SIZE , 4,
GLX_DEPTH_SIZE , 16,
GLX_SAMPLE_BUFFERS , 1,
GLX_SAMPLES , 4,
None
#endif
}; };


PuglInternals* PuglInternals*
@@ -95,33 +67,186 @@ puglInitInternals(void)
return (PuglInternals*)calloc(1, sizeof(PuglInternals)); 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) {
/**
Attributes for single-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer.
*/
int attrListSgl[] = {
GLX_RGBA,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 16,
GLX_ARB_multisample, 1,
None
};

/**
Attributes for double-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer.
*/
int attrListDbl[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 16,
GLX_ARB_multisample, 1,
None
};

/**
Attributes for double-buffered RGBA with multi-sampling
(antialiasing)
*/
int attrListDblMS[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_ALPHA_SIZE, 4,
GLX_DEPTH_SIZE, 16,
GLX_SAMPLE_BUFFERS, 1,
GLX_SAMPLES, 4,
None
};

impl->doubleBuffered = True;

vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);

if (vi == NULL) {
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
PUGL_LOG("multisampling (antialiasing) is not available\n");
}

if (vi == NULL) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n");
}
}
#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;
}

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);
return (impl->ctx != NULL);
}
#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);
if (impl->surface == NULL) {
PUGL_LOG("failed to create cairo surface\n");
return false;
}
impl->cr = cairo_create(impl->surface);
if (impl->cr == NULL) {
cairo_surface_destroy(impl->surface);
impl->surface = NULL;
PUGL_LOG("failed to create cairo context\n");
return false;
}
return true;
}
#endif

return false;
}

static void
destroyContext(PuglView* view)
{
PuglInternals* const impl = view->impl;

#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
glXDestroyContext(impl->display, impl->ctx);
impl->ctx = NULL;
}
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
cairo_destroy(impl->cr);
impl->cr = NULL;

cairo_surface_destroy(impl->surface);
impl->surface = NULL;
}
#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
}

void
puglLeaveContext(PuglView* view, bool flush)
{
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL && flush) {
glFlush();
if (view->impl->doubleBuffered) {
glXSwapBuffers(view->impl->display, view->impl->win);
}
}
#endif
}

int int
puglCreateWindow(PuglView* view, const char* title) puglCreateWindow(PuglView* view, const char* title)
{ {
PuglInternals* impl = view->impl;
PuglInternals* const impl = view->impl;


impl->display = XOpenDisplay(NULL); impl->display = XOpenDisplay(NULL);
impl->screen = DefaultScreen(impl->display); impl->screen = DefaultScreen(impl->display);
impl->doubleBuffered = True;

XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);


XVisualInfo* const vi = getVisual(view);
if (!vi) { if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
PUGL_LOG("multisampling (antialiasing) is not available\n");
}

if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n");
XCloseDisplay(impl->display);
impl->display = NULL;
return 1;
} }


#ifdef PUGL_HAVE_GL
int glxMajor, glxMinor; int glxMajor, glxMinor;
glXQueryVersion(impl->display, &glxMajor, &glxMinor); glXQueryVersion(impl->display, &glxMajor, &glxMinor);
PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor); PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor);

impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);
#endif


Window xParent = view->parent Window xParent = view->parent
? (Window)view->parent ? (Window)view->parent
@@ -132,20 +257,29 @@ puglCreateWindow(PuglView* view, const char* title)


XSetWindowAttributes attr; XSetWindowAttributes attr;
memset(&attr, 0, sizeof(XSetWindowAttributes)); memset(&attr, 0, sizeof(XSetWindowAttributes));
attr.colormap = cmap;
attr.border_pixel = 0;

attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask
| ButtonPressMask | ButtonReleaseMask
#ifdef PUGL_GRAB_FOCUS
| EnterWindowMask
#endif
| PointerMotionMask | StructureNotifyMask;
attr.background_pixel = BlackPixel(impl->display, impl->screen);
attr.border_pixel = BlackPixel(impl->display, impl->screen);
attr.colormap = cmap;
attr.event_mask = (ExposureMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask |
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask);


impl->win = XCreateWindow( impl->win = XCreateWindow(
impl->display, xParent, impl->display, xParent,
0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual, 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &attr);
CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr);

if (!createContext(view, vi)) {
XDestroyWindow(impl->display, impl->win);
impl->win = 0;

XCloseDisplay(impl->display);
impl->display = NULL;

return 1;
}


XSizeHints sizeHints; XSizeHints sizeHints;
memset(&sizeHints, 0, sizeof(sizeHints)); memset(&sizeHints, 0, sizeof(sizeHints));
@@ -156,6 +290,11 @@ puglCreateWindow(PuglView* view, const char* title)
sizeHints.max_width = view->width; sizeHints.max_width = view->width;
sizeHints.max_height = view->height; sizeHints.max_height = view->height;
XSetNormalHints(impl->display, impl->win, &sizeHints); XSetNormalHints(impl->display, impl->win, &sizeHints);
} else if (view->min_width > 0 && view->min_height > 0) {
sizeHints.flags = PMinSize;
sizeHints.min_width = view->min_width;
sizeHints.min_height = view->min_height;
XSetNormalHints(impl->display, impl->win, &sizeHints);
} }


if (title) { if (title) {
@@ -175,25 +314,19 @@ puglCreateWindow(PuglView* view, const char* title)


XFree(vi); XFree(vi);


glXMakeCurrent(view->impl->display, view->impl->win, view->impl->ctx);

return 0;
return PUGL_SUCCESS;
} }


void void
puglShowWindow(PuglView* view) puglShowWindow(PuglView* view)
{ {
PuglInternals* impl = view->impl;

XMapRaised(impl->display, impl->win);
XMapRaised(view->impl->display, view->impl->win);
} }


void void
puglHideWindow(PuglView* view) puglHideWindow(PuglView* view)
{ {
PuglInternals* impl = view->impl;

XUnmapWindow(impl->display, impl->win);
XUnmapWindow(view->impl->display, view->impl->win);
} }


void void
@@ -205,7 +338,7 @@ puglDestroy(PuglView* view)


x_fib_close(view->impl->display); x_fib_close(view->impl->display);


glXDestroyContext(view->impl->display, view->impl->ctx);
destroyContext(view);
XDestroyWindow(view->impl->display, view->impl->win); XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display); XCloseDisplay(view->impl->display);
free(view->impl); free(view->impl);
@@ -462,3 +595,14 @@ puglGetNativeWindow(PuglView* view)
{ {
return view->impl->win; 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;
}

Loading…
Cancel
Save