aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-10-03 19:38:53 +0200
committerDavid Robillard <d@drobilla.net>2020-10-04 12:51:32 +0200
commitcc5c38b1aaf93157f5558df95383491a6163cc5a (patch)
treea1b858c00ad84a0479b98247f84e608ac0d62866
parent6ca124d3787a901129252a2e26c091da1c1ff455 (diff)
Add puglGetViewHint()
This allows retrieving properties of the view that may be needed, such as the actual bit depth (which may vary from the suggested depth provided as a hint).
-rw-r--r--pugl/detail/implementation.c10
-rw-r--r--pugl/detail/mac.m14
-rw-r--r--pugl/detail/mac_gl.m30
-rw-r--r--pugl/detail/win.c14
-rw-r--r--pugl/detail/win_gl.c18
-rw-r--r--pugl/detail/x11.h5
-rw-r--r--pugl/detail/x11_gl.c24
-rw-r--r--pugl/pugl.h10
-rw-r--r--pugl/pugl.hpp6
-rw-r--r--test/test_gl_hints.c86
-rw-r--r--test/test_stub_hints.c77
-rw-r--r--wscript24
12 files changed, 310 insertions, 8 deletions
diff --git a/pugl/detail/implementation.c b/pugl/detail/implementation.c
index 5534662..31ee643 100644
--- a/pugl/detail/implementation.c
+++ b/pugl/detail/implementation.c
@@ -262,6 +262,16 @@ puglSetViewHint(PuglView* view, PuglViewHint hint, int value)
return PUGL_BAD_PARAMETER;
}
+int
+puglGetViewHint(const PuglView* view, PuglViewHint hint)
+{
+ if (hint < PUGL_NUM_VIEW_HINTS) {
+ return view->hints[hint];
+ }
+
+ return PUGL_DONT_CARE;
+}
+
PuglStatus
puglSetParentWindow(PuglView* view, PuglNativeView parent)
{
diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m
index 23671ae..0c50d20 100644
--- a/pugl/detail/mac.m
+++ b/pugl/detail/mac.m
@@ -866,6 +866,20 @@ puglRealize(PuglView* view)
const NSScreen* const screen = [NSScreen mainScreen];
const double scaleFactor = [screen backingScaleFactor];
+ // Getting depth from the display mode seems tedious, just set usual values
+ if (view->hints[PUGL_RED_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_RED_BITS] = 8;
+ }
+ if (view->hints[PUGL_BLUE_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_BLUE_BITS] = 8;
+ }
+ if (view->hints[PUGL_GREEN_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_GREEN_BITS] = 8;
+ }
+ if (view->hints[PUGL_ALPHA_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_ALPHA_BITS] = 8;
+ }
+
if (view->frame.width == 0.0 && view->frame.height == 0.0) {
if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) {
return PUGL_BAD_CONFIGURATION;
diff --git a/pugl/detail/mac_gl.m b/pugl/detail/mac_gl.m
index 4bf6fc1..4d4f324 100644
--- a/pugl/detail/mac_gl.m
+++ b/pugl/detail/mac_gl.m
@@ -48,12 +48,36 @@
? NSOpenGLProfileVersion4_1Core
: NSOpenGLProfileVersion3_2Core));
- NSOpenGLPixelFormatAttribute pixelAttribs[16] = {
+ // Set attributes to default if they are unset
+ // (There is no GLX_DONT_CARE equivalent on MacOS)
+ if (puglview->hints[PUGL_DEPTH_BITS] == PUGL_DONT_CARE) {
+ puglview->hints[PUGL_DEPTH_BITS] = 0;
+ }
+ if (puglview->hints[PUGL_STENCIL_BITS] == PUGL_DONT_CARE) {
+ puglview->hints[PUGL_STENCIL_BITS] = 0;
+ }
+ if (puglview->hints[PUGL_SAMPLES] == PUGL_DONT_CARE) {
+ puglview->hints[PUGL_SAMPLES] = 1;
+ }
+ if (puglview->hints[PUGL_DOUBLE_BUFFER] == PUGL_DONT_CARE) {
+ puglview->hints[PUGL_DOUBLE_BUFFER] = 1;
+ }
+ if (puglview->hints[PUGL_SWAP_INTERVAL] == PUGL_DONT_CARE) {
+ puglview->hints[PUGL_SWAP_INTERVAL] = 1;
+ }
+
+ const unsigned colorSize = (unsigned)(puglview->hints[PUGL_RED_BITS] +
+ puglview->hints[PUGL_BLUE_BITS] +
+ puglview->hints[PUGL_GREEN_BITS] +
+ puglview->hints[PUGL_ALPHA_BITS]);
+
+ NSOpenGLPixelFormatAttribute pixelAttribs[17] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAOpenGLProfile, profile,
- NSOpenGLPFAColorSize, 32,
- NSOpenGLPFADepthSize, 32,
+ NSOpenGLPFAColorSize, colorSize,
+ NSOpenGLPFADepthSize, (unsigned)puglview->hints[PUGL_DEPTH_BITS],
+ NSOpenGLPFAStencilSize, (unsigned)puglview->hints[PUGL_STENCIL_BITS],
NSOpenGLPFAMultisample, samples ? 1 : 0,
NSOpenGLPFASampleBuffers, samples ? 1 : 0,
NSOpenGLPFASamples, samples,
diff --git a/pugl/detail/win.c b/pugl/detail/win.c
index 4f7afee..38eca9d 100644
--- a/pugl/detail/win.c
+++ b/pugl/detail/win.c
@@ -166,6 +166,20 @@ puglRealize(PuglView* view)
{
PuglInternals* impl = view->impl;
+ // Getting depth from the display mode seems tedious, just set usual values
+ if (view->hints[PUGL_RED_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_RED_BITS] = 8;
+ }
+ if (view->hints[PUGL_BLUE_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_BLUE_BITS] = 8;
+ }
+ if (view->hints[PUGL_GREEN_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_GREEN_BITS] = 8;
+ }
+ if (view->hints[PUGL_ALPHA_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_ALPHA_BITS] = 8;
+ }
+
// Get refresh rate for resize draw timer
DEVMODEA devMode = {0};
EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devMode);
diff --git a/pugl/detail/win_gl.c b/pugl/detail/win_gl.c
index 8cdad76..096c715 100644
--- a/pugl/detail/win_gl.c
+++ b/pugl/detail/win_gl.c
@@ -108,6 +108,24 @@ puglWinGlConfigure(PuglView* view)
{
PuglInternals* impl = view->impl;
+ // Set attributes to default if they are unset
+ // (There is no GLX_DONT_CARE equivalent on Windows)
+ if (view->hints[PUGL_DEPTH_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_DEPTH_BITS] = 0;
+ }
+ if (view->hints[PUGL_STENCIL_BITS] == PUGL_DONT_CARE) {
+ view->hints[PUGL_STENCIL_BITS] = 0;
+ }
+ if (view->hints[PUGL_SAMPLES] == PUGL_DONT_CARE) {
+ view->hints[PUGL_SAMPLES] = 1;
+ }
+ if (view->hints[PUGL_DOUBLE_BUFFER] == PUGL_DONT_CARE) {
+ view->hints[PUGL_DOUBLE_BUFFER] = 1;
+ }
+ if (view->hints[PUGL_SWAP_INTERVAL] == PUGL_DONT_CARE) {
+ view->hints[PUGL_SWAP_INTERVAL] = 1;
+ }
+
// clang-format off
const int pixelAttrs[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
diff --git a/pugl/detail/x11.h b/pugl/detail/x11.h
index cf647ed..4b0109d 100644
--- a/pugl/detail/x11.h
+++ b/pugl/detail/x11.h
@@ -83,5 +83,10 @@ puglX11StubConfigure(PuglView* view)
pat.screen = impl->screen;
impl->vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
+ view->hints[PUGL_RED_BITS] = impl->vi->bits_per_rgb;
+ view->hints[PUGL_GREEN_BITS] = impl->vi->bits_per_rgb;
+ view->hints[PUGL_BLUE_BITS] = impl->vi->bits_per_rgb;
+ view->hints[PUGL_ALPHA_BITS] = 0;
+
return PUGL_SUCCESS;
}
diff --git a/pugl/detail/x11_gl.c b/pugl/detail/x11_gl.c
index e4a0ea8..228a530 100644
--- a/pugl/detail/x11_gl.c
+++ b/pugl/detail/x11_gl.c
@@ -71,7 +71,7 @@ puglX11GlConfigure(PuglView* view)
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_SAMPLES, view->hints[PUGL_SAMPLES],
+ GLX_SAMPLES, puglX11GlHintValue(view->hints[PUGL_SAMPLES]),
GLX_RED_SIZE, puglX11GlHintValue(view->hints[PUGL_RED_BITS]),
GLX_GREEN_SIZE, puglX11GlHintValue(view->hints[PUGL_GREEN_BITS]),
GLX_BLUE_SIZE, puglX11GlHintValue(view->hints[PUGL_BLUE_BITS]),
@@ -91,6 +91,23 @@ puglX11GlConfigure(PuglView* view)
surface->fb_config = fbc[0];
impl->vi = glXGetVisualFromFBConfig(impl->display, fbc[0]);
+ view->hints[PUGL_RED_BITS] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_RED_SIZE);
+ view->hints[PUGL_GREEN_BITS] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_GREEN_SIZE);
+ view->hints[PUGL_BLUE_BITS] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_BLUE_SIZE);
+ view->hints[PUGL_ALPHA_BITS] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_ALPHA_SIZE);
+ view->hints[PUGL_DEPTH_BITS] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_DEPTH_SIZE);
+ view->hints[PUGL_STENCIL_BITS] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_STENCIL_SIZE);
+ view->hints[PUGL_SAMPLES] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_SAMPLES);
+ view->hints[PUGL_DOUBLE_BUFFER] = puglX11GlGetAttrib(
+ display, fbc[0], GLX_DOUBLEBUFFER);
+
char msg[128];
snprintf(
@@ -182,6 +199,11 @@ puglX11GlCreate(PuglView* view)
GLX_DOUBLEBUFFER,
&view->hints[PUGL_DOUBLE_BUFFER]);
+ glXQueryDrawable(display,
+ impl->win,
+ GLX_SWAP_INTERVAL_EXT,
+ (unsigned int*)&view->hints[PUGL_SWAP_INTERVAL]);
+
return PUGL_SUCCESS;
}
diff --git a/pugl/pugl.h b/pugl/pugl.h
index c32a17d..7e27425 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -939,6 +939,16 @@ PUGL_API PuglStatus
puglSetViewHint(PuglView* view, PuglViewHint hint, int value);
/**
+ Get the value for a view hint.
+
+ If the view has been realized, this can be used to get the actual value of a
+ hint which was initially set to PUGL_DONT_CARE, or has been adjusted from
+ the suggested value.
+*/
+PUGL_API int
+puglGetViewHint(const PuglView* view, PuglViewHint hint);
+
+/**
@}
@anchor frame
@name Frame
diff --git a/pugl/pugl.hpp b/pugl/pugl.hpp
index 3072560..4968da4 100644
--- a/pugl/pugl.hpp
+++ b/pugl/pugl.hpp
@@ -418,6 +418,12 @@ public:
puglSetViewHint(cobj(), static_cast<PuglViewHint>(hint), value));
}
+ /// @copydoc puglGetViewHint
+ int getHint(ViewHint hint)
+ {
+ return puglGetViewHint(cobj(), static_cast<PuglViewHint>(hint));
+ }
+
/**
@}
@name Frame
diff --git a/test/test_gl_hints.c b/test/test_gl_hints.c
new file mode 100644
index 0000000..9830e2e
--- /dev/null
+++ b/test/test_gl_hints.c
@@ -0,0 +1,86 @@
+/*
+ Copyright 2020 David Robillard <d@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.
+*/
+
+/*
+ Tests that all hints are set to real values after a view is realized.
+*/
+
+#undef NDEBUG
+
+#include "test_utils.h"
+
+#include "pugl/pugl.h"
+#include "pugl/pugl_gl.h"
+
+#include <assert.h>
+
+static PuglStatus
+onEvent(PuglView* view, const PuglEvent* event)
+{
+ (void)view;
+ (void)event;
+
+ return PUGL_SUCCESS;
+}
+
+int
+main(void)
+{
+ PuglWorld* const world = puglNewWorld(PUGL_PROGRAM, 0);
+ PuglView* const view = puglNewView(world);
+
+ // Set up view
+ puglSetClassName(world, "Pugl Test");
+ puglSetBackend(view, puglGlBackend());
+ puglSetEventFunc(view, onEvent);
+ puglSetDefaultSize(view, 512, 512);
+
+ // Set all hints that support it to PUGL_DONT_CARE
+ assert(!puglSetViewHint(view, PUGL_RED_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_GREEN_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_BLUE_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_ALPHA_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_DEPTH_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_STENCIL_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_SAMPLES, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_DOUBLE_BUFFER, PUGL_DONT_CARE));
+
+ // Realize view and print all hints for debugging convenience
+ assert(!puglRealize(view));
+
+ // Check that no hints are set to PUGL_DONT_CARE
+ assert(puglGetViewHint(view, PUGL_USE_COMPAT_PROFILE) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_USE_DEBUG_CONTEXT) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_CONTEXT_VERSION_MINOR) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_RED_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_GREEN_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_BLUE_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_ALPHA_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_DEPTH_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_STENCIL_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_SAMPLES) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_DOUBLE_BUFFER) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_SWAP_INTERVAL) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_RESIZABLE) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_IGNORE_KEY_REPEAT) != PUGL_DONT_CARE);
+
+ // Tear down
+ puglFreeView(view);
+ puglFreeWorld(world);
+
+ return 0;
+}
diff --git a/test/test_stub_hints.c b/test/test_stub_hints.c
new file mode 100644
index 0000000..cd4db6a
--- /dev/null
+++ b/test/test_stub_hints.c
@@ -0,0 +1,77 @@
+/*
+ Copyright 2020 David Robillard <d@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.
+*/
+
+/*
+ Tests that all hints are set to real values after a view is realized.
+*/
+
+#undef NDEBUG
+
+#include "test_utils.h"
+
+#include "pugl/pugl.h"
+#include "pugl/pugl_stub.h"
+
+#include <assert.h>
+
+static PuglStatus
+onEvent(PuglView* view, const PuglEvent* event)
+{
+ (void)view;
+ (void)event;
+
+ return PUGL_SUCCESS;
+}
+
+int
+main(void)
+{
+ PuglWorld* const world = puglNewWorld(PUGL_PROGRAM, 0);
+ PuglView* const view = puglNewView(world);
+
+ // Set up view
+ puglSetClassName(world, "Pugl Test");
+ puglSetBackend(view, puglStubBackend());
+ puglSetEventFunc(view, onEvent);
+ puglSetDefaultSize(view, 512, 512);
+
+ // Set all relevant hints that support it to PUGL_DONT_CARE
+ assert(!puglSetViewHint(view, PUGL_RED_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_GREEN_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_BLUE_BITS, PUGL_DONT_CARE));
+ assert(!puglSetViewHint(view, PUGL_ALPHA_BITS, PUGL_DONT_CARE));
+
+ // Realize view and print all hints for debugging convenience
+ assert(!puglRealize(view));
+
+ // Check that no relevant hints are set to PUGL_DONT_CARE
+ assert(puglGetViewHint(view, PUGL_USE_COMPAT_PROFILE) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_USE_DEBUG_CONTEXT) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_CONTEXT_VERSION_MINOR) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_RED_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_GREEN_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_BLUE_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_ALPHA_BITS) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_RESIZABLE) != PUGL_DONT_CARE);
+ assert(puglGetViewHint(view, PUGL_IGNORE_KEY_REPEAT) != PUGL_DONT_CARE);
+
+ // Tear down
+ puglFreeView(view);
+ puglFreeWorld(world);
+
+ return 0;
+}
diff --git a/wscript b/wscript
index 0855ef1..10be77c 100644
--- a/wscript
+++ b/wscript
@@ -255,7 +255,9 @@ def _build_pc_file(bld, name, desc, target, libname, deps={}, requires=[]):
LIBS=' '.join(link_flags))
-tests = ['redisplay', 'show_hide', 'update', 'timer']
+gl_tests = ['gl_hints']
+basic_tests = ['stub_hints', 'redisplay', 'show_hide', 'update', 'timer']
+tests = ['gl_hints', 'stub_hints', 'redisplay', 'show_hide', 'update', 'timer']
def build(bld):
@@ -430,18 +432,28 @@ def build(bld):
cflags=glad_cflags,
uselib=['DL', 'GL', 'M'])
+ for test in gl_tests:
+ bld(features = 'c cprogram',
+ source = 'test/test_%s.c' % test,
+ target = 'test/test_%s' % test,
+ install_path = '',
+ use = ['pugl_%s_static' % platform,
+ 'pugl_%s_gl_static' % platform],
+ uselib = deps[platform]['uselib'] + ['GL'])
+
if bld.env.HAVE_CAIRO:
build_example('pugl_cairo_demo', ['examples/pugl_cairo_demo.c'],
platform, 'cairo',
uselib=['M', 'CAIRO'])
- for test in tests:
+ for test in basic_tests:
bld(features = 'c cprogram',
source = 'test/test_%s.c' % test,
target = 'test/test_%s' % test,
install_path = '',
use = ['pugl_%s_static' % platform,
- 'pugl_%s_stub_static' % platform],
+ 'pugl_%s_stub_static' % platform,
+ 'pugl_%s_gl_static' % platform],
uselib = deps[platform]['uselib'] + ['CAIRO'])
# Make a hyper strict warning environment for checking API headers
@@ -488,9 +500,13 @@ def build(bld):
def test(tst):
if tst.options.gui_tests:
with tst.group('gui') as check:
- for test in tests:
+ for test in basic_tests:
check(['test/test_%s' % test])
+ if tst.env.HAVE_GL:
+ for test in gl_tests:
+ check(['test/test_%s' % test])
+
class LintContext(Build.BuildContext):
fun = cmd = 'lint'