Browse Source

software rendering with Cairo

pull/99/head
JP Cimalando Filipe Coelho <falktx@falktx.com> 6 years ago
parent
commit
d80c799b8c
18 changed files with 799 additions and 111 deletions
  1. +4
    -2
      Makefile.base.mk
  2. +15
    -0
      dgl/Base.hpp
  3. +4
    -0
      dgl/Color.hpp
  4. +14
    -0
      dgl/Geometry.hpp
  5. +4
    -0
      dgl/Widget.hpp
  6. +4
    -0
      dgl/Window.hpp
  7. +33
    -0
      dgl/src/Color.cpp
  8. +14
    -0
      dgl/src/Geometry.cpp
  9. +7
    -0
      dgl/src/Widget.cpp
  10. +4
    -0
      dgl/src/WidgetPrivateData.hpp
  11. +32
    -2
      dgl/src/Window.cpp
  12. +22
    -0
      dgl/src/pugl/pugl.h
  13. +9
    -0
      dgl/src/pugl/pugl_internal.h
  14. +386
    -38
      dgl/src/pugl/pugl_osx.m
  15. +108
    -41
      dgl/src/pugl/pugl_win.cpp
  16. +135
    -26
      dgl/src/pugl/pugl_x11.c
  17. +2
    -2
      distrho/src/DistrhoPluginChecks.h
  18. +2
    -0
      distrho/src/DistrhoUI.cpp

+ 4
- 2
Makefile.base.mk View File

@@ -189,6 +189,8 @@ endif


ifeq ($(HAVE_DGL),true) ifeq ($(HAVE_DGL),true)


DGL_FLAGS += -DHAVE_DGL

ifeq ($(MACOS),true) ifeq ($(MACOS),true)
DGL_LIBS = -framework OpenGL -framework Cocoa DGL_LIBS = -framework OpenGL -framework Cocoa
endif endif
@@ -198,8 +200,8 @@ DGL_LIBS = -lopengl32 -lgdi32
endif endif


ifneq ($(MACOS_OR_WIN32),true) ifneq ($(MACOS_OR_WIN32),true)
DGL_FLAGS = $(shell pkg-config --cflags gl x11)
DGL_LIBS = $(shell pkg-config --libs gl x11)
DGL_FLAGS += $(shell pkg-config --cflags gl x11)
DGL_LIBS += $(shell pkg-config --libs gl x11)
endif endif


endif # HAVE_DGL endif # HAVE_DGL


+ 15
- 0
dgl/Base.hpp View File

@@ -73,6 +73,8 @@
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// OpenGL includes // OpenGL includes


#if defined(HAVE_DGL)

#ifdef DISTRHO_OS_MAC #ifdef DISTRHO_OS_MAC
# include <OpenGL/gl.h> # include <OpenGL/gl.h>
#else #else
@@ -83,9 +85,20 @@
# include <GL/glext.h> # include <GL/glext.h>
#endif #endif


#endif

// -----------------------------------------------------------------------
// Cairo includes

#if defined(HAVE_DCAIRO)
# include <cairo/cairo.h>
#endif

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Missing OpenGL defines // Missing OpenGL defines


#if defined(HAVE_DGL)

#if defined(GL_BGR_EXT) && ! defined(GL_BGR) #if defined(GL_BGR_EXT) && ! defined(GL_BGR)
# define GL_BGR GL_BGR_EXT # define GL_BGR GL_BGR_EXT
#endif #endif
@@ -98,6 +111,8 @@
# define GL_CLAMP_TO_BORDER 0x812D # define GL_CLAMP_TO_BORDER 0x812D
#endif #endif


#endif

#ifdef DISTRHO_OS_WINDOWS #ifdef DISTRHO_OS_WINDOWS
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Fix OpenGL includes for Windows, based on glfw code // Fix OpenGL includes for Windows, based on glfw code


+ 4
- 0
dgl/Color.hpp View File

@@ -19,7 +19,9 @@


#include "Base.hpp" #include "Base.hpp"


#if !defined(HAVE_DCAIRO)
struct NVGcolor; struct NVGcolor;
#endif


START_NAMESPACE_DGL START_NAMESPACE_DGL


@@ -95,12 +97,14 @@ struct Color {
*/ */
void fixBounds() noexcept; void fixBounds() noexcept;


#if !defined(HAVE_DCAIRO)
/** /**
@internal @internal
Needed for NanoVG compatibility. Needed for NanoVG compatibility.
*/ */
Color(const NVGcolor&) noexcept; Color(const NVGcolor&) noexcept;
operator NVGcolor() const noexcept; operator NVGcolor() const noexcept;
#endif
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


+ 14
- 0
dgl/Geometry.hpp View File

@@ -346,10 +346,12 @@ public:
*/ */
void moveBy(const Point<T>& pos) noexcept; void moveBy(const Point<T>& pos) noexcept;


#if defined(HAVE_DGL)
/** /**
Draw this line using the current OpenGL state. Draw this line using the current OpenGL state.
*/ */
void draw(); void draw();
#endif


/** /**
Return true if line is null (start and end pos are equal). Return true if line is null (start and end pos are equal).
@@ -460,6 +462,7 @@ public:
*/ */
void setNumSegments(const uint num); void setNumSegments(const uint num);


#if defined(HAVE_DGL)
/** /**
Draw this circle using the current OpenGL state. Draw this circle using the current OpenGL state.
*/ */
@@ -469,6 +472,7 @@ public:
Draw lines (outline of this circle) using the current OpenGL state. Draw lines (outline of this circle) using the current OpenGL state.
*/ */
void drawOutline(); void drawOutline();
#endif


Circle<T>& operator=(const Circle<T>& cir) noexcept; Circle<T>& operator=(const Circle<T>& cir) noexcept;
bool operator==(const Circle<T>& cir) const noexcept; bool operator==(const Circle<T>& cir) const noexcept;
@@ -482,7 +486,9 @@ private:
// cached values // cached values
float fTheta, fCos, fSin; float fTheta, fCos, fSin;


#if defined(HAVE_DGL)
void _draw(const bool outline); void _draw(const bool outline);
#endif
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -516,6 +522,7 @@ public:
*/ */
Triangle(const Triangle<T>& tri) noexcept; Triangle(const Triangle<T>& tri) noexcept;


#if defined(HAVE_DGL)
/** /**
Draw this triangle using the current OpenGL state. Draw this triangle using the current OpenGL state.
*/ */
@@ -525,6 +532,7 @@ public:
Draw lines (outline of this triangle) using the current OpenGL state. Draw lines (outline of this triangle) using the current OpenGL state.
*/ */
void drawOutline(); void drawOutline();
#endif


/** /**
Return true if triangle is null (all its points are equal). Return true if triangle is null (all its points are equal).
@@ -556,7 +564,9 @@ public:
private: private:
Point<T> fPos1, fPos2, fPos3; Point<T> fPos1, fPos2, fPos3;


#if defined(HAVE_DGL)
void _draw(const bool outline); void _draw(const bool outline);
#endif
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -720,6 +730,7 @@ public:
*/ */
bool containsY(const T& y) const noexcept; bool containsY(const T& y) const noexcept;


#if defined(HAVE_DGL)
/** /**
Draw this rectangle using the current OpenGL state. Draw this rectangle using the current OpenGL state.
*/ */
@@ -729,6 +740,7 @@ public:
Draw lines (outline of this rectangle) using the current OpenGL state. Draw lines (outline of this rectangle) using the current OpenGL state.
*/ */
void drawOutline(); void drawOutline();
#endif


Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept; Rectangle<T>& operator=(const Rectangle<T>& rect) noexcept;
Rectangle<T>& operator*=(double m) noexcept; Rectangle<T>& operator*=(double m) noexcept;
@@ -740,7 +752,9 @@ private:
Point<T> fPos; Point<T> fPos;
Size<T> fSize; Size<T> fSize;


#if defined(HAVE_DGL)
void _draw(const bool outline); void _draw(const bool outline);
#endif
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


+ 4
- 0
dgl/Widget.hpp View File

@@ -312,6 +312,10 @@ public:
*/ */
Window& getParentWindow() const noexcept; Window& getParentWindow() const noexcept;


#if defined(HAVE_DCAIRO)
cairo_t* getGraphics() const noexcept;
#endif

/** /**
Check if this widget contains the point defined by @a x and @a y. Check if this widget contains the point defined by @a x and @a y.
*/ */


+ 4
- 0
dgl/Window.hpp View File

@@ -119,6 +119,10 @@ public:
Application& getApp() const noexcept; Application& getApp() const noexcept;
intptr_t getWindowId() const noexcept; intptr_t getWindowId() const noexcept;


#if defined(HAVE_DCAIRO)
cairo_t* getGraphics() const noexcept;
#endif

void addIdleCallback(IdleCallback* const callback); void addIdleCallback(IdleCallback* const callback);
void removeIdleCallback(IdleCallback* const callback); void removeIdleCallback(IdleCallback* const callback);




+ 33
- 0
dgl/src/Color.cpp View File

@@ -16,7 +16,9 @@


#include "../Color.hpp" #include "../Color.hpp"


#if !defined(HAVE_DCAIRO)
#include "nanovg/nanovg.h" #include "nanovg/nanovg.h"
#endif


START_NAMESPACE_DGL START_NAMESPACE_DGL


@@ -105,7 +107,36 @@ Color::Color(const Color& color1, const Color& color2, float u) noexcept


Color Color::fromHSL(float hue, float saturation, float lightness, float alpha) Color Color::fromHSL(float hue, float saturation, float lightness, float alpha)
{ {
#if defined(HAVE_DGL)
return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f)); return nvgHSLA(hue, saturation, lightness, static_cast<uchar>(getFixedRange(alpha)*255.0f));
#else
float m1, m2;
Color col;
hue = fmodf(hue, 1.0f);
if (hue < 0.0f) hue += 1.0f;
fixRange(saturation);
fixRange(lightness);
m2 = lightness <= 0.5f ? (lightness * (1 + saturation)) : (lightness + saturation - lightness * saturation);
m1 = 2 * lightness - m2;
auto hue_ = [](float h, float m1, float m2) -> float
{
if (h < 0) h += 1;
if (h > 1) h -= 1;
if (h < 1.0f/6.0f)
return m1 + (m2 - m1) * h * 6.0f;
else if (h < 3.0f/6.0f)
return m2;
else if (h < 4.0f/6.0f)
return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f;
return m1;
};
col.red = hue_(hue + 1.0f/3.0f, m1, m2);
col.green = hue_(hue, m1, m2);
col.blue = hue_(hue - 1.0f/3.0f, m1, m2);
col.alpha = alpha;
col.fixBounds();
return col;
#endif
} }


Color Color::fromHTML(const char* rgb, float alpha) Color Color::fromHTML(const char* rgb, float alpha)
@@ -224,6 +255,7 @@ void Color::fixBounds() noexcept


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


#if !defined(HAVE_DCAIRO)
Color::Color(const NVGcolor& c) noexcept Color::Color(const NVGcolor& c) noexcept
: red(c.r), green(c.g), blue(c.b), alpha(c.a) : red(c.r), green(c.g), blue(c.b), alpha(c.a)
{ {
@@ -239,6 +271,7 @@ Color::operator NVGcolor() const noexcept
nc.a = alpha; nc.a = alpha;
return nc; return nc;
} }
#endif


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------




+ 14
- 0
dgl/src/Geometry.cpp View File

@@ -441,6 +441,7 @@ void Line<T>::moveBy(const Point<T>& pos) noexcept
fPosEnd.moveBy(pos); fPosEnd.moveBy(pos);
} }


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Line<T>::draw() void Line<T>::draw()
{ {
@@ -455,6 +456,7 @@ void Line<T>::draw()


glEnd(); glEnd();
} }
#endif


template<typename T> template<typename T>
bool Line<T>::isNull() const noexcept bool Line<T>::isNull() const noexcept
@@ -614,6 +616,7 @@ void Circle<T>::setNumSegments(const uint num)
fSin = std::sin(fTheta); fSin = std::sin(fTheta);
} }


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Circle<T>::draw() void Circle<T>::draw()
{ {
@@ -625,6 +628,7 @@ void Circle<T>::drawOutline()
{ {
_draw(true); _draw(true);
} }
#endif


template<typename T> template<typename T>
Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept Circle<T>& Circle<T>::operator=(const Circle<T>& cir) noexcept
@@ -650,6 +654,7 @@ bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept
return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments); return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments);
} }


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Circle<T>::_draw(const bool outline) void Circle<T>::_draw(const bool outline)
{ {
@@ -670,6 +675,7 @@ void Circle<T>::_draw(const bool outline)


glEnd(); glEnd();
} }
#endif


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Triangle // Triangle
@@ -698,6 +704,7 @@ Triangle<T>::Triangle(const Triangle<T>& tri) noexcept
fPos2(tri.fPos2), fPos2(tri.fPos2),
fPos3(tri.fPos3) {} fPos3(tri.fPos3) {}


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Triangle<T>::draw() void Triangle<T>::draw()
{ {
@@ -709,6 +716,7 @@ void Triangle<T>::drawOutline()
{ {
_draw(true); _draw(true);
} }
#endif


template<typename T> template<typename T>
bool Triangle<T>::isNull() const noexcept bool Triangle<T>::isNull() const noexcept
@@ -755,6 +763,7 @@ bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept
return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3); return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3);
} }


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Triangle<T>::_draw(const bool outline) void Triangle<T>::_draw(const bool outline)
{ {
@@ -770,6 +779,7 @@ void Triangle<T>::_draw(const bool outline)


glEnd(); glEnd();
} }
#endif


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Rectangle // Rectangle
@@ -952,6 +962,7 @@ bool Rectangle<T>::containsY(const T& y) const noexcept
return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight); return (y >= fPos.fY && y <= fPos.fY + fSize.fHeight);
} }


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Rectangle<T>::draw() void Rectangle<T>::draw()
{ {
@@ -963,6 +974,7 @@ void Rectangle<T>::drawOutline()
{ {
_draw(true); _draw(true);
} }
#endif


template<typename T> template<typename T>
Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept
@@ -998,6 +1010,7 @@ bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept
return (fPos != rect.fPos || fSize != rect.fSize); return (fPos != rect.fPos || fSize != rect.fSize);
} }


#if defined(HAVE_DGL)
template<typename T> template<typename T>
void Rectangle<T>::_draw(const bool outline) void Rectangle<T>::_draw(const bool outline)
{ {
@@ -1021,6 +1034,7 @@ void Rectangle<T>::_draw(const bool outline)


glEnd(); glEnd();
} }
#endif


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Possible template data types // Possible template data types


+ 7
- 0
dgl/src/Widget.cpp View File

@@ -189,6 +189,13 @@ Window& Widget::getParentWindow() const noexcept
return pData->parent; return pData->parent;
} }


#if defined(HAVE_DCAIRO)
cairo_t* Widget::getGraphics() const noexcept
{
return pData->parent.getGraphics();
}
#endif

bool Widget::contains(int x, int y) const noexcept bool Widget::contains(int x, int y) const noexcept
{ {
return (x >= 0 && y >= 0 && static_cast<uint>(x) < pData->size.getWidth() && static_cast<uint>(y) < pData->size.getHeight()); return (x >= 0 && y >= 0 && static_cast<uint>(x) < pData->size.getWidth() && static_cast<uint>(y) < pData->size.getHeight());


+ 4
- 0
dgl/src/WidgetPrivateData.hpp View File

@@ -68,6 +68,7 @@ struct Widget::PrivateData {
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible) if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
return; return;


#if defined(HAVE_DGL)
bool needsDisableScissor = false; bool needsDisableScissor = false;


// reset color // reset color
@@ -106,15 +107,18 @@ struct Widget::PrivateData {
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
needsDisableScissor = true; needsDisableScissor = true;
} }
#endif


// display widget // display widget
self->onDisplay(); self->onDisplay();


#if defined(HAVE_DGL)
if (needsDisableScissor) if (needsDisableScissor)
{ {
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
needsDisableScissor = false; needsDisableScissor = false;
} }
#endif


displaySubWidgets(width, height, scaling); displaySubWidgets(width, height, scaling);
} }


+ 32
- 2
dgl/src/Window.cpp View File

@@ -19,6 +19,16 @@


#include "../Base.hpp" #include "../Base.hpp"


#undef PUGL_HAVE_CAIRO
#undef PUGL_HAVE_GL

#if defined(HAVE_DGL)
#define PUGL_HAVE_GL 1
#endif
#if defined(HAVE_DCAIRO)
#define PUGL_HAVE_CAIRO 1
#endif

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


#if defined(__GNUC__) && (__GNUC__ >= 7) #if defined(__GNUC__) && (__GNUC__ >= 7)
@@ -203,6 +213,14 @@ struct Window::PrivateData {
return; return;
} }


#if defined(HAVE_DGL)
PuglContextType contextType = PUGL_GL;
#endif
#if defined(HAVE_DCAIRO)
PuglContextType contextType = PUGL_CAIRO;
#endif

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


@@ -222,11 +240,12 @@ struct Window::PrivateData {
puglCreateWindow(fView, nullptr); puglCreateWindow(fView, nullptr);


PuglInternals* impl = fView->impl; PuglInternals* impl = fView->impl;

#if defined(DISTRHO_OS_WINDOWS) #if defined(DISTRHO_OS_WINDOWS)
hwnd = impl->hwnd; hwnd = impl->hwnd;
DISTRHO_SAFE_ASSERT(hwnd != 0); DISTRHO_SAFE_ASSERT(hwnd != 0);
#elif defined(DISTRHO_OS_MAC) #elif defined(DISTRHO_OS_MAC)
mView = impl->glview;
mView = impl->view;
mWindow = impl->window; mWindow = impl->window;
DISTRHO_SAFE_ASSERT(mView != nullptr); DISTRHO_SAFE_ASSERT(mView != nullptr);
if (fUsingEmbed) { if (fUsingEmbed) {
@@ -1081,7 +1100,7 @@ struct Window::PrivateData {
HWND hwndParent; HWND hwndParent;
#elif defined(DISTRHO_OS_MAC) #elif defined(DISTRHO_OS_MAC)
bool fNeedsIdle; bool fNeedsIdle;
PuglOpenGLView* mView;
NSView<PuglGenericView>* mView;
id mWindow; id mWindow;
id mParentWindow; id mParentWindow;
#else #else
@@ -1365,6 +1384,13 @@ intptr_t Window::getWindowId() const noexcept
return puglGetNativeWindow(pData->fView); return puglGetNativeWindow(pData->fView);
} }


#if defined(HAVE_DCAIRO)
cairo_t* Window::getGraphics() const noexcept
{
return (cairo_t*)puglGetContext(pData->fView);
}
#endif

void Window::_addWidget(Widget* const widget) void Window::_addWidget(Widget* const widget)
{ {
pData->addWidget(widget); pData->addWidget(widget);
@@ -1400,8 +1426,10 @@ void Window::removeIdleCallback(IdleCallback* const callback)


void Window::onDisplayBefore() void Window::onDisplayBefore()
{ {
#if defined(HAVE_DGL)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); glLoadIdentity();
#endif
} }


void Window::onDisplayAfter() void Window::onDisplayAfter()
@@ -1410,6 +1438,7 @@ void Window::onDisplayAfter()


void Window::onReshape(uint width, uint height) void Window::onReshape(uint width, uint height)
{ {
#if defined(HAVE_DGL)
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@@ -1418,6 +1447,7 @@ void Window::onReshape(uint width, uint height)
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
#endif
} }


void Window::onClose() void Window::onClose()


+ 22
- 0
dgl/src/pugl/pugl.h View File

@@ -273,6 +273,20 @@ puglInitUserResizable(PuglView* view, bool resizable);
PUGL_API void PUGL_API void
puglInitTransientFor(PuglView* view, uintptr_t parent); puglInitTransientFor(PuglView* view, uintptr_t parent);


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

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

/** /**
@} @}
*/ */
@@ -349,6 +363,14 @@ 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.
*/ */


+ 9
- 0
dgl/src/pugl/pugl_internal.h View File

@@ -41,6 +41,7 @@ struct PuglViewImpl {


PuglInternals* impl; PuglInternals* impl;
PuglNativeWindow parent; PuglNativeWindow parent;
PuglContextType ctx_type;
uintptr_t transient_parent; uintptr_t transient_parent;


int width; int width;
@@ -140,6 +141,12 @@ puglCreate(PuglNativeWindow parent,
return view; return view;
} }


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

void void
puglSetHandle(PuglView* view, PuglHandle handle) puglSetHandle(PuglView* view, PuglHandle handle)
{ {
@@ -239,6 +246,7 @@ puglLeaveContext(PuglView* view, bool flush);
static void static void
puglDefaultReshape(int width, int height) puglDefaultReshape(int width, int height)
{ {
#ifdef PUGL_HAVE_GL
#ifdef ROBTK_HERE #ifdef ROBTK_HERE
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@@ -257,4 +265,5 @@ puglDefaultReshape(int width, int height)
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
#endif #endif
#endif
} }

+ 386
- 38
dgl/src/pugl/pugl_osx.m View File

@@ -21,6 +21,10 @@
#include <stdlib.h> #include <stdlib.h>


#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#ifdef PUGL_HAVE_CAIRO
#import <cairo.h>
#import <cairo-quartz.h>
#endif


#include "pugl_internal.h" #include "pugl_internal.h"


@@ -93,7 +97,40 @@ puglDisplay(PuglView* view)
} }
} }


@interface PuglOpenGLView : NSOpenGLView
@protocol PuglGenericView
@required
- (PuglView *) puglView;
- (void) setPuglview:(PuglView *)pv;
@end

static unsigned
getModifiers(PuglView* view, NSEvent* ev)
{
const unsigned modifierFlags = [ev modifierFlags];

view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);

unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0;
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0;
return mods;
}

static int
getFixedAppKitButton(NSInteger button)
{
switch (button) {
case 0: return 1;
case 1: return 3;
case 2: return 2;
default: return button;
}
}

#ifdef PUGL_HAVE_GL
@interface PuglOpenGLView : NSOpenGLView<PuglGenericView>
{ {
@public @public
PuglView* puglview; PuglView* puglview;
@@ -101,6 +138,9 @@ puglDisplay(PuglView* view)
bool doubleBuffered; bool doubleBuffered;
} }


- (PuglView *) puglView;
- (void) setPuglview:(PuglView *)pv;

- (BOOL) acceptsFirstMouse:(NSEvent*)e; - (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder; - (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped; - (BOOL) isFlipped;
@@ -130,6 +170,13 @@ puglDisplay(PuglView* view)
@end @end


@implementation PuglOpenGLView @implementation PuglOpenGLView
- (PuglView *) puglView {
return self->puglview;
}

- (void) setPuglview:(PuglView *)pv {
self->puglview = pv;
}


- (BOOL) acceptsFirstMouse:(NSEvent*)e - (BOOL) acceptsFirstMouse:(NSEvent*)e
{ {
@@ -277,32 +324,296 @@ puglDisplay(PuglView* view)
[super viewWillMoveToWindow:newWindow]; [super viewWillMoveToWindow:newWindow];
} }


static unsigned
getModifiers(PuglView* view, NSEvent* ev)
- (void) mouseMoved:(NSEvent*)event
{ {
const unsigned modifierFlags = [ev modifierFlags];
if (puglview->motionFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->motionFunc(puglview, loc.x, loc.y);
}
}


view->event_timestamp_ms = fmod([ev timestamp] * 1000.0, UINT32_MAX);
- (void) mouseDragged:(NSEvent*)event
{
[self mouseMoved:event];
}


unsigned mods = 0;
mods |= (modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0;
mods |= (modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0;
mods |= (modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0;
mods |= (modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0;
return mods;
- (void) rightMouseDragged:(NSEvent*)event
{
[self mouseDragged:event];
} }


static int
getFixedAppKitButton(NSInteger button)
- (void) otherMouseDragged:(NSEvent*)event
{ {
switch (button) {
case 0: return 1;
case 1: return 3;
case 2: return 2;
default: return button;
[self mouseDragged:event];
}

- (void) mouseDown:(NSEvent*)event
{
if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), true, loc.x, loc.y);
}
}

- (void) rightMouseDown:(NSEvent*)event
{
[self mouseDown:event];
}

- (void) otherMouseDown:(NSEvent*)event
{
[self mouseDown:event];
}

- (void) mouseUp:(NSEvent*)event
{
if (puglview->mouseFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->mouseFunc(puglview, getFixedAppKitButton([event buttonNumber]), false, loc.x, loc.y);
} }
} }


- (void) rightMouseUp:(NSEvent*)event
{
[self mouseUp:event];
}

- (void) otherMouseUp:(NSEvent*)event
{
[self mouseUp:event];
}

- (void) scrollWheel:(NSEvent*)event
{
if (puglview->scrollFunc) {
NSPoint loc = [self convertPoint:[event locationInWindow] fromView:nil];
puglview->mods = getModifiers(puglview, event);
puglview->scrollFunc(puglview,
loc.x, loc.y,
[event deltaX], [event deltaY]);
}
}

- (void) keyDown:(NSEvent*)event
{
if (puglview->keyboardFunc && !(puglview->ignoreKeyRepeat && [event isARepeat])) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, true, [chars characterAtIndex:0]);
}
}

- (void) keyUp:(NSEvent*)event
{
if (puglview->keyboardFunc) {
NSString* chars = [event characters];
puglview->mods = getModifiers(puglview, event);
puglview->keyboardFunc(puglview, false, [chars characterAtIndex:0]);
}
}

- (void) flagsChanged:(NSEvent*)event
{
if (puglview->specialFunc) {
const unsigned mods = getModifiers(puglview, event);
if ((mods & PUGL_MOD_SHIFT) != (puglview->mods & PUGL_MOD_SHIFT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SHIFT, PUGL_KEY_SHIFT);
} else if ((mods & PUGL_MOD_CTRL) != (puglview->mods & PUGL_MOD_CTRL)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_CTRL, PUGL_KEY_CTRL);
} else if ((mods & PUGL_MOD_ALT) != (puglview->mods & PUGL_MOD_ALT)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_ALT, PUGL_KEY_ALT);
} else if ((mods & PUGL_MOD_SUPER) != (puglview->mods & PUGL_MOD_SUPER)) {
puglview->specialFunc(puglview, mods & PUGL_MOD_SUPER, PUGL_KEY_SUPER);
}
puglview->mods = mods;
}
}

@end
#endif

#ifdef PUGL_HAVE_CAIRO
@interface PuglCairoView : NSView<PuglGenericView>
{
PuglView* puglview;
cairo_t* cr;
NSTrackingArea* trackingArea;
}

- (PuglView *) puglView;
- (void) setPuglview:(PuglView *)pv;

- (cairo_t *) cairoContext;

- (BOOL) acceptsFirstMouse:(NSEvent*)e;
- (BOOL) acceptsFirstResponder;
- (BOOL) isFlipped;
- (BOOL) isOpaque;
- (BOOL) preservesContentInLiveResize;
- (id) initWithFrame:(NSRect)frame;
- (void) reshape;
- (void) drawRect:(NSRect)r;
/* TODO: duplication of code from PuglOpenGLView */
- (void) cursorUpdate:(NSEvent*)e;
- (void) updateTrackingAreas;
- (void) viewWillMoveToWindow:(NSWindow*)newWindow;
- (void) mouseMoved:(NSEvent*)event;
- (void) mouseDragged:(NSEvent*)event;
- (void) rightMouseDragged:(NSEvent*)event;
- (void) otherMouseDragged:(NSEvent*)event;
- (void) mouseDown:(NSEvent*)event;
- (void) rightMouseDown:(NSEvent*)event;
- (void) otherMouseDown:(NSEvent*)event;
- (void) mouseUp:(NSEvent*)event;
- (void) rightMouseUp:(NSEvent*)event;
- (void) otherMouseUp:(NSEvent*)event;
- (void) scrollWheel:(NSEvent*)event;
- (void) keyDown:(NSEvent*)event;
- (void) keyUp:(NSEvent*)event;
- (void) flagsChanged:(NSEvent*)event;
@end

@implementation PuglCairoView
- (PuglView *) puglView {
return self->puglview;
}

- (void) setPuglview:(PuglView *)pv {
self->puglview = pv;
}

- (cairo_t *) cairoContext {
return cr;
}

- (BOOL) acceptsFirstMouse:(NSEvent*)e
{
return YES;

// unused
(void)e;
}

- (BOOL) acceptsFirstResponder
{
return YES;
}

- (BOOL) isFlipped
{
return YES;
}

- (BOOL) isOpaque
{
return YES;
}

- (BOOL) preservesContentInLiveResize
{
return NO;
}

- (id) initWithFrame:(NSRect)frame {
puglview = nil;
cr = NULL;
trackingArea = nil;
[super initWithFrame:frame];
return self;
}

- (void) reshape
{
if (!puglview) {
/* NOTE: Apparently reshape gets called when the GC gets around to
deleting the view (?), so we must have reset puglview to NULL when
this comes around.
*/
return;
}

NSRect bounds = [self bounds];
int width = bounds.size.width;
int height = bounds.size.height;

puglEnterContext(puglview);

if (puglview->reshapeFunc) {
puglview->reshapeFunc(puglview, width, height);
} else {
puglDefaultReshape(width, height);
}

puglLeaveContext(puglview, false);

puglview->width = width;
puglview->height = height;
}

- (void) drawRect:(NSRect)r {
CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
NSRect bounds = [self bounds];
cairo_surface_t* surface;
cairo_t* cairo;

surface = cairo_quartz_surface_create_for_cg_context(ctx, bounds.size.width, bounds.size.height);
if (surface) {
cairo = cairo_create(surface);
if (cairo) {
self->cr = cairo;
puglEnterContext(puglview);
puglDisplay(puglview);
puglLeaveContext(puglview, true);
self->cr = NULL;
cairo_destroy(cairo);
}
cairo_surface_destroy(surface);
}
}

- (void) cursorUpdate:(NSEvent*)e
{
[[NSCursor arrowCursor] set];

// unused
return; (void)e;
}

- (void) updateTrackingAreas
{
static const int opts = NSTrackingMouseEnteredAndExited
| NSTrackingMouseMoved
| NSTrackingEnabledDuringMouseDrag
| NSTrackingInVisibleRect
| NSTrackingActiveAlways
| NSTrackingCursorUpdate;

if (trackingArea != nil) {
[self removeTrackingArea:trackingArea];
[trackingArea release];
}

trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:opts
owner:self
userInfo:nil];
[self addTrackingArea:trackingArea];
[super updateTrackingAreas];
}

- (void) viewWillMoveToWindow:(NSWindow*)newWindow
{
if (newWindow != nil) {
[newWindow setAcceptsMouseMovedEvents:YES];
[newWindow makeFirstResponder:self];
}

[super viewWillMoveToWindow:newWindow];
}

- (void) mouseMoved:(NSEvent*)event - (void) mouseMoved:(NSEvent*)event
{ {
if (puglview->motionFunc) { if (puglview->motionFunc) {
@@ -410,11 +721,19 @@ getFixedAppKitButton(NSInteger button)
puglview->mods = mods; puglview->mods = mods;
} }
} }

@end @end
#endif


struct PuglInternalsImpl { struct PuglInternalsImpl {
PuglOpenGLView* glview;
union {
NSView<PuglGenericView>* view;
#ifdef PUGL_HAVE_GL
PuglOpenGLView* glview;
#endif
#ifdef PUGL_HAVE_CAIRO
PuglCairoView* cairoview;
#endif
};
id window; id window;
}; };


@@ -427,13 +746,18 @@ puglInitInternals()
void void
puglEnterContext(PuglView* view) puglEnterContext(PuglView* view)
{ {
[[view->impl->glview openGLContext] makeCurrentContext];
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
[[view->impl->glview openGLContext] makeCurrentContext];
}
#endif
} }


void void
puglLeaveContext(PuglView* view, bool flush) puglLeaveContext(PuglView* view, bool flush)
{ {
if (flush) {
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL && flush) {
if (view->impl->glview->doubleBuffered) { if (view->impl->glview->doubleBuffered) {
[[view->impl->glview openGLContext] flushBuffer]; [[view->impl->glview openGLContext] flushBuffer];
} else { } else {
@@ -441,6 +765,7 @@ puglLeaveContext(PuglView* view, bool flush)
} }
//[NSOpenGLContext clearCurrentContext]; //[NSOpenGLContext clearCurrentContext];
} }
#endif
} }


int int
@@ -451,22 +776,31 @@ puglCreateWindow(PuglView* view, const char* title)
[NSAutoreleasePool new]; [NSAutoreleasePool new];
[NSApplication sharedApplication]; [NSApplication sharedApplication];


impl->glview = [PuglOpenGLView new];
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
impl->glview = [PuglOpenGLView new];
}
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
impl->cairoview = [PuglCairoView new];
}
#endif


if (!impl->glview) {
if (!impl->view) {
return 1; return 1;
} }
impl->glview->puglview = view;
[impl->view setPuglview:view];


if (view->user_resizable) { if (view->user_resizable) {
[impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
[impl->view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
} }


if (view->parent) { if (view->parent) {
[impl->glview retain];
[impl->view retain];
NSView* pview = (NSView*)view->parent; NSView* pview = (NSView*)view->parent;
[pview addSubview:impl->glview];
[pview addSubview:impl->view];
return 0; return 0;
} }


@@ -482,8 +816,8 @@ puglCreateWindow(PuglView* view, const char* title)
} }


[window setPuglview:view]; [window setPuglview:view];
[window setContentView:impl->glview];
[window makeFirstResponder:impl->glview];
[window setContentView:impl->view];
[window makeFirstResponder:impl->view];
[window makeKeyAndOrderFront:window]; [window makeKeyAndOrderFront:window];


// wait for first puglShowWindow // wait for first puglShowWindow
@@ -505,7 +839,7 @@ puglShowWindow(PuglView* view)
if (impl->window) { if (impl->window) {
[impl->window setIsVisible:YES]; [impl->window setIsVisible:YES];
} else { } else {
[view->impl->glview setHidden:NO];
[view->impl->view setHidden:NO];
} }
} }


@@ -517,21 +851,21 @@ puglHideWindow(PuglView* view)
if (impl->window) { if (impl->window) {
[impl->window setIsVisible:NO]; [impl->window setIsVisible:NO];
} else { } else {
[impl->glview setHidden:YES];
[impl->view setHidden:YES];
} }
} }


void void
puglDestroy(PuglView* view) puglDestroy(PuglView* view)
{ {
view->impl->glview->puglview = NULL;
[view->impl->view setPuglview:NULL];


if (view->impl->window) { if (view->impl->window) {
[view->impl->window close]; [view->impl->window close];
[view->impl->glview release];
[view->impl->view release];
[view->impl->window release]; [view->impl->window release];
} else { } else {
[view->impl->glview release];
[view->impl->view release];
} }


free(view->impl); free(view->impl);
@@ -551,13 +885,27 @@ void
puglPostRedisplay(PuglView* view) puglPostRedisplay(PuglView* view)
{ {
view->redisplay = true; view->redisplay = true;
[view->impl->glview setNeedsDisplay:YES];
[view->impl->view setNeedsDisplay:YES];
} }


PuglNativeWindow PuglNativeWindow
puglGetNativeWindow(PuglView* view) puglGetNativeWindow(PuglView* view)
{ {
return (PuglNativeWindow)view->impl->glview;
return (PuglNativeWindow)view->impl->view;
}

void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
return [view->impl->cairoview cairoContext];
}
#endif
return NULL;

// may be unused
(void)view;
} }


int int


+ 108
- 41
dgl/src/pugl/pugl_win.cpp View File

@@ -21,7 +21,13 @@
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <windowsx.h> #include <windowsx.h>
#ifdef PUGL_HAVE_GL
#include <GL/gl.h> #include <GL/gl.h>
#endif
#ifdef PUGL_HAVE_CAIRO
#include <cairo/cairo.h>
#include <cairo/cairo-win32.h>
#endif


#include <ctime> #include <ctime>
#include <cstdio> #include <cstdio>
@@ -48,8 +54,13 @@ HINSTANCE hInstance = NULL;


struct PuglInternalsImpl { struct PuglInternalsImpl {
HWND hwnd; HWND hwnd;
#ifdef PUGL_HAVE_GL
HDC hdc; HDC hdc;
HGLRC hglrc; HGLRC hglrc;
#endif
#ifdef PUGL_HAVE_CAIRO
cairo_t* cr;
#endif
WNDCLASS wc; WNDCLASS wc;
}; };


@@ -76,17 +87,25 @@ puglInitInternals()
void void
puglEnterContext(PuglView* view) puglEnterContext(PuglView* view)
{ {
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
wglMakeCurrent(view->impl->hdc, view->impl->hglrc);
}
#endif
} }


void void
puglLeaveContext(PuglView* view, bool flush) puglLeaveContext(PuglView* view, bool flush)
{ {
if (flush) {
glFlush();
SwapBuffers(view->impl->hdc);
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
if (flush) {
glFlush();
SwapBuffers(view->impl->hdc);
}
wglMakeCurrent(NULL, NULL);
} }
wglMakeCurrent(NULL, NULL);
#endif
} }


int int
@@ -124,7 +143,6 @@ puglCreateWindow(PuglView* view, const char* title)
if (!RegisterClass(&impl->wc)) { if (!RegisterClass(&impl->wc)) {
free((void*)impl->wc.lpszClassName); free((void*)impl->wc.lpszClassName);
free(impl); free(impl);
free(view);
return 1; return 1;
} }


@@ -155,37 +173,39 @@ puglCreateWindow(PuglView* view, const char* title)
UnregisterClass(impl->wc.lpszClassName, NULL); UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName); free((void*)impl->wc.lpszClassName);
free(impl); free(impl);
free(view);
return 1; return 1;
} }


SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);


impl->hdc = GetDC(impl->hwnd);

PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;

int format = ChoosePixelFormat(impl->hdc, &pfd);
SetPixelFormat(impl->hdc, format, &pfd);

impl->hglrc = wglCreateContext(impl->hdc);
if (!impl->hglrc) {
ReleaseDC (impl->hwnd, impl->hdc);
DestroyWindow (impl->hwnd);
UnregisterClass (impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view);
return 1;
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
impl->hdc = GetDC(impl->hwnd);

PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;

int format = ChoosePixelFormat(impl->hdc, &pfd);
SetPixelFormat(impl->hdc, format, &pfd);

impl->hglrc = wglCreateContext(impl->hdc);
if (!impl->hglrc) {
ReleaseDC (impl->hwnd, impl->hdc);
DestroyWindow (impl->hwnd);
UnregisterClass (impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
return 1;
}
} }
#endif


return PUGL_SUCCESS; return PUGL_SUCCESS;
} }
@@ -205,13 +225,23 @@ puglHideWindow(PuglView* view)
void void
puglDestroy(PuglView* view) puglDestroy(PuglView* view)
{ {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(view->impl->hglrc);
ReleaseDC(view->impl->hwnd, view->impl->hdc);
DestroyWindow(view->impl->hwnd);
UnregisterClass(view->impl->wc.lpszClassName, NULL);
free((void*)view->impl->wc.lpszClassName);
free(view->impl);
if (!view) {
return;
}

PuglInternals* const impl = view->impl;

#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(impl->hglrc);
}
ReleaseDC(impl->hwnd, impl->hdc);
#endif
DestroyWindow(impl->hwnd);
UnregisterClass(impl->wc.lpszClassName, NULL);
free((void*)impl->wc.lpszClassName);
free(impl);
free(view); free(view);
} }


@@ -329,9 +359,32 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
mmi->ptMinTrackSize.y = view->min_height; mmi->ptMinTrackSize.y = view->min_height;
break; break;
case WM_PAINT: case WM_PAINT:
BeginPaint(view->impl->hwnd, &ps);
puglDisplay(view);
EndPaint(view->impl->hwnd, &ps);
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
BeginPaint(view->impl->hwnd, &ps);
puglDisplay(view);
EndPaint(view->impl->hwnd, &ps);
}
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
HDC hdc = BeginPaint(view->impl->hwnd, &ps);
if (hdc == NULL)
break;
cairo_surface_t *surface = cairo_win32_surface_create(hdc);
if (surface) {
cairo_t *cr = cairo_create(surface);
if (cr) {
view->impl->cr = cr;
puglDisplay(view);
view->impl->cr = NULL;
cairo_destroy(cr);
}
cairo_surface_destroy(surface);
}
EndPaint(view->impl->hwnd, &ps);
}
#endif
break; break;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if (view->motionFunc) { if (view->motionFunc) {
@@ -469,6 +522,20 @@ puglGetNativeWindow(PuglView* view)
return (PuglNativeWindow)view->impl->hwnd; return (PuglNativeWindow)view->impl->hwnd;
} }


void*
puglGetContext(PuglView* view)
{
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
return view->impl->cr;
}
#endif
return NULL;

// may be unused
(void)view;
}

int int
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
{ {


+ 135
- 26
dgl/src/pugl/pugl_x11.c View File

@@ -24,8 +24,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>


#ifdef PUGL_HAVE_GL
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glx.h> #include <GL/glx.h>
#endif
#ifdef PUGL_HAVE_CAIRO
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#endif
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
@@ -53,10 +59,17 @@ struct PuglInternalsImpl {
Display* display; Display* display;
int screen; int screen;
Window win; Window win;
#ifdef PUGL_HAVE_CAIRO
cairo_t* cr;
cairo_surface_t* surface;
#endif
#ifdef PUGL_HAVE_GL
GLXContext ctx; GLXContext ctx;
Bool doubleBuffered; Bool doubleBuffered;
#endif
}; };


#ifdef PUGL_HAVE_GL
/** /**
Attributes for single-buffered RGBA with at least Attributes for single-buffered RGBA with at least
4 bits per color and a 16 bit depth buffer. 4 bits per color and a 16 bit depth buffer.
@@ -102,6 +115,7 @@ static int attrListDblMS[] = {
GLX_SAMPLES, 4, GLX_SAMPLES, 4,
None None
}; };
#endif


PuglInternals* PuglInternals*
puglInitInternals(void) puglInitInternals(void)
@@ -112,25 +126,33 @@ puglInitInternals(void)
void void
puglEnterContext(PuglView* view) puglEnterContext(PuglView* view)
{ {
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
} }


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


int int
puglCreateWindow(PuglView* view, const char* title) puglCreateWindow(PuglView* view, const char* title)
{ {
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
PuglInternals* impl = view->impl;
if (!impl) { if (!impl) {
return 1; return 1;
} }
@@ -142,21 +164,35 @@ puglCreateWindow(PuglView* view, const char* title)
return 1; return 1;
} }
impl->screen = DefaultScreen(impl->display); impl->screen = DefaultScreen(impl->display);
impl->doubleBuffered = True;


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


if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
impl->doubleBuffered = True;
vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS);

if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListDbl);
#ifdef PUGL_VERBOSE #ifdef PUGL_VERBOSE
printf("puGL: multisampling (antialiasing) is not available\n");
printf("puGL: multisampling (antialiasing) is not available\n");
#endif #endif
}
}


if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
if (!vi) {
vi = glXChooseVisual(impl->display, impl->screen, attrListSgl);
impl->doubleBuffered = False;
}
} }
#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


if (!vi) { if (!vi) {
XCloseDisplay(impl->display); XCloseDisplay(impl->display);
@@ -165,18 +201,25 @@ puglCreateWindow(PuglView* view, const char* title)
} }


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


impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE);


if (!impl->ctx) {
XCloseDisplay(impl->display);
free(impl);
return 1;
if (!impl->ctx) {
XFree(vi);
XCloseDisplay(impl->display);
free(impl);
return 1;
}
} }
#endif


Window xParent = view->parent Window xParent = view->parent
? (Window)view->parent ? (Window)view->parent
@@ -201,11 +244,40 @@ puglCreateWindow(PuglView* view, const char* title)
CWBorderPixel | CWColormap | CWEventMask, &attr); CWBorderPixel | CWColormap | CWEventMask, &attr);


if (!impl->win) { if (!impl->win) {
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
glXDestroyContext(impl->display, impl->ctx);
}
#endif
XFree(vi);
XCloseDisplay(impl->display); XCloseDisplay(impl->display);
free(impl); free(impl);
return 1; return 1;
} }


#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 || cairo_surface_status(impl->surface) != CAIRO_STATUS_SUCCESS) {
printf("puGL: failed to create cairo surface\n");
}
else {
impl->cr = cairo_create(impl->surface);
}
if (impl->cr == NULL || cairo_status(impl->cr) != CAIRO_STATUS_SUCCESS) {
cairo_destroy(impl->cr);
cairo_surface_destroy(impl->surface);
XDestroyWindow(impl->display, impl->win);
XFree(vi);
XCloseDisplay(impl->display);
free(impl);
printf("puGL: failed to create cairo context\n");
return 1;
}
}
#endif

if (view->width > 1 || view->height > 1) { if (view->width > 1 || view->height > 1) {
puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width);
XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); XResizeWindow(view->impl->display, view->impl->win, view->width, view->height);
@@ -227,11 +299,13 @@ puglCreateWindow(PuglView* view, const char* title)
} }


#ifdef PUGL_VERBOSE #ifdef PUGL_VERBOSE
#ifdef PUGL_HAVE_GL
if (glXIsDirect(impl->display, impl->ctx)) { if (glXIsDirect(impl->display, impl->ctx)) {
printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n");
} else { } else {
printf("puGL: No DRI available\n"); printf("puGL: No DRI available\n");
} }
#endif
#endif #endif


XFree(vi); XFree(vi);
@@ -244,14 +318,27 @@ puglDestroy(PuglView* view)
if (!view) { if (!view) {
return; return;
} }

PuglInternals* const impl = view->impl;

#ifndef DGL_FILE_BROWSER_DISABLED #ifndef DGL_FILE_BROWSER_DISABLED
x_fib_close(view->impl->display);
x_fib_close(impl->display);
#endif #endif


glXDestroyContext(view->impl->display, view->impl->ctx);
XDestroyWindow(view->impl->display, view->impl->win);
XCloseDisplay(view->impl->display);
free(view->impl);
#ifdef PUGL_HAVE_GL
if (view->ctx_type == PUGL_GL) {
glXDestroyContext(impl->display, impl->ctx);
}
#endif
#ifdef PUGL_HAVE_CAIRO
if (view->ctx_type == PUGL_CAIRO) {
cairo_destroy(impl->cr);
cairo_surface_destroy(impl->surface);
}
#endif
XDestroyWindow(impl->display, impl->win);
XCloseDisplay(impl->display);
free(impl);
free(view); free(view);
} }


@@ -554,6 +641,14 @@ puglProcessEvents(PuglView* view)
} }


if (conf_width != -1) { if (conf_width != -1) {
#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,
conf_width, conf_height);
}
#endif
puglReshape(view, conf_width, conf_height); puglReshape(view, conf_width, conf_height);
} }


@@ -586,6 +681,20 @@ 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;

// may be unused
(void)view;
}

int int
puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
{ {


+ 2
- 2
distrho/src/DistrhoPluginChecks.h View File

@@ -93,7 +93,7 @@
// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed // Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed


#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI #ifndef DISTRHO_PLUGIN_HAS_EMBED_UI
# ifdef HAVE_DGL
# if defined(HAVE_DGL) || defined(HAVE_DCAIRO)
# define DISTRHO_PLUGIN_HAS_EMBED_UI 1 # define DISTRHO_PLUGIN_HAS_EMBED_UI 1
# else # else
# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 # define DISTRHO_PLUGIN_HAS_EMBED_UI 0
@@ -135,7 +135,7 @@
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Disable UI if DGL or External UI is not available // Disable UI if DGL or External UI is not available


#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_DGL)
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI && ! defined(HAVE_DGL) && ! defined(HAVE_DCAIRO)
# undef DISTRHO_PLUGIN_HAS_UI # undef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0 # define DISTRHO_PLUGIN_HAS_UI 0
#endif #endif


+ 2
- 0
distrho/src/DistrhoUI.cpp View File

@@ -152,6 +152,7 @@ void UI::uiFileBrowserSelected(const char*)


void UI::uiReshape(uint width, uint height) void UI::uiReshape(uint width, uint height)
{ {
#if defined(HAVE_DGL)
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@@ -160,6 +161,7 @@ void UI::uiReshape(uint width, uint height)
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
#endif
} }


/* ------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------


Loading…
Cancel
Save