aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format124
-rw-r--r--.editorconfig3
-rw-r--r--bindings/cxx/include/pugl/cairo.hpp2
-rw-r--r--bindings/cxx/include/pugl/gl.hpp8
-rw-r--r--bindings/cxx/include/pugl/pugl.hpp858
-rw-r--r--bindings/cxx/include/pugl/stub.hpp2
-rw-r--r--bindings/cxx/include/pugl/vulkan.hpp120
-rw-r--r--examples/cube_view.h148
-rw-r--r--examples/demo_utils.h102
-rw-r--r--examples/file_utils.c54
-rw-r--r--examples/pugl_cairo_demo.c373
-rw-r--r--examples/pugl_cursor_demo.c200
-rw-r--r--examples/pugl_cxx_demo.cpp158
-rw-r--r--examples/pugl_embed_demo.c566
-rw-r--r--examples/pugl_print_events.c66
-rw-r--r--examples/pugl_shader_demo.c702
-rw-r--r--examples/pugl_vulkan_cxx_demo.cpp2743
-rw-r--r--examples/pugl_vulkan_demo.c1774
-rw-r--r--examples/pugl_window_demo.c378
-rw-r--r--examples/rects.h52
-rw-r--r--examples/shader_utils.h123
-rw-r--r--examples/shaders/header_330.glsl1
-rw-r--r--examples/shaders/header_420.glsl1
-rw-r--r--examples/shaders/rect.frag22
-rw-r--r--examples/shaders/rect.vert27
-rw-r--r--examples/sybok.hpp3881
-rw-r--r--include/pugl/cairo.h4
-rw-r--r--include/pugl/gl.h45
-rw-r--r--include/pugl/pugl.h762
-rw-r--r--include/pugl/stub.h3
-rw-r--r--include/pugl/vulkan.h25
-rw-r--r--src/implementation.c456
-rw-r--r--src/mac.h18
-rw-r--r--src/mac.m1726
-rw-r--r--src/mac_cairo.m137
-rw-r--r--src/mac_gl.m232
-rw-r--r--src/mac_stub.m68
-rw-r--r--src/mac_vulkan.m168
-rw-r--r--src/stub.h28
-rw-r--r--src/types.h92
-rw-r--r--src/win.c1591
-rw-r--r--src/win.h168
-rw-r--r--src/win_cairo.c163
-rw-r--r--src/win_gl.c444
-rw-r--r--src/win_stub.c64
-rw-r--r--src/win_vulkan.c97
-rw-r--r--src/x11.c1983
-rw-r--r--src/x11.h61
-rw-r--r--src/x11_cairo.c171
-rw-r--r--src/x11_gl.c280
-rw-r--r--src/x11_stub.c40
-rw-r--r--src/x11_vulkan.c105
-rw-r--r--test/test_build.c2
-rw-r--r--test/test_build.cpp2
-rw-r--r--test/test_clipboard.c116
-rw-r--r--test/test_gl_hints.c100
-rw-r--r--test/test_realize.c100
-rw-r--r--test/test_redisplay.c170
-rw-r--r--test/test_show_hide.c186
-rw-r--r--test/test_stub_hints.c82
-rw-r--r--test/test_timer.c168
-rw-r--r--test/test_update.c144
-rw-r--r--test/test_utils.h512
63 files changed, 11434 insertions, 11567 deletions
diff --git a/.clang-format b/.clang-format
index a505e26..f0275a9 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,127 +1,27 @@
---
-# Language: Cpp
-# BasedOnStyle: Mozilla
-AccessModifierOffset: -4
-AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
-AlignEscapedNewlines: Left
-AlignOperands: true
-AlignTrailingComments: true
-AllowAllArgumentsOnNextLine: true
-AllowAllConstructorInitializersOnNextLine: false
-AllowAllParametersOfDeclarationOnNextLine: false
-AllowShortBlocksOnASingleLine: false
-AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: Inline
-AllowShortLambdasOnASingleLine: All
-AllowShortIfStatementsOnASingleLine: Never
-AllowShortLoopsOnASingleLine: false
-AlwaysBreakAfterDefinitionReturnType: TopLevel
-AlwaysBreakAfterReturnType: TopLevel
-AlwaysBreakBeforeMultilineStrings: false
-AlwaysBreakTemplateDeclarations: Yes
-BinPackArguments: false
-BinPackParameters: false
+AlignEscapedNewlinesLeft: true
+BasedOnStyle: Mozilla
BraceWrapping:
- AfterCaseLabel: false
- AfterClass: true
- AfterControlStatement: false
- AfterEnum: false
- AfterFunction: true
- AfterNamespace: false
- AfterObjCDeclaration: true
- AfterStruct: false
- AfterUnion: false
+ AfterNamespace: false
+ AfterClass: true
+ AfterEnum: false
AfterExternBlock: false
- BeforeCatch: false
- BeforeElse: false
- IndentBraces: false
- SplitEmptyFunction: true
+ AfterFunction: true
+ AfterStruct: false
+ SplitEmptyFunction: false
SplitEmptyRecord: false
- SplitEmptyNamespace: true
-BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
-BreakBeforeInheritanceComma: false
-BreakInheritanceList: BeforeComma
-BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: false
-BreakConstructorInitializers: BeforeComma
-BreakAfterJavaFieldAnnotations: false
-BreakStringLiterals: true
-ColumnLimit: 80
-CommentPragmas: '^ IWYU pragma:'
-CompactNamespaces: false
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
-ConstructorInitializerIndentWidth: 4
-ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
-DerivePointerAlignment: false
-DisableFormat: false
-ExperimentalAutoDetectBinPacking: false
-FixNamespaceComments: true
-ForEachMacros:
- - foreach
- - Q_FOREACH
- - BOOST_FOREACH
-IncludeBlocks: Preserve
-IncludeCategories:
- - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
- Priority: 2
- - Regex: '^(<|"(gtest|gmock|isl|json)/)'
- Priority: 3
- - Regex: '.*'
- Priority: 1
-IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: AfterHash
-IndentWidth: 4
-IndentWrappedFunctionNames: false
-JavaScriptQuotes: Leave
-JavaScriptWrapImports: true
-KeepEmptyLinesAtTheStartOfBlocks: true
-MacroBlockBegin: ''
-MacroBlockEnd: ''
-MaxEmptyLinesToKeep: 1
-NamespaceIndentation: None
-ObjCBinPackProtocolList: Auto
-ObjCBlockIndentWidth: 4
-ObjCSpaceAfterProperty: true
-ObjCSpaceBeforeProtocolList: false
-PenaltyBreakAssignment: 100
-PenaltyBreakBeforeFirstCallParameter: 100
-PenaltyBreakComment: 300
-PenaltyBreakFirstLessLess: 120
-PenaltyBreakString: 1000
-PenaltyBreakTemplateDeclaration: 10
-PenaltyExcessCharacter: 1000000
-PenaltyReturnTypeOnItsOwnLine: 0
-PointerAlignment: Left
-ReflowComments: true
-SortIncludes: true
-SortUsingDeclarations: true
-SpaceAfterCStyleCast: false
-SpaceAfterLogicalNot: false
-SpaceAfterTemplateKeyword: false
-SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: false
-SpaceBeforeCtorInitializerColon: true
-SpaceBeforeInheritanceColon: true
-SpaceBeforeParens: ControlStatements
-SpaceBeforeRangeBasedForLoopColon: true
-SpaceInEmptyParentheses: false
-SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
-SpacesInContainerLiterals: true
-SpacesInCStyleCastParentheses: false
-SpacesInParentheses: false
-SpacesInSquareBrackets: false
-Standard: Cpp11
+KeepEmptyLinesAtTheStartOfBlocks: false
+SpacesInContainerLiterals: false
StatementMacros:
- PUGL_API
+ - PUGL_CONST_FUNC
- PUGL_DEPRECATED_BY
- PUGL_UNUSED
-TabWidth: 4
-UseTab: ForIndentation
+ - _Pragma
...
-
diff --git a/.editorconfig b/.editorconfig
index 5213b6b..c2d35dd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -7,7 +7,8 @@ trim_trailing_whitespace = true
insert_final_newline = true
[*.{c,h,m,cpp,hpp,mm,glsl,frag,vert}]
-indent_style = tab
+indent_style = space
+indent_size = 2
[wscript]
indent_style = space
diff --git a/bindings/cxx/include/pugl/cairo.hpp b/bindings/cxx/include/pugl/cairo.hpp
index 7416589..126bfe3 100644
--- a/bindings/cxx/include/pugl/cairo.hpp
+++ b/bindings/cxx/include/pugl/cairo.hpp
@@ -33,7 +33,7 @@ namespace pugl {
inline const PuglBackend*
cairoBackend() noexcept
{
- return puglCairoBackend();
+ return puglCairoBackend();
}
/**
diff --git a/bindings/cxx/include/pugl/gl.hpp b/bindings/cxx/include/pugl/gl.hpp
index d8459a8..c845d80 100644
--- a/bindings/cxx/include/pugl/gl.hpp
+++ b/bindings/cxx/include/pugl/gl.hpp
@@ -37,28 +37,28 @@ using GlFunc = PuglGlFunc;
inline GlFunc
getProcAddress(const char* name) noexcept
{
- return puglGetProcAddress(name);
+ return puglGetProcAddress(name);
}
/// @copydoc puglEnterContext
inline Status
enterContext(View& view) noexcept
{
- return static_cast<Status>(puglEnterContext(view.cobj()));
+ return static_cast<Status>(puglEnterContext(view.cobj()));
}
/// @copydoc puglLeaveContext
inline Status
leaveContext(View& view) noexcept
{
- return static_cast<Status>(puglLeaveContext(view.cobj()));
+ return static_cast<Status>(puglLeaveContext(view.cobj()));
}
/// @copydoc puglGlBackend
inline const PuglBackend*
glBackend() noexcept
{
- return puglGlBackend();
+ return puglGlBackend();
}
/**
diff --git a/bindings/cxx/include/pugl/pugl.hpp b/bindings/cxx/include/pugl/pugl.hpp
index 1a07734..9e65589 100644
--- a/bindings/cxx/include/pugl/pugl.hpp
+++ b/bindings/cxx/include/pugl/pugl.hpp
@@ -22,9 +22,9 @@
#include <cstdint>
#if defined(PUGL_HPP_THROW_FAILED_CONSTRUCTION)
-# include <exception>
+# include <exception>
#elif defined(PUGL_HPP_ASSERT_CONSTRUCTION)
-# include <cassert>
+# include <cassert>
#endif
namespace pugl {
@@ -46,34 +46,34 @@ template<class T, FreeFunc<T> Free>
class Wrapper
{
public:
- Wrapper(const Wrapper&) = delete;
- Wrapper& operator=(const Wrapper&) = delete;
+ Wrapper(const Wrapper&) = delete;
+ Wrapper& operator=(const Wrapper&) = delete;
- Wrapper(Wrapper&& wrapper) noexcept
- : _ptr{wrapper._ptr}
- {
- wrapper._ptr = nullptr;
- }
+ Wrapper(Wrapper&& wrapper) noexcept
+ : _ptr{wrapper._ptr}
+ {
+ wrapper._ptr = nullptr;
+ }
- Wrapper& operator=(Wrapper&& wrapper) noexcept
- {
- _ptr = wrapper._ptr;
- wrapper._ptr = nullptr;
- return *this;
- }
+ Wrapper& operator=(Wrapper&& wrapper) noexcept
+ {
+ _ptr = wrapper._ptr;
+ wrapper._ptr = nullptr;
+ return *this;
+ }
- ~Wrapper() noexcept { Free(_ptr); }
+ ~Wrapper() noexcept { Free(_ptr); }
- T* cobj() noexcept { return _ptr; }
- const T* cobj() const noexcept { return _ptr; }
+ T* cobj() noexcept { return _ptr; }
+ const T* cobj() const noexcept { return _ptr; }
protected:
- explicit Wrapper(T* ptr) noexcept
- : _ptr{ptr}
- {}
+ explicit Wrapper(T* ptr) noexcept
+ : _ptr{ptr}
+ {}
private:
- T* _ptr;
+ T* _ptr;
};
} // namespace detail
@@ -97,11 +97,11 @@ using Rect = PuglRect; ///< @copydoc PuglRect
*/
template<PuglEventType t, class Base>
struct Event final : Base {
- /// The type of the corresponding C event structure
- using BaseEvent = Base;
+ /// The type of the corresponding C event structure
+ using BaseEvent = Base;
- /// The `type` field of the corresponding C event structure
- static constexpr const PuglEventType type = t;
+ /// The `type` field of the corresponding C event structure
+ static constexpr const PuglEventType type = t;
};
using Mod = PuglMod; ///< @copydoc PuglMod
@@ -189,18 +189,18 @@ using LoopLeaveEvent = Event<PUGL_LOOP_LEAVE, PuglEventLoopLeave>;
/// @copydoc PuglStatus
enum class Status {
- success, ///< @copydoc PUGL_SUCCESS
- failure, ///< @copydoc PUGL_FAILURE
- unknownError, ///< @copydoc PUGL_UNKNOWN_ERROR
- badBackend, ///< @copydoc PUGL_BAD_BACKEND
- badConfiguration, ///< @copydoc PUGL_BAD_CONFIGURATION
- badParameter, ///< @copydoc PUGL_BAD_PARAMETER
- backendFailed, ///< @copydoc PUGL_BACKEND_FAILED
- registrationFailed, ///< @copydoc PUGL_REGISTRATION_FAILED
- realizeFailed, ///< @copydoc PUGL_REALIZE_FAILED
- setFormatFailed, ///< @copydoc PUGL_SET_FORMAT_FAILED
- createContextFailed, ///< @copydoc PUGL_CREATE_CONTEXT_FAILED
- unsupportedType, ///< @copydoc PUGL_UNSUPPORTED_TYPE
+ success, ///< @copydoc PUGL_SUCCESS
+ failure, ///< @copydoc PUGL_FAILURE
+ unknownError, ///< @copydoc PUGL_UNKNOWN_ERROR
+ badBackend, ///< @copydoc PUGL_BAD_BACKEND
+ badConfiguration, ///< @copydoc PUGL_BAD_CONFIGURATION
+ badParameter, ///< @copydoc PUGL_BAD_PARAMETER
+ backendFailed, ///< @copydoc PUGL_BACKEND_FAILED
+ registrationFailed, ///< @copydoc PUGL_REGISTRATION_FAILED
+ realizeFailed, ///< @copydoc PUGL_REALIZE_FAILED
+ setFormatFailed, ///< @copydoc PUGL_SET_FORMAT_FAILED
+ createContextFailed, ///< @copydoc PUGL_CREATE_CONTEXT_FAILED
+ unsupportedType, ///< @copydoc PUGL_UNSUPPORTED_TYPE
};
static_assert(Status(PUGL_UNSUPPORTED_TYPE) == Status::unsupportedType, "");
@@ -209,7 +209,7 @@ static_assert(Status(PUGL_UNSUPPORTED_TYPE) == Status::unsupportedType, "");
inline const char*
strerror(const Status status) noexcept
{
- return puglStrerror(static_cast<PuglStatus>(status));
+ return puglStrerror(static_cast<PuglStatus>(status));
}
/**
@@ -220,15 +220,15 @@ strerror(const Status status) noexcept
/// @copydoc PuglWorldType
enum class WorldType {
- program, ///< @copydoc PUGL_PROGRAM
- module, ///< @copydoc PUGL_MODULE
+ program, ///< @copydoc PUGL_PROGRAM
+ module, ///< @copydoc PUGL_MODULE
};
static_assert(WorldType(PUGL_MODULE) == WorldType::module, "");
/// @copydoc PuglWorldFlag
enum class WorldFlag {
- threads = PUGL_WORLD_THREADS, ///< @copydoc PUGL_WORLD_THREADS
+ threads = PUGL_WORLD_THREADS, ///< @copydoc PUGL_WORLD_THREADS
};
static_assert(WorldFlag(PUGL_WORLD_THREADS) == WorldFlag::threads, "");
@@ -241,25 +241,25 @@ using WorldFlags = PuglWorldFlags; ///< @copydoc PuglWorldFlags
class FailedConstructionError : public std::exception
{
public:
- FailedConstructionError(const char* const msg) noexcept
- : _msg{msg}
- {}
+ FailedConstructionError(const char* const msg) noexcept
+ : _msg{msg}
+ {}
- virtual const char* what() const noexcept override;
+ virtual const char* what() const noexcept override;
private:
- const char* _msg;
+ const char* _msg;
};
-# define PUGL_CHECK_CONSTRUCTION(cond, msg) \
- do { \
- if (!(cond)) { \
- throw FailedConstructionError(msg); \
- } \
- } while (0)
+# define PUGL_CHECK_CONSTRUCTION(cond, msg) \
+ do { \
+ if (!(cond)) { \
+ throw FailedConstructionError(msg); \
+ } \
+ } while (0)
#elif defined(PUGL_HPP_ASSERT_CONSTRUCTION)
-# define PUGL_CHECK_CONSTRUCTION(cond, msg) assert(cond);
+# define PUGL_CHECK_CONSTRUCTION(cond, msg) assert(cond);
#else
/**
Configurable macro for handling construction failure.
@@ -272,55 +272,55 @@ private:
Otherwise, this does nothing.
*/
-# define PUGL_CHECK_CONSTRUCTION(cond, msg)
+# define PUGL_CHECK_CONSTRUCTION(cond, msg)
#endif
/// @copydoc PuglWorld
class World : public detail::Wrapper<PuglWorld, puglFreeWorld>
{
public:
- World(const World&) = delete;
- World& operator=(const World&) = delete;
-
- World(World&&) = delete;
- World& operator=(World&&) = delete;
-
- ~World() = default;
-
- World(WorldType type, WorldFlag flag)
- : Wrapper{puglNewWorld(static_cast<PuglWorldType>(type),
- static_cast<PuglWorldFlags>(flag))}
- {
- PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::World");
- }
-
- World(WorldType type, WorldFlags flags)
- : Wrapper{puglNewWorld(static_cast<PuglWorldType>(type), flags)}
- {
- PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::World");
- }
-
- explicit World(WorldType type)
- : World{type, WorldFlags{}}
- {}
-
- /// @copydoc puglGetNativeWorld
- void* nativeWorld() noexcept { return puglGetNativeWorld(cobj()); }
-
- /// @copydoc puglSetClassName
- Status setClassName(const char* const name) noexcept
- {
- return static_cast<Status>(puglSetClassName(cobj(), name));
- }
-
- /// @copydoc puglGetTime
- double time() const noexcept { return puglGetTime(cobj()); }
-
- /// @copydoc puglUpdate
- Status update(const double timeout) noexcept
- {
- return static_cast<Status>(puglUpdate(cobj(), timeout));
- }
+ World(const World&) = delete;
+ World& operator=(const World&) = delete;
+
+ World(World&&) = delete;
+ World& operator=(World&&) = delete;
+
+ ~World() = default;
+
+ World(WorldType type, WorldFlag flag)
+ : Wrapper{puglNewWorld(static_cast<PuglWorldType>(type),
+ static_cast<PuglWorldFlags>(flag))}
+ {
+ PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::World");
+ }
+
+ World(WorldType type, WorldFlags flags)
+ : Wrapper{puglNewWorld(static_cast<PuglWorldType>(type), flags)}
+ {
+ PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::World");
+ }
+
+ explicit World(WorldType type)
+ : World{type, WorldFlags{}}
+ {}
+
+ /// @copydoc puglGetNativeWorld
+ void* nativeWorld() noexcept { return puglGetNativeWorld(cobj()); }
+
+ /// @copydoc puglSetClassName
+ Status setClassName(const char* const name) noexcept
+ {
+ return static_cast<Status>(puglSetClassName(cobj(), name));
+ }
+
+ /// @copydoc puglGetTime
+ double time() const noexcept { return puglGetTime(cobj()); }
+
+ /// @copydoc puglUpdate
+ Status update(const double timeout) noexcept
+ {
+ return static_cast<Status>(puglUpdate(cobj(), timeout));
+ }
};
/**
@@ -334,22 +334,22 @@ using NativeView = PuglNativeView; ///< @copydoc PuglNativeView
/// @copydoc PuglViewHint
enum class ViewHint {
- useCompatProfile, ///< @copydoc PUGL_USE_COMPAT_PROFILE
- useDebugContext, ///< @copydoc PUGL_USE_DEBUG_CONTEXT
- contextVersionMajor, ///< @copydoc PUGL_CONTEXT_VERSION_MAJOR
- contextVersionMinor, ///< @copydoc PUGL_CONTEXT_VERSION_MINOR
- redBits, ///< @copydoc PUGL_RED_BITS
- greenBits, ///< @copydoc PUGL_GREEN_BITS
- blueBits, ///< @copydoc PUGL_BLUE_BITS
- alphaBits, ///< @copydoc PUGL_ALPHA_BITS
- depthBits, ///< @copydoc PUGL_DEPTH_BITS
- stencilBits, ///< @copydoc PUGL_STENCIL_BITS
- samples, ///< @copydoc PUGL_SAMPLES
- doubleBuffer, ///< @copydoc PUGL_DOUBLE_BUFFER
- swapInterval, ///< @copydoc PUGL_SWAP_INTERVAL
- resizable, ///< @copydoc PUGL_RESIZABLE
- ignoreKeyRepeat, ///< @copydoc PUGL_IGNORE_KEY_REPEAT
- refreshRate, ///< @copydoc PUGL_REFRESH_RATE
+ useCompatProfile, ///< @copydoc PUGL_USE_COMPAT_PROFILE
+ useDebugContext, ///< @copydoc PUGL_USE_DEBUG_CONTEXT
+ contextVersionMajor, ///< @copydoc PUGL_CONTEXT_VERSION_MAJOR
+ contextVersionMinor, ///< @copydoc PUGL_CONTEXT_VERSION_MINOR
+ redBits, ///< @copydoc PUGL_RED_BITS
+ greenBits, ///< @copydoc PUGL_GREEN_BITS
+ blueBits, ///< @copydoc PUGL_BLUE_BITS
+ alphaBits, ///< @copydoc PUGL_ALPHA_BITS
+ depthBits, ///< @copydoc PUGL_DEPTH_BITS
+ stencilBits, ///< @copydoc PUGL_STENCIL_BITS
+ samples, ///< @copydoc PUGL_SAMPLES
+ doubleBuffer, ///< @copydoc PUGL_DOUBLE_BUFFER
+ swapInterval, ///< @copydoc PUGL_SWAP_INTERVAL
+ resizable, ///< @copydoc PUGL_RESIZABLE
+ ignoreKeyRepeat, ///< @copydoc PUGL_IGNORE_KEY_REPEAT
+ refreshRate, ///< @copydoc PUGL_REFRESH_RATE
};
static_assert(ViewHint(PUGL_REFRESH_RATE) == ViewHint::refreshRate, "");
@@ -358,13 +358,13 @@ using ViewHintValue = PuglViewHintValue; ///< @copydoc PuglViewHintValue
/// @copydoc PuglCursor
enum class Cursor {
- arrow, ///< @copydoc PUGL_CURSOR_ARROW
- caret, ///< @copydoc PUGL_CURSOR_CARET
- crosshair, ///< @copydoc PUGL_CURSOR_CROSSHAIR
- hand, ///< @copydoc PUGL_CURSOR_HAND
- no, ///< @copydoc PUGL_CURSOR_NO
- leftRight, ///< @copydoc PUGL_CURSOR_LEFT_RIGHT
- upDown, ///< @copydoc PUGL_CURSOR_UP_DOWN
+ arrow, ///< @copydoc PUGL_CURSOR_ARROW
+ caret, ///< @copydoc PUGL_CURSOR_CARET
+ crosshair, ///< @copydoc PUGL_CURSOR_CROSSHAIR
+ hand, ///< @copydoc PUGL_CURSOR_HAND
+ no, ///< @copydoc PUGL_CURSOR_NO
+ leftRight, ///< @copydoc PUGL_CURSOR_LEFT_RIGHT
+ upDown, ///< @copydoc PUGL_CURSOR_UP_DOWN
};
static_assert(Cursor(PUGL_CURSOR_UP_DOWN) == Cursor::upDown, "");
@@ -373,332 +373,312 @@ static_assert(Cursor(PUGL_CURSOR_UP_DOWN) == Cursor::upDown, "");
class View : protected detail::Wrapper<PuglView, puglFreeView>
{
public:
- /**
- @name Setup
- Methods for creating and destroying a view.
- @{
- */
-
- explicit View(World& world)
- : Wrapper{puglNewView(world.cobj())}
- , _world(world)
- {
- PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::View");
- }
-
- const World& world() const noexcept { return _world; }
- World& world() noexcept { return _world; }
-
- /**
- Set the object that will be called to handle events.
-
- This is a type-safe wrapper for the C functions puglSetHandle() and
- puglSetEventFunc() that will automatically dispatch events to the
- `onEvent` method of `handler` that takes the appropriate event type.
- The handler must have such a method defined for every event type, but if
- the handler is the view itself, a `using` declaration can be used to
- "inherit" the default implementation to avoid having to define every
- method. For example:
-
- @code
- class MyView : public pugl::View
- {
- public:
- explicit MyView(pugl::World& world)
- : pugl::View{world}
- {
- setEventHandler(*this);
- }
-
- using pugl::View::onEvent;
-
- pugl::Status onEvent(const pugl::ConfigureEvent& event) noexcept;
- pugl::Status onEvent(const pugl::ExposeEvent& event) noexcept;
- };
- @endcode
-
- This facility is just a convenience, applications may use the C API
- directly to set a handle and event function to set up a different
- approach for event handling.
- */
- template<class Handler>
- Status setEventHandler(Handler& handler)
- {
- puglSetHandle(cobj(), &handler);
- return static_cast<Status>(
- puglSetEventFunc(cobj(), eventFunc<Handler>));
- }
-
- /// @copydoc puglSetBackend
- Status setBackend(const PuglBackend* backend) noexcept
- {
- return static_cast<Status>(puglSetBackend(cobj(), backend));
- }
-
- /// @copydoc puglSetViewHint
- Status setHint(ViewHint hint, int value) noexcept
- {
- return static_cast<Status>(
- puglSetViewHint(cobj(), static_cast<PuglViewHint>(hint), value));
- }
-
- /// @copydoc puglGetViewHint
- int getHint(ViewHint hint) noexcept
- {
- return puglGetViewHint(cobj(), static_cast<PuglViewHint>(hint));
- }
-
- /**
- @}
- @name Frame
- Methods for working with the position and size of a view.
- @{
- */
-
- /// @copydoc puglGetFrame
- Rect frame() const noexcept { return puglGetFrame(cobj()); }
-
- /// @copydoc puglSetFrame
- Status setFrame(Rect frame) noexcept
- {
- return static_cast<Status>(puglSetFrame(cobj(), frame));
- }
-
- /// @copydoc puglSetDefaultSize
- Status setDefaultSize(int width, int height) noexcept
- {
- return static_cast<Status>(puglSetDefaultSize(cobj(), width, height));
- }
-
- /// @copydoc puglSetMinSize
- Status setMinSize(int width, int height) noexcept
- {
- return static_cast<Status>(puglSetMinSize(cobj(), width, height));
- }
-
- /// @copydoc puglSetMaxSize
- Status setMaxSize(int width, int height) noexcept
- {
- return static_cast<Status>(puglSetMaxSize(cobj(), width, height));
- }
-
- /// @copydoc puglSetAspectRatio
- Status setAspectRatio(int minX, int minY, int maxX, int maxY) noexcept
- {
- return static_cast<Status>(
- puglSetAspectRatio(cobj(), minX, minY, maxX, maxY));
- }
-
- /**
- @}
- @name Windows
- Methods for working with top-level windows.
- @{
- */
-
- /// @copydoc puglSetWindowTitle
- Status setWindowTitle(const char* title) noexcept
- {
- return static_cast<Status>(puglSetWindowTitle(cobj(), title));
- }
-
- /// @copydoc puglSetParentWindow
- Status setParentWindow(NativeView parent) noexcept
- {
- return static_cast<Status>(puglSetParentWindow(cobj(), parent));
- }
-
- /// @copydoc puglSetTransientFor
- Status setTransientFor(NativeView parent) noexcept
- {
- return static_cast<Status>(puglSetTransientFor(cobj(), parent));
- }
-
- /// @copydoc puglRealize
- Status realize() noexcept
- {
- return static_cast<Status>(puglRealize(cobj()));
- }
-
- /// @copydoc puglShow
- Status show() noexcept
- {
- return static_cast<Status>(puglShow(cobj()));
- }
-
- /// @copydoc puglHide
- Status hide() noexcept
- {
- return static_cast<Status>(puglHide(cobj()));
- }
-
- /// @copydoc puglGetVisible
- bool visible() const noexcept { return puglGetVisible(cobj()); }
-
- /// @copydoc puglGetNativeWindow
- NativeView nativeWindow() noexcept { return puglGetNativeWindow(cobj()); }
-
- /**
- @}
- @name Graphics
- Methods for working with the graphics context and scheduling
- redisplays.
- @{
- */
-
- /// @copydoc puglGetContext
- void* context() noexcept { return puglGetContext(cobj()); }
-
- /// @copydoc puglPostRedisplay
- Status postRedisplay() noexcept
- {
- return static_cast<Status>(puglPostRedisplay(cobj()));
- }
-
- /// @copydoc puglPostRedisplayRect
- Status postRedisplayRect(const Rect rect) noexcept
- {
- return static_cast<Status>(puglPostRedisplayRect(cobj(), rect));
- }
-
- /**
- @}
- @name Interaction
- Methods for interacting with the user and window system.
- @{
- */
-
- /// @copydoc puglGrabFocus
- Status grabFocus() noexcept
- {
- return static_cast<Status>(puglGrabFocus(cobj()));
- }
-
- /// @copydoc puglHasFocus
- bool hasFocus() const noexcept { return puglHasFocus(cobj()); }
-
- /// @copydoc puglSetCursor
- Status setCursor(const Cursor cursor) noexcept
- {
- return static_cast<Status>(
- puglSetCursor(cobj(), static_cast<PuglCursor>(cursor)));
- }
-
- /// @copydoc puglRequestAttention
- Status requestAttention() noexcept
- {
- return static_cast<Status>(puglRequestAttention(cobj()));
- }
-
- /// @copydoc puglStartTimer
- Status startTimer(const uintptr_t id, const double timeout) noexcept
- {
- return static_cast<Status>(puglStartTimer(cobj(), id, timeout));
- }
-
- /// @copydoc puglStopTimer
- Status stopTimer(const uintptr_t id) noexcept
- {
- return static_cast<Status>(puglStopTimer(cobj(), id));
- }
-
- /**
- @}
- */
-
- PuglView* cobj() noexcept { return Wrapper::cobj(); }
- const PuglView* cobj() const noexcept { return Wrapper::cobj(); }
+ /**
+ @name Setup
+ Methods for creating and destroying a view.
+ @{
+ */
+
+ explicit View(World& world)
+ : Wrapper{puglNewView(world.cobj())}
+ , _world(world)
+ {
+ PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::View");
+ }
+
+ const World& world() const noexcept { return _world; }
+ World& world() noexcept { return _world; }
+
+ /**
+ Set the object that will be called to handle events.
+
+ This is a type-safe wrapper for the C functions puglSetHandle() and
+ puglSetEventFunc() that will automatically dispatch events to the
+ `onEvent` method of `handler` that takes the appropriate event type.
+ The handler must have such a method defined for every event type, but if
+ the handler is the view itself, a `using` declaration can be used to
+ "inherit" the default implementation to avoid having to define every
+ method. For example:
+
+ @code
+ class MyView : public pugl::View
+ {
+ public:
+ explicit MyView(pugl::World& world)
+ : pugl::View{world}
+ {
+ setEventHandler(*this);
+ }
+
+ using pugl::View::onEvent;
+
+ pugl::Status onEvent(const pugl::ConfigureEvent& event) noexcept;
+ pugl::Status onEvent(const pugl::ExposeEvent& event) noexcept;
+ };
+ @endcode
+
+ This facility is just a convenience, applications may use the C API
+ directly to set a handle and event function to set up a different
+ approach for event handling.
+ */
+ template<class Handler>
+ Status setEventHandler(Handler& handler)
+ {
+ puglSetHandle(cobj(), &handler);
+ return static_cast<Status>(puglSetEventFunc(cobj(), eventFunc<Handler>));
+ }
+
+ /// @copydoc puglSetBackend
+ Status setBackend(const PuglBackend* backend) noexcept
+ {
+ return static_cast<Status>(puglSetBackend(cobj(), backend));
+ }
+
+ /// @copydoc puglSetViewHint
+ Status setHint(ViewHint hint, int value) noexcept
+ {
+ return static_cast<Status>(
+ puglSetViewHint(cobj(), static_cast<PuglViewHint>(hint), value));
+ }
+
+ /// @copydoc puglGetViewHint
+ int getHint(ViewHint hint) noexcept
+ {
+ return puglGetViewHint(cobj(), static_cast<PuglViewHint>(hint));
+ }
+
+ /**
+ @}
+ @name Frame
+ Methods for working with the position and size of a view.
+ @{
+ */
+
+ /// @copydoc puglGetFrame
+ Rect frame() const noexcept { return puglGetFrame(cobj()); }
+
+ /// @copydoc puglSetFrame
+ Status setFrame(Rect frame) noexcept
+ {
+ return static_cast<Status>(puglSetFrame(cobj(), frame));
+ }
+
+ /// @copydoc puglSetDefaultSize
+ Status setDefaultSize(int width, int height) noexcept
+ {
+ return static_cast<Status>(puglSetDefaultSize(cobj(), width, height));
+ }
+
+ /// @copydoc puglSetMinSize
+ Status setMinSize(int width, int height) noexcept
+ {
+ return static_cast<Status>(puglSetMinSize(cobj(), width, height));
+ }
+
+ /// @copydoc puglSetMaxSize
+ Status setMaxSize(int width, int height) noexcept
+ {
+ return static_cast<Status>(puglSetMaxSize(cobj(), width, height));
+ }
+
+ /// @copydoc puglSetAspectRatio
+ Status setAspectRatio(int minX, int minY, int maxX, int maxY) noexcept
+ {
+ return static_cast<Status>(
+ puglSetAspectRatio(cobj(), minX, minY, maxX, maxY));
+ }
+
+ /**
+ @}
+ @name Windows
+ Methods for working with top-level windows.
+ @{
+ */
+
+ /// @copydoc puglSetWindowTitle
+ Status setWindowTitle(const char* title) noexcept
+ {
+ return static_cast<Status>(puglSetWindowTitle(cobj(), title));
+ }
+
+ /// @copydoc puglSetParentWindow
+ Status setParentWindow(NativeView parent) noexcept
+ {
+ return static_cast<Status>(puglSetParentWindow(cobj(), parent));
+ }
+
+ /// @copydoc puglSetTransientFor
+ Status setTransientFor(NativeView parent) noexcept
+ {
+ return static_cast<Status>(puglSetTransientFor(cobj(), parent));
+ }
+
+ /// @copydoc puglRealize
+ Status realize() noexcept { return static_cast<Status>(puglRealize(cobj())); }
+
+ /// @copydoc puglShow
+ Status show() noexcept { return static_cast<Status>(puglShow(cobj())); }
+
+ /// @copydoc puglHide
+ Status hide() noexcept { return static_cast<Status>(puglHide(cobj())); }
+
+ /// @copydoc puglGetVisible
+ bool visible() const noexcept { return puglGetVisible(cobj()); }
+
+ /// @copydoc puglGetNativeWindow
+ NativeView nativeWindow() noexcept { return puglGetNativeWindow(cobj()); }
+
+ /**
+ @}
+ @name Graphics
+ Methods for working with the graphics context and scheduling
+ redisplays.
+ @{
+ */
+
+ /// @copydoc puglGetContext
+ void* context() noexcept { return puglGetContext(cobj()); }
+
+ /// @copydoc puglPostRedisplay
+ Status postRedisplay() noexcept
+ {
+ return static_cast<Status>(puglPostRedisplay(cobj()));
+ }
+
+ /// @copydoc puglPostRedisplayRect
+ Status postRedisplayRect(const Rect rect) noexcept
+ {
+ return static_cast<Status>(puglPostRedisplayRect(cobj(), rect));
+ }
+
+ /**
+ @}
+ @name Interaction
+ Methods for interacting with the user and window system.
+ @{
+ */
+
+ /// @copydoc puglGrabFocus
+ Status grabFocus() noexcept
+ {
+ return static_cast<Status>(puglGrabFocus(cobj()));
+ }
+
+ /// @copydoc puglHasFocus
+ bool hasFocus() const noexcept { return puglHasFocus(cobj()); }
+
+ /// @copydoc puglSetCursor
+ Status setCursor(const Cursor cursor) noexcept
+ {
+ return static_cast<Status>(
+ puglSetCursor(cobj(), static_cast<PuglCursor>(cursor)));
+ }
+
+ /// @copydoc puglRequestAttention
+ Status requestAttention() noexcept
+ {
+ return static_cast<Status>(puglRequestAttention(cobj()));
+ }
+
+ /// @copydoc puglStartTimer
+ Status startTimer(const uintptr_t id, const double timeout) noexcept
+ {
+ return static_cast<Status>(puglStartTimer(cobj(), id, timeout));
+ }
+
+ /// @copydoc puglStopTimer
+ Status stopTimer(const uintptr_t id) noexcept
+ {
+ return static_cast<Status>(puglStopTimer(cobj(), id));
+ }
+
+ /**
+ @}
+ */
+
+ PuglView* cobj() noexcept { return Wrapper::cobj(); }
+ const PuglView* cobj() const noexcept { return Wrapper::cobj(); }
private:
- template<class Target>
- static Status dispatch(Target& target, const PuglEvent* event)
- {
- switch (event->type) {
- case PUGL_NOTHING:
- return Status::success;
- case PUGL_CREATE:
- return target.onEvent(static_cast<const CreateEvent&>(event->any));
- case PUGL_DESTROY:
- return target.onEvent(static_cast<const DestroyEvent&>(event->any));
- case PUGL_CONFIGURE:
- return target.onEvent(
- static_cast<const ConfigureEvent&>(event->configure));
- case PUGL_MAP:
- return target.onEvent(static_cast<const MapEvent&>(event->any));
- case PUGL_UNMAP:
- return target.onEvent(static_cast<const UnmapEvent&>(event->any));
- case PUGL_UPDATE:
- return target.onEvent(static_cast<const UpdateEvent&>(event->any));
- case PUGL_EXPOSE:
- return target.onEvent(
- static_cast<const ExposeEvent&>(event->expose));
- case PUGL_CLOSE:
- return target.onEvent(static_cast<const CloseEvent&>(event->any));
- case PUGL_FOCUS_IN:
- return target.onEvent(
- static_cast<const FocusInEvent&>(event->focus));
- case PUGL_FOCUS_OUT:
- return target.onEvent(
- static_cast<const FocusOutEvent&>(event->focus));
- case PUGL_KEY_PRESS:
- return target.onEvent(
- static_cast<const KeyPressEvent&>(event->key));
- case PUGL_KEY_RELEASE:
- return target.onEvent(
- static_cast<const KeyReleaseEvent&>(event->key));
- case PUGL_TEXT:
- return target.onEvent(static_cast<const TextEvent&>(event->text));
- case PUGL_POINTER_IN:
- return target.onEvent(
- static_cast<const PointerInEvent&>(event->crossing));
- case PUGL_POINTER_OUT:
- return target.onEvent(
- static_cast<const PointerOutEvent&>(event->crossing));
- case PUGL_BUTTON_PRESS:
- return target.onEvent(
- static_cast<const ButtonPressEvent&>(event->button));
- case PUGL_BUTTON_RELEASE:
- return target.onEvent(
- static_cast<const ButtonReleaseEvent&>(event->button));
- case PUGL_MOTION:
- return target.onEvent(
- static_cast<const MotionEvent&>(event->motion));
- case PUGL_SCROLL:
- return target.onEvent(
- static_cast<const ScrollEvent&>(event->scroll));
- case PUGL_CLIENT:
- return target.onEvent(
- static_cast<const ClientEvent&>(event->client));
- case PUGL_TIMER:
- return target.onEvent(static_cast<const TimerEvent&>(event->timer));
- case PUGL_LOOP_ENTER:
- return target.onEvent(
- static_cast<const LoopEnterEvent&>(event->any));
- case PUGL_LOOP_LEAVE:
- return target.onEvent(
- static_cast<const LoopLeaveEvent&>(event->any));
- }
-
- return Status::failure;
- }
-
- template<class Target>
- static PuglStatus eventFunc(PuglView* view, const PuglEvent* event) noexcept
- {
- auto* target = static_cast<Target*>(puglGetHandle(view));
+ template<class Target>
+ static Status dispatch(Target& target, const PuglEvent* event)
+ {
+ switch (event->type) {
+ case PUGL_NOTHING:
+ return Status::success;
+ case PUGL_CREATE:
+ return target.onEvent(static_cast<const CreateEvent&>(event->any));
+ case PUGL_DESTROY:
+ return target.onEvent(static_cast<const DestroyEvent&>(event->any));
+ case PUGL_CONFIGURE:
+ return target.onEvent(
+ static_cast<const ConfigureEvent&>(event->configure));
+ case PUGL_MAP:
+ return target.onEvent(static_cast<const MapEvent&>(event->any));
+ case PUGL_UNMAP:
+ return target.onEvent(static_cast<const UnmapEvent&>(event->any));
+ case PUGL_UPDATE:
+ return target.onEvent(static_cast<const UpdateEvent&>(event->any));
+ case PUGL_EXPOSE:
+ return target.onEvent(static_cast<const ExposeEvent&>(event->expose));
+ case PUGL_CLOSE:
+ return target.onEvent(static_cast<const CloseEvent&>(event->any));
+ case PUGL_FOCUS_IN:
+ return target.onEvent(static_cast<const FocusInEvent&>(event->focus));
+ case PUGL_FOCUS_OUT:
+ return target.onEvent(static_cast<const FocusOutEvent&>(event->focus));
+ case PUGL_KEY_PRESS:
+ return target.onEvent(static_cast<const KeyPressEvent&>(event->key));
+ case PUGL_KEY_RELEASE:
+ return target.onEvent(static_cast<const KeyReleaseEvent&>(event->key));
+ case PUGL_TEXT:
+ return target.onEvent(static_cast<const TextEvent&>(event->text));
+ case PUGL_POINTER_IN:
+ return target.onEvent(
+ static_cast<const PointerInEvent&>(event->crossing));
+ case PUGL_POINTER_OUT:
+ return target.onEvent(
+ static_cast<const PointerOutEvent&>(event->crossing));
+ case PUGL_BUTTON_PRESS:
+ return target.onEvent(
+ static_cast<const ButtonPressEvent&>(event->button));
+ case PUGL_BUTTON_RELEASE:
+ return target.onEvent(
+ static_cast<const ButtonReleaseEvent&>(event->button));
+ case PUGL_MOTION:
+ return target.onEvent(static_cast<const MotionEvent&>(event->motion));
+ case PUGL_SCROLL:
+ return target.onEvent(static_cast<const ScrollEvent&>(event->scroll));
+ case PUGL_CLIENT:
+ return target.onEvent(static_cast<const ClientEvent&>(event->client));
+ case PUGL_TIMER:
+ return target.onEvent(static_cast<const TimerEvent&>(event->timer));
+ case PUGL_LOOP_ENTER:
+ return target.onEvent(static_cast<const LoopEnterEvent&>(event->any));
+ case PUGL_LOOP_LEAVE:
+ return target.onEvent(static_cast<const LoopLeaveEvent&>(event->any));
+ }
+
+ return Status::failure;
+ }
+
+ template<class Target>
+ static PuglStatus eventFunc(PuglView* view, const PuglEvent* event) noexcept
+ {
+ auto* target = static_cast<Target*>(puglGetHandle(view));
#ifdef __cpp_exceptions
- try {
- return static_cast<PuglStatus>(dispatch(*target, event));
- } catch (...) {
- return PUGL_UNKNOWN_ERROR;
- }
+ try {
+ return static_cast<PuglStatus>(dispatch(*target, event));
+ } catch (...) {
+ return PUGL_UNKNOWN_ERROR;
+ }
#else
- return static_cast<PuglStatus>(pugl::dispatch(*target, event));
+ return static_cast<PuglStatus>(pugl::dispatch(*target, event));
#endif
- }
+ }
- World& _world;
+ World& _world;
};
/**
diff --git a/bindings/cxx/include/pugl/stub.hpp b/bindings/cxx/include/pugl/stub.hpp
index 8b37da4..6946fe0 100644
--- a/bindings/cxx/include/pugl/stub.hpp
+++ b/bindings/cxx/include/pugl/stub.hpp
@@ -33,7 +33,7 @@ namespace pugl {
inline const PuglBackend*
stubBackend() noexcept
{
- return puglStubBackend();
+ return puglStubBackend();
}
/**
diff --git a/bindings/cxx/include/pugl/vulkan.hpp b/bindings/cxx/include/pugl/vulkan.hpp
index 65d1e57..21341b3 100644
--- a/bindings/cxx/include/pugl/vulkan.hpp
+++ b/bindings/cxx/include/pugl/vulkan.hpp
@@ -49,48 +49,48 @@ namespace pugl {
/// @copydoc PuglVulkanLoader
class VulkanLoader final
- : public detail::Wrapper<PuglVulkanLoader, puglFreeVulkanLoader>
+ : public detail::Wrapper<PuglVulkanLoader, puglFreeVulkanLoader>
{
public:
- /**
- Create a new dynamic loader for Vulkan functions.
-
- This dynamically loads the Vulkan library and gets the load functions
- from it.
-
- Note that this constructor does not throw exceptions, though failure is
- possible. To check if the Vulkan library failed to load, test this
- loader, which is explicitly convertible to `bool`. It is safe to use a
- failed loader, but the accessors will always return null.
- */
- explicit VulkanLoader(World& world) noexcept
- : Wrapper{puglNewVulkanLoader(world.cobj())}
- {}
-
- /**
- Return the `vkGetInstanceProcAddr` function.
-
- @return Null if the Vulkan library failed to load, or does not contain
- this function (which is unlikely and indicates a broken system).
- */
- PFN_vkGetInstanceProcAddr getInstanceProcAddrFunc() const noexcept
- {
- return cobj() ? puglGetInstanceProcAddrFunc(cobj()) : nullptr;
- }
-
- /**
- Return the `vkGetDeviceProcAddr` function.
-
- @return Null if the Vulkan library failed to load, or does not contain
- this function (which is unlikely and indicates a broken system).
- */
- PFN_vkGetDeviceProcAddr getDeviceProcAddrFunc() const noexcept
- {
- return cobj() ? puglGetDeviceProcAddrFunc(cobj()) : nullptr;
- }
-
- /// Return true if this loader is valid to use
- explicit operator bool() const noexcept { return cobj(); }
+ /**
+ Create a new dynamic loader for Vulkan functions.
+
+ This dynamically loads the Vulkan library and gets the load functions
+ from it.
+
+ Note that this constructor does not throw exceptions, though failure is
+ possible. To check if the Vulkan library failed to load, test this
+ loader, which is explicitly convertible to `bool`. It is safe to use a
+ failed loader, but the accessors will always return null.
+ */
+ explicit VulkanLoader(World& world) noexcept
+ : Wrapper{puglNewVulkanLoader(world.cobj())}
+ {}
+
+ /**
+ Return the `vkGetInstanceProcAddr` function.
+
+ @return Null if the Vulkan library failed to load, or does not contain
+ this function (which is unlikely and indicates a broken system).
+ */
+ PFN_vkGetInstanceProcAddr getInstanceProcAddrFunc() const noexcept
+ {
+ return cobj() ? puglGetInstanceProcAddrFunc(cobj()) : nullptr;
+ }
+
+ /**
+ Return the `vkGetDeviceProcAddr` function.
+
+ @return Null if the Vulkan library failed to load, or does not contain
+ this function (which is unlikely and indicates a broken system).
+ */
+ PFN_vkGetDeviceProcAddr getDeviceProcAddrFunc() const noexcept
+ {
+ return cobj() ? puglGetDeviceProcAddrFunc(cobj()) : nullptr;
+ }
+
+ /// Return true if this loader is valid to use
+ explicit operator bool() const noexcept { return cobj(); }
};
/**
@@ -102,23 +102,23 @@ public:
class StaticStringArray final
{
public:
- using value_type = const char*;
- using const_iterator = const char* const*;
- using size_type = uint32_t;
+ using value_type = const char*;
+ using const_iterator = const char* const*;
+ using size_type = uint32_t;
- StaticStringArray(const char* const* strings, const uint32_t size) noexcept
- : _strings{strings}
- , _size{size}
- {}
+ StaticStringArray(const char* const* strings, const uint32_t size) noexcept
+ : _strings{strings}
+ , _size{size}
+ {}
- const char* const* begin() const noexcept { return _strings; }
- const char* const* end() const noexcept { return _strings + _size; }
- const char* const* data() const noexcept { return _strings; }
- uint32_t size() const noexcept { return _size; }
+ const char* const* begin() const noexcept { return _strings; }
+ const char* const* end() const noexcept { return _strings + _size; }
+ const char* const* data() const noexcept { return _strings; }
+ uint32_t size() const noexcept { return _size; }
private:
- const char* const* _strings;
- uint32_t _size;
+ const char* const* _strings;
+ uint32_t _size;
};
/**
@@ -132,10 +132,10 @@ private:
inline StaticStringArray
getInstanceExtensions() noexcept
{
- uint32_t count = 0;
- const char* const* const extensions = puglGetInstanceExtensions(&count);
+ uint32_t count = 0;
+ const char* const* const extensions = puglGetInstanceExtensions(&count);
- return StaticStringArray{extensions, count};
+ return StaticStringArray{extensions, count};
}
/// @copydoc puglCreateSurface
@@ -146,17 +146,17 @@ createSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
const VkAllocationCallbacks* const allocator,
VkSurfaceKHR* const surface) noexcept
{
- const VkResult r = puglCreateSurface(
- vkGetInstanceProcAddr, view.cobj(), instance, allocator, surface);
+ const VkResult r = puglCreateSurface(
+ vkGetInstanceProcAddr, view.cobj(), instance, allocator, surface);
- return (!r && !surface) ? VK_ERROR_INITIALIZATION_FAILED : r;
+ return (!r && !surface) ? VK_ERROR_INITIALIZATION_FAILED : r;
}
/// @copydoc puglVulkanBackend
inline const PuglBackend*
vulkanBackend() noexcept
{
- return puglVulkanBackend();
+ return puglVulkanBackend();
}
/**
diff --git a/examples/cube_view.h b/examples/cube_view.h
index 87bf3b5..e0c86eb 100644
--- a/examples/cube_view.h
+++ b/examples/cube_view.h
@@ -26,48 +26,48 @@
// clang-format off
static const float cubeStripVertices[] = {
- -1.0f, 1.0f, 1.0f, // Front top left
- 1.0f, 1.0f, 1.0f, // Front top right
- -1.0f, -1.0f, 1.0f, // Front bottom left
- 1.0f, -1.0f, 1.0f, // Front bottom right
- 1.0f, -1.0f, -1.0f, // Back bottom right
- 1.0f, 1.0f, 1.0f, // Front top right
- 1.0f, 1.0f, -1.0f, // Back top right
- -1.0f, 1.0f, 1.0f, // Front top left
- -1.0f, 1.0f, -1.0f, // Back top left
- -1.0f, -1.0f, 1.0f, // Front bottom left
- -1.0f, -1.0f, -1.0f, // Back bottom left
- 1.0f, -1.0f, -1.0f, // Back bottom right
- -1.0f, 1.0f, -1.0f, // Back top left
- 1.0f, 1.0f, -1.0f // Back top right
+ -1.0f, 1.0f, 1.0f, // Front top left
+ 1.0f, 1.0f, 1.0f, // Front top right
+ -1.0f, -1.0f, 1.0f, // Front bottom left
+ 1.0f, -1.0f, 1.0f, // Front bottom right
+ 1.0f, -1.0f, -1.0f, // Back bottom right
+ 1.0f, 1.0f, 1.0f, // Front top right
+ 1.0f, 1.0f, -1.0f, // Back top right
+ -1.0f, 1.0f, 1.0f, // Front top left
+ -1.0f, 1.0f, -1.0f, // Back top left
+ -1.0f, -1.0f, 1.0f, // Front bottom left
+ -1.0f, -1.0f, -1.0f, // Back bottom left
+ 1.0f, -1.0f, -1.0f, // Back bottom right
+ -1.0f, 1.0f, -1.0f, // Back top left
+ 1.0f, 1.0f, -1.0f // Back top right
};
static const float cubeFrontLineLoop[] = {
- -1.0f, 1.0f, 1.0f, // Front top left
- 1.0f, 1.0f, 1.0f, // Front top right
- 1.0f, -1.0f, 1.0f, // Front bottom right
- -1.0f, -1.0f, 1.0f, // Front bottom left
+ -1.0f, 1.0f, 1.0f, // Front top left
+ 1.0f, 1.0f, 1.0f, // Front top right
+ 1.0f, -1.0f, 1.0f, // Front bottom right
+ -1.0f, -1.0f, 1.0f, // Front bottom left
};
static const float cubeBackLineLoop[] = {
- -1.0f, 1.0f, -1.0f, // Back top left
- 1.0f, 1.0f, -1.0f, // Back top right
- 1.0f, -1.0f, -1.0f, // Back bottom right
- -1.0f, -1.0f, -1.0f, // Back bottom left
+ -1.0f, 1.0f, -1.0f, // Back top left
+ 1.0f, 1.0f, -1.0f, // Back top right
+ 1.0f, -1.0f, -1.0f, // Back bottom right
+ -1.0f, -1.0f, -1.0f, // Back bottom left
};
static const float cubeSideLines[] = {
- -1.0f, 1.0f, 1.0f, // Front top left
- -1.0f, 1.0f, -1.0f, // Back top left
+ -1.0f, 1.0f, 1.0f, // Front top left
+ -1.0f, 1.0f, -1.0f, // Back top left
- -1.0f, -1.0f, 1.0f, // Front bottom left
- -1.0f, -1.0f, -1.0f, // Back bottom left
+ -1.0f, -1.0f, 1.0f, // Front bottom left
+ -1.0f, -1.0f, -1.0f, // Back bottom left
- 1.0f, 1.0f, 1.0f, // Front top right
- 1.0f, 1.0f, -1.0f, // Back top right
+ 1.0f, 1.0f, 1.0f, // Front top right
+ 1.0f, 1.0f, -1.0f, // Back top right
- 1.0f, -1.0f, 1.0f, // Front bottom right
- 1.0f, -1.0f, -1.0f, // Back bottom right
+ 1.0f, -1.0f, 1.0f, // Front bottom right
+ 1.0f, -1.0f, -1.0f, // Back bottom right
};
// clang-format on
@@ -75,19 +75,19 @@ static const float cubeSideLines[] = {
static inline void
reshapeCube(const float width, const float height)
{
- const float aspect = width / height;
+ const float aspect = width / height;
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glViewport(0, 0, (int)width, (int)height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glViewport(0, 0, (int)width, (int)height);
- float projection[16];
- perspective(projection, 1.8f, aspect, 1.0f, 100.0f);
- glLoadMatrixf(projection);
+ float projection[16];
+ perspective(projection, 1.8f, aspect, 1.0f, 100.0f);
+ glLoadMatrixf(projection);
}
static inline void
@@ -97,40 +97,40 @@ displayCube(PuglView* const view,
const float yAngle,
const bool entered)
{
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.0f, 0.0f, distance * -1.0f);
- glRotatef(xAngle, 0.0f, 1.0f, 0.0f);
- glRotatef(yAngle, 1.0f, 0.0f, 0.0f);
-
- const float bg = entered ? 0.2f : 0.0f;
- glClearColor(bg, bg, bg, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- if (puglHasFocus(view)) {
- // Draw cube surfaces
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, cubeStripVertices);
- glColorPointer(3, GL_FLOAT, 0, cubeStripVertices);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glColor3f(0.0f, 0.0f, 0.0f);
- } else {
- glColor3f(1.0f, 1.0f, 1.0f);
- }
-
- // Draw cube wireframe
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, cubeFrontLineLoop);
- glDrawArrays(GL_LINE_LOOP, 0, 4);
- glVertexPointer(3, GL_FLOAT, 0, cubeBackLineLoop);
- glDrawArrays(GL_LINE_LOOP, 0, 4);
- glVertexPointer(3, GL_FLOAT, 0, cubeSideLines);
- glDrawArrays(GL_LINES, 0, 8);
- glDisableClientState(GL_VERTEX_ARRAY);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0f, 0.0f, distance * -1.0f);
+ glRotatef(xAngle, 0.0f, 1.0f, 0.0f);
+ glRotatef(yAngle, 1.0f, 0.0f, 0.0f);
+
+ const float bg = entered ? 0.2f : 0.0f;
+ glClearColor(bg, bg, bg, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (puglHasFocus(view)) {
+ // Draw cube surfaces
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, cubeStripVertices);
+ glColorPointer(3, GL_FLOAT, 0, cubeStripVertices);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ glColor3f(0.0f, 0.0f, 0.0f);
+ } else {
+ glColor3f(1.0f, 1.0f, 1.0f);
+ }
+
+ // Draw cube wireframe
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, cubeFrontLineLoop);
+ glDrawArrays(GL_LINE_LOOP, 0, 4);
+ glVertexPointer(3, GL_FLOAT, 0, cubeBackLineLoop);
+ glDrawArrays(GL_LINE_LOOP, 0, 4);
+ glVertexPointer(3, GL_FLOAT, 0, cubeSideLines);
+ glDrawArrays(GL_LINES, 0, 8);
+ glDisableClientState(GL_VERTEX_ARRAY);
}
#endif // EXAMPLES_CUBE_VIEW_H
diff --git a/examples/demo_utils.h b/examples/demo_utils.h
index 9057a32..e76d304 100644
--- a/examples/demo_utils.h
+++ b/examples/demo_utils.h
@@ -25,7 +25,7 @@
#include <string.h>
typedef struct {
- double lastReportTime;
+ double lastReportTime;
} PuglFpsPrinter;
typedef float vec4[4];
@@ -34,32 +34,32 @@ typedef vec4 mat4[4];
static inline void
mat4Identity(mat4 m)
{
- for (int c = 0; c < 4; ++c) {
- for (int r = 0; r < 4; ++r) {
- m[c][r] = c == r ? 1.0f : 0.0f;
- }
- }
+ for (int c = 0; c < 4; ++c) {
+ for (int r = 0; r < 4; ++r) {
+ m[c][r] = c == r ? 1.0f : 0.0f;
+ }
+ }
}
static inline void
mat4Translate(mat4 m, const float x, const float y, const float z)
{
- m[3][0] = x;
- m[3][1] = y;
- m[3][2] = z;
+ m[3][0] = x;
+ m[3][1] = y;
+ m[3][2] = z;
}
static inline void
mat4Mul(mat4 m, mat4 a, mat4 b)
{
- for (int c = 0; c < 4; ++c) {
- for (int r = 0; r < 4; ++r) {
- m[c][r] = 0.0f;
- for (int k = 0; k < 4; ++k) {
- m[c][r] += a[k][r] * b[c][k];
- }
- }
- }
+ for (int c = 0; c < 4; ++c) {
+ for (int r = 0; r < 4; ++r) {
+ m[c][r] = 0.0f;
+ for (int k = 0; k < 4; ++k) {
+ m[c][r] += a[k][r] * b[c][k];
+ }
+ }
+ }
}
static inline void
@@ -71,37 +71,37 @@ mat4Ortho(mat4 m,
const float n,
const float f)
{
- m[0][0] = 2.0f / (r - l);
- m[0][1] = m[0][2] = m[0][3] = 0.0f;
+ m[0][0] = 2.0f / (r - l);
+ m[0][1] = m[0][2] = m[0][3] = 0.0f;
- m[1][1] = 2.0f / (t - b);
- m[1][0] = m[1][2] = m[1][3] = 0.0f;
+ m[1][1] = 2.0f / (t - b);
+ m[1][0] = m[1][2] = m[1][3] = 0.0f;
- m[2][2] = -2.0f / (f - n);
- m[2][0] = m[2][1] = m[2][3] = 0.0f;
+ m[2][2] = -2.0f / (f - n);
+ m[2][0] = m[2][1] = m[2][3] = 0.0f;
- m[3][0] = -(r + l) / (r - l);
- m[3][1] = -(t + b) / (t - b);
- m[3][2] = -(f + n) / (f - n);
- m[3][3] = 1.0f;
+ m[3][0] = -(r + l) / (r - l);
+ m[3][1] = -(t + b) / (t - b);
+ m[3][2] = -(f + n) / (f - n);
+ m[3][3] = 1.0f;
}
/// Calculate a projection matrix for a given perspective
static inline void
perspective(float* m, float fov, float aspect, float zNear, float zFar)
{
- const float h = tanf(fov);
- const float w = h / aspect;
- const float depth = zNear - zFar;
- const float q = (zFar + zNear) / depth;
- const float qn = 2 * zFar * zNear / depth;
-
- // clang-format off
- m[0] = w; m[1] = 0; m[2] = 0; m[3] = 0;
- m[4] = 0; m[5] = h; m[6] = 0; m[7] = 0;
- m[8] = 0; m[9] = 0; m[10] = q; m[11] = -1;
- m[12] = 0; m[13] = 0; m[14] = qn; m[15] = 0;
- // clang-format on
+ const float h = tanf(fov);
+ const float w = h / aspect;
+ const float depth = zNear - zFar;
+ const float q = (zFar + zNear) / depth;
+ const float qn = 2 * zFar * zNear / depth;
+
+ // clang-format off
+ m[0] = w; m[1] = 0; m[2] = 0; m[3] = 0;
+ m[4] = 0; m[5] = h; m[6] = 0; m[7] = 0;
+ m[8] = 0; m[9] = 0; m[10] = q; m[11] = -1;
+ m[12] = 0; m[13] = 0; m[14] = qn; m[15] = 0;
+ // clang-format on
}
static inline void
@@ -109,18 +109,18 @@ puglPrintFps(const PuglWorld* world,
PuglFpsPrinter* printer,
unsigned* const framesDrawn)
{
- const double thisTime = puglGetTime(world);
- if (thisTime > printer->lastReportTime + 5) {
- const double fps = *framesDrawn / (thisTime - printer->lastReportTime);
- fprintf(stderr,
- "FPS: %.2f (%u frames in %.0f seconds)\n",
- fps,
- *framesDrawn,
- thisTime - printer->lastReportTime);
-
- printer->lastReportTime = thisTime;
- *framesDrawn = 0;
- }
+ const double thisTime = puglGetTime(world);
+ if (thisTime > printer->lastReportTime + 5) {
+ const double fps = *framesDrawn / (thisTime - printer->lastReportTime);
+ fprintf(stderr,
+ "FPS: %.2f (%u frames in %.0f seconds)\n",
+ fps,
+ *framesDrawn,
+ thisTime - printer->lastReportTime);
+
+ printer->lastReportTime = thisTime;
+ *framesDrawn = 0;
+ }
}
#endif // EXAMPLES_DEMO_UTILS_H
diff --git a/examples/file_utils.c b/examples/file_utils.c
index 2b00bdc..8ecbca4 100644
--- a/examples/file_utils.c
+++ b/examples/file_utils.c
@@ -15,18 +15,18 @@
*/
#if !defined(__APPLE__) && !defined(_GNU_SOURCE)
-# define _GNU_SOURCE
+# define _GNU_SOURCE
#endif
#include "file_utils.h"
#ifdef _WIN32
-# include <io.h>
-# include <windows.h>
-# define F_OK 0
+# include <io.h>
+# include <windows.h>
+# define F_OK 0
#else
-# include <libgen.h>
-# include <unistd.h>
+# include <libgen.h>
+# include <unistd.h>
#endif
#include <stdio.h>
@@ -36,33 +36,33 @@
char*
resourcePath(const char* const programPath, const char* const name)
{
- char* const binary = strdup(programPath);
+ char* const binary = strdup(programPath);
#ifdef _WIN32
- char programDir[_MAX_DIR];
- _splitpath(binary, programDir, NULL, NULL, NULL);
- _splitpath(binary, NULL, programDir + strlen(programDir), NULL, NULL);
- programDir[strlen(programDir) - 1] = '\0';
+ char programDir[_MAX_DIR];
+ _splitpath(binary, programDir, NULL, NULL, NULL);
+ _splitpath(binary, NULL, programDir + strlen(programDir), NULL, NULL);
+ programDir[strlen(programDir) - 1] = '\0';
#else
- char* const programDir = dirname(binary);
+ char* const programDir = dirname(binary);
#endif
- const size_t programDirLen = strlen(programDir);
- const size_t nameLen = strlen(name);
- const size_t totalLen = programDirLen + nameLen + 4;
+ const size_t programDirLen = strlen(programDir);
+ const size_t nameLen = strlen(name);
+ const size_t totalLen = programDirLen + nameLen + 4;
- char* const programRelative = (char*)calloc(totalLen, 1);
- snprintf(programRelative, totalLen, "%s/%s", programDir, name);
- if (!access(programRelative, F_OK)) {
- free(binary);
- return programRelative;
- }
+ char* const programRelative = (char*)calloc(totalLen, 1);
+ snprintf(programRelative, totalLen, "%s/%s", programDir, name);
+ if (!access(programRelative, F_OK)) {
+ free(binary);
+ return programRelative;
+ }
- free(programRelative);
- free(binary);
+ free(programRelative);
+ free(binary);
- const size_t sysPathLen = strlen(PUGL_DATA_DIR) + nameLen + 4;
- char* const sysPath = (char*)calloc(sysPathLen, 1);
- snprintf(sysPath, sysPathLen, "%s/%s", PUGL_DATA_DIR, name);
- return sysPath;
+ const size_t sysPathLen = strlen(PUGL_DATA_DIR) + nameLen + 4;
+ char* const sysPath = (char*)calloc(sysPathLen, 1);
+ snprintf(sysPath, sysPathLen, "%s/%s", PUGL_DATA_DIR, name);
+ return sysPath;
}
diff --git a/examples/pugl_cairo_demo.c b/examples/pugl_cairo_demo.c
index 48a02db..4da0caf 100644
--- a/examples/pugl_cairo_demo.c
+++ b/examples/pugl_cairo_demo.c
@@ -28,20 +28,20 @@
#include <string.h>
typedef struct {
- PuglWorld* world;
- PuglTestOptions opts;
- unsigned framesDrawn;
- int quit;
- bool entered;
- bool mouseDown;
+ PuglWorld* world;
+ PuglTestOptions opts;
+ unsigned framesDrawn;
+ int quit;
+ bool entered;
+ bool mouseDown;
} PuglTestApp;
typedef struct {
- int x;
- int y;
- int w;
- int h;
- const char* label;
+ int x;
+ int y;
+ int w;
+ int h;
+ const char* label;
} Button;
static const Button buttons[] = {{128, 128, 64, 64, "1"},
@@ -53,213 +53,208 @@ static const Button buttons[] = {{128, 128, 64, 64, "1"},
static void
roundedBox(cairo_t* cr, double x, double y, double w, double h)
{
- static const double radius = 10;
- static const double degrees = 3.14159265 / 180.0;
-
- cairo_new_sub_path(cr);
- cairo_arc(cr,
- x + w - radius,
- y + radius,
- radius, -90 * degrees, 0 * degrees);
- cairo_arc(cr,
- x + w - radius, y + h - radius,
- radius, 0 * degrees, 90 * degrees);
- cairo_arc(cr,
- x + radius, y + h - radius,
- radius, 90 * degrees, 180 * degrees);
- cairo_arc(cr,
- x + radius, y + radius,
- radius, 180 * degrees, 270 * degrees);
- cairo_close_path(cr);
+ static const double radius = 10;
+ static const double degrees = 3.14159265 / 180.0;
+
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, x + w - radius, y + radius, radius, -90 * degrees, 0 * degrees);
+
+ cairo_arc(
+ cr, x + w - radius, y + h - radius, radius, 0 * degrees, 90 * degrees);
+
+ cairo_arc(
+ cr, x + radius, y + h - radius, radius, 90 * degrees, 180 * degrees);
+
+ cairo_arc(cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
+ cairo_close_path(cr);
}
static void
buttonDraw(PuglTestApp* app, cairo_t* cr, const Button* but, const double time)
{
- cairo_save(cr);
- cairo_translate(cr, but->x, but->y);
- cairo_rotate(cr, sin(time) * 3.141592);
-
- // Draw base
- if (app->mouseDown) {
- cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1);
- } else {
- cairo_set_source_rgba(cr, 0.3, 0.5, 0.1, 1);
- }
- roundedBox(cr, 0, 0, but->w, but->h);
- cairo_fill_preserve(cr);
-
- // Draw border
- cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1);
- cairo_set_line_width(cr, 4.0);
- cairo_stroke(cr);
-
- // Draw label
- cairo_text_extents_t extents;
- cairo_set_font_size(cr, 32.0);
- cairo_text_extents(cr, but->label, &extents);
- cairo_move_to(cr,
- (but->w / 2.0) - extents.width / 2,
- (but->h / 2.0) + extents.height / 2);
- cairo_set_source_rgba(cr, 0, 0, 0, 1);
- cairo_show_text(cr, but->label);
-
- cairo_restore(cr);
+ cairo_save(cr);
+ cairo_translate(cr, but->x, but->y);
+ cairo_rotate(cr, sin(time) * 3.141592);
+
+ // Draw base
+ if (app->mouseDown) {
+ cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1);
+ } else {
+ cairo_set_source_rgba(cr, 0.3, 0.5, 0.1, 1);
+ }
+ roundedBox(cr, 0, 0, but->w, but->h);
+ cairo_fill_preserve(cr);
+
+ // Draw border
+ cairo_set_source_rgba(cr, 0.4, 0.9, 0.1, 1);
+ cairo_set_line_width(cr, 4.0);
+ cairo_stroke(cr);
+
+ // Draw label
+ cairo_text_extents_t extents;
+ cairo_set_font_size(cr, 32.0);
+ cairo_text_extents(cr, but->label, &extents);
+ cairo_move_to(cr,
+ (but->w / 2.0) - extents.width / 2,
+ (but->h / 2.0) + extents.height / 2);
+ cairo_set_source_rgba(cr, 0, 0, 0, 1);
+ cairo_show_text(cr, but->label);
+
+ cairo_restore(cr);
}
static void
postButtonRedisplay(PuglView* view)
{
- const PuglRect frame = puglGetFrame(view);
- const double width = frame.width;
- const double height = frame.height;
- const double scaleX = (width - (512 / width)) / 512.0;
- const double scaleY = (height - (512 / height)) / 512.0;
-
- for (const Button* b = buttons; b->label; ++b) {
- const double span = sqrt(b->w * b->w + b->h * b->h);
- const PuglRect rect = {(b->x - span) * scaleX,
- (b->y - span) * scaleY,
- span * 2.0 * scaleX,
- span * 2.0 * scaleY};
-
- puglPostRedisplayRect(view, rect);
- }
+ const PuglRect frame = puglGetFrame(view);
+ const double width = frame.width;
+ const double height = frame.height;
+ const double scaleX = (width - (512 / width)) / 512.0;
+ const double scaleY = (height - (512 / height)) / 512.0;
+
+ for (const Button* b = buttons; b->label; ++b) {
+ const double span = sqrt(b->w * b->w + b->h * b->h);
+ const PuglRect rect = {(b->x - span) * scaleX,
+ (b->y - span) * scaleY,
+ span * 2.0 * scaleX,
+ span * 2.0 * scaleY};
+
+ puglPostRedisplayRect(view, rect);
+ }
}
static void
onDisplay(PuglTestApp* app, PuglView* view, const PuglEventExpose* event)
{
- cairo_t* cr = (cairo_t*)puglGetContext(view);
-
- cairo_rectangle(cr, event->x, event->y, event->width, event->height);
- cairo_clip_preserve(cr);
-
- // Draw background
- const PuglRect frame = puglGetFrame(view);
- const double width = frame.width;
- const double height = frame.height;
- if (app->entered) {
- cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
- } else {
- cairo_set_source_rgb(cr, 0, 0, 0);
- }
- cairo_fill(cr);
-
- // Scale to view size
- const double scaleX = (width - (512 / width)) / 512.0;
- const double scaleY = (height - (512 / height)) / 512.0;
- cairo_scale(cr, scaleX, scaleY);
-
- // Draw button
- for (const Button* b = buttons; b->label; ++b) {
- buttonDraw(app,
- cr,
- b,
- app->opts.continuous ? puglGetTime(app->world) : 0.0);
- }
-
- ++app->framesDrawn;
+ cairo_t* cr = (cairo_t*)puglGetContext(view);
+
+ cairo_rectangle(cr, event->x, event->y, event->width, event->height);
+ cairo_clip_preserve(cr);
+
+ // Draw background
+ const PuglRect frame = puglGetFrame(view);
+ const double width = frame.width;
+ const double height = frame.height;
+ if (app->entered) {
+ cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
+ } else {
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ }
+ cairo_fill(cr);
+
+ // Scale to view size
+ const double scaleX = (width - (512 / width)) / 512.0;
+ const double scaleY = (height - (512 / height)) / 512.0;
+ cairo_scale(cr, scaleX, scaleY);
+
+ // Draw button
+ for (const Button* b = buttons; b->label; ++b) {
+ buttonDraw(
+ app, cr, b, app->opts.continuous ? puglGetTime(app->world) : 0.0);
+ }
+
+ ++app->framesDrawn;
}
static void
onClose(PuglView* view)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- app->quit = 1;
+ app->quit = 1;
}
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
-
- printEvent(event, "Event: ", app->opts.verbose);
-
- switch (event->type) {
- case PUGL_KEY_PRESS:
- if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
- app->quit = 1;
- }
- break;
- case PUGL_BUTTON_PRESS:
- app->mouseDown = true;
- postButtonRedisplay(view);
- break;
- case PUGL_BUTTON_RELEASE:
- app->mouseDown = false;
- postButtonRedisplay(view);
- break;
- case PUGL_POINTER_IN:
- app->entered = true;
- puglPostRedisplay(view);
- break;
- case PUGL_POINTER_OUT:
- app->entered = false;
- puglPostRedisplay(view);
- break;
- case PUGL_UPDATE:
- if (app->opts.continuous) {
- puglPostRedisplay(view);
- }
- break;
- case PUGL_EXPOSE:
- onDisplay(app, view, &event->expose);
- break;
- case PUGL_CLOSE:
- onClose(view);
- break;
- default: break;
- }
-
- return PUGL_SUCCESS;
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+
+ printEvent(event, "Event: ", app->opts.verbose);
+
+ switch (event->type) {
+ case PUGL_KEY_PRESS:
+ if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
+ app->quit = 1;
+ }
+ break;
+ case PUGL_BUTTON_PRESS:
+ app->mouseDown = true;
+ postButtonRedisplay(view);
+ break;
+ case PUGL_BUTTON_RELEASE:
+ app->mouseDown = false;
+ postButtonRedisplay(view);
+ break;
+ case PUGL_POINTER_IN:
+ app->entered = true;
+ puglPostRedisplay(view);
+ break;
+ case PUGL_POINTER_OUT:
+ app->entered = false;
+ puglPostRedisplay(view);
+ break;
+ case PUGL_UPDATE:
+ if (app->opts.continuous) {
+ puglPostRedisplay(view);
+ }
+ break;
+ case PUGL_EXPOSE:
+ onDisplay(app, view, &event->expose);
+ break;
+ case PUGL_CLOSE:
+ onClose(view);
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTestApp app;
- memset(&app, 0, sizeof(app));
-
- app.opts = puglParseTestOptions(&argc, &argv);
- if (app.opts.help) {
- puglPrintTestUsage("pugl_test", "");
- return 1;
- }
-
- app.world = puglNewWorld(PUGL_PROGRAM, 0);
- puglSetClassName(app.world, "PuglCairoTest");
-
- PuglView* view = puglNewView(app.world);
-
- puglSetWindowTitle(view, "Pugl Cairo Demo");
- puglSetDefaultSize(view, 512, 512);
- puglSetMinSize(view, 256, 256);
- puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable);
- puglSetHandle(view, &app);
- puglSetBackend(view, puglCairoBackend());
- puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, app.opts.ignoreKeyRepeat);
- puglSetEventFunc(view, onEvent);
-
- PuglStatus st = puglRealize(view);
- if (st) {
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
-
- puglShow(view);
-
- PuglFpsPrinter fpsPrinter = { puglGetTime(app.world) };
- const double timeout = app.opts.continuous ? (1 / 60.0) : -1.0;
- while (!app.quit) {
- puglUpdate(app.world, timeout);
-
- if (app.opts.continuous) {
- puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
- }
- }
-
- puglFreeView(view);
- puglFreeWorld(app.world);
- return 0;
+ PuglTestApp app;
+ memset(&app, 0, sizeof(app));
+
+ app.opts = puglParseTestOptions(&argc, &argv);
+ if (app.opts.help) {
+ puglPrintTestUsage("pugl_test", "");
+ return 1;
+ }
+
+ app.world = puglNewWorld(PUGL_PROGRAM, 0);
+ puglSetClassName(app.world, "PuglCairoTest");
+
+ PuglView* view = puglNewView(app.world);
+
+ puglSetWindowTitle(view, "Pugl Cairo Demo");
+ puglSetDefaultSize(view, 512, 512);
+ puglSetMinSize(view, 256, 256);
+ puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable);
+ puglSetHandle(view, &app);
+ puglSetBackend(view, puglCairoBackend());
+ puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, app.opts.ignoreKeyRepeat);
+ puglSetEventFunc(view, onEvent);
+
+ PuglStatus st = puglRealize(view);
+ if (st) {
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
+
+ puglShow(view);
+
+ PuglFpsPrinter fpsPrinter = {puglGetTime(app.world)};
+ const double timeout = app.opts.continuous ? (1 / 60.0) : -1.0;
+ while (!app.quit) {
+ puglUpdate(app.world, timeout);
+
+ if (app.opts.continuous) {
+ puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
+ }
+ }
+
+ puglFreeView(view);
+ puglFreeWorld(app.world);
+ return 0;
}
diff --git a/examples/pugl_cursor_demo.c b/examples/pugl_cursor_demo.c
index f20b0ea..60ec3d3 100644
--- a/examples/pugl_cursor_demo.c
+++ b/examples/pugl_cursor_demo.c
@@ -26,143 +26,143 @@ static const int N_ROWS = 2;
static const int N_COLS = 4;
typedef struct {
- PuglWorld* world;
- PuglTestOptions opts;
- bool quit;
+ PuglWorld* world;
+ PuglTestOptions opts;
+ bool quit;
} PuglTestApp;
static void
onConfigure(const double width, const double height)
{
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glViewport(0, 0, (int)width, (int)height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glViewport(0, 0, (int)width, (int)height);
}
static void
onExpose(void)
{
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glColor3f(0.6f, 0.6f, 0.6f);
-
- for (int row = 1; row < N_ROWS; ++row) {
- const float y = (float)row * (2.0f / (float)N_ROWS) - 1.0f;
- glBegin(GL_LINES);
- glVertex2f(-1.0f, y);
- glVertex2f(1.0f, y);
- glEnd();
- }
-
- for (int col = 1; col < N_COLS; ++col) {
- const float x = (float)col * (2.0f / (float)N_COLS) - 1.0f;
- glBegin(GL_LINES);
- glVertex2f(x, -1.0f);
- glVertex2f(x, 1.0f);
- glEnd();
- }
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glColor3f(0.6f, 0.6f, 0.6f);
+
+ for (int row = 1; row < N_ROWS; ++row) {
+ const float y = (float)row * (2.0f / (float)N_ROWS) - 1.0f;
+ glBegin(GL_LINES);
+ glVertex2f(-1.0f, y);
+ glVertex2f(1.0f, y);
+ glEnd();
+ }
+
+ for (int col = 1; col < N_COLS; ++col) {
+ const float x = (float)col * (2.0f / (float)N_COLS) - 1.0f;
+ glBegin(GL_LINES);
+ glVertex2f(x, -1.0f);
+ glVertex2f(x, 1.0f);
+ glEnd();
+ }
}
static void
onMotion(PuglView* view, double x, double y)
{
- const PuglRect frame = puglGetFrame(view);
- int row = (int)(y * N_ROWS / frame.height);
- int col = (int)(x * N_COLS / frame.width);
+ const PuglRect frame = puglGetFrame(view);
+ int row = (int)(y * N_ROWS / frame.height);
+ int col = (int)(x * N_COLS / frame.width);
- row = (row < 0) ? 0 : (row >= N_ROWS) ? (N_ROWS - 1) : row;
- col = (col < 0) ? 0 : (col >= N_COLS) ? (N_COLS - 1) : col;
+ row = (row < 0) ? 0 : (row >= N_ROWS) ? (N_ROWS - 1) : row;
+ col = (col < 0) ? 0 : (col >= N_COLS) ? (N_COLS - 1) : col;
- const PuglCursor cursor = (PuglCursor)((row * N_COLS + col) % N_CURSORS);
- puglSetCursor(view, cursor);
+ const PuglCursor cursor = (PuglCursor)((row * N_COLS + col) % N_CURSORS);
+ puglSetCursor(view, cursor);
}
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
-
- printEvent(event, "Event: ", app->opts.verbose);
-
- switch (event->type) {
- case PUGL_CONFIGURE:
- onConfigure(event->configure.width, event->configure.height);
- break;
- case PUGL_KEY_PRESS:
- if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
- app->quit = 1;
- }
- break;
- case PUGL_MOTION:
- onMotion(view, event->motion.x, event->motion.y);
- break;
- case PUGL_EXPOSE:
- onExpose();
- break;
- case PUGL_POINTER_OUT:
- puglSetCursor(view, PUGL_CURSOR_ARROW);
- break;
- case PUGL_CLOSE:
- app->quit = 1;
- break;
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+
+ printEvent(event, "Event: ", app->opts.verbose);
+
+ switch (event->type) {
+ case PUGL_CONFIGURE:
+ onConfigure(event->configure.width, event->configure.height);
+ break;
+ case PUGL_KEY_PRESS:
+ if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
+ app->quit = 1;
+ }
+ break;
+ case PUGL_MOTION:
+ onMotion(view, event->motion.x, event->motion.y);
+ break;
+ case PUGL_EXPOSE:
+ onExpose();
+ break;
+ case PUGL_POINTER_OUT:
+ puglSetCursor(view, PUGL_CURSOR_ARROW);
+ break;
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTestApp app = {0};
+ PuglTestApp app = {0};
- app.opts = puglParseTestOptions(&argc, &argv);
- if (app.opts.help) {
- puglPrintTestUsage(argv[0], "");
- return 1;
- }
+ app.opts = puglParseTestOptions(&argc, &argv);
+ if (app.opts.help) {
+ puglPrintTestUsage(argv[0], "");
+ return 1;
+ }
- app.world = puglNewWorld(PUGL_PROGRAM, 0);
+ app.world = puglNewWorld(PUGL_PROGRAM, 0);
- puglSetWorldHandle(app.world, &app);
- puglSetClassName(app.world, "Pugl Test");
+ puglSetWorldHandle(app.world, &app);
+ puglSetClassName(app.world, "Pugl Test");
- PuglView* view = puglNewView(app.world);
+ PuglView* view = puglNewView(app.world);
- puglSetWindowTitle(view, "Pugl Window Demo");
- puglSetDefaultSize(view, 512, 256);
- puglSetMinSize(view, 128, 64);
- puglSetBackend(view, puglGlBackend());
+ puglSetWindowTitle(view, "Pugl Window Demo");
+ puglSetDefaultSize(view, 512, 256);
+ puglSetMinSize(view, 128, 64);
+ puglSetBackend(view, puglGlBackend());
- puglSetViewHint(view, PUGL_USE_DEBUG_CONTEXT, app.opts.errorChecking);
- puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable);
- puglSetViewHint(view, PUGL_SAMPLES, app.opts.samples);
- puglSetViewHint(view, PUGL_DOUBLE_BUFFER, app.opts.doubleBuffer);
- puglSetViewHint(view, PUGL_SWAP_INTERVAL, app.opts.sync);
- puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, app.opts.ignoreKeyRepeat);
- puglSetHandle(view, &app);
- puglSetEventFunc(view, onEvent);
+ puglSetViewHint(view, PUGL_USE_DEBUG_CONTEXT, app.opts.errorChecking);
+ puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable);
+ puglSetViewHint(view, PUGL_SAMPLES, app.opts.samples);
+ puglSetViewHint(view, PUGL_DOUBLE_BUFFER, app.opts.doubleBuffer);
+ puglSetViewHint(view, PUGL_SWAP_INTERVAL, app.opts.sync);
+ puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, app.opts.ignoreKeyRepeat);
+ puglSetHandle(view, &app);
+ puglSetEventFunc(view, onEvent);
- const PuglStatus st = puglRealize(view);
- if (st) {
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
+ const PuglStatus st = puglRealize(view);
+ if (st) {
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
- puglShow(view);
+ puglShow(view);
- while (!app.quit) {
- puglUpdate(app.world, -1.0);
- }
+ while (!app.quit) {
+ puglUpdate(app.world, -1.0);
+ }
- puglFreeView(view);
- puglFreeWorld(app.world);
+ puglFreeView(view);
+ puglFreeWorld(app.world);
- return 0;
+ return 0;
}
diff --git a/examples/pugl_cxx_demo.cpp b/examples/pugl_cxx_demo.cpp
index 8269ae4..4914724 100644
--- a/examples/pugl_cxx_demo.cpp
+++ b/examples/pugl_cxx_demo.cpp
@@ -27,121 +27,121 @@
class CubeView : public pugl::View
{
public:
- explicit CubeView(pugl::World& world)
- : pugl::View{world}
- {
- setEventHandler(*this);
- }
-
- template<PuglEventType t, class Base>
- pugl::Status onEvent(const pugl::Event<t, Base>&) noexcept
- {
- return pugl::Status::success;
- }
-
- static pugl::Status onEvent(const pugl::ConfigureEvent& event) noexcept;
- pugl::Status onEvent(const pugl::UpdateEvent& event) noexcept;
- pugl::Status onEvent(const pugl::ExposeEvent& event) noexcept;
- pugl::Status onEvent(const pugl::KeyPressEvent& event) noexcept;
- pugl::Status onEvent(const pugl::CloseEvent& event) noexcept;
-
- bool quit() const { return _quit; }
+ explicit CubeView(pugl::World& world)
+ : pugl::View{world}
+ {
+ setEventHandler(*this);
+ }
+
+ template<PuglEventType t, class Base>
+ pugl::Status onEvent(const pugl::Event<t, Base>&) noexcept
+ {
+ return pugl::Status::success;
+ }
+
+ static pugl::Status onEvent(const pugl::ConfigureEvent& event) noexcept;
+ pugl::Status onEvent(const pugl::UpdateEvent& event) noexcept;
+ pugl::Status onEvent(const pugl::ExposeEvent& event) noexcept;
+ pugl::Status onEvent(const pugl::KeyPressEvent& event) noexcept;
+ pugl::Status onEvent(const pugl::CloseEvent& event) noexcept;
+
+ bool quit() const { return _quit; }
private:
- double _xAngle{0.0};
- double _yAngle{0.0};
- double _lastDrawTime{0.0};
- bool _quit{false};
+ double _xAngle{0.0};
+ double _yAngle{0.0};
+ double _lastDrawTime{0.0};
+ bool _quit{false};
};
pugl::Status
CubeView::onEvent(const pugl::ConfigureEvent& event) noexcept
{
- reshapeCube(static_cast<float>(event.width),
- static_cast<float>(event.height));
+ reshapeCube(static_cast<float>(event.width),
+ static_cast<float>(event.height));
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
CubeView::onEvent(const pugl::UpdateEvent&) noexcept
{
- return postRedisplay();
+ return postRedisplay();
}
pugl::Status
CubeView::onEvent(const pugl::ExposeEvent&) noexcept
{
- const double thisTime = world().time();
- const double dTime = thisTime - _lastDrawTime;
- const double dAngle = dTime * 100.0;
+ const double thisTime = world().time();
+ const double dTime = thisTime - _lastDrawTime;
+ const double dAngle = dTime * 100.0;
- _xAngle = fmod(_xAngle + dAngle, 360.0);
- _yAngle = fmod(_yAngle + dAngle, 360.0);
- displayCube(cobj(),
- 8.0f,
- static_cast<float>(_xAngle),
- static_cast<float>(_yAngle),
- false);
+ _xAngle = fmod(_xAngle + dAngle, 360.0);
+ _yAngle = fmod(_yAngle + dAngle, 360.0);
+ displayCube(cobj(),
+ 8.0f,
+ static_cast<float>(_xAngle),
+ static_cast<float>(_yAngle),
+ false);
- _lastDrawTime = thisTime;
+ _lastDrawTime = thisTime;
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
CubeView::onEvent(const pugl::KeyPressEvent& event) noexcept
{
- if (event.key == PUGL_KEY_ESCAPE || event.key == 'q') {
- _quit = true;
- }
+ if (event.key == PUGL_KEY_ESCAPE || event.key == 'q') {
+ _quit = true;
+ }
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
CubeView::onEvent(const pugl::CloseEvent&) noexcept
{
- _quit = true;
+ _quit = true;
- return pugl::Status::success;
+ return pugl::Status::success;
}
int
main(int argc, char** argv)
{
- const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
- if (opts.help) {
- puglPrintTestUsage("pugl_cxx_demo", "");
- return 1;
- }
-
- pugl::World world{pugl::WorldType::program};
- CubeView view{world};
- PuglFpsPrinter fpsPrinter{};
-
- world.setClassName("PuglCppTest");
-
- view.setWindowTitle("Pugl C++ Test");
- view.setDefaultSize(512, 512);
- view.setMinSize(64, 64);
- view.setAspectRatio(1, 1, 16, 9);
- view.setBackend(pugl::glBackend());
- view.setHint(pugl::ViewHint::resizable, opts.resizable);
- view.setHint(pugl::ViewHint::samples, opts.samples);
- view.setHint(pugl::ViewHint::doubleBuffer, opts.doubleBuffer);
- view.setHint(pugl::ViewHint::swapInterval, opts.sync);
- view.setHint(pugl::ViewHint::ignoreKeyRepeat, opts.ignoreKeyRepeat);
- view.realize();
- view.show();
-
- unsigned framesDrawn = 0;
- while (!view.quit()) {
- world.update(0.0);
-
- ++framesDrawn;
- puglPrintFps(world.cobj(), &fpsPrinter, &framesDrawn);
- }
-
- return 0;
+ const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
+ if (opts.help) {
+ puglPrintTestUsage("pugl_cxx_demo", "");
+ return 1;
+ }
+
+ pugl::World world{pugl::WorldType::program};
+ CubeView view{world};
+ PuglFpsPrinter fpsPrinter{};
+
+ world.setClassName("PuglCppTest");
+
+ view.setWindowTitle("Pugl C++ Test");
+ view.setDefaultSize(512, 512);
+ view.setMinSize(64, 64);
+ view.setAspectRatio(1, 1, 16, 9);
+ view.setBackend(pugl::glBackend());
+ view.setHint(pugl::ViewHint::resizable, opts.resizable);
+ view.setHint(pugl::ViewHint::samples, opts.samples);
+ view.setHint(pugl::ViewHint::doubleBuffer, opts.doubleBuffer);
+ view.setHint(pugl::ViewHint::swapInterval, opts.sync);
+ view.setHint(pugl::ViewHint::ignoreKeyRepeat, opts.ignoreKeyRepeat);
+ view.realize();
+ view.show();
+
+ unsigned framesDrawn = 0;
+ while (!view.quit()) {
+ world.update(0.0);
+
+ ++framesDrawn;
+ puglPrintFps(world.cobj(), &fpsPrinter, &framesDrawn);
+ }
+
+ return 0;
}
diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c
index 55480f6..0e12ddb 100644
--- a/examples/pugl_embed_demo.c
+++ b/examples/pugl_embed_demo.c
@@ -30,333 +30,325 @@
static const int borderWidth = 64;
static const uintptr_t reverseTimerId = 1u;
-typedef struct
-{
- PuglWorld* world;
- PuglView* parent;
- PuglView* child;
- double xAngle;
- double yAngle;
- double lastMouseX;
- double lastMouseY;
- double lastDrawTime;
- float dist;
- int quit;
- bool continuous;
- bool mouseEntered;
- bool verbose;
- bool reversing;
+typedef struct {
+ PuglWorld* world;
+ PuglView* parent;
+ PuglView* child;
+ double xAngle;
+ double yAngle;
+ double lastMouseX;
+ double lastMouseY;
+ double lastDrawTime;
+ float dist;
+ int quit;
+ bool continuous;
+ bool mouseEntered;
+ bool verbose;
+ bool reversing;
} PuglTestApp;
+// clang-format off
static const float backgroundVertices[] = {
- -1.0f, 1.0f, -1.0f, // Top left
- 1.0f, 1.0f, -1.0f, // Top right
- -1.0f, -1.0f, -1.0f, // Bottom left
- 1.0f, -1.0f, -1.0f, // Bottom right
+ -1.0f, 1.0f, -1.0f, // Top left
+ 1.0f, 1.0f, -1.0f, // Top right
+ -1.0f, -1.0f, -1.0f, // Bottom left
+ 1.0f, -1.0f, -1.0f, // Bottom right
};
+// clang-format on
static PuglRect
getChildFrame(const PuglRect parentFrame)
{
- const PuglRect childFrame = {
- borderWidth,
- borderWidth,
- parentFrame.width - 2 * borderWidth,
- parentFrame.height - 2 * borderWidth
- };
-
- return childFrame;
+ const PuglRect childFrame = {borderWidth,
+ borderWidth,
+ parentFrame.width - 2 * borderWidth,
+ parentFrame.height - 2 * borderWidth};
+
+ return childFrame;
}
static void
onDisplay(PuglView* view)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- const double thisTime = puglGetTime(app->world);
- if (app->continuous) {
- const double dTime = (thisTime - app->lastDrawTime) *
- (app->reversing ? -1.0 : 1.0);
+ const double thisTime = puglGetTime(app->world);
+ if (app->continuous) {
+ const double dTime =
+ (thisTime - app->lastDrawTime) * (app->reversing ? -1.0 : 1.0);
- app->xAngle = fmod(app->xAngle + dTime * 100.0, 360.0);
- app->yAngle = fmod(app->yAngle + dTime * 100.0, 360.0);
- }
+ app->xAngle = fmod(app->xAngle + dTime * 100.0, 360.0);
+ app->yAngle = fmod(app->yAngle + dTime * 100.0, 360.0);
+ }
- displayCube(view,
- app->dist,
- (float)app->xAngle,
- (float)app->yAngle,
- app->mouseEntered);
+ displayCube(
+ view, app->dist, (float)app->xAngle, (float)app->yAngle, app->mouseEntered);
- app->lastDrawTime = thisTime;
+ app->lastDrawTime = thisTime;
}
static void
swapFocus(PuglTestApp* app)
{
- if (puglHasFocus(app->parent)) {
- puglGrabFocus(app->child);
- } else {
- puglGrabFocus(app->parent);
- }
-
- if (!app->continuous) {
- puglPostRedisplay(app->parent);
- puglPostRedisplay(app->child);
- }
+ if (puglHasFocus(app->parent)) {
+ puglGrabFocus(app->child);
+ } else {
+ puglGrabFocus(app->parent);
+ }
+
+ if (!app->continuous) {
+ puglPostRedisplay(app->parent);
+ puglPostRedisplay(app->child);
+ }
}
static void
onKeyPress(PuglView* view, const PuglEventKey* event, const char* prefix)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- PuglRect frame = puglGetFrame(view);
-
- if (event->key == '\t') {
- swapFocus(app);
- } else if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) {
- app->quit = 1;
- } else if (event->state & PUGL_MOD_CTRL && event->key == 'c') {
- puglSetClipboard(view, NULL, "Pugl test", strlen("Pugl test") + 1);
- fprintf(stderr, "%sCopy \"Pugl test\"\n", prefix);
- } else if (event->state & PUGL_MOD_CTRL && event->key == 'v') {
- const char* type = NULL;
- size_t len = 0;
- const char* text = (const char*)puglGetClipboard(view, &type, &len);
- fprintf(stderr, "%sPaste \"%s\"\n", prefix, text);
- } else if (event->state & PUGL_MOD_SHIFT) {
- if (event->key == PUGL_KEY_UP) {
- frame.height += 10;
- } else if (event->key == PUGL_KEY_DOWN) {
- frame.height -= 10;
- } else if (event->key == PUGL_KEY_LEFT) {
- frame.width -= 10;
- } else if (event->key == PUGL_KEY_RIGHT) {
- frame.width += 10;
- } else {
- return;
- }
- puglSetFrame(view, frame);
- } else {
- if (event->key == PUGL_KEY_UP) {
- frame.y -= 10;
- } else if (event->key == PUGL_KEY_DOWN) {
- frame.y += 10;
- } else if (event->key == PUGL_KEY_LEFT) {
- frame.x -= 10;
- } else if (event->key == PUGL_KEY_RIGHT) {
- frame.x += 10;
- } else {
- return;
- }
- puglSetFrame(view, frame);
- }
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+ PuglRect frame = puglGetFrame(view);
+
+ if (event->key == '\t') {
+ swapFocus(app);
+ } else if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) {
+ app->quit = 1;
+ } else if (event->state & PUGL_MOD_CTRL && event->key == 'c') {
+ puglSetClipboard(view, NULL, "Pugl test", strlen("Pugl test") + 1);
+ fprintf(stderr, "%sCopy \"Pugl test\"\n", prefix);
+ } else if (event->state & PUGL_MOD_CTRL && event->key == 'v') {
+ const char* type = NULL;
+ size_t len = 0;
+ const char* text = (const char*)puglGetClipboard(view, &type, &len);
+ fprintf(stderr, "%sPaste \"%s\"\n", prefix, text);
+ } else if (event->state & PUGL_MOD_SHIFT) {
+ if (event->key == PUGL_KEY_UP) {
+ frame.height += 10;
+ } else if (event->key == PUGL_KEY_DOWN) {
+ frame.height -= 10;
+ } else if (event->key == PUGL_KEY_LEFT) {
+ frame.width -= 10;
+ } else if (event->key == PUGL_KEY_RIGHT) {
+ frame.width += 10;
+ } else {
+ return;
+ }
+ puglSetFrame(view, frame);
+ } else {
+ if (event->key == PUGL_KEY_UP) {
+ frame.y -= 10;
+ } else if (event->key == PUGL_KEY_DOWN) {
+ frame.y += 10;
+ } else if (event->key == PUGL_KEY_LEFT) {
+ frame.x -= 10;
+ } else if (event->key == PUGL_KEY_RIGHT) {
+ frame.x += 10;
+ } else {
+ return;
+ }
+ puglSetFrame(view, frame);
+ }
}
static PuglStatus
onParentEvent(PuglView* view, const PuglEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- const PuglRect parentFrame = puglGetFrame(view);
-
- printEvent(event, "Parent: ", app->verbose);
-
- switch (event->type) {
- case PUGL_CONFIGURE:
- reshapeCube((float)event->configure.width,
- (float)event->configure.height);
-
- puglSetFrame(app->child, getChildFrame(parentFrame));
- break;
- case PUGL_UPDATE:
- if (app->continuous) {
- puglPostRedisplay(view);
- }
- break;
- case PUGL_EXPOSE:
- if (puglHasFocus(app->parent)) {
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, backgroundVertices);
- glColorPointer(3, GL_FLOAT, 0, backgroundVertices);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- } else {
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
- break;
- case PUGL_KEY_PRESS:
- onKeyPress(view, &event->key, "Parent: ");
- break;
- case PUGL_MOTION:
- break;
- case PUGL_CLOSE:
- app->quit = 1;
- break;
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+ const PuglRect parentFrame = puglGetFrame(view);
+
+ printEvent(event, "Parent: ", app->verbose);
+
+ switch (event->type) {
+ case PUGL_CONFIGURE:
+ reshapeCube((float)event->configure.width, (float)event->configure.height);
+
+ puglSetFrame(app->child, getChildFrame(parentFrame));
+ break;
+ case PUGL_UPDATE:
+ if (app->continuous) {
+ puglPostRedisplay(view);
+ }
+ break;
+ case PUGL_EXPOSE:
+ if (puglHasFocus(app->parent)) {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, backgroundVertices);
+ glColorPointer(3, GL_FLOAT, 0, backgroundVertices);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ } else {
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ break;
+ case PUGL_KEY_PRESS:
+ onKeyPress(view, &event->key, "Parent: ");
+ break;
+ case PUGL_MOTION:
+ break;
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
-
- printEvent(event, "Child: ", app->verbose);
-
- switch (event->type) {
- case PUGL_CONFIGURE:
- reshapeCube((float)event->configure.width,
- (float)event->configure.height);
- break;
- case PUGL_UPDATE:
- if (app->continuous) {
- puglPostRedisplay(view);
- }
- break;
- case PUGL_EXPOSE:
- onDisplay(view);
- break;
- case PUGL_CLOSE:
- app->quit = 1;
- break;
- case PUGL_KEY_PRESS:
- onKeyPress(view, &event->key, "Child: ");
- break;
- case PUGL_MOTION:
- app->xAngle -= event->motion.x - app->lastMouseX;
- app->yAngle += event->motion.y - app->lastMouseY;
- app->lastMouseX = event->motion.x;
- app->lastMouseY = event->motion.y;
- if (!app->continuous) {
- puglPostRedisplay(view);
- puglPostRedisplay(app->parent);
- }
- break;
- case PUGL_SCROLL:
- app->dist = fmaxf(10.0f, app->dist + (float)event->scroll.dy);
- if (!app->continuous) {
- puglPostRedisplay(view);
- }
- break;
- case PUGL_POINTER_IN:
- app->mouseEntered = true;
- break;
- case PUGL_POINTER_OUT:
- app->mouseEntered = false;
- break;
- case PUGL_TIMER:
- app->reversing = !app->reversing;
- break;
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+
+ printEvent(event, "Child: ", app->verbose);
+
+ switch (event->type) {
+ case PUGL_CONFIGURE:
+ reshapeCube((float)event->configure.width, (float)event->configure.height);
+ break;
+ case PUGL_UPDATE:
+ if (app->continuous) {
+ puglPostRedisplay(view);
+ }
+ break;
+ case PUGL_EXPOSE:
+ onDisplay(view);
+ break;
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ case PUGL_KEY_PRESS:
+ onKeyPress(view, &event->key, "Child: ");
+ break;
+ case PUGL_MOTION:
+ app->xAngle -= event->motion.x - app->lastMouseX;
+ app->yAngle += event->motion.y - app->lastMouseY;
+ app->lastMouseX = event->motion.x;
+ app->lastMouseY = event->motion.y;
+ if (!app->continuous) {
+ puglPostRedisplay(view);
+ puglPostRedisplay(app->parent);
+ }
+ break;
+ case PUGL_SCROLL:
+ app->dist = fmaxf(10.0f, app->dist + (float)event->scroll.dy);
+ if (!app->continuous) {
+ puglPostRedisplay(view);
+ }
+ break;
+ case PUGL_POINTER_IN:
+ app->mouseEntered = true;
+ break;
+ case PUGL_POINTER_OUT:
+ app->mouseEntered = false;
+ break;
+ case PUGL_TIMER:
+ app->reversing = !app->reversing;
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTestApp app = {0};
-
- app.dist = 10;
-
- const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
- if (opts.help) {
- puglPrintTestUsage("pugl_test", "");
- return 1;
- }
-
- app.continuous = opts.continuous;
- app.verbose = opts.verbose;
-
- app.world = puglNewWorld(PUGL_PROGRAM, 0);
- app.parent = puglNewView(app.world);
- app.child = puglNewView(app.world);
-
- puglSetClassName(app.world, "Pugl Test");
-
- const PuglRect parentFrame = { 0, 0, 512, 512 };
- puglSetDefaultSize(app.parent, 512, 512);
- puglSetMinSize(app.parent, borderWidth * 3, borderWidth * 3);
- puglSetMaxSize(app.parent, 1024, 1024);
- puglSetAspectRatio(app.parent, 1, 1, 16, 9);
- puglSetBackend(app.parent, puglGlBackend());
-
- puglSetViewHint(app.parent, PUGL_USE_DEBUG_CONTEXT, opts.errorChecking);
- puglSetViewHint(app.parent, PUGL_RESIZABLE, opts.resizable);
- puglSetViewHint(app.parent, PUGL_SAMPLES, opts.samples);
- puglSetViewHint(app.parent, PUGL_DOUBLE_BUFFER, opts.doubleBuffer);
- puglSetViewHint(app.parent, PUGL_SWAP_INTERVAL, opts.sync);
- puglSetViewHint(app.parent, PUGL_IGNORE_KEY_REPEAT, opts.ignoreKeyRepeat);
- puglSetHandle(app.parent, &app);
- puglSetEventFunc(app.parent, onParentEvent);
-
- PuglStatus st = PUGL_SUCCESS;
- const uint8_t title[] = { 'P', 'u', 'g', 'l', ' ',
- 'P', 'r', 0xC3, 0xBC, 'f', 'u', 'n', 'g', 0 };
-
- puglSetWindowTitle(app.parent, (const char*)title);
-
- if ((st = puglRealize(app.parent))) {
- return logError("Failed to create parent window (%s)\n",
- puglStrerror(st));
- }
-
- puglSetFrame(app.child, getChildFrame(parentFrame));
- puglSetParentWindow(app.child, puglGetNativeWindow(app.parent));
-
- puglSetViewHint(app.child, PUGL_USE_DEBUG_CONTEXT, opts.errorChecking);
- puglSetViewHint(app.child, PUGL_SAMPLES, opts.samples);
- puglSetViewHint(app.child, PUGL_DOUBLE_BUFFER, opts.doubleBuffer);
- puglSetViewHint(app.child, PUGL_SWAP_INTERVAL, opts.sync);
- puglSetBackend(app.child, puglGlBackend());
- puglSetViewHint(app.child, PUGL_IGNORE_KEY_REPEAT, opts.ignoreKeyRepeat);
- puglSetHandle(app.child, &app);
- puglSetEventFunc(app.child, onEvent);
-
- if ((st = puglRealize(app.child))) {
- return logError("Failed to create child window (%s)\n",
- puglStrerror(st));
- }
-
- puglShow(app.parent);
- puglShow(app.child);
-
- puglStartTimer(app.child, reverseTimerId, 3.6);
-
- PuglFpsPrinter fpsPrinter = { puglGetTime(app.world) };
- unsigned framesDrawn = 0;
- bool requestedAttention = false;
- while (!app.quit) {
- const double thisTime = puglGetTime(app.world);
-
- puglUpdate(app.world, app.continuous ? 0.0 : -1.0);
- ++framesDrawn;
-
- if (!requestedAttention && thisTime > 5.0) {
- puglRequestAttention(app.parent);
- requestedAttention = true;
- }
-
- if (app.continuous) {
- puglPrintFps(app.world, &fpsPrinter, &framesDrawn);
- }
- }
-
- puglFreeView(app.child);
- puglFreeView(app.parent);
- puglFreeWorld(app.world);
-
- return 0;
+ PuglTestApp app = {0};
+
+ app.dist = 10;
+
+ const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
+ if (opts.help) {
+ puglPrintTestUsage("pugl_test", "");
+ return 1;
+ }
+
+ app.continuous = opts.continuous;
+ app.verbose = opts.verbose;
+
+ app.world = puglNewWorld(PUGL_PROGRAM, 0);
+ app.parent = puglNewView(app.world);
+ app.child = puglNewView(app.world);
+
+ puglSetClassName(app.world, "Pugl Test");
+
+ const PuglRect parentFrame = {0, 0, 512, 512};
+ puglSetDefaultSize(app.parent, 512, 512);
+ puglSetMinSize(app.parent, borderWidth * 3, borderWidth * 3);
+ puglSetMaxSize(app.parent, 1024, 1024);
+ puglSetAspectRatio(app.parent, 1, 1, 16, 9);
+ puglSetBackend(app.parent, puglGlBackend());
+
+ puglSetViewHint(app.parent, PUGL_USE_DEBUG_CONTEXT, opts.errorChecking);
+ puglSetViewHint(app.parent, PUGL_RESIZABLE, opts.resizable);
+ puglSetViewHint(app.parent, PUGL_SAMPLES, opts.samples);
+ puglSetViewHint(app.parent, PUGL_DOUBLE_BUFFER, opts.doubleBuffer);
+ puglSetViewHint(app.parent, PUGL_SWAP_INTERVAL, opts.sync);
+ puglSetViewHint(app.parent, PUGL_IGNORE_KEY_REPEAT, opts.ignoreKeyRepeat);
+ puglSetHandle(app.parent, &app);
+ puglSetEventFunc(app.parent, onParentEvent);
+
+ PuglStatus st = PUGL_SUCCESS;
+ const uint8_t title[] = {
+ 'P', 'u', 'g', 'l', ' ', 'P', 'r', 0xC3, 0xBC, 'f', 'u', 'n', 'g', 0};
+
+ puglSetWindowTitle(app.parent, (const char*)title);
+
+ if ((st = puglRealize(app.parent))) {
+ return logError("Failed to create parent window (%s)\n", puglStrerror(st));
+ }
+
+ puglSetFrame(app.child, getChildFrame(parentFrame));
+ puglSetParentWindow(app.child, puglGetNativeWindow(app.parent));
+
+ puglSetViewHint(app.child, PUGL_USE_DEBUG_CONTEXT, opts.errorChecking);
+ puglSetViewHint(app.child, PUGL_SAMPLES, opts.samples);
+ puglSetViewHint(app.child, PUGL_DOUBLE_BUFFER, opts.doubleBuffer);
+ puglSetViewHint(app.child, PUGL_SWAP_INTERVAL, opts.sync);
+ puglSetBackend(app.child, puglGlBackend());
+ puglSetViewHint(app.child, PUGL_IGNORE_KEY_REPEAT, opts.ignoreKeyRepeat);
+ puglSetHandle(app.child, &app);
+ puglSetEventFunc(app.child, onEvent);
+
+ if ((st = puglRealize(app.child))) {
+ return logError("Failed to create child window (%s)\n", puglStrerror(st));
+ }
+
+ puglShow(app.parent);
+ puglShow(app.child);
+
+ puglStartTimer(app.child, reverseTimerId, 3.6);
+
+ PuglFpsPrinter fpsPrinter = {puglGetTime(app.world)};
+ unsigned framesDrawn = 0;
+ bool requestedAttention = false;
+ while (!app.quit) {
+ const double thisTime = puglGetTime(app.world);
+
+ puglUpdate(app.world, app.continuous ? 0.0 : -1.0);
+ ++framesDrawn;
+
+ if (!requestedAttention && thisTime > 5.0) {
+ puglRequestAttention(app.parent);
+ requestedAttention = true;
+ }
+
+ if (app.continuous) {
+ puglPrintFps(app.world, &fpsPrinter, &framesDrawn);
+ }
+ }
+
+ puglFreeView(app.child);
+ puglFreeView(app.parent);
+ puglFreeWorld(app.world);
+
+ return 0;
}
diff --git a/examples/pugl_print_events.c b/examples/pugl_print_events.c
index 8f8874b..dfa217e 100644
--- a/examples/pugl_print_events.c
+++ b/examples/pugl_print_events.c
@@ -22,56 +22,58 @@
#include <stdbool.h>
#include <stdio.h>
-typedef struct
-{
- PuglWorld* world;
- PuglView* view;
- int quit;
+typedef struct {
+ PuglWorld* world;
+ PuglView* view;
+ int quit;
} PuglPrintEventsApp;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglPrintEventsApp* app = (PuglPrintEventsApp*)puglGetHandle(view);
+ PuglPrintEventsApp* app = (PuglPrintEventsApp*)puglGetHandle(view);
- printEvent(event, "Event: ", true);
+ printEvent(event, "Event: ", true);
- switch (event->type) {
- case PUGL_CLOSE: app->quit = 1; break;
- default: break;
- }
+ switch (event->type) {
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ default:
+ break;
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
int
main(void)
{
- PuglPrintEventsApp app = {NULL, NULL, 0};
+ PuglPrintEventsApp app = {NULL, NULL, 0};
- app.world = puglNewWorld(PUGL_PROGRAM, 0);
- app.view = puglNewView(app.world);
+ app.world = puglNewWorld(PUGL_PROGRAM, 0);
+ app.view = puglNewView(app.world);
- puglSetClassName(app.world, "Pugl Print Events");
- puglSetWindowTitle(app.view, "Pugl Event Printer");
- puglSetDefaultSize(app.view, 512, 512);
- puglSetBackend(app.view, puglStubBackend());
- puglSetHandle(app.view, &app);
- puglSetEventFunc(app.view, onEvent);
+ puglSetClassName(app.world, "Pugl Print Events");
+ puglSetWindowTitle(app.view, "Pugl Event Printer");
+ puglSetDefaultSize(app.view, 512, 512);
+ puglSetBackend(app.view, puglStubBackend());
+ puglSetHandle(app.view, &app);
+ puglSetEventFunc(app.view, onEvent);
- PuglStatus st = puglRealize(app.view);
- if (st) {
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
+ PuglStatus st = puglRealize(app.view);
+ if (st) {
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
- puglShow(app.view);
+ puglShow(app.view);
- while (!app.quit) {
- puglUpdate(app.world, -1.0);
- }
+ while (!app.quit) {
+ puglUpdate(app.world, -1.0);
+ }
- puglFreeView(app.view);
- puglFreeWorld(app.world);
+ puglFreeView(app.view);
+ puglFreeWorld(app.world);
- return 0;
+ return 0;
}
diff --git a/examples/pugl_shader_demo.c b/examples/pugl_shader_demo.c
index 8ebbe60..d038b3f 100644
--- a/examples/pugl_shader_demo.c
+++ b/examples/pugl_shader_demo.c
@@ -56,30 +56,28 @@ static const int defaultWidth = 512;
static const int defaultHeight = 512;
static const uintptr_t resizeTimerId = 1u;
-typedef struct
-{
- mat4 projection;
+typedef struct {
+ mat4 projection;
} RectUniforms;
-typedef struct
-{
- const char* programPath;
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
- size_t numRects;
- Rect* rects;
- Program drawRect;
- GLuint vao;
- GLuint vbo;
- GLuint instanceVbo;
- GLuint ibo;
- double lastDrawDuration;
- double lastFrameEndTime;
- unsigned framesDrawn;
- int glMajorVersion;
- int glMinorVersion;
- int quit;
+typedef struct {
+ const char* programPath;
+ PuglWorld* world;
+ PuglView* view;
+ PuglTestOptions opts;
+ size_t numRects;
+ Rect* rects;
+ Program drawRect;
+ GLuint vao;
+ GLuint vbo;
+ GLuint instanceVbo;
+ GLuint ibo;
+ double lastDrawDuration;
+ double lastFrameEndTime;
+ unsigned framesDrawn;
+ int glMajorVersion;
+ int glMinorVersion;
+ int quit;
} PuglTestApp;
static PuglStatus
@@ -91,393 +89,379 @@ teardownGl(PuglTestApp* app);
static void
onConfigure(PuglView* view, double width, double height)
{
- (void)view;
+ (void)view;
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glViewport(0, 0, (int)width, (int)height);
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glViewport(0, 0, (int)width, (int)height);
}
static void
onExpose(PuglView* view)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
- const PuglRect frame = puglGetFrame(view);
- const float width = (float)frame.width;
- const float height = (float)frame.height;
- const double time = puglGetTime(puglGetWorld(view));
-
- // Construct projection matrix for 2D window surface (in pixels)
- mat4 proj;
- mat4Ortho(proj,
- 0.0f,
- (float)frame.width,
- 0.0f,
- (float)frame.height,
- -1.0f,
- 1.0f);
-
- // Clear and bind everything that is the same for every rect
- glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(app->drawRect.program);
- glBindVertexArray(app->vao);
-
- for (size_t i = 0; i < app->numRects; ++i) {
- moveRect(&app->rects[i], i, app->numRects, width, height, time);
- }
-
- glBufferData(GL_UNIFORM_BUFFER, sizeof(proj), &proj, GL_STREAM_DRAW);
-
- glBufferSubData(GL_ARRAY_BUFFER,
- 0,
- (GLsizeiptr)(app->numRects * sizeof(Rect)),
- app->rects);
-
- glDrawElementsInstanced(GL_TRIANGLE_STRIP,
- 4,
- GL_UNSIGNED_INT,
- NULL,
- (GLsizei)(app->numRects * 4));
-
- ++app->framesDrawn;
-
- app->lastFrameEndTime = puglGetTime(puglGetWorld(view));
- app->lastDrawDuration = app->lastFrameEndTime - time;
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+ const PuglRect frame = puglGetFrame(view);
+ const float width = (float)frame.width;
+ const float height = (float)frame.height;
+ const double time = puglGetTime(puglGetWorld(view));
+
+ // Construct projection matrix for 2D window surface (in pixels)
+ mat4 proj;
+ mat4Ortho(
+ proj, 0.0f, (float)frame.width, 0.0f, (float)frame.height, -1.0f, 1.0f);
+
+ // Clear and bind everything that is the same for every rect
+ glClear(GL_COLOR_BUFFER_BIT);
+ glUseProgram(app->drawRect.program);
+ glBindVertexArray(app->vao);
+
+ for (size_t i = 0; i < app->numRects; ++i) {
+ moveRect(&app->rects[i], i, app->numRects, width, height, time);
+ }
+
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(proj), &proj, GL_STREAM_DRAW);
+
+ glBufferSubData(
+ GL_ARRAY_BUFFER, 0, (GLsizeiptr)(app->numRects * sizeof(Rect)), app->rects);
+
+ glDrawElementsInstanced(
+ GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, NULL, (GLsizei)(app->numRects * 4));
+
+ ++app->framesDrawn;
+
+ app->lastFrameEndTime = puglGetTime(puglGetWorld(view));
+ app->lastDrawDuration = app->lastFrameEndTime - time;
}
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
-
- printEvent(event, "Event: ", app->opts.verbose);
-
- switch (event->type) {
- case PUGL_CREATE:
- setupGl(app);
- break;
- case PUGL_DESTROY:
- teardownGl(app);
- break;
- case PUGL_CONFIGURE:
- onConfigure(view, event->configure.width, event->configure.height);
- break;
- case PUGL_UPDATE:
- puglPostRedisplay(view);
- break;
- case PUGL_EXPOSE: onExpose(view); break;
- case PUGL_CLOSE: app->quit = 1; break;
- case PUGL_LOOP_ENTER:
- puglStartTimer(view,
- resizeTimerId,
- 1.0 / (double)puglGetViewHint(view, PUGL_REFRESH_RATE));
- break;
- case PUGL_LOOP_LEAVE:
- puglStopTimer(view, resizeTimerId);
- break;
- case PUGL_KEY_PRESS:
- if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
- app->quit = 1;
- }
- break;
- case PUGL_TIMER:
- if (event->timer.id == resizeTimerId) {
- puglPostRedisplay(view);
- }
- break;
- default: break;
- }
-
- return PUGL_SUCCESS;
+ PuglTestApp* app = (PuglTestApp*)puglGetHandle(view);
+
+ printEvent(event, "Event: ", app->opts.verbose);
+
+ switch (event->type) {
+ case PUGL_CREATE:
+ setupGl(app);
+ break;
+ case PUGL_DESTROY:
+ teardownGl(app);
+ break;
+ case PUGL_CONFIGURE:
+ onConfigure(view, event->configure.width, event->configure.height);
+ break;
+ case PUGL_UPDATE:
+ puglPostRedisplay(view);
+ break;
+ case PUGL_EXPOSE:
+ onExpose(view);
+ break;
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ case PUGL_LOOP_ENTER:
+ puglStartTimer(view,
+ resizeTimerId,
+ 1.0 / (double)puglGetViewHint(view, PUGL_REFRESH_RATE));
+ break;
+ case PUGL_LOOP_LEAVE:
+ puglStopTimer(view, resizeTimerId);
+ break;
+ case PUGL_KEY_PRESS:
+ if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) {
+ app->quit = 1;
+ }
+ break;
+ case PUGL_TIMER:
+ if (event->timer.id == resizeTimerId) {
+ puglPostRedisplay(view);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
static Rect*
makeRects(const size_t numRects)
{
- Rect* rects = (Rect*)calloc(numRects, sizeof(Rect));
- for (size_t i = 0; i < numRects; ++i) {
- rects[i] = makeRect(i, (float)defaultWidth);
- }
+ Rect* rects = (Rect*)calloc(numRects, sizeof(Rect));
+ for (size_t i = 0; i < numRects; ++i) {
+ rects[i] = makeRect(i, (float)defaultWidth);
+ }
- return rects;
+ return rects;
}
static char*
loadShader(const char* const programPath, const char* const name)
{
- char* const path = resourcePath(programPath, name);
- fprintf(stderr, "Loading shader %s\n", path);
+ char* const path = resourcePath(programPath, name);
+ fprintf(stderr, "Loading shader %s\n", path);
- FILE* const file = fopen(path, "r");
- if (!file) {
- logError("Failed to open '%s'\n", path);
- return NULL;
- }
+ FILE* const file = fopen(path, "r");
+ if (!file) {
+ logError("Failed to open '%s'\n", path);
+ return NULL;
+ }
- free(path);
- fseek(file, 0, SEEK_END);
- const size_t fileSize = (size_t)ftell(file);
+ free(path);
+ fseek(file, 0, SEEK_END);
+ const size_t fileSize = (size_t)ftell(file);
- fseek(file, 0, SEEK_SET);
- char* source = (char*)calloc(1, fileSize + 1u);
+ fseek(file, 0, SEEK_SET);
+ char* source = (char*)calloc(1, fileSize + 1u);
- fread(source, 1, fileSize, file);
- fclose(file);
+ fread(source, 1, fileSize, file);
+ fclose(file);
- return source;
+ return source;
}
static int
parseOptions(PuglTestApp* app, int argc, char** argv)
{
- char* endptr = NULL;
-
- // Parse command line options
- app->numRects = 1024;
- app->opts = puglParseTestOptions(&argc, &argv);
- if (app->opts.help) {
- return 1;
- }
-
- // Parse number of rectangles argument, if given
- if (argc >= 1) {
- app->numRects = (size_t)strtol(argv[0], &endptr, 10);
- if (endptr != argv[0] + strlen(argv[0])) {
- logError("Invalid number of rectangles: %s\n", argv[0]);
- return 1;
- }
- }
-
- // Parse OpenGL major version argument, if given
- if (argc >= 2) {
- app->glMajorVersion = (int)strtol(argv[1], &endptr, 10);
- if (endptr != argv[1] + strlen(argv[1])) {
- logError("Invalid GL major version: %s\n", argv[1]);
- return 1;
- } else if (app->glMajorVersion == 4) {
- app->glMinorVersion = 2;
- } else if (app->glMajorVersion != 3) {
- logError("Unsupported GL major version %d\n", app->glMajorVersion);
- return 1;
- }
- }
-
- return 0;
+ char* endptr = NULL;
+
+ // Parse command line options
+ app->numRects = 1024;
+ app->opts = puglParseTestOptions(&argc, &argv);
+ if (app->opts.help) {
+ return 1;
+ }
+
+ // Parse number of rectangles argument, if given
+ if (argc >= 1) {
+ app->numRects = (size_t)strtol(argv[0], &endptr, 10);
+ if (endptr != argv[0] + strlen(argv[0])) {
+ logError("Invalid number of rectangles: %s\n", argv[0]);
+ return 1;
+ }
+ }
+
+ // Parse OpenGL major version argument, if given
+ if (argc >= 2) {
+ app->glMajorVersion = (int)strtol(argv[1], &endptr, 10);
+ if (endptr != argv[1] + strlen(argv[1])) {
+ logError("Invalid GL major version: %s\n", argv[1]);
+ return 1;
+ } else if (app->glMajorVersion == 4) {
+ app->glMinorVersion = 2;
+ } else if (app->glMajorVersion != 3) {
+ logError("Unsupported GL major version %d\n", app->glMajorVersion);
+ return 1;
+ }
+ }
+
+ return 0;
}
static void
setupPugl(PuglTestApp* app)
{
- // Create world, view, and rect data
- app->world = puglNewWorld(PUGL_PROGRAM, 0);
- app->view = puglNewView(app->world);
- app->rects = makeRects(app->numRects);
-
- // Set up world and view
- puglSetClassName(app->world, "PuglGL3Demo");
- puglSetWindowTitle(app->view, "Pugl OpenGL 3");
- puglSetDefaultSize(app->view, defaultWidth, defaultHeight);
- puglSetMinSize(app->view, defaultWidth / 4, defaultHeight / 4);
- puglSetAspectRatio(app->view, 1, 1, 16, 9);
- puglSetBackend(app->view, puglGlBackend());
- puglSetViewHint(app->view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE);
- puglSetViewHint(app->view, PUGL_USE_DEBUG_CONTEXT, app->opts.errorChecking);
- puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MAJOR, app->glMajorVersion);
- puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MINOR, app->glMinorVersion);
- puglSetViewHint(app->view, PUGL_RESIZABLE, app->opts.resizable);
- puglSetViewHint(app->view, PUGL_SAMPLES, app->opts.samples);
- puglSetViewHint(app->view, PUGL_DOUBLE_BUFFER, app->opts.doubleBuffer);
- puglSetViewHint(app->view, PUGL_SWAP_INTERVAL, app->opts.sync);
- puglSetViewHint(app->view, PUGL_IGNORE_KEY_REPEAT, PUGL_TRUE);
- puglSetHandle(app->view, app);
- puglSetEventFunc(app->view, onEvent);
+ // Create world, view, and rect data
+ app->world = puglNewWorld(PUGL_PROGRAM, 0);
+ app->view = puglNewView(app->world);
+ app->rects = makeRects(app->numRects);
+
+ // Set up world and view
+ puglSetClassName(app->world, "PuglGL3Demo");
+ puglSetWindowTitle(app->view, "Pugl OpenGL 3");
+ puglSetDefaultSize(app->view, defaultWidth, defaultHeight);
+ puglSetMinSize(app->view, defaultWidth / 4, defaultHeight / 4);
+ puglSetAspectRatio(app->view, 1, 1, 16, 9);
+ puglSetBackend(app->view, puglGlBackend());
+ puglSetViewHint(app->view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE);
+ puglSetViewHint(app->view, PUGL_USE_DEBUG_CONTEXT, app->opts.errorChecking);
+ puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MAJOR, app->glMajorVersion);
+ puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MINOR, app->glMinorVersion);
+ puglSetViewHint(app->view, PUGL_RESIZABLE, app->opts.resizable);
+ puglSetViewHint(app->view, PUGL_SAMPLES, app->opts.samples);
+ puglSetViewHint(app->view, PUGL_DOUBLE_BUFFER, app->opts.doubleBuffer);
+ puglSetViewHint(app->view, PUGL_SWAP_INTERVAL, app->opts.sync);
+ puglSetViewHint(app->view, PUGL_IGNORE_KEY_REPEAT, PUGL_TRUE);
+ puglSetHandle(app->view, app);
+ puglSetEventFunc(app->view, onEvent);
}
static PuglStatus
setupGl(PuglTestApp* app)
{
- // Load GL functions via GLAD
- if (!gladLoadGLLoader((GLADloadproc)&puglGetProcAddress)) {
- logError("Failed to load GL\n");
- return PUGL_FAILURE;
- }
-
- const char* const headerFile = (app->glMajorVersion == 3
- ? "shaders/header_330.glsl"
- : "shaders/header_420.glsl");
-
- // Load shader sources
- char* const headerSource = loadShader(app->programPath, headerFile);
-
- char* const vertexSource = loadShader(app->programPath,
- "shaders/rect.vert");
-
- char* const fragmentSource = loadShader(app->programPath,
- "shaders/rect.frag");
-
- if (!vertexSource || !fragmentSource) {
- logError("Failed to load shader sources\n");
- return PUGL_FAILURE;
- }
-
- // Compile rectangle shaders and program
- app->drawRect = compileProgram(headerSource, vertexSource, fragmentSource);
- free(fragmentSource);
- free(vertexSource);
- free(headerSource);
- if (!app->drawRect.program) {
- return PUGL_FAILURE;
- }
-
- // Get location of rectangle shader uniform block
- const GLuint globalsIndex = glGetUniformBlockIndex(app->drawRect.program,
- "UniformBufferObject");
-
- // Generate/bind a uniform buffer for setting rectangle properties
- GLuint uboHandle = 0;
- glGenBuffers(1, &uboHandle);
- glBindBuffer(GL_UNIFORM_BUFFER, uboHandle);
- glBindBufferBase(GL_UNIFORM_BUFFER, globalsIndex, uboHandle);
-
- // Generate/bind a VAO to track state
- glGenVertexArrays(1, &app->vao);
- glBindVertexArray(app->vao);
-
- // Generate/bind a VBO to store vertex position data
- glGenBuffers(1, &app->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, app->vbo);
- glBufferData(GL_ARRAY_BUFFER,
- sizeof(rectVertices),
- rectVertices,
- GL_STATIC_DRAW);
-
- // Attribute 0 is position, 2 floats from the VBO
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
-
- // Generate/bind a VBO to store instance attribute data
- glGenBuffers(1, &app->instanceVbo);
- glBindBuffer(GL_ARRAY_BUFFER, app->instanceVbo);
- glBufferData(GL_ARRAY_BUFFER,
- (GLsizeiptr)(app->numRects * sizeof(Rect)),
- app->rects,
- GL_STREAM_DRAW);
-
- // Attribute 1 is Rect::position
- glEnableVertexAttribArray(1);
- glVertexAttribDivisor(1, 4);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Rect), NULL);
-
- // Attribute 2 is Rect::size
- glEnableVertexAttribArray(2);
- glVertexAttribDivisor(2, 4);
- glVertexAttribPointer(2,
- 2,
- GL_FLOAT,
- GL_FALSE,
- sizeof(Rect),
- (const void*)offsetof(Rect, size));
-
- // Attribute 3 is Rect::fillColor
- glEnableVertexAttribArray(3);
- glVertexAttribDivisor(3, 4);
- glVertexAttribPointer(3,
- 4,
- GL_FLOAT,
- GL_FALSE,
- sizeof(Rect),
- (const void*)offsetof(Rect, fillColor));
-
- // Set up the IBO to index into the VBO
- glGenBuffers(1, &app->ibo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, app->ibo);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
- sizeof(rectIndices),
- rectIndices,
- GL_STATIC_DRAW);
-
- return PUGL_SUCCESS;
+ // Load GL functions via GLAD
+ if (!gladLoadGLLoader((GLADloadproc)&puglGetProcAddress)) {
+ logError("Failed to load GL\n");
+ return PUGL_FAILURE;
+ }
+
+ const char* const headerFile =
+ (app->glMajorVersion == 3 ? "shaders/header_330.glsl"
+ : "shaders/header_420.glsl");
+
+ // Load shader sources
+ char* const headerSource = loadShader(app->programPath, headerFile);
+
+ char* const vertexSource = loadShader(app->programPath, "shaders/rect.vert");
+
+ char* const fragmentSource =
+ loadShader(app->programPath, "shaders/rect.frag");
+
+ if (!vertexSource || !fragmentSource) {
+ logError("Failed to load shader sources\n");
+ return PUGL_FAILURE;
+ }
+
+ // Compile rectangle shaders and program
+ app->drawRect = compileProgram(headerSource, vertexSource, fragmentSource);
+ free(fragmentSource);
+ free(vertexSource);
+ free(headerSource);
+ if (!app->drawRect.program) {
+ return PUGL_FAILURE;
+ }
+
+ // Get location of rectangle shader uniform block
+ const GLuint globalsIndex =
+ glGetUniformBlockIndex(app->drawRect.program, "UniformBufferObject");
+
+ // Generate/bind a uniform buffer for setting rectangle properties
+ GLuint uboHandle = 0;
+ glGenBuffers(1, &uboHandle);
+ glBindBuffer(GL_UNIFORM_BUFFER, uboHandle);
+ glBindBufferBase(GL_UNIFORM_BUFFER, globalsIndex, uboHandle);
+
+ // Generate/bind a VAO to track state
+ glGenVertexArrays(1, &app->vao);
+ glBindVertexArray(app->vao);
+
+ // Generate/bind a VBO to store vertex position data
+ glGenBuffers(1, &app->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, app->vbo);
+ glBufferData(
+ GL_ARRAY_BUFFER, sizeof(rectVertices), rectVertices, GL_STATIC_DRAW);
+
+ // Attribute 0 is position, 2 floats from the VBO
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
+
+ // Generate/bind a VBO to store instance attribute data
+ glGenBuffers(1, &app->instanceVbo);
+ glBindBuffer(GL_ARRAY_BUFFER, app->instanceVbo);
+ glBufferData(GL_ARRAY_BUFFER,
+ (GLsizeiptr)(app->numRects * sizeof(Rect)),
+ app->rects,
+ GL_STREAM_DRAW);
+
+ // Attribute 1 is Rect::position
+ glEnableVertexAttribArray(1);
+ glVertexAttribDivisor(1, 4);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Rect), NULL);
+
+ // Attribute 2 is Rect::size
+ glEnableVertexAttribArray(2);
+ glVertexAttribDivisor(2, 4);
+ glVertexAttribPointer(
+ 2, 2, GL_FLOAT, GL_FALSE, sizeof(Rect), (const void*)offsetof(Rect, size));
+
+ // Attribute 3 is Rect::fillColor
+ glEnableVertexAttribArray(3);
+ glVertexAttribDivisor(3, 4);
+ glVertexAttribPointer(3,
+ 4,
+ GL_FLOAT,
+ GL_FALSE,
+ sizeof(Rect),
+ (const void*)offsetof(Rect, fillColor));
+
+ // Set up the IBO to index into the VBO
+ glGenBuffers(1, &app->ibo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, app->ibo);
+ glBufferData(
+ GL_ELEMENT_ARRAY_BUFFER, sizeof(rectIndices), rectIndices, GL_STATIC_DRAW);
+
+ return PUGL_SUCCESS;
}
static void
teardownGl(PuglTestApp* app)
{
- glDeleteBuffers(1, &app->ibo);
- glDeleteBuffers(1, &app->vbo);
- glDeleteBuffers(1, &app->instanceVbo);
- glDeleteVertexArrays(1, &app->vao);
- deleteProgram(app->drawRect);
+ glDeleteBuffers(1, &app->ibo);
+ glDeleteBuffers(1, &app->vbo);
+ glDeleteBuffers(1, &app->instanceVbo);
+ glDeleteVertexArrays(1, &app->vao);
+ deleteProgram(app->drawRect);
}
int
main(int argc, char** argv)
{
- PuglTestApp app = {0};
-
- app.programPath = argv[0];
- app.glMajorVersion = 3;
- app.glMinorVersion = 3;
-
- // Parse command line options
- if (parseOptions(&app, argc, argv)) {
- puglPrintTestUsage("pugl_shader_demo", "[NUM_RECTS] [GL_MAJOR]");
- return 1;
- }
-
- // Create and configure world and view
- setupPugl(&app);
-
- // Create window (which will send a PUGL_CREATE event)
- const PuglStatus st = puglRealize(app.view);
- if (st) {
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
-
- // Show window
- printViewHints(app.view);
- puglShow(app.view);
-
- // Calculate ideal frame duration to drive the main loop at a good rate
- const int refreshRate = puglGetViewHint(app.view, PUGL_REFRESH_RATE);
- const double frameDuration = 1.0 / (double)refreshRate;
-
- // Grind away, drawing continuously
- const double startTime = puglGetTime(app.world);
- PuglFpsPrinter fpsPrinter = {startTime};
- while (!app.quit) {
- /* To minimize input latency and get smooth performance during window
- resizing, we want to poll for events as long as possible before
- starting to draw the next frame. This ensures that as many events
- are consumed as possible before starting to draw, or, equivalently,
- that the next rendered frame represents the latest events possible.
- This is particularly important for mouse input and "live" window
- resizing, where many events tend to pile up within a frame.
-
- To do this, we keep track of the time when the last frame was
- finished drawing, and how long it took to expose (and assume this is
- relatively stable). Then, we can calculate how much time there is
- from now until the time when we should start drawing to not miss the
- deadline, and use that as the timeout for puglUpdate().
- */
-
- const double now = puglGetTime(app.world);
- const double nextFrameEndTime = app.lastFrameEndTime + frameDuration;
- const double nextExposeTime = nextFrameEndTime - app.lastDrawDuration;
- const double timeUntilNext = nextExposeTime - now;
- const double timeout = app.opts.sync ? timeUntilNext : 0.0;
-
- puglUpdate(app.world, fmax(0.0, timeout));
- puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
- }
-
- // Destroy window (which will send a PUGL_DESTROY event)
- puglFreeView(app.view);
-
- // Free everything else
- puglFreeWorld(app.world);
- free(app.rects);
-
- return 0;
+ PuglTestApp app = {0};
+
+ app.programPath = argv[0];
+ app.glMajorVersion = 3;
+ app.glMinorVersion = 3;
+
+ // Parse command line options
+ if (parseOptions(&app, argc, argv)) {
+ puglPrintTestUsage("pugl_shader_demo", "[NUM_RECTS] [GL_MAJOR]");
+ return 1;
+ }
+
+ // Create and configure world and view
+ setupPugl(&app);
+
+ // Create window (which will send a PUGL_CREATE event)
+ const PuglStatus st = puglRealize(app.view);
+ if (st) {
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
+
+ // Show window
+ printViewHints(app.view);
+ puglShow(app.view);
+
+ // Calculate ideal frame duration to drive the main loop at a good rate
+ const int refreshRate = puglGetViewHint(app.view, PUGL_REFRESH_RATE);
+ const double frameDuration = 1.0 / (double)refreshRate;
+
+ // Grind away, drawing continuously
+ const double startTime = puglGetTime(app.world);
+ PuglFpsPrinter fpsPrinter = {startTime};
+ while (!app.quit) {
+ /* To minimize input latency and get smooth performance during window
+ resizing, we want to poll for events as long as possible before
+ starting to draw the next frame. This ensures that as many events
+ are consumed as possible before starting to draw, or, equivalently,
+ that the next rendered frame represents the latest events possible.
+ This is particularly important for mouse input and "live" window
+ resizing, where many events tend to pile up within a frame.
+
+ To do this, we keep track of the time when the last frame was
+ finished drawing, and how long it took to expose (and assume this is
+ relatively stable). Then, we can calculate how much time there is
+ from now until the time when we should start drawing to not miss the
+ deadline, and use that as the timeout for puglUpdate().
+ */
+
+ const double now = puglGetTime(app.world);
+ const double nextFrameEndTime = app.lastFrameEndTime + frameDuration;
+ const double nextExposeTime = nextFrameEndTime - app.lastDrawDuration;
+ const double timeUntilNext = nextExposeTime - now;
+ const double timeout = app.opts.sync ? timeUntilNext : 0.0;
+
+ puglUpdate(app.world, fmax(0.0, timeout));
+ puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
+ }
+
+ // Destroy window (which will send a PUGL_DESTROY event)
+ puglFreeView(app.view);
+
+ // Free everything else
+ puglFreeWorld(app.world);
+ free(app.rects);
+
+ return 0;
}
diff --git a/examples/pugl_vulkan_cxx_demo.cpp b/examples/pugl_vulkan_cxx_demo.cpp
index 21fd4df..3dab5ce 100644
--- a/examples/pugl_vulkan_cxx_demo.cpp
+++ b/examples/pugl_vulkan_cxx_demo.cpp
@@ -61,152 +61,154 @@ namespace {
constexpr uintptr_t resizeTimerId = 1u;
struct PhysicalDeviceSelection {
- sk::PhysicalDevice physicalDevice;
- uint32_t graphicsFamilyIndex;
+ sk::PhysicalDevice physicalDevice;
+ uint32_t graphicsFamilyIndex;
};
/// Basic Vulkan context associated with the window
struct VulkanContext {
- VkResult init(pugl::VulkanLoader& loader, const PuglTestOptions& opts);
+ VkResult init(pugl::VulkanLoader& loader, const PuglTestOptions& opts);
- sk::VulkanApi vk;
- sk::Instance instance;
- sk::DebugReportCallbackEXT debugCallback;
+ sk::VulkanApi vk;
+ sk::Instance instance;
+ sk::DebugReportCallbackEXT debugCallback;
};
/// Basic setup of graphics device
struct GraphicsDevice {
- VkResult init(const pugl::VulkanLoader& loader,
- const VulkanContext& context,
- pugl::View& view,
- const PuglTestOptions& opts);
-
- sk::SurfaceKHR surface;
- sk::PhysicalDevice physicalDevice{};
- uint32_t graphicsIndex{};
- VkSurfaceFormatKHR surfaceFormat{};
- VkPresentModeKHR presentMode{};
- VkPresentModeKHR resizePresentMode{};
- sk::Device device{};
- sk::Queue graphicsQueue{};
- sk::CommandPool commandPool{};
+ VkResult init(const pugl::VulkanLoader& loader,
+ const VulkanContext& context,
+ pugl::View& view,
+ const PuglTestOptions& opts);
+
+ sk::SurfaceKHR surface;
+ sk::PhysicalDevice physicalDevice{};
+ uint32_t graphicsIndex{};
+ VkSurfaceFormatKHR surfaceFormat{};
+ VkPresentModeKHR presentMode{};
+ VkPresentModeKHR resizePresentMode{};
+ sk::Device device{};
+ sk::Queue graphicsQueue{};
+ sk::CommandPool commandPool{};
};
/// Buffer allocated on the GPU
struct Buffer {
- VkResult init(const sk::VulkanApi& vk,
- const GraphicsDevice& gpu,
- VkDeviceSize size,
- VkBufferUsageFlags usage,
- VkMemoryPropertyFlags properties);
-
- sk::Buffer buffer;
- sk::DeviceMemory deviceMemory;
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ VkDeviceSize size,
+ VkBufferUsageFlags usage,
+ VkMemoryPropertyFlags properties);
+
+ sk::Buffer buffer;
+ sk::DeviceMemory deviceMemory;
};
/// A set of frames that can be rendered concurrently
struct Swapchain {
- VkResult init(const sk::VulkanApi& vk,
- const GraphicsDevice& gpu,
- VkSurfaceCapabilitiesKHR capabilities,
- VkExtent2D extent,
- VkSwapchainKHR oldSwapchain,
- bool resizing);
-
- VkSurfaceCapabilitiesKHR capabilities{};
- VkExtent2D extent{};
- sk::SwapchainKHR swapchain{};
- std::vector<sk::ImageView> imageViews{};
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ VkSurfaceCapabilitiesKHR capabilities,
+ VkExtent2D extent,
+ VkSwapchainKHR oldSwapchain,
+ bool resizing);
+
+ VkSurfaceCapabilitiesKHR capabilities{};
+ VkExtent2D extent{};
+ sk::SwapchainKHR swapchain{};
+ std::vector<sk::ImageView> imageViews{};
};
/// A pass that renders to a target
struct RenderPass {
- VkResult init(const sk::VulkanApi& vk,
- const GraphicsDevice& gpu,
- const Swapchain& swapchain);
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ const Swapchain& swapchain);
- sk::RenderPass renderPass;
- std::vector<sk::Framebuffer> framebuffers;
- sk::CommandBuffers<std::vector<VkCommandBuffer>> commandBuffers;
+ sk::RenderPass renderPass;
+ std::vector<sk::Framebuffer> framebuffers;
+ sk::CommandBuffers<std::vector<VkCommandBuffer>> commandBuffers;
};
/// Uniform buffer for constant data used in shaders
struct UniformBufferObject {
- mat4 projection;
+ mat4 projection;
};
/// Rectangle data that does not depend on renderer configuration
struct RectData {
- VkResult
- init(const sk::VulkanApi& vk, const GraphicsDevice& gpu, size_t nRects);
-
- sk::DescriptorSetLayout descriptorSetLayout{};
- Buffer uniformBuffer{};
- sk::MappedMemory uniformData{};
- Buffer modelBuffer{};
- Buffer instanceBuffer{};
- sk::MappedMemory vertexData{};
- size_t numRects{};
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ size_t nRects);
+
+ sk::DescriptorSetLayout descriptorSetLayout{};
+ Buffer uniformBuffer{};
+ sk::MappedMemory uniformData{};
+ Buffer modelBuffer{};
+ Buffer instanceBuffer{};
+ sk::MappedMemory vertexData{};
+ size_t numRects{};
};
/// Shader modules for drawing rectangles
struct RectShaders {
- VkResult init(const sk::VulkanApi& vk,
- const GraphicsDevice& gpu,
- const std::string& programPath);
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ const std::string& programPath);
- sk::ShaderModule vert{};
- sk::ShaderModule frag{};
+ sk::ShaderModule vert{};
+ sk::ShaderModule frag{};
};
/// A pipeline to render rectangles with our shaders
struct RectPipeline {
- VkResult init(const sk::VulkanApi& vk,
- const GraphicsDevice& gpu,
- const RectData& rectData,
- const RectShaders& shaders,
- const Swapchain& swapchain,
- const RenderPass& renderPass);
-
- sk::DescriptorPool descriptorPool{};
- sk::DescriptorSets<std::vector<VkDescriptorSet>> descriptorSets{};
- sk::PipelineLayout pipelineLayout{};
- std::array<sk::Pipeline, 1> pipelines{};
- uint32_t numImages{};
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ const RectData& rectData,
+ const RectShaders& shaders,
+ const Swapchain& swapchain,
+ const RenderPass& renderPass);
+
+ sk::DescriptorPool descriptorPool{};
+ sk::DescriptorSets<std::vector<VkDescriptorSet>> descriptorSets{};
+ sk::PipelineLayout pipelineLayout{};
+ std::array<sk::Pipeline, 1> pipelines{};
+ uint32_t numImages{};
};
/// Synchronization primitives used to coordinate drawing frames
struct RenderSync {
- VkResult
- init(const sk::VulkanApi& vk, const sk::Device& device, uint32_t numImages);
-
- std::vector<sk::Semaphore> imageAvailable{};
- std::vector<sk::Semaphore> renderFinished{};
- std::vector<sk::Fence> inFlight{};
- size_t currentFrame{};
+ VkResult init(const sk::VulkanApi& vk,
+ const sk::Device& device,
+ uint32_t numImages);
+
+ std::vector<sk::Semaphore> imageAvailable{};
+ std::vector<sk::Semaphore> renderFinished{};
+ std::vector<sk::Fence> inFlight{};
+ size_t currentFrame{};
};
/// Renderer that owns the above and everything required to draw
struct Renderer {
- VkResult init(const sk::VulkanApi& vk,
- const GraphicsDevice& gpu,
- const RectData& rectData,
- const RectShaders& rectShaders,
- VkExtent2D extent,
- bool resizing);
-
- VkResult recreate(const sk::VulkanApi& vk,
- const sk::SurfaceKHR& surface,
- const GraphicsDevice& gpu,
- const RectData& rectData,
- const RectShaders& rectShaders,
- VkExtent2D extent,
- bool resizing);
-
- Swapchain swapchain;
- RenderPass renderPass;
- RectPipeline rectPipeline;
- RenderSync sync;
+ VkResult init(const sk::VulkanApi& vk,
+ const GraphicsDevice& gpu,
+ const RectData& rectData,
+ const RectShaders& rectShaders,
+ VkExtent2D extent,
+ bool resizing);
+
+ VkResult recreate(const sk::VulkanApi& vk,
+ const sk::SurfaceKHR& surface,
+ const GraphicsDevice& gpu,
+ const RectData& rectData,
+ const RectShaders& rectShaders,
+ VkExtent2D extent,
+ bool resizing);
+
+ Swapchain swapchain;
+ RenderPass renderPass;
+ RectPipeline rectPipeline;
+ RenderSync sync;
};
VkResult
@@ -215,22 +217,21 @@ selectSurfaceFormat(const sk::VulkanApi& vk,
const sk::SurfaceKHR& surface,
VkSurfaceFormatKHR& surfaceFormat)
{
- std::vector<VkSurfaceFormatKHR> formats;
- if (VkResult r = vk.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
- surface,
- formats)) {
- return r;
- }
-
- for (const auto& format : formats) {
- if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
- format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
- surfaceFormat = format;
- return VK_SUCCESS;
- }
- }
-
- return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ std::vector<VkSurfaceFormatKHR> formats;
+ if (VkResult r = vk.getPhysicalDeviceSurfaceFormatsKHR(
+ physicalDevice, surface, formats)) {
+ return r;
+ }
+
+ for (const auto& format : formats) {
+ if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
+ format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
+ surfaceFormat = format;
+ return VK_SUCCESS;
+ }
+ }
+
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
VkResult
@@ -241,54 +242,53 @@ selectPresentMode(const sk::VulkanApi& vk,
const bool sync,
VkPresentModeKHR& presentMode)
{
- // Map command line options to mode priorities
- static constexpr VkPresentModeKHR priorities[][2][4] = {
- {
- // No double buffer, no sync
- {VK_PRESENT_MODE_IMMEDIATE_KHR,
- VK_PRESENT_MODE_MAILBOX_KHR,
- VK_PRESENT_MODE_FIFO_RELAXED_KHR,
- VK_PRESENT_MODE_FIFO_KHR},
-
- // No double buffer, sync (nonsense, map to FIFO relaxed)
- {VK_PRESENT_MODE_FIFO_RELAXED_KHR,
- VK_PRESENT_MODE_FIFO_KHR,
- VK_PRESENT_MODE_MAILBOX_KHR,
- VK_PRESENT_MODE_IMMEDIATE_KHR},
- },
- {
- // Double buffer, no sync
- {
- VK_PRESENT_MODE_MAILBOX_KHR,
- VK_PRESENT_MODE_IMMEDIATE_KHR,
- VK_PRESENT_MODE_FIFO_RELAXED_KHR,
- VK_PRESENT_MODE_FIFO_KHR,
- },
-
- // Double buffer, sync
- {VK_PRESENT_MODE_FIFO_KHR,
- VK_PRESENT_MODE_FIFO_RELAXED_KHR,
- VK_PRESENT_MODE_MAILBOX_KHR,
- VK_PRESENT_MODE_IMMEDIATE_KHR},
- },
- };
-
- std::vector<VkPresentModeKHR> modes;
- if (VkResult r = vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice,
- surface,
- modes)) {
- return r;
- }
-
- const auto& tryModes = priorities[bool(multiBuffer)][bool(sync)];
- for (const auto m : tryModes) {
- if (std::find(modes.begin(), modes.end(), m) != modes.end()) {
- presentMode = m;
- return VK_SUCCESS;
- }
- }
-
- return VK_ERROR_INCOMPATIBLE_DRIVER;
+ // Map command line options to mode priorities
+ static constexpr VkPresentModeKHR priorities[][2][4] = {
+ {
+ // No double buffer, no sync
+ {VK_PRESENT_MODE_IMMEDIATE_KHR,
+ VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ VK_PRESENT_MODE_FIFO_KHR},
+
+ // No double buffer, sync (nonsense, map to FIFO relaxed)
+ {VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ VK_PRESENT_MODE_FIFO_KHR,
+ VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_IMMEDIATE_KHR},
+ },
+ {
+ // Double buffer, no sync
+ {
+ VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_IMMEDIATE_KHR,
+ VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ VK_PRESENT_MODE_FIFO_KHR,
+ },
+
+ // Double buffer, sync
+ {VK_PRESENT_MODE_FIFO_KHR,
+ VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_IMMEDIATE_KHR},
+ },
+ };
+
+ std::vector<VkPresentModeKHR> modes;
+ if (VkResult r = vk.getPhysicalDeviceSurfacePresentModesKHR(
+ physicalDevice, surface, modes)) {
+ return r;
+ }
+
+ const auto& tryModes = priorities[bool(multiBuffer)][bool(sync)];
+ for (const auto m : tryModes) {
+ if (std::find(modes.begin(), modes.end(), m) != modes.end()) {
+ presentMode = m;
+ return VK_SUCCESS;
+ }
+ }
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
}
VkResult
@@ -297,26 +297,26 @@ openDevice(const sk::VulkanApi& vk,
const uint32_t graphicsFamilyIndex,
sk::Device& device)
{
- const float graphicsQueuePriority = 1.0f;
- const char* const swapchainName = "VK_KHR_swapchain";
-
- const VkDeviceQueueCreateInfo queueCreateInfo{
- VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
- nullptr,
- 0u,
- graphicsFamilyIndex,
- SK_COUNTED(1u, &graphicsQueuePriority),
- };
-
- const VkDeviceCreateInfo createInfo{VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- nullptr,
- 0u,
- SK_COUNTED(1u, &queueCreateInfo),
- SK_COUNTED(0u, nullptr), // Deprecated
- SK_COUNTED(1u, &swapchainName),
- nullptr};
-
- return vk.createDevice(physicalDevice, createInfo, device);
+ const float graphicsQueuePriority = 1.0f;
+ const char* const swapchainName = "VK_KHR_swapchain";
+
+ const VkDeviceQueueCreateInfo queueCreateInfo{
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ nullptr,
+ 0u,
+ graphicsFamilyIndex,
+ SK_COUNTED(1u, &graphicsQueuePriority),
+ };
+
+ const VkDeviceCreateInfo createInfo{VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ nullptr,
+ 0u,
+ SK_COUNTED(1u, &queueCreateInfo),
+ SK_COUNTED(0u, nullptr), // Deprecated
+ SK_COUNTED(1u, &swapchainName),
+ nullptr};
+
+ return vk.createDevice(physicalDevice, createInfo, device);
}
/// Return whether the physical device supports the extensions we require
@@ -325,21 +325,19 @@ deviceSupportsRequiredExtensions(const sk::VulkanApi& vk,
const sk::PhysicalDevice& device,
bool& supported)
{
- VkResult r = VK_SUCCESS;
+ VkResult r = VK_SUCCESS;
- std::vector<VkExtensionProperties> props;
- if ((r = vk.enumerateDeviceExtensionProperties(device, props))) {
- return r;
- }
+ std::vector<VkExtensionProperties> props;
+ if ((r = vk.enumerateDeviceExtensionProperties(device, props))) {
+ return r;
+ }
- supported = std::any_of(props.begin(),
- props.end(),
- [&](const VkExtensionProperties& e) {
- return !strcmp(e.extensionName,
- "VK_KHR_swapchain");
- });
+ supported = std::any_of(
+ props.begin(), props.end(), [&](const VkExtensionProperties& e) {
+ return !strcmp(e.extensionName, "VK_KHR_swapchain");
+ });
- return VK_SUCCESS;
+ return VK_SUCCESS;
}
/// Return the index of the graphics queue, if there is one
@@ -349,29 +347,29 @@ findGraphicsQueue(const sk::VulkanApi& vk,
const sk::PhysicalDevice& device,
uint32_t& queueIndex)
{
- VkResult r = VK_SUCCESS;
-
- std::vector<VkQueueFamilyProperties> queueProps;
- if ((r = vk.getPhysicalDeviceQueueFamilyProperties(device, queueProps))) {
- return r;
- }
-
- for (uint32_t q = 0u; q < queueProps.size(); ++q) {
- if (queueProps[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
- bool supported = false;
- if ((r = vk.getPhysicalDeviceSurfaceSupportKHR(
- device, q, surface, supported))) {
- return r;
- }
-
- if (supported) {
- queueIndex = q;
- return VK_SUCCESS;
- }
- }
- }
-
- return VK_ERROR_FEATURE_NOT_PRESENT;
+ VkResult r = VK_SUCCESS;
+
+ std::vector<VkQueueFamilyProperties> queueProps;
+ if ((r = vk.getPhysicalDeviceQueueFamilyProperties(device, queueProps))) {
+ return r;
+ }
+
+ for (uint32_t q = 0u; q < queueProps.size(); ++q) {
+ if (queueProps[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ bool supported = false;
+ if ((r = vk.getPhysicalDeviceSurfaceSupportKHR(
+ device, q, surface, supported))) {
+ return r;
+ }
+
+ if (supported) {
+ queueIndex = q;
+ return VK_SUCCESS;
+ }
+ }
+ }
+
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
/// Select a physical graphics device to use (simply the first found)
@@ -381,31 +379,31 @@ selectPhysicalDevice(const sk::VulkanApi& vk,
const sk::SurfaceKHR& surface,
PhysicalDeviceSelection& selection)
{
- VkResult r = VK_SUCCESS;
-
- std::vector<sk::PhysicalDevice> devices;
- if ((r = vk.enumeratePhysicalDevices(instance, devices))) {
- return r;
- }
-
- for (const auto& device : devices) {
- auto supported = false;
- if ((r = deviceSupportsRequiredExtensions(vk, device, supported))) {
- return r;
- }
-
- if (supported) {
- auto queueIndex = 0u;
- if ((r = findGraphicsQueue(vk, surface, device, queueIndex))) {
- return r;
- }
-
- selection = PhysicalDeviceSelection{device, queueIndex};
- return VK_SUCCESS;
- }
- }
-
- return VK_ERROR_INCOMPATIBLE_DISPLAY_KHR;
+ VkResult r = VK_SUCCESS;
+
+ std::vector<sk::PhysicalDevice> devices;
+ if ((r = vk.enumeratePhysicalDevices(instance, devices))) {
+ return r;
+ }
+
+ for (const auto& device : devices) {
+ auto supported = false;
+ if ((r = deviceSupportsRequiredExtensions(vk, device, supported))) {
+ return r;
+ }
+
+ if (supported) {
+ auto queueIndex = 0u;
+ if ((r = findGraphicsQueue(vk, surface, device, queueIndex))) {
+ return r;
+ }
+
+ selection = PhysicalDeviceSelection{device, queueIndex};
+ return VK_SUCCESS;
+ }
+ }
+
+ return VK_ERROR_INCOMPATIBLE_DISPLAY_KHR;
}
VkResult
@@ -414,55 +412,55 @@ GraphicsDevice::init(const pugl::VulkanLoader& loader,
pugl::View& view,
const PuglTestOptions& opts)
{
- const auto& vk = context.vk;
- VkResult r = VK_SUCCESS;
-
- // Create a Vulkan surface for the window using the Pugl API
- VkSurfaceKHR surfaceHandle = {};
- if ((r = pugl::createSurface(loader.getInstanceProcAddrFunc(),
- view,
- context.instance,
- nullptr,
- &surfaceHandle))) {
- return r;
- }
-
- // Wrap surface in a safe RAII handle
- surface = sk::SurfaceKHR{surfaceHandle,
- {context.instance, vk.vkDestroySurfaceKHR}};
-
- PhysicalDeviceSelection physicalDeviceSelection = {};
- // Select a physical device to use
- if ((r = selectPhysicalDevice(
- vk, context.instance, surface, physicalDeviceSelection))) {
- return r;
- }
-
- physicalDevice = physicalDeviceSelection.physicalDevice;
- graphicsIndex = physicalDeviceSelection.graphicsFamilyIndex;
-
- if ((r = selectSurfaceFormat(vk, physicalDevice, surface, surfaceFormat)) ||
- (r = selectPresentMode(vk,
- physicalDevice,
- surface,
- opts.doubleBuffer,
- opts.sync,
- presentMode)) ||
- (r = selectPresentMode(
- vk, physicalDevice, surface, true, false, resizePresentMode)) ||
- (r = openDevice(vk, physicalDevice, graphicsIndex, device))) {
- return r;
- }
-
- const VkCommandPoolCreateInfo commandPoolInfo{
- VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, {}, graphicsIndex};
-
- if ((r = vk.createCommandPool(device, commandPoolInfo, commandPool))) {
- return r;
- }
-
- graphicsQueue = vk.getDeviceQueue(device, graphicsIndex, 0);
- return VK_SUCCESS;
+ const auto& vk = context.vk;
+ VkResult r = VK_SUCCESS;
+
+ // Create a Vulkan surface for the window using the Pugl API
+ VkSurfaceKHR surfaceHandle = {};
+ if ((r = pugl::createSurface(loader.getInstanceProcAddrFunc(),
+ view,
+ context.instance,
+ nullptr,
+ &surfaceHandle))) {
+ return r;
+ }
+
+ // Wrap surface in a safe RAII handle
+ surface =
+ sk::SurfaceKHR{surfaceHandle, {context.instance, vk.vkDestroySurfaceKHR}};
+
+ PhysicalDeviceSelection physicalDeviceSelection = {};
+ // Select a physical device to use
+ if ((r = selectPhysicalDevice(
+ vk, context.instance, surface, physicalDeviceSelection))) {
+ return r;
+ }
+
+ physicalDevice = physicalDeviceSelection.physicalDevice;
+ graphicsIndex = physicalDeviceSelection.graphicsFamilyIndex;
+
+ if ((r = selectSurfaceFormat(vk, physicalDevice, surface, surfaceFormat)) ||
+ (r = selectPresentMode(vk,
+ physicalDevice,
+ surface,
+ opts.doubleBuffer,
+ opts.sync,
+ presentMode)) ||
+ (r = selectPresentMode(
+ vk, physicalDevice, surface, true, false, resizePresentMode)) ||
+ (r = openDevice(vk, physicalDevice, graphicsIndex, device))) {
+ return r;
+ }
+
+ const VkCommandPoolCreateInfo commandPoolInfo{
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, {}, graphicsIndex};
+
+ if ((r = vk.createCommandPool(device, commandPoolInfo, commandPool))) {
+ return r;
+ }
+
+ graphicsQueue = vk.getDeviceQueue(device, graphicsIndex, 0);
+ return VK_SUCCESS;
}
uint32_t
@@ -471,18 +469,17 @@ findMemoryType(const sk::VulkanApi& vk,
const uint32_t typeFilter,
const VkMemoryPropertyFlags& properties)
{
- VkPhysicalDeviceMemoryProperties memProperties =
- vk.getPhysicalDeviceMemoryProperties(physicalDevice);
-
- for (uint32_t i = 0; i < memProperties.memoryTypeCount; ++i) {
- if ((typeFilter & (1 << i)) &&
- (memProperties.memoryTypes[i].propertyFlags & properties) ==
- properties) {
- return i;
- }
- }
-
- return UINT32_MAX;
+ VkPhysicalDeviceMemoryProperties memProperties =
+ vk.getPhysicalDeviceMemoryProperties(physicalDevice);
+
+ for (uint32_t i = 0; i < memProperties.memoryTypeCount; ++i) {
+ if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags &
+ properties) == properties) {
+ return i;
+ }
+ }
+
+ return UINT32_MAX;
}
VkResult
@@ -492,42 +489,40 @@ Buffer::init(const sk::VulkanApi& vk,
const VkBufferUsageFlags usage,
const VkMemoryPropertyFlags properties)
{
- const VkBufferCreateInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
- nullptr,
- {},
- size,
- usage,
- VK_SHARING_MODE_EXCLUSIVE,
- SK_COUNTED(0, nullptr)};
-
- const auto& device = gpu.device;
-
- VkResult r = VK_SUCCESS;
- if ((r = vk.createBuffer(device, bufferInfo, buffer))) {
- return r;
- }
-
- const auto requirements = vk.getBufferMemoryRequirements(device, buffer);
- const auto memoryTypeIndex = findMemoryType(vk,
- gpu.physicalDevice,
- requirements.memoryTypeBits,
- properties);
-
- if (memoryTypeIndex == UINT32_MAX) {
- return VK_ERROR_FEATURE_NOT_PRESENT;
- }
-
- const VkMemoryAllocateInfo allocInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- nullptr,
- requirements.size,
- memoryTypeIndex};
-
- if ((r = vk.allocateMemory(device, allocInfo, deviceMemory)) ||
- (r = vk.bindBufferMemory(device, buffer, deviceMemory, 0))) {
- return r;
- }
-
- return VK_SUCCESS;
+ const VkBufferCreateInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ nullptr,
+ {},
+ size,
+ usage,
+ VK_SHARING_MODE_EXCLUSIVE,
+ SK_COUNTED(0, nullptr)};
+
+ const auto& device = gpu.device;
+
+ VkResult r = VK_SUCCESS;
+ if ((r = vk.createBuffer(device, bufferInfo, buffer))) {
+ return r;
+ }
+
+ const auto requirements = vk.getBufferMemoryRequirements(device, buffer);
+ const auto memoryTypeIndex = findMemoryType(
+ vk, gpu.physicalDevice, requirements.memoryTypeBits, properties);
+
+ if (memoryTypeIndex == UINT32_MAX) {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ const VkMemoryAllocateInfo allocInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ requirements.size,
+ memoryTypeIndex};
+
+ if ((r = vk.allocateMemory(device, allocInfo, deviceMemory)) ||
+ (r = vk.bindBufferMemory(device, buffer, deviceMemory, 0))) {
+ return r;
+ }
+
+ return VK_SUCCESS;
}
VkResult
@@ -538,62 +533,59 @@ Swapchain::init(const sk::VulkanApi& vk,
VkSwapchainKHR oldSwapchain,
bool resizing)
{
- capabilities = surfaceCapabilities;
- extent = surfaceExtent;
-
- const auto minNumImages = (!capabilities.maxImageCount ||
- capabilities.maxImageCount >= 3u)
- ? 3u
- : capabilities.maxImageCount;
-
- const VkSwapchainCreateInfoKHR swapchainCreateInfo{
- VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
- nullptr,
- {},
- gpu.surface,
- minNumImages,
- gpu.surfaceFormat.format,
- gpu.surfaceFormat.colorSpace,
- surfaceExtent,
- 1,
- (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
- VK_SHARING_MODE_EXCLUSIVE,
- SK_COUNTED(0, nullptr),
- capabilities.currentTransform,
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
- resizing ? gpu.resizePresentMode : gpu.presentMode,
- VK_TRUE,
- oldSwapchain};
-
- VkResult r = VK_SUCCESS;
- std::vector<VkImage> images;
- if ((r = vk.createSwapchainKHR(gpu.device,
- swapchainCreateInfo,
- swapchain)) ||
- (r = vk.getSwapchainImagesKHR(gpu.device, swapchain, images))) {
- return r;
- }
-
- imageViews = std::vector<sk::ImageView>(images.size());
- for (size_t i = 0; i < images.size(); ++i) {
- const VkImageViewCreateInfo imageViewCreateInfo{
- VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- nullptr,
- {},
- images[i],
- VK_IMAGE_VIEW_TYPE_2D,
- gpu.surfaceFormat.format,
- {},
- {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
-
- if ((r = vk.createImageView(gpu.device,
- imageViewCreateInfo,
- imageViews[i]))) {
- return r;
- }
- }
-
- return VK_SUCCESS;
+ capabilities = surfaceCapabilities;
+ extent = surfaceExtent;
+
+ const auto minNumImages =
+ (!capabilities.maxImageCount || capabilities.maxImageCount >= 3u)
+ ? 3u
+ : capabilities.maxImageCount;
+
+ const VkSwapchainCreateInfoKHR swapchainCreateInfo{
+ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ nullptr,
+ {},
+ gpu.surface,
+ minNumImages,
+ gpu.surfaceFormat.format,
+ gpu.surfaceFormat.colorSpace,
+ surfaceExtent,
+ 1,
+ (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
+ VK_SHARING_MODE_EXCLUSIVE,
+ SK_COUNTED(0, nullptr),
+ capabilities.currentTransform,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
+ resizing ? gpu.resizePresentMode : gpu.presentMode,
+ VK_TRUE,
+ oldSwapchain};
+
+ VkResult r = VK_SUCCESS;
+ std::vector<VkImage> images;
+ if ((r = vk.createSwapchainKHR(gpu.device, swapchainCreateInfo, swapchain)) ||
+ (r = vk.getSwapchainImagesKHR(gpu.device, swapchain, images))) {
+ return r;
+ }
+
+ imageViews = std::vector<sk::ImageView>(images.size());
+ for (size_t i = 0; i < images.size(); ++i) {
+ const VkImageViewCreateInfo imageViewCreateInfo{
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ nullptr,
+ {},
+ images[i],
+ VK_IMAGE_VIEW_TYPE_2D,
+ gpu.surfaceFormat.format,
+ {},
+ {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
+
+ if ((r = vk.createImageView(
+ gpu.device, imageViewCreateInfo, imageViews[i]))) {
+ return r;
+ }
+ }
+
+ return VK_SUCCESS;
}
VkResult
@@ -601,121 +593,116 @@ RenderPass::init(const sk::VulkanApi& vk,
const GraphicsDevice& gpu,
const Swapchain& swapchain)
{
- const auto numImages = static_cast<uint32_t>(swapchain.imageViews.size());
-
- assert(numImages > 0);
-
- // Create command buffers
- const VkCommandBufferAllocateInfo commandBufferAllocateInfo{
- VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- nullptr,
- gpu.commandPool,
- VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- numImages};
-
- VkResult r = VK_SUCCESS;
- if ((r = vk.allocateCommandBuffers(gpu.device,
- commandBufferAllocateInfo,
- commandBuffers))) {
- return r;
- }
-
- static constexpr VkAttachmentReference colorAttachmentRef{
- 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
-
- static constexpr VkSubpassDescription subpass{
- {},
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- SK_COUNTED(0, nullptr),
- SK_COUNTED(1, &colorAttachmentRef, nullptr, nullptr),
- SK_COUNTED(0u, nullptr)};
-
- static constexpr VkSubpassDependency dependency{
- VK_SUBPASS_EXTERNAL,
- 0,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
- (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
- VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
- {},
- {}};
-
- const VkAttachmentDescription colorAttachment{
- {},
- gpu.surfaceFormat.format,
- VK_SAMPLE_COUNT_1_BIT,
- VK_ATTACHMENT_LOAD_OP_CLEAR,
- VK_ATTACHMENT_STORE_OP_STORE,
- VK_ATTACHMENT_LOAD_OP_DONT_CARE,
- VK_ATTACHMENT_STORE_OP_DONT_CARE,
- VK_IMAGE_LAYOUT_UNDEFINED,
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
- };
-
- const VkRenderPassCreateInfo renderPassCreateInfo{
- VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- nullptr,
- {},
- SK_COUNTED(1, &colorAttachment),
- SK_COUNTED(1, &subpass),
- SK_COUNTED(1, &dependency)};
-
- if ((r = vk.createRenderPass(gpu.device,
- renderPassCreateInfo,
- renderPass))) {
- return r;
- }
-
- // Create framebuffers
- framebuffers = std::vector<sk::Framebuffer>(numImages);
- for (uint32_t i = 0; i < numImages; ++i) {
- const VkFramebufferCreateInfo framebufferCreateInfo{
- VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- nullptr,
- {},
- renderPass,
- SK_COUNTED(1, &swapchain.imageViews[i].get()),
- swapchain.extent.width,
- swapchain.extent.height,
- 1};
-
- if ((r = vk.createFramebuffer(gpu.device,
- framebufferCreateInfo,
- framebuffers[i]))) {
- return r;
- }
- }
-
- return VK_SUCCESS;
+ const auto numImages = static_cast<uint32_t>(swapchain.imageViews.size());
+
+ assert(numImages > 0);
+
+ // Create command buffers
+ const VkCommandBufferAllocateInfo commandBufferAllocateInfo{
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ nullptr,
+ gpu.commandPool,
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ numImages};
+
+ VkResult r = VK_SUCCESS;
+ if ((r = vk.allocateCommandBuffers(
+ gpu.device, commandBufferAllocateInfo, commandBuffers))) {
+ return r;
+ }
+
+ static constexpr VkAttachmentReference colorAttachmentRef{
+ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
+
+ static constexpr VkSubpassDescription subpass{
+ {},
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ SK_COUNTED(0, nullptr),
+ SK_COUNTED(1, &colorAttachmentRef, nullptr, nullptr),
+ SK_COUNTED(0u, nullptr)};
+
+ static constexpr VkSubpassDependency dependency{
+ VK_SUBPASS_EXTERNAL,
+ 0,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
+ {},
+ {}};
+
+ const VkAttachmentDescription colorAttachment{
+ {},
+ gpu.surfaceFormat.format,
+ VK_SAMPLE_COUNT_1_BIT,
+ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ VK_ATTACHMENT_STORE_OP_STORE,
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ };
+
+ const VkRenderPassCreateInfo renderPassCreateInfo{
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ nullptr,
+ {},
+ SK_COUNTED(1, &colorAttachment),
+ SK_COUNTED(1, &subpass),
+ SK_COUNTED(1, &dependency)};
+
+ if ((r = vk.createRenderPass(gpu.device, renderPassCreateInfo, renderPass))) {
+ return r;
+ }
+
+ // Create framebuffers
+ framebuffers = std::vector<sk::Framebuffer>(numImages);
+ for (uint32_t i = 0; i < numImages; ++i) {
+ const VkFramebufferCreateInfo framebufferCreateInfo{
+ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ nullptr,
+ {},
+ renderPass,
+ SK_COUNTED(1, &swapchain.imageViews[i].get()),
+ swapchain.extent.width,
+ swapchain.extent.height,
+ 1};
+
+ if ((r = vk.createFramebuffer(
+ gpu.device, framebufferCreateInfo, framebuffers[i]))) {
+ return r;
+ }
+ }
+
+ return VK_SUCCESS;
}
std::vector<uint32_t>
readFile(const char* const programPath, const std::string& filename)
{
- std::unique_ptr<char, decltype(&free)> path{resourcePath(programPath,
- filename.c_str()),
- &free};
+ std::unique_ptr<char, decltype(&free)> path{
+ resourcePath(programPath, filename.c_str()), &free};
- std::cerr << "Loading shader: " << path.get() << std::endl;
+ std::cerr << "Loading shader: " << path.get() << std::endl;
- std::unique_ptr<FILE, decltype(&fclose)> file{fopen(path.get(), "rb"),
- &fclose};
+ std::unique_ptr<FILE, decltype(&fclose)> file{fopen(path.get(), "rb"),
+ &fclose};
- if (!file) {
- std::cerr << "Failed to open file '" << filename << "'\n";
- return {};
- }
+ if (!file) {
+ std::cerr << "Failed to open file '" << filename << "'\n";
+ return {};
+ }
- fseek(file.get(), 0, SEEK_END);
- const auto fileSize = static_cast<size_t>(ftell(file.get()));
- fseek(file.get(), 0, SEEK_SET);
+ fseek(file.get(), 0, SEEK_END);
+ const auto fileSize = static_cast<size_t>(ftell(file.get()));
+ fseek(file.get(), 0, SEEK_SET);
- const auto numWords = fileSize / sizeof(uint32_t);
- std::vector<uint32_t> buffer(numWords);
+ const auto numWords = fileSize / sizeof(uint32_t);
+ std::vector<uint32_t> buffer(numWords);
- fread(buffer.data(), sizeof(uint32_t), numWords, file.get());
+ fread(buffer.data(), sizeof(uint32_t), numWords, file.get());
- return buffer;
+ return buffer;
}
VkResult
@@ -724,14 +711,14 @@ createShaderModule(const sk::VulkanApi& vk,
const std::vector<uint32_t>& code,
sk::ShaderModule& shaderModule)
{
- const VkShaderModuleCreateInfo createInfo{
- VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- nullptr,
- {},
- code.size() * sizeof(uint32_t),
- code.data()};
-
- return vk.createShaderModule(gpu.device, createInfo, shaderModule);
+ const VkShaderModuleCreateInfo createInfo{
+ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ nullptr,
+ {},
+ code.size() * sizeof(uint32_t),
+ code.data()};
+
+ return vk.createShaderModule(gpu.device, createInfo, shaderModule);
}
VkResult
@@ -739,23 +726,21 @@ RectShaders::init(const sk::VulkanApi& vk,
const GraphicsDevice& gpu,
const std::string& programPath)
{
- auto vertShaderCode = readFile(programPath.c_str(),
- "shaders/rect.vert.spv");
+ auto vertShaderCode = readFile(programPath.c_str(), "shaders/rect.vert.spv");
- auto fragShaderCode = readFile(programPath.c_str(),
- "shaders/rect.frag.spv");
+ auto fragShaderCode = readFile(programPath.c_str(), "shaders/rect.frag.spv");
- if (vertShaderCode.empty() || fragShaderCode.empty()) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
+ if (vertShaderCode.empty() || fragShaderCode.empty()) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
- VkResult r = VK_SUCCESS;
- if ((r = createShaderModule(vk, gpu, vertShaderCode, vert)) ||
- (r = createShaderModule(vk, gpu, fragShaderCode, frag))) {
- return r;
- }
+ VkResult r = VK_SUCCESS;
+ if ((r = createShaderModule(vk, gpu, vertShaderCode, vert)) ||
+ (r = createShaderModule(vk, gpu, fragShaderCode, frag))) {
+ return r;
+ }
- return VK_SUCCESS;
+ return VK_SUCCESS;
}
VkResult
@@ -766,222 +751,214 @@ RectPipeline::init(const sk::VulkanApi& vk,
const Swapchain& swapchain,
const RenderPass& renderPass)
{
- const auto oldNumImages = numImages;
- VkResult r = VK_SUCCESS;
-
- numImages = static_cast<uint32_t>(swapchain.imageViews.size());
- pipelines = {};
- pipelineLayout = {};
- descriptorSets = {};
-
- if (numImages != oldNumImages) {
- // Create layout descriptor pool
-
- const VkDescriptorPoolSize poolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- numImages};
-
- const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
- VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
- nullptr,
- VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
- numImages,
- 1u,
- &poolSize};
- if ((r = vk.createDescriptorPool(gpu.device,
- descriptorPoolCreateInfo,
- descriptorPool))) {
- return r;
- }
- }
-
- const std::vector<VkDescriptorSetLayout> layouts(
- numImages, rectData.descriptorSetLayout.get());
-
- const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
- VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
- nullptr,
- descriptorPool,
- numImages,
- layouts.data()};
- if ((r = vk.allocateDescriptorSets(gpu.device,
- descriptorSetAllocateInfo,
- descriptorSets))) {
- return r;
- }
-
- const VkDescriptorBufferInfo bufferInfo{rectData.uniformBuffer.buffer,
- 0,
- sizeof(UniformBufferObject)};
-
- const std::array<VkWriteDescriptorSet, 1> descriptorWrites{
- {{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- nullptr,
- descriptorSets[0],
- 0,
- 0,
- 1,
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- nullptr,
- &bufferInfo,
- nullptr}}};
-
- const std::array<VkCopyDescriptorSet, 0> descriptorCopies{};
-
- vk.updateDescriptorSets(gpu.device, descriptorWrites, descriptorCopies);
-
- static constexpr std::array<VkVertexInputAttributeDescription, 4>
- vertexAttributeDescriptions{
- {// Model
- {0u, 0u, VK_FORMAT_R32G32_SFLOAT, 0},
-
- // Rect instance attributes
- {1u, 1u, VK_FORMAT_R32G32_SFLOAT, offsetof(Rect, pos)},
- {2u, 1u, VK_FORMAT_R32G32_SFLOAT, offsetof(Rect, size)},
- {3u,
- 1u,
- VK_FORMAT_R32G32B32A32_SFLOAT,
- offsetof(Rect, fillColor)}}};
-
- static constexpr std::array<VkVertexInputBindingDescription, 2>
- vertexBindingDescriptions{
- VkVertexInputBindingDescription{0,
- sizeof(vec2),
- VK_VERTEX_INPUT_RATE_VERTEX},
- VkVertexInputBindingDescription{1u,
- sizeof(Rect),
- VK_VERTEX_INPUT_RATE_INSTANCE}};
-
- static constexpr VkPipelineInputAssemblyStateCreateInfo inputAssembly{
- VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- nullptr,
- {},
- VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- false};
-
- static constexpr VkPipelineRasterizationStateCreateInfo rasterizer{
- VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
- nullptr,
- {},
- 0,
- 0,
- VK_POLYGON_MODE_FILL,
- VK_CULL_MODE_BACK_BIT,
- VK_FRONT_FACE_CLOCKWISE,
- 0,
- 0,
- 0,
- 0,
- 1.0f};
-
- static constexpr VkPipelineMultisampleStateCreateInfo multisampling{
- VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
- nullptr,
- {},
- VK_SAMPLE_COUNT_1_BIT,
- false,
- 0.0f,
- nullptr,
- false,
- false};
-
- static constexpr VkPipelineColorBlendAttachmentState colorBlendAttachment{
- true,
- VK_BLEND_FACTOR_SRC_ALPHA,
- VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
- VK_BLEND_OP_ADD,
- VK_BLEND_FACTOR_ONE,
- VK_BLEND_FACTOR_ZERO,
- VK_BLEND_OP_ADD,
- (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
- VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)};
-
- const VkPipelineShaderStageCreateInfo shaderStages[] = {
- {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- nullptr,
- {},
- VK_SHADER_STAGE_VERTEX_BIT,
- shaders.vert.get(),
- "main",
- nullptr},
- {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- nullptr,
- {},
- VK_SHADER_STAGE_FRAGMENT_BIT,
- shaders.frag.get(),
- "main",
- nullptr}};
-
- const VkPipelineVertexInputStateCreateInfo vertexInputInfo{
- VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- nullptr,
- {},
- SK_COUNTED(static_cast<uint32_t>(vertexBindingDescriptions.size()),
- vertexBindingDescriptions.data()),
- SK_COUNTED(static_cast<uint32_t>(vertexAttributeDescriptions.size()),
- vertexAttributeDescriptions.data())};
-
- const VkViewport viewport{0.0f,
- 0.0f,
- float(swapchain.extent.width),
- float(swapchain.extent.height),
- 0.0f,
- 1.0f};
-
- const VkRect2D scissor{{0, 0}, swapchain.extent};
-
- const VkPipelineViewportStateCreateInfo viewportState{
- VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
- nullptr,
- {},
- SK_COUNTED(1, &viewport),
- SK_COUNTED(1, &scissor)};
-
- const VkPipelineColorBlendStateCreateInfo colorBlending{
- VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- nullptr,
- {},
- false,
- VK_LOGIC_OP_COPY,
- SK_COUNTED(1, &colorBlendAttachment),
- {1.0f, 0.0f, 0.0f, 0.0f}};
-
- const VkPipelineLayoutCreateInfo layoutInfo{
- VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- nullptr,
- {},
- SK_COUNTED(1, &rectData.descriptorSetLayout.get()),
- SK_COUNTED(0, nullptr)};
-
- if ((r = vk.createPipelineLayout(gpu.device, layoutInfo, pipelineLayout))) {
- return r;
- }
-
- const std::array<VkGraphicsPipelineCreateInfo, 1> pipelineInfos{
- {{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
- nullptr,
- {},
- SK_COUNTED(2, shaderStages),
- &vertexInputInfo,
- &inputAssembly,
- nullptr,
- &viewportState,
- &rasterizer,
- &multisampling,
- nullptr,
- &colorBlending,
- nullptr,
- pipelineLayout,
- renderPass.renderPass,
- 0u,
- {},
- 0}}};
-
- if ((r = vk.createGraphicsPipelines(
- gpu.device, {}, pipelineInfos, pipelines))) {
- return r;
- }
-
- return VK_SUCCESS;
+ const auto oldNumImages = numImages;
+ VkResult r = VK_SUCCESS;
+
+ numImages = static_cast<uint32_t>(swapchain.imageViews.size());
+ pipelines = {};
+ pipelineLayout = {};
+ descriptorSets = {};
+
+ if (numImages != oldNumImages) {
+ // Create layout descriptor pool
+
+ const VkDescriptorPoolSize poolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ numImages};
+
+ const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
+ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ nullptr,
+ VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+ numImages,
+ 1u,
+ &poolSize};
+ if ((r = vk.createDescriptorPool(
+ gpu.device, descriptorPoolCreateInfo, descriptorPool))) {
+ return r;
+ }
+ }
+
+ const std::vector<VkDescriptorSetLayout> layouts(
+ numImages, rectData.descriptorSetLayout.get());
+
+ const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ descriptorPool,
+ numImages,
+ layouts.data()};
+ if ((r = vk.allocateDescriptorSets(
+ gpu.device, descriptorSetAllocateInfo, descriptorSets))) {
+ return r;
+ }
+
+ const VkDescriptorBufferInfo bufferInfo{
+ rectData.uniformBuffer.buffer, 0, sizeof(UniformBufferObject)};
+
+ const std::array<VkWriteDescriptorSet, 1> descriptorWrites{
+ {{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ nullptr,
+ descriptorSets[0],
+ 0,
+ 0,
+ 1,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ nullptr,
+ &bufferInfo,
+ nullptr}}};
+
+ const std::array<VkCopyDescriptorSet, 0> descriptorCopies{};
+
+ vk.updateDescriptorSets(gpu.device, descriptorWrites, descriptorCopies);
+
+ static constexpr std::array<VkVertexInputAttributeDescription, 4>
+ vertexAttributeDescriptions{
+ {// Model
+ {0u, 0u, VK_FORMAT_R32G32_SFLOAT, 0},
+
+ // Rect instance attributes
+ {1u, 1u, VK_FORMAT_R32G32_SFLOAT, offsetof(Rect, pos)},
+ {2u, 1u, VK_FORMAT_R32G32_SFLOAT, offsetof(Rect, size)},
+ {3u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Rect, fillColor)}}};
+
+ static constexpr std::array<VkVertexInputBindingDescription, 2>
+ vertexBindingDescriptions{
+ VkVertexInputBindingDescription{
+ 0, sizeof(vec2), VK_VERTEX_INPUT_RATE_VERTEX},
+ VkVertexInputBindingDescription{
+ 1u, sizeof(Rect), VK_VERTEX_INPUT_RATE_INSTANCE}};
+
+ static constexpr VkPipelineInputAssemblyStateCreateInfo inputAssembly{
+ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ nullptr,
+ {},
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+ false};
+
+ static constexpr VkPipelineRasterizationStateCreateInfo rasterizer{
+ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ nullptr,
+ {},
+ 0,
+ 0,
+ VK_POLYGON_MODE_FILL,
+ VK_CULL_MODE_BACK_BIT,
+ VK_FRONT_FACE_CLOCKWISE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1.0f};
+
+ static constexpr VkPipelineMultisampleStateCreateInfo multisampling{
+ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ nullptr,
+ {},
+ VK_SAMPLE_COUNT_1_BIT,
+ false,
+ 0.0f,
+ nullptr,
+ false,
+ false};
+
+ static constexpr VkPipelineColorBlendAttachmentState colorBlendAttachment{
+ true,
+ VK_BLEND_FACTOR_SRC_ALPHA,
+ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ VK_BLEND_OP_ADD,
+ VK_BLEND_FACTOR_ONE,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_OP_ADD,
+ (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)};
+
+ const VkPipelineShaderStageCreateInfo shaderStages[] = {
+ {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ {},
+ VK_SHADER_STAGE_VERTEX_BIT,
+ shaders.vert.get(),
+ "main",
+ nullptr},
+ {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ {},
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ shaders.frag.get(),
+ "main",
+ nullptr}};
+
+ const VkPipelineVertexInputStateCreateInfo vertexInputInfo{
+ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ nullptr,
+ {},
+ SK_COUNTED(static_cast<uint32_t>(vertexBindingDescriptions.size()),
+ vertexBindingDescriptions.data()),
+ SK_COUNTED(static_cast<uint32_t>(vertexAttributeDescriptions.size()),
+ vertexAttributeDescriptions.data())};
+
+ const VkViewport viewport{0.0f,
+ 0.0f,
+ float(swapchain.extent.width),
+ float(swapchain.extent.height),
+ 0.0f,
+ 1.0f};
+
+ const VkRect2D scissor{{0, 0}, swapchain.extent};
+
+ const VkPipelineViewportStateCreateInfo viewportState{
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ nullptr,
+ {},
+ SK_COUNTED(1, &viewport),
+ SK_COUNTED(1, &scissor)};
+
+ const VkPipelineColorBlendStateCreateInfo colorBlending{
+ VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ nullptr,
+ {},
+ false,
+ VK_LOGIC_OP_COPY,
+ SK_COUNTED(1, &colorBlendAttachment),
+ {1.0f, 0.0f, 0.0f, 0.0f}};
+
+ const VkPipelineLayoutCreateInfo layoutInfo{
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ nullptr,
+ {},
+ SK_COUNTED(1, &rectData.descriptorSetLayout.get()),
+ SK_COUNTED(0, nullptr)};
+
+ if ((r = vk.createPipelineLayout(gpu.device, layoutInfo, pipelineLayout))) {
+ return r;
+ }
+
+ const std::array<VkGraphicsPipelineCreateInfo, 1> pipelineInfos{
+ {{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ nullptr,
+ {},
+ SK_COUNTED(2, shaderStages),
+ &vertexInputInfo,
+ &inputAssembly,
+ nullptr,
+ &viewportState,
+ &rasterizer,
+ &multisampling,
+ nullptr,
+ &colorBlending,
+ nullptr,
+ pipelineLayout,
+ renderPass.renderPass,
+ 0u,
+ {},
+ 0}}};
+
+ if ((r = vk.createGraphicsPipelines(
+ gpu.device, {}, pipelineInfos, pipelines))) {
+ return r;
+ }
+
+ return VK_SUCCESS;
}
VkResult
@@ -989,86 +966,85 @@ RectData::init(const sk::VulkanApi& vk,
const GraphicsDevice& gpu,
const size_t nRects)
{
- numRects = nRects;
-
- static constexpr VkDescriptorSetLayoutBinding uboLayoutBinding{
- 0,
- VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- 1,
- VK_SHADER_STAGE_VERTEX_BIT,
- nullptr};
-
- const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{
- VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- nullptr,
- {},
- 1,
- &uboLayoutBinding};
-
- VkResult r = VK_SUCCESS;
- if ((r = vk.createDescriptorSetLayout(gpu.device,
- descriptorSetLayoutInfo,
- descriptorSetLayout)) ||
- (r = uniformBuffer.init(vk,
- gpu,
- sizeof(UniformBufferObject),
- VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ||
- (r = vk.mapMemory(gpu.device,
- uniformBuffer.deviceMemory,
- 0,
- sizeof(UniformBufferObject),
- {},
- uniformData))) {
- return r;
- }
-
- const VkBufferUsageFlags usageFlags = (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
- VK_BUFFER_USAGE_TRANSFER_DST_BIT);
-
- const VkMemoryPropertyFlags propertyFlags =
- (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
-
- if ((r = modelBuffer.init(
- vk, gpu, sizeof(rectVertices), usageFlags, propertyFlags))) {
- return r;
- }
-
- {
- // Copy model vertices (directly, we do this only once)
- sk::MappedMemory modelData;
- if ((r = vk.mapMemory(gpu.device,
- modelBuffer.deviceMemory,
- 0,
- static_cast<VkDeviceSize>(sizeof(rectVertices)),
- {},
- modelData))) {
- return r;
- }
-
- memcpy(modelData.get(), rectVertices, sizeof(rectVertices));
- }
-
- if ((r = instanceBuffer.init(
- vk, gpu, sizeof(Rect) * numRects, usageFlags, propertyFlags))) {
- return r;
- }
-
- // Map attribute vertices (we will update them every frame)
- const auto rectsSize = static_cast<VkDeviceSize>(sizeof(Rect) * numRects);
- if ((r = vk.mapMemory(gpu.device,
- instanceBuffer.deviceMemory,
- 0,
- rectsSize,
- {},
- vertexData))) {
- return r;
- }
-
- return VK_SUCCESS;
+ numRects = nRects;
+
+ static constexpr VkDescriptorSetLayoutBinding uboLayoutBinding{
+ 0,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr};
+
+ const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ {},
+ 1,
+ &uboLayoutBinding};
+
+ VkResult r = VK_SUCCESS;
+ if ((r = vk.createDescriptorSetLayout(
+ gpu.device, descriptorSetLayoutInfo, descriptorSetLayout)) ||
+ (r = uniformBuffer.init(vk,
+ gpu,
+ sizeof(UniformBufferObject),
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ||
+ (r = vk.mapMemory(gpu.device,
+ uniformBuffer.deviceMemory,
+ 0,
+ sizeof(UniformBufferObject),
+ {},
+ uniformData))) {
+ return r;
+ }
+
+ const VkBufferUsageFlags usageFlags =
+ (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+
+ const VkMemoryPropertyFlags propertyFlags =
+ (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+ if ((r = modelBuffer.init(
+ vk, gpu, sizeof(rectVertices), usageFlags, propertyFlags))) {
+ return r;
+ }
+
+ {
+ // Copy model vertices (directly, we do this only once)
+ sk::MappedMemory modelData;
+ if ((r = vk.mapMemory(gpu.device,
+ modelBuffer.deviceMemory,
+ 0,
+ static_cast<VkDeviceSize>(sizeof(rectVertices)),
+ {},
+ modelData))) {
+ return r;
+ }
+
+ memcpy(modelData.get(), rectVertices, sizeof(rectVertices));
+ }
+
+ if ((r = instanceBuffer.init(
+ vk, gpu, sizeof(Rect) * numRects, usageFlags, propertyFlags))) {
+ return r;
+ }
+
+ // Map attribute vertices (we will update them every frame)
+ const auto rectsSize = static_cast<VkDeviceSize>(sizeof(Rect) * numRects);
+ if ((r = vk.mapMemory(gpu.device,
+ instanceBuffer.deviceMemory,
+ 0,
+ rectsSize,
+ {},
+ vertexData))) {
+ return r;
+ }
+
+ return VK_SUCCESS;
}
VkResult
@@ -1076,38 +1052,34 @@ RenderSync::init(const sk::VulkanApi& vk,
const sk::Device& device,
const uint32_t numImages)
{
- const auto maxInFlight = std::max(1u, numImages - 1u);
- VkResult r = VK_SUCCESS;
-
- imageAvailable = std::vector<sk::Semaphore>(numImages);
- renderFinished = std::vector<sk::Semaphore>(numImages);
- for (uint32_t i = 0; i < numImages; ++i) {
- static constexpr VkSemaphoreCreateInfo semaphoreInfo{
- VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, {}};
-
- if ((r = vk.createSemaphore(device,
- semaphoreInfo,
- imageAvailable[i])) ||
- (r = vk.createSemaphore(device,
- semaphoreInfo,
- renderFinished[i]))) {
- return r;
- }
- }
-
- inFlight = std::vector<sk::Fence>(maxInFlight);
- for (uint32_t i = 0; i < maxInFlight; ++i) {
- static constexpr VkFenceCreateInfo fenceInfo{
- VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
- nullptr,
- VK_FENCE_CREATE_SIGNALED_BIT};
-
- if ((r = vk.createFence(device, fenceInfo, inFlight[i]))) {
- return r;
- }
- }
-
- return VK_SUCCESS;
+ const auto maxInFlight = std::max(1u, numImages - 1u);
+ VkResult r = VK_SUCCESS;
+
+ imageAvailable = std::vector<sk::Semaphore>(numImages);
+ renderFinished = std::vector<sk::Semaphore>(numImages);
+ for (uint32_t i = 0; i < numImages; ++i) {
+ static constexpr VkSemaphoreCreateInfo semaphoreInfo{
+ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, {}};
+
+ if ((r = vk.createSemaphore(device, semaphoreInfo, imageAvailable[i])) ||
+ (r = vk.createSemaphore(device, semaphoreInfo, renderFinished[i]))) {
+ return r;
+ }
+ }
+
+ inFlight = std::vector<sk::Fence>(maxInFlight);
+ for (uint32_t i = 0; i < maxInFlight; ++i) {
+ static constexpr VkFenceCreateInfo fenceInfo{
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ nullptr,
+ VK_FENCE_CREATE_SIGNALED_BIT};
+
+ if ((r = vk.createFence(device, fenceInfo, inFlight[i]))) {
+ return r;
+ }
+ }
+
+ return VK_SUCCESS;
}
VkResult
@@ -1118,21 +1090,20 @@ Renderer::init(const sk::VulkanApi& vk,
const VkExtent2D extent,
bool resizing)
{
- VkResult r = VK_SUCCESS;
- VkSurfaceCapabilitiesKHR capabilities = {};
-
- if ((r = vk.getPhysicalDeviceSurfaceCapabilitiesKHR(gpu.physicalDevice,
- gpu.surface,
- capabilities)) ||
- (r = swapchain.init(vk, gpu, capabilities, extent, {}, resizing)) ||
- (r = renderPass.init(vk, gpu, swapchain)) ||
- (r = rectPipeline.init(
- vk, gpu, rectData, rectShaders, swapchain, renderPass))) {
- return r;
- }
-
- const auto numFrames = static_cast<uint32_t>(swapchain.imageViews.size());
- return sync.init(vk, gpu.device, numFrames);
+ VkResult r = VK_SUCCESS;
+ VkSurfaceCapabilitiesKHR capabilities = {};
+
+ if ((r = vk.getPhysicalDeviceSurfaceCapabilitiesKHR(
+ gpu.physicalDevice, gpu.surface, capabilities)) ||
+ (r = swapchain.init(vk, gpu, capabilities, extent, {}, resizing)) ||
+ (r = renderPass.init(vk, gpu, swapchain)) ||
+ (r = rectPipeline.init(
+ vk, gpu, rectData, rectShaders, swapchain, renderPass))) {
+ return r;
+ }
+
+ const auto numFrames = static_cast<uint32_t>(swapchain.imageViews.size());
+ return sync.init(vk, gpu.device, numFrames);
}
VkResult
@@ -1144,27 +1115,26 @@ Renderer::recreate(const sk::VulkanApi& vk,
const VkExtent2D extent,
bool resizing)
{
- VkResult r = VK_SUCCESS;
- const auto oldNumImages = swapchain.imageViews.size();
-
- VkSurfaceCapabilitiesKHR capabilities = {};
- if ((r = vk.getPhysicalDeviceSurfaceCapabilitiesKHR(gpu.physicalDevice,
- surface,
- capabilities)) ||
- (r = swapchain.init(
- vk, gpu, capabilities, extent, swapchain.swapchain, resizing)) ||
- (r = renderPass.init(vk, gpu, swapchain)) ||
- (r = rectPipeline.init(
- vk, gpu, rectData, rectShaders, swapchain, renderPass))) {
- return r;
- }
-
- const auto numFrames = static_cast<uint32_t>(swapchain.imageViews.size());
- if (swapchain.imageViews.size() != oldNumImages) {
- return sync.init(vk, gpu.device, numFrames);
- }
-
- return VK_SUCCESS;
+ VkResult r = VK_SUCCESS;
+ const auto oldNumImages = swapchain.imageViews.size();
+
+ VkSurfaceCapabilitiesKHR capabilities = {};
+ if ((r = vk.getPhysicalDeviceSurfaceCapabilitiesKHR(
+ gpu.physicalDevice, surface, capabilities)) ||
+ (r = swapchain.init(
+ vk, gpu, capabilities, extent, swapchain.swapchain, resizing)) ||
+ (r = renderPass.init(vk, gpu, swapchain)) ||
+ (r = rectPipeline.init(
+ vk, gpu, rectData, rectShaders, swapchain, renderPass))) {
+ return r;
+ }
+
+ const auto numFrames = static_cast<uint32_t>(swapchain.imageViews.size());
+ if (swapchain.imageViews.size() != oldNumImages) {
+ return sync.init(vk, gpu.device, numFrames);
+ }
+
+ return VK_SUCCESS;
}
VKAPI_ATTR
@@ -1178,43 +1148,43 @@ debugCallback(VkDebugReportFlagsEXT flags,
const char* msg,
void*)
{
- std::cerr << sk::string(static_cast<VkDebugReportFlagBitsEXT>(flags))
- << ": " << layerPrefix << ": " << msg << std::endl;
+ std::cerr << sk::string(static_cast<VkDebugReportFlagBitsEXT>(flags)) << ": "
+ << layerPrefix << ": " << msg << std::endl;
- return VK_FALSE;
+ return VK_FALSE;
}
bool
hasExtension(const char* name,
const std::vector<VkExtensionProperties>& properties)
{
- for (const auto& p : properties) {
- if (!strcmp(p.extensionName, name)) {
- return true;
- }
- }
+ for (const auto& p : properties) {
+ if (!strcmp(p.extensionName, name)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
bool
hasLayer(const char* name, const std::vector<VkLayerProperties>& properties)
{
- for (const auto& p : properties) {
- if (!strcmp(p.layerName, name)) {
- return true;
- }
- }
+ for (const auto& p : properties) {
+ if (!strcmp(p.layerName, name)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
template<class Value>
void
logInfo(const char* heading, const Value& value)
{
- std::cout << std::setw(26) << std::left << (std::string(heading) + ":")
- << value << std::endl;
+ std::cout << std::setw(26) << std::left << (std::string(heading) + ":")
+ << value << std::endl;
}
VkResult
@@ -1222,62 +1192,62 @@ createInstance(sk::VulkanInitApi& initApi,
const PuglTestOptions& opts,
sk::Instance& instance)
{
- VkResult r = VK_SUCCESS;
-
- std::vector<VkLayerProperties> layerProps;
- std::vector<VkExtensionProperties> extProps;
- if ((r = initApi.enumerateInstanceLayerProperties(layerProps)) ||
- (r = initApi.enumerateInstanceExtensionProperties(extProps))) {
- return r;
- }
-
- const auto puglExtensions = pugl::getInstanceExtensions();
- auto extensions = std::vector<const char*>(puglExtensions.begin(),
- puglExtensions.end());
-
- // Add extra extensions we want to use if they are supported
- if (hasExtension("VK_EXT_debug_report", extProps)) {
- extensions.push_back("VK_EXT_debug_report");
- }
-
- // Add validation layers if error checking is enabled
- std::vector<const char*> layers;
- if (opts.errorChecking) {
- for (const char* l : {"VK_LAYER_KHRONOS_validation",
- "VK_LAYER_LUNARG_standard_validation"}) {
- if (hasLayer(l, layerProps)) {
- layers.push_back(l);
- }
- }
- }
-
- for (const auto& e : extensions) {
- logInfo("Using instance extension", e);
- }
-
- for (const auto& l : layers) {
- logInfo("Using instance layer", l);
- }
-
- static constexpr VkApplicationInfo appInfo{
- VK_STRUCTURE_TYPE_APPLICATION_INFO,
- nullptr,
- "Pugl Vulkan Demo",
- 0,
- nullptr,
- 0,
- VK_MAKE_VERSION(1, 0, 0),
- };
-
- const VkInstanceCreateInfo createInfo{
- VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
- nullptr,
- VkInstanceCreateFlags{},
- &appInfo,
- SK_COUNTED(uint32_t(layers.size()), layers.data()),
- SK_COUNTED(uint32_t(extensions.size()), extensions.data())};
-
- return initApi.createInstance(createInfo, instance);
+ VkResult r = VK_SUCCESS;
+
+ std::vector<VkLayerProperties> layerProps;
+ std::vector<VkExtensionProperties> extProps;
+ if ((r = initApi.enumerateInstanceLayerProperties(layerProps)) ||
+ (r = initApi.enumerateInstanceExtensionProperties(extProps))) {
+ return r;
+ }
+
+ const auto puglExtensions = pugl::getInstanceExtensions();
+ auto extensions =
+ std::vector<const char*>(puglExtensions.begin(), puglExtensions.end());
+
+ // Add extra extensions we want to use if they are supported
+ if (hasExtension("VK_EXT_debug_report", extProps)) {
+ extensions.push_back("VK_EXT_debug_report");
+ }
+
+ // Add validation layers if error checking is enabled
+ std::vector<const char*> layers;
+ if (opts.errorChecking) {
+ for (const char* l : {"VK_LAYER_KHRONOS_validation",
+ "VK_LAYER_LUNARG_standard_validation"}) {
+ if (hasLayer(l, layerProps)) {
+ layers.push_back(l);
+ }
+ }
+ }
+
+ for (const auto& e : extensions) {
+ logInfo("Using instance extension", e);
+ }
+
+ for (const auto& l : layers) {
+ logInfo("Using instance layer", l);
+ }
+
+ static constexpr VkApplicationInfo appInfo{
+ VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ nullptr,
+ "Pugl Vulkan Demo",
+ 0,
+ nullptr,
+ 0,
+ VK_MAKE_VERSION(1, 0, 0),
+ };
+
+ const VkInstanceCreateInfo createInfo{
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ nullptr,
+ VkInstanceCreateFlags{},
+ &appInfo,
+ SK_COUNTED(uint32_t(layers.size()), layers.data()),
+ SK_COUNTED(uint32_t(extensions.size()), extensions.data())};
+
+ return initApi.createInstance(createInfo, instance);
}
VkResult
@@ -1286,28 +1256,27 @@ getDebugReportCallback(sk::VulkanApi& api,
const bool verbose,
sk::DebugReportCallbackEXT& callback)
{
- if (api.vkCreateDebugReportCallbackEXT) {
- VkDebugReportFlagsEXT flags =
- (VK_DEBUG_REPORT_WARNING_BIT_EXT |
- VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
- VK_DEBUG_REPORT_ERROR_BIT_EXT);
-
- if (verbose) {
- flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
- flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
- }
-
- const VkDebugReportCallbackCreateInfoEXT createInfo{
- VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
- nullptr,
- flags,
- debugCallback,
- nullptr};
-
- return api.createDebugReportCallbackEXT(instance, createInfo, callback);
- }
-
- return VK_ERROR_FEATURE_NOT_PRESENT;
+ if (api.vkCreateDebugReportCallbackEXT) {
+ VkDebugReportFlagsEXT flags = (VK_DEBUG_REPORT_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_ERROR_BIT_EXT);
+
+ if (verbose) {
+ flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+ flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ }
+
+ const VkDebugReportCallbackCreateInfoEXT createInfo{
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
+ nullptr,
+ flags,
+ debugCallback,
+ nullptr};
+
+ return api.createDebugReportCallbackEXT(instance, createInfo, callback);
+ }
+
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
void
@@ -1318,40 +1287,36 @@ recordCommandBuffer(sk::CommandScope& cmd,
const RectData& rectData,
const size_t imageIndex)
{
- const VkClearColorValue clearColorValue{{0.0f, 0.0f, 0.0f, 1.0f}};
- const VkClearValue clearValue{clearColorValue};
-
- const VkRenderPassBeginInfo renderPassBegin{
- VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- nullptr,
- renderPass.renderPass,
- renderPass.framebuffers[imageIndex],
- VkRect2D{{0, 0}, swapchain.extent},
- SK_COUNTED(1, &clearValue)};
-
- auto pass = cmd.beginRenderPass(renderPassBegin,
- VK_SUBPASS_CONTENTS_INLINE);
-
- pass.bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
- rectPipeline.pipelines[0]);
-
- const std::array<VkDeviceSize, 1> offsets{0};
- pass.bindVertexBuffers(
- 0u, SK_COUNTED(1u, &rectData.modelBuffer.buffer.get(), offsets.data()));
-
- pass.bindVertexBuffers(1u,
- SK_COUNTED(1u,
- &rectData.instanceBuffer.buffer.get(),
- offsets.data()));
-
- pass.bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
- rectPipeline.pipelineLayout,
- 0u,
- SK_COUNTED(1u, rectPipeline.descriptorSets.get()),
- 0u,
- nullptr);
-
- pass.draw(4u, static_cast<uint32_t>(rectData.numRects), 0u, 0u);
+ const VkClearColorValue clearColorValue{{0.0f, 0.0f, 0.0f, 1.0f}};
+ const VkClearValue clearValue{clearColorValue};
+
+ const VkRenderPassBeginInfo renderPassBegin{
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ nullptr,
+ renderPass.renderPass,
+ renderPass.framebuffers[imageIndex],
+ VkRect2D{{0, 0}, swapchain.extent},
+ SK_COUNTED(1, &clearValue)};
+
+ auto pass = cmd.beginRenderPass(renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
+
+ pass.bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, rectPipeline.pipelines[0]);
+
+ const std::array<VkDeviceSize, 1> offsets{0};
+ pass.bindVertexBuffers(
+ 0u, SK_COUNTED(1u, &rectData.modelBuffer.buffer.get(), offsets.data()));
+
+ pass.bindVertexBuffers(
+ 1u, SK_COUNTED(1u, &rectData.instanceBuffer.buffer.get(), offsets.data()));
+
+ pass.bindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS,
+ rectPipeline.pipelineLayout,
+ 0u,
+ SK_COUNTED(1u, rectPipeline.descriptorSets.get()),
+ 0u,
+ nullptr);
+
+ pass.draw(4u, static_cast<uint32_t>(rectData.numRects), 0u, 0u);
}
VkResult
@@ -1361,30 +1326,29 @@ recordCommandBuffers(const sk::VulkanApi& vk,
const RectPipeline& rectPipeline,
const RectData& rectData)
{
- VkResult r = VK_SUCCESS;
-
- for (size_t i = 0; i < swapchain.imageViews.size(); ++i) {
- const VkCommandBufferBeginInfo beginInfo{
- VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- nullptr,
- VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
- nullptr};
-
- auto* const commandBuffer = renderPass.commandBuffers[i];
- auto cmd = vk.beginCommandBuffer(commandBuffer, beginInfo);
- if (!cmd) {
- return cmd.error();
- }
-
- recordCommandBuffer(
- cmd, swapchain, renderPass, rectPipeline, rectData, i);
-
- if ((r = cmd.end())) {
- return r;
- }
- }
-
- return VK_SUCCESS;
+ VkResult r = VK_SUCCESS;
+
+ for (size_t i = 0; i < swapchain.imageViews.size(); ++i) {
+ const VkCommandBufferBeginInfo beginInfo{
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ nullptr,
+ VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
+ nullptr};
+
+ auto* const commandBuffer = renderPass.commandBuffers[i];
+ auto cmd = vk.beginCommandBuffer(commandBuffer, beginInfo);
+ if (!cmd) {
+ return cmd.error();
+ }
+
+ recordCommandBuffer(cmd, swapchain, renderPass, rectPipeline, rectData, i);
+
+ if ((r = cmd.end())) {
+ return r;
+ }
+ }
+
+ return VK_SUCCESS;
}
class PuglVulkanDemo;
@@ -1392,76 +1356,76 @@ class PuglVulkanDemo;
class View : public pugl::View
{
public:
- View(pugl::World& world, PuglVulkanDemo& app)
- : pugl::View{world}
- , _app{app}
- {
- setEventHandler(*this);
- }
-
- template<PuglEventType t, class Base>
- pugl::Status onEvent(const pugl::Event<t, Base>&) noexcept
- {
- return pugl::Status::success;
- }
-
- pugl::Status onEvent(const pugl::ConfigureEvent& event);
- pugl::Status onEvent(const pugl::UpdateEvent& event);
- pugl::Status onEvent(const pugl::ExposeEvent& event);
- pugl::Status onEvent(const pugl::LoopEnterEvent& event);
- pugl::Status onEvent(const pugl::TimerEvent& event);
- pugl::Status onEvent(const pugl::LoopLeaveEvent& event);
- pugl::Status onEvent(const pugl::KeyPressEvent& event);
- pugl::Status onEvent(const pugl::CloseEvent& event);
+ View(pugl::World& world, PuglVulkanDemo& app)
+ : pugl::View{world}
+ , _app{app}
+ {
+ setEventHandler(*this);
+ }
+
+ template<PuglEventType t, class Base>
+ pugl::Status onEvent(const pugl::Event<t, Base>&) noexcept
+ {
+ return pugl::Status::success;
+ }
+
+ pugl::Status onEvent(const pugl::ConfigureEvent& event);
+ pugl::Status onEvent(const pugl::UpdateEvent& event);
+ pugl::Status onEvent(const pugl::ExposeEvent& event);
+ pugl::Status onEvent(const pugl::LoopEnterEvent& event);
+ pugl::Status onEvent(const pugl::TimerEvent& event);
+ pugl::Status onEvent(const pugl::LoopLeaveEvent& event);
+ pugl::Status onEvent(const pugl::KeyPressEvent& event);
+ pugl::Status onEvent(const pugl::CloseEvent& event);
private:
- PuglVulkanDemo& _app;
+ PuglVulkanDemo& _app;
};
class PuglVulkanDemo
{
public:
- PuglVulkanDemo(const char* executablePath,
- const PuglTestOptions& o,
- size_t numRects);
-
- const char* programPath;
- PuglTestOptions opts;
- pugl::World world;
- pugl::VulkanLoader loader;
- View view;
- VulkanContext vulkan;
- GraphicsDevice gpu;
- Renderer renderer;
- RectData rectData;
- RectShaders rectShaders;
- uint32_t framesDrawn{0};
- VkExtent2D extent{512u, 512u};
- std::vector<Rect> rects;
- bool resizing{false};
- bool quit{false};
+ PuglVulkanDemo(const char* executablePath,
+ const PuglTestOptions& o,
+ size_t numRects);
+
+ const char* programPath;
+ PuglTestOptions opts;
+ pugl::World world;
+ pugl::VulkanLoader loader;
+ View view;
+ VulkanContext vulkan;
+ GraphicsDevice gpu;
+ Renderer renderer;
+ RectData rectData;
+ RectShaders rectShaders;
+ uint32_t framesDrawn{0};
+ VkExtent2D extent{512u, 512u};
+ std::vector<Rect> rects;
+ bool resizing{false};
+ bool quit{false};
};
std::vector<Rect>
makeRects(const size_t numRects, const uint32_t windowWidth)
{
- std::vector<Rect> rects(numRects);
- for (size_t i = 0; i < numRects; ++i) {
- rects[i] = makeRect(i, static_cast<float>(windowWidth));
- }
+ std::vector<Rect> rects(numRects);
+ for (size_t i = 0; i < numRects; ++i) {
+ rects[i] = makeRect(i, static_cast<float>(windowWidth));
+ }
- return rects;
+ return rects;
}
PuglVulkanDemo::PuglVulkanDemo(const char* const executablePath,
const PuglTestOptions& o,
const size_t numRects)
- : programPath{executablePath}
- , opts{o}
- , world{pugl::WorldType::program, pugl::WorldFlag::threads}
- , loader{world}
- , view{world, *this}
- , rects{makeRects(numRects, extent.width)}
+ : programPath{executablePath}
+ , opts{o}
+ , world{pugl::WorldType::program, pugl::WorldFlag::threads}
+ , loader{world}
+ , view{world, *this}
+ , rects{makeRects(numRects, extent.width)}
{}
VkResult
@@ -1472,148 +1436,140 @@ recreateRenderer(PuglVulkanDemo& app,
const RectData& rectData,
const RectShaders& rectShaders)
{
- VkResult r = VK_SUCCESS;
- VkSurfaceCapabilitiesKHR capabilities = {};
- if ((r = vk.getPhysicalDeviceSurfaceCapabilitiesKHR(gpu.physicalDevice,
- gpu.surface,
- capabilities))) {
- return r;
- }
-
- // There is a known race issue here, so we clamp and hope for the best
- const VkExtent2D clampedExtent{
- std::min(capabilities.maxImageExtent.width,
- std::max(capabilities.minImageExtent.width, extent.width)),
- std::min(capabilities.maxImageExtent.height,
- std::max(capabilities.minImageExtent.height, extent.height))};
-
- if ((r = vk.deviceWaitIdle(gpu.device)) ||
- (r = app.renderer.recreate(vk,
- gpu.surface,
- gpu,
- rectData,
- rectShaders,
- clampedExtent,
- app.resizing))) {
- return r;
- }
-
- // Reset current (initially signaled) fence because we already waited
- vk.resetFence(gpu.device,
- app.renderer.sync.inFlight[app.renderer.sync.currentFrame]);
-
- // Record new command buffers
- return recordCommandBuffers(vk,
- app.renderer.swapchain,
- app.renderer.renderPass,
- app.renderer.rectPipeline,
- rectData);
+ VkResult r = VK_SUCCESS;
+ VkSurfaceCapabilitiesKHR capabilities = {};
+ if ((r = vk.getPhysicalDeviceSurfaceCapabilitiesKHR(
+ gpu.physicalDevice, gpu.surface, capabilities))) {
+ return r;
+ }
+
+ // There is a known race issue here, so we clamp and hope for the best
+ const VkExtent2D clampedExtent{
+ std::min(capabilities.maxImageExtent.width,
+ std::max(capabilities.minImageExtent.width, extent.width)),
+ std::min(capabilities.maxImageExtent.height,
+ std::max(capabilities.minImageExtent.height, extent.height))};
+
+ if ((r = vk.deviceWaitIdle(gpu.device)) ||
+ (r = app.renderer.recreate(vk,
+ gpu.surface,
+ gpu,
+ rectData,
+ rectShaders,
+ clampedExtent,
+ app.resizing))) {
+ return r;
+ }
+
+ // Reset current (initially signaled) fence because we already waited
+ vk.resetFence(gpu.device,
+ app.renderer.sync.inFlight[app.renderer.sync.currentFrame]);
+
+ // Record new command buffers
+ return recordCommandBuffers(vk,
+ app.renderer.swapchain,
+ app.renderer.renderPass,
+ app.renderer.rectPipeline,
+ rectData);
}
pugl::Status
View::onEvent(const pugl::ConfigureEvent& event)
{
- // We just record the size here and lazily resize the surface when exposed
- _app.extent = {static_cast<uint32_t>(event.width),
- static_cast<uint32_t>(event.height)};
+ // We just record the size here and lazily resize the surface when exposed
+ _app.extent = {static_cast<uint32_t>(event.width),
+ static_cast<uint32_t>(event.height)};
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
View::onEvent(const pugl::UpdateEvent&)
{
- return postRedisplay();
+ return postRedisplay();
}
VkResult
beginFrame(PuglVulkanDemo& app, const sk::Device& device, uint32_t& imageIndex)
{
- const auto& vk = app.vulkan.vk;
-
- VkResult r = VK_SUCCESS;
-
- // Wait until we can start rendering the next frame
- if ((r = vk.waitForFence(
- device,
- app.renderer.sync.inFlight[app.renderer.sync.currentFrame])) ||
- (r = vk.resetFence(
- device,
- app.renderer.sync.inFlight[app.renderer.sync.currentFrame]))) {
- return r;
- }
-
- // Rebuild the renderer first if the window size has changed
- if (app.extent.width != app.renderer.swapchain.extent.width ||
- app.extent.height != app.renderer.swapchain.extent.height) {
- if ((r = recreateRenderer(app,
- vk,
- app.gpu,
- app.extent,
- app.rectData,
- app.rectShaders))) {
- return r;
- }
- }
-
- // Acquire the next image to render, rebuilding if necessary
- while (
- (r = vk.acquireNextImageKHR(
- device,
- app.renderer.swapchain.swapchain,
- UINT64_MAX,
- app.renderer.sync.imageAvailable[app.renderer.sync.currentFrame],
- {},
- &imageIndex))) {
- switch (r) {
- case VK_SUBOPTIMAL_KHR:
- case VK_ERROR_OUT_OF_DATE_KHR:
- if ((r = recreateRenderer(app,
- vk,
- app.gpu,
- app.renderer.swapchain.extent,
- app.rectData,
- app.rectShaders))) {
- return r;
- }
- continue;
- default:
- return r;
- }
- }
-
- return VK_SUCCESS;
+ const auto& vk = app.vulkan.vk;
+
+ VkResult r = VK_SUCCESS;
+
+ // Wait until we can start rendering the next frame
+ if ((r = vk.waitForFence(
+ device, app.renderer.sync.inFlight[app.renderer.sync.currentFrame])) ||
+ (r = vk.resetFence(
+ device, app.renderer.sync.inFlight[app.renderer.sync.currentFrame]))) {
+ return r;
+ }
+
+ // Rebuild the renderer first if the window size has changed
+ if (app.extent.width != app.renderer.swapchain.extent.width ||
+ app.extent.height != app.renderer.swapchain.extent.height) {
+ if ((r = recreateRenderer(
+ app, vk, app.gpu, app.extent, app.rectData, app.rectShaders))) {
+ return r;
+ }
+ }
+
+ // Acquire the next image to render, rebuilding if necessary
+ while ((r = vk.acquireNextImageKHR(
+ device,
+ app.renderer.swapchain.swapchain,
+ UINT64_MAX,
+ app.renderer.sync.imageAvailable[app.renderer.sync.currentFrame],
+ {},
+ &imageIndex))) {
+ switch (r) {
+ case VK_SUBOPTIMAL_KHR:
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ if ((r = recreateRenderer(app,
+ vk,
+ app.gpu,
+ app.renderer.swapchain.extent,
+ app.rectData,
+ app.rectShaders))) {
+ return r;
+ }
+ continue;
+ default:
+ return r;
+ }
+ }
+
+ return VK_SUCCESS;
}
void
update(PuglVulkanDemo& app, const double time)
{
- // Animate rectangles
- for (size_t i = 0; i < app.rects.size(); ++i) {
- moveRect(&app.rects[i],
- i,
- app.rects.size(),
- static_cast<float>(app.extent.width),
- static_cast<float>(app.extent.height),
- time);
- }
-
- // Update vertex buffer
- memcpy(app.rectData.vertexData.get(),
- app.rects.data(),
- sizeof(Rect) * app.rects.size());
-
- // Update uniform buffer
- UniformBufferObject ubo = {{}};
- mat4Ortho(ubo.projection,
- 0.0f,
- float(app.renderer.swapchain.extent.width),
- 0.0f,
- float(app.renderer.swapchain.extent.height),
- -1.0f,
- 1.0f);
-
- memcpy(app.rectData.uniformData.get(), &ubo, sizeof(ubo));
+ // Animate rectangles
+ for (size_t i = 0; i < app.rects.size(); ++i) {
+ moveRect(&app.rects[i],
+ i,
+ app.rects.size(),
+ static_cast<float>(app.extent.width),
+ static_cast<float>(app.extent.height),
+ time);
+ }
+
+ // Update vertex buffer
+ memcpy(app.rectData.vertexData.get(),
+ app.rects.data(),
+ sizeof(Rect) * app.rects.size());
+
+ // Update uniform buffer
+ UniformBufferObject ubo = {{}};
+ mat4Ortho(ubo.projection,
+ 0.0f,
+ float(app.renderer.swapchain.extent.width),
+ 0.0f,
+ float(app.renderer.swapchain.extent.height),
+ -1.0f,
+ 1.0f);
+
+ memcpy(app.rectData.uniformData.get(), &ubo, sizeof(ubo));
}
VkResult
@@ -1622,133 +1578,132 @@ endFrame(const sk::VulkanApi& vk,
const Renderer& renderer,
const uint32_t imageIndex)
{
- const auto currentFrame = renderer.sync.currentFrame;
- VkResult r = VK_SUCCESS;
-
- static constexpr VkPipelineStageFlags waitStage =
- VK_PIPELINE_STAGE_TRANSFER_BIT;
-
- const VkSubmitInfo submitInfo{
- VK_STRUCTURE_TYPE_SUBMIT_INFO,
- nullptr,
- SK_COUNTED(1, &renderer.sync.imageAvailable[currentFrame].get()),
- &waitStage,
- SK_COUNTED(1, &renderer.renderPass.commandBuffers[imageIndex]),
- SK_COUNTED(1, &renderer.sync.renderFinished[imageIndex].get())};
-
- if ((r = vk.queueSubmit(gpu.graphicsQueue,
- submitInfo,
- renderer.sync.inFlight[currentFrame]))) {
- return r;
- }
-
- const VkPresentInfoKHR presentInfo{
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
- nullptr,
- SK_COUNTED(1, &renderer.sync.renderFinished[imageIndex].get()),
- SK_COUNTED(1, &renderer.swapchain.swapchain.get(), &imageIndex),
- nullptr};
-
- switch ((r = vk.queuePresentKHR(gpu.graphicsQueue, presentInfo))) {
- case VK_SUCCESS: // Sucessfully presented
- case VK_SUBOPTIMAL_KHR: // Probably a resize race, ignore
- case VK_ERROR_OUT_OF_DATE_KHR: // Probably a resize race, ignore
- break;
- default:
- return r;
- }
-
- return VK_SUCCESS;
+ const auto currentFrame = renderer.sync.currentFrame;
+ VkResult r = VK_SUCCESS;
+
+ static constexpr VkPipelineStageFlags waitStage =
+ VK_PIPELINE_STAGE_TRANSFER_BIT;
+
+ const VkSubmitInfo submitInfo{
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ nullptr,
+ SK_COUNTED(1, &renderer.sync.imageAvailable[currentFrame].get()),
+ &waitStage,
+ SK_COUNTED(1, &renderer.renderPass.commandBuffers[imageIndex]),
+ SK_COUNTED(1, &renderer.sync.renderFinished[imageIndex].get())};
+
+ if ((r = vk.queueSubmit(gpu.graphicsQueue,
+ submitInfo,
+ renderer.sync.inFlight[currentFrame]))) {
+ return r;
+ }
+
+ const VkPresentInfoKHR presentInfo{
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ nullptr,
+ SK_COUNTED(1, &renderer.sync.renderFinished[imageIndex].get()),
+ SK_COUNTED(1, &renderer.swapchain.swapchain.get(), &imageIndex),
+ nullptr};
+
+ switch ((r = vk.queuePresentKHR(gpu.graphicsQueue, presentInfo))) {
+ case VK_SUCCESS: // Sucessfully presented
+ case VK_SUBOPTIMAL_KHR: // Probably a resize race, ignore
+ case VK_ERROR_OUT_OF_DATE_KHR: // Probably a resize race, ignore
+ break;
+ default:
+ return r;
+ }
+
+ return VK_SUCCESS;
}
pugl::Status
View::onEvent(const pugl::ExposeEvent&)
{
- const auto& vk = _app.vulkan.vk;
- const auto& gpu = _app.gpu;
+ const auto& vk = _app.vulkan.vk;
+ const auto& gpu = _app.gpu;
- // Acquire the next image, waiting and/or rebuilding if necessary
- auto nextImageIndex = 0u;
- if (beginFrame(_app, gpu.device, nextImageIndex)) {
- return pugl::Status::unknownError;
- }
+ // Acquire the next image, waiting and/or rebuilding if necessary
+ auto nextImageIndex = 0u;
+ if (beginFrame(_app, gpu.device, nextImageIndex)) {
+ return pugl::Status::unknownError;
+ }
- // Ready to go, update the data to the current time
- update(_app, world().time());
+ // Ready to go, update the data to the current time
+ update(_app, world().time());
- // Submit the frame to the queue and present it
- endFrame(vk, gpu, _app.renderer, nextImageIndex);
+ // Submit the frame to the queue and present it
+ endFrame(vk, gpu, _app.renderer, nextImageIndex);
- ++_app.framesDrawn;
- ++_app.renderer.sync.currentFrame;
- _app.renderer.sync.currentFrame %= _app.renderer.sync.inFlight.size();
+ ++_app.framesDrawn;
+ ++_app.renderer.sync.currentFrame;
+ _app.renderer.sync.currentFrame %= _app.renderer.sync.inFlight.size();
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
View::onEvent(const pugl::LoopEnterEvent&)
{
- _app.resizing = true;
- startTimer(resizeTimerId,
- 1.0 / static_cast<double>(getHint(pugl::ViewHint::refreshRate)));
+ _app.resizing = true;
+ startTimer(resizeTimerId,
+ 1.0 / static_cast<double>(getHint(pugl::ViewHint::refreshRate)));
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
View::onEvent(const pugl::TimerEvent&)
{
- return postRedisplay();
+ return postRedisplay();
}
pugl::Status
View::onEvent(const pugl::LoopLeaveEvent&)
{
- stopTimer(resizeTimerId);
+ stopTimer(resizeTimerId);
- // Trigger a swapchain recreation with the normal present mode
- _app.renderer.swapchain.extent = {};
- _app.resizing = false;
+ // Trigger a swapchain recreation with the normal present mode
+ _app.renderer.swapchain.extent = {};
+ _app.resizing = false;
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
View::onEvent(const pugl::KeyPressEvent& event)
{
- if (event.key == PUGL_KEY_ESCAPE || event.key == 'q') {
- _app.quit = true;
- }
+ if (event.key == PUGL_KEY_ESCAPE || event.key == 'q') {
+ _app.quit = true;
+ }
- return pugl::Status::success;
+ return pugl::Status::success;
}
pugl::Status
View::onEvent(const pugl::CloseEvent&)
{
- _app.quit = true;
+ _app.quit = true;
- return pugl::Status::success;
+ return pugl::Status::success;
}
VkResult
VulkanContext::init(pugl::VulkanLoader& loader, const PuglTestOptions& opts)
{
- VkResult r = VK_SUCCESS;
+ VkResult r = VK_SUCCESS;
- sk::VulkanInitApi initApi{};
+ sk::VulkanInitApi initApi{};
- // Load Vulkan API and set up the fundamentals
- if ((r = initApi.init(loader.getInstanceProcAddrFunc())) ||
- (r = createInstance(initApi, opts, instance)) ||
- (r = vk.init(initApi, instance)) ||
- (r = getDebugReportCallback(
- vk, instance, opts.verbose, debugCallback))) {
- return r;
- }
+ // Load Vulkan API and set up the fundamentals
+ if ((r = initApi.init(loader.getInstanceProcAddrFunc())) ||
+ (r = createInstance(initApi, opts, instance)) ||
+ (r = vk.init(initApi, instance)) ||
+ (r = getDebugReportCallback(vk, instance, opts.verbose, debugCallback))) {
+ return r;
+ }
- return VK_SUCCESS;
+ return VK_SUCCESS;
}
int
@@ -1756,90 +1711,90 @@ run(const char* const programPath,
const PuglTestOptions opts,
const size_t numRects)
{
- PuglVulkanDemo app{programPath, opts, numRects};
-
- VkResult r = VK_SUCCESS;
- const auto width = static_cast<int>(app.extent.width);
- const auto height = static_cast<int>(app.extent.height);
-
- // Realize window so we can set up Vulkan
- app.world.setClassName("PuglVulkanDemo");
- app.view.setWindowTitle("Pugl Vulkan Demo");
- app.view.setAspectRatio(1, 1, 16, 9);
- app.view.setDefaultSize(width, height);
- app.view.setMinSize(width / 4, height / 4);
- app.view.setBackend(pugl::vulkanBackend());
- app.view.setHint(pugl::ViewHint::resizable, opts.resizable);
- const pugl::Status st = app.view.realize();
- if (st != pugl::Status::success) {
- return logError("Failed to create window (%s)\n", pugl::strerror(st));
- }
-
- if (!app.loader) {
- return logError("Failed to load Vulkan library\n");
- }
-
- // Load Vulkan for the view
- if ((r = app.vulkan.init(app.loader, opts))) {
- return logError("Failed to set up Vulkan API (%s)\n", sk::string(r));
- }
-
- const auto& vk = app.vulkan.vk;
-
- // Set up the graphics device
- if ((r = app.gpu.init(app.loader, app.vulkan, app.view, opts))) {
- return logError("Failed to set up device (%s)\n", sk::string(r));
- }
-
- logInfo("Present mode", sk::string(app.gpu.presentMode));
- logInfo("Resize present mode", sk::string(app.gpu.resizePresentMode));
-
- // Set up the rectangle data we will render every frame
- if ((r = app.rectData.init(vk, app.gpu, app.rects.size()))) {
- return logError("Failed to allocate render data (%s)\n", sk::string(r));
- }
-
- // Load shader modules
- if ((r = app.rectShaders.init(vk, app.gpu, app.programPath))) {
- return logError("Failed to load shaders (%s)\n", sk::string(r));
- }
-
- if ((r = app.renderer.init(app.vulkan.vk,
- app.gpu,
- app.rectData,
- app.rectShaders,
- app.extent,
- false))) {
- return logError("Failed to create renderer (%s)\n", sk::string(r));
- }
-
- logInfo("Swapchain frames",
- std::to_string(app.renderer.swapchain.imageViews.size()));
- logInfo("Frames in flight",
- std::to_string(app.renderer.sync.inFlight.size()));
-
- recordCommandBuffers(app.vulkan.vk,
- app.renderer.swapchain,
- app.renderer.renderPass,
- app.renderer.rectPipeline,
- app.rectData);
-
- const int refreshRate = app.view.getHint(pugl::ViewHint::refreshRate);
- const double frameDuration = 1.0 / static_cast<double>(refreshRate);
- const double timeout = app.opts.sync ? frameDuration : 0.0;
-
- PuglFpsPrinter fpsPrinter = {app.world.time()};
- app.view.show();
- while (!app.quit) {
- app.world.update(timeout);
- puglPrintFps(app.world.cobj(), &fpsPrinter, &app.framesDrawn);
- }
-
- if ((r = app.vulkan.vk.deviceWaitIdle(app.gpu.device))) {
- return logError("Failed to wait for device idle (%s)\n", sk::string(r));
- }
-
- return 0;
+ PuglVulkanDemo app{programPath, opts, numRects};
+
+ VkResult r = VK_SUCCESS;
+ const auto width = static_cast<int>(app.extent.width);
+ const auto height = static_cast<int>(app.extent.height);
+
+ // Realize window so we can set up Vulkan
+ app.world.setClassName("PuglVulkanDemo");
+ app.view.setWindowTitle("Pugl Vulkan Demo");
+ app.view.setAspectRatio(1, 1, 16, 9);
+ app.view.setDefaultSize(width, height);
+ app.view.setMinSize(width / 4, height / 4);
+ app.view.setBackend(pugl::vulkanBackend());
+ app.view.setHint(pugl::ViewHint::resizable, opts.resizable);
+ const pugl::Status st = app.view.realize();
+ if (st != pugl::Status::success) {
+ return logError("Failed to create window (%s)\n", pugl::strerror(st));
+ }
+
+ if (!app.loader) {
+ return logError("Failed to load Vulkan library\n");
+ }
+
+ // Load Vulkan for the view
+ if ((r = app.vulkan.init(app.loader, opts))) {
+ return logError("Failed to set up Vulkan API (%s)\n", sk::string(r));
+ }
+
+ const auto& vk = app.vulkan.vk;
+
+ // Set up the graphics device
+ if ((r = app.gpu.init(app.loader, app.vulkan, app.view, opts))) {
+ return logError("Failed to set up device (%s)\n", sk::string(r));
+ }
+
+ logInfo("Present mode", sk::string(app.gpu.presentMode));
+ logInfo("Resize present mode", sk::string(app.gpu.resizePresentMode));
+
+ // Set up the rectangle data we will render every frame
+ if ((r = app.rectData.init(vk, app.gpu, app.rects.size()))) {
+ return logError("Failed to allocate render data (%s)\n", sk::string(r));
+ }
+
+ // Load shader modules
+ if ((r = app.rectShaders.init(vk, app.gpu, app.programPath))) {
+ return logError("Failed to load shaders (%s)\n", sk::string(r));
+ }
+
+ if ((r = app.renderer.init(app.vulkan.vk,
+ app.gpu,
+ app.rectData,
+ app.rectShaders,
+ app.extent,
+ false))) {
+ return logError("Failed to create renderer (%s)\n", sk::string(r));
+ }
+
+ logInfo("Swapchain frames",
+ std::to_string(app.renderer.swapchain.imageViews.size()));
+ logInfo("Frames in flight",
+ std::to_string(app.renderer.sync.inFlight.size()));
+
+ recordCommandBuffers(app.vulkan.vk,
+ app.renderer.swapchain,
+ app.renderer.renderPass,
+ app.renderer.rectPipeline,
+ app.rectData);
+
+ const int refreshRate = app.view.getHint(pugl::ViewHint::refreshRate);
+ const double frameDuration = 1.0 / static_cast<double>(refreshRate);
+ const double timeout = app.opts.sync ? frameDuration : 0.0;
+
+ PuglFpsPrinter fpsPrinter = {app.world.time()};
+ app.view.show();
+ while (!app.quit) {
+ app.world.update(timeout);
+ puglPrintFps(app.world.cobj(), &fpsPrinter, &app.framesDrawn);
+ }
+
+ if ((r = app.vulkan.vk.deviceWaitIdle(app.gpu.device))) {
+ return logError("Failed to wait for device idle (%s)\n", sk::string(r));
+ }
+
+ return 0;
}
} // namespace
@@ -1847,25 +1802,25 @@ run(const char* const programPath,
int
main(int argc, char** argv)
{
- // Parse command line options
- const char* const programPath = argv[0];
- const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
- if (opts.help) {
- puglPrintTestUsage(programPath, "");
- return 0;
- }
-
- // Parse number of rectangles argument, if given
- int64_t numRects = 1000;
- if (argc >= 1) {
- char* endptr = nullptr;
- numRects = strtol(argv[0], &endptr, 10);
- if (endptr != argv[0] + strlen(argv[0]) || numRects < 1) {
- logError("Invalid number of rectangles: %s\n", argv[0]);
- return 1;
- }
- }
-
- // Run application
- return run(programPath, opts, static_cast<size_t>(numRects));
+ // Parse command line options
+ const char* const programPath = argv[0];
+ const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
+ if (opts.help) {
+ puglPrintTestUsage(programPath, "");
+ return 0;
+ }
+
+ // Parse number of rectangles argument, if given
+ int64_t numRects = 1000;
+ if (argc >= 1) {
+ char* endptr = nullptr;
+ numRects = strtol(argv[0], &endptr, 10);
+ if (endptr != argv[0] + strlen(argv[0]) || numRects < 1) {
+ logError("Invalid number of rectangles: %s\n", argv[0]);
+ return 1;
+ }
+ }
+
+ // Run application
+ return run(programPath, opts, static_cast<size_t>(numRects));
}
diff --git a/examples/pugl_vulkan_demo.c b/examples/pugl_vulkan_demo.c
index ec96ec3..4a8324e 100644
--- a/examples/pugl_vulkan_demo.c
+++ b/examples/pugl_vulkan_demo.c
@@ -50,55 +50,55 @@
/// Dynamically loaded Vulkan API functions
typedef struct {
- PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
- PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
+ PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
+ PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
} InstanceAPI;
/// Vulkan swapchain and everything that depends on it
typedef struct {
- VkSwapchainKHR rawSwapchain;
- uint32_t nImages;
- VkExtent2D extent;
- VkImage* images;
- VkImageView* imageViews;
- VkFence* fences;
- VkCommandBuffer* commandBuffers;
+ VkSwapchainKHR rawSwapchain;
+ uint32_t nImages;
+ VkExtent2D extent;
+ VkImage* images;
+ VkImageView* imageViews;
+ VkFence* fences;
+ VkCommandBuffer* commandBuffers;
} Swapchain;
/// Synchronization semaphores
typedef struct {
- VkSemaphore presentComplete;
- VkSemaphore renderFinished;
+ VkSemaphore presentComplete;
+ VkSemaphore renderFinished;
} Sync;
/// Vulkan state, purely Vulkan functions can depend on only this
typedef struct {
- InstanceAPI api;
- VkInstance instance;
- VkDebugReportCallbackEXT debugCallback;
- VkSurfaceKHR surface;
- VkSurfaceFormatKHR surfaceFormat;
- VkPresentModeKHR presentMode;
- VkPhysicalDeviceProperties deviceProperties;
- VkPhysicalDevice physicalDevice;
- uint32_t graphicsIndex;
- VkDevice device;
- VkQueue graphicsQueue;
- VkCommandPool commandPool;
- Swapchain* swapchain;
- Sync sync;
+ InstanceAPI api;
+ VkInstance instance;
+ VkDebugReportCallbackEXT debugCallback;
+ VkSurfaceKHR surface;
+ VkSurfaceFormatKHR surfaceFormat;
+ VkPresentModeKHR presentMode;
+ VkPhysicalDeviceProperties deviceProperties;
+ VkPhysicalDevice physicalDevice;
+ uint32_t graphicsIndex;
+ VkDevice device;
+ VkQueue graphicsQueue;
+ VkCommandPool commandPool;
+ Swapchain* swapchain;
+ Sync sync;
} VulkanState;
/// Complete application
typedef struct {
- PuglTestOptions opts;
- PuglWorld* world;
- PuglView* view;
- VulkanState vk;
- uint32_t framesDrawn;
- uint32_t width;
- uint32_t height;
- bool quit;
+ PuglTestOptions opts;
+ PuglWorld* world;
+ PuglView* view;
+ VulkanState vk;
+ uint32_t framesDrawn;
+ uint32_t width;
+ uint32_t height;
+ bool quit;
} VulkanApp;
static VKAPI_ATTR VkBool32 VKAPI_CALL
@@ -111,27 +111,27 @@ debugCallback(VkDebugReportFlagsEXT flags,
const char* msg,
void* userData)
{
- (void)userData;
- (void)objType;
- (void)obj;
- (void)location;
- (void)code;
-
- if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
- fprintf(stderr, "note: ");
- } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
- fprintf(stderr, "warning: ");
- } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
- fprintf(stderr, "performance warning: ");
- } else if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
- fprintf(stderr, "error: ");
- } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
- fprintf(stderr, "debug: ");
- }
-
- fprintf(stderr, "%s: ", layerPrefix);
- fprintf(stderr, "%s\n", msg);
- return VK_FALSE;
+ (void)userData;
+ (void)objType;
+ (void)obj;
+ (void)location;
+ (void)code;
+
+ if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
+ fprintf(stderr, "note: ");
+ } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ fprintf(stderr, "warning: ");
+ } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
+ fprintf(stderr, "performance warning: ");
+ } else if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ fprintf(stderr, "error: ");
+ } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
+ fprintf(stderr, "debug: ");
+ }
+
+ fprintf(stderr, "%s: ", layerPrefix);
+ fprintf(stderr, "%s\n", msg);
+ return VK_FALSE;
}
static bool
@@ -139,13 +139,13 @@ hasExtension(const char* const name,
const VkExtensionProperties* const properties,
const uint32_t count)
{
- for (uint32_t i = 0; i < count; ++i) {
- if (!strcmp(properties[i].extensionName, name)) {
- return true;
- }
- }
+ for (uint32_t i = 0; i < count; ++i) {
+ if (!strcmp(properties[i].extensionName, name)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static bool
@@ -153,13 +153,13 @@ hasLayer(const char* const name,
const VkLayerProperties* const properties,
const uint32_t count)
{
- for (uint32_t i = 0; i < count; ++i) {
- if (!strcmp(properties[i].layerName, name)) {
- return true;
- }
- }
+ for (uint32_t i = 0; i < count; ++i) {
+ if (!strcmp(properties[i].layerName, name)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static void
@@ -167,129 +167,129 @@ pushString(const char*** const array,
uint32_t* const count,
const char* const string)
{
- *array = (const char**)realloc(*array, (*count + 1) * sizeof(const char*));
- (*array)[*count] = string;
- ++*count;
+ *array = (const char**)realloc(*array, (*count + 1) * sizeof(const char*));
+ (*array)[*count] = string;
+ ++*count;
}
static VkResult
createInstance(VulkanApp* const app)
{
- const VkApplicationInfo appInfo = {
- VK_STRUCTURE_TYPE_APPLICATION_INFO,
- NULL,
- "Pugl Vulkan Test",
- VK_MAKE_VERSION(0, 1, 0),
- "Pugl Vulkan Test Engine",
- VK_MAKE_VERSION(0, 1, 0),
- VK_MAKE_VERSION(1, 0, 0),
- };
-
- // Get the number of supported extensions and layers
- VkResult vr = VK_SUCCESS;
- uint32_t nExtProps = 0;
- uint32_t nLayerProps = 0;
- if ((vr = vkEnumerateInstanceLayerProperties(&nLayerProps, NULL)) ||
- (vr = vkEnumerateInstanceExtensionProperties(NULL, &nExtProps, NULL))) {
- return vr;
- }
-
- // Get properties of supported extensions
- VkExtensionProperties* extProps = AALLOC(nExtProps, VkExtensionProperties);
- vkEnumerateInstanceExtensionProperties(NULL, &nExtProps, extProps);
-
- uint32_t nExtensions = 0;
- const char** extensions = NULL;
-
- // Add extensions required by pugl
- uint32_t nPuglExts = 0;
- const char* const* puglExts = puglGetInstanceExtensions(&nPuglExts);
- for (uint32_t i = 0; i < nPuglExts; ++i) {
- pushString(&extensions, &nExtensions, puglExts[i]);
- }
-
- // Add extra extensions we want to use if they are supported
- if (hasExtension("VK_EXT_debug_report", extProps, nExtProps)) {
- pushString(&extensions, &nExtensions, "VK_EXT_debug_report");
- }
-
- // Get properties of supported layers
- VkLayerProperties* layerProps = AALLOC(nLayerProps, VkLayerProperties);
- vkEnumerateInstanceLayerProperties(&nLayerProps, layerProps);
-
- // Add validation layers if error checking is enabled
- uint32_t nLayers = 0;
- const char** layers = NULL;
- if (app->opts.errorChecking) {
- const char* debugLayers[] = {"VK_LAYER_KHRONOS_validation",
- "VK_LAYER_LUNARG_standard_validation",
- NULL};
-
- for (const char** l = debugLayers; *l; ++l) {
- if (hasLayer(*l, layerProps, nLayerProps)) {
- pushString(&layers, &nLayers, *l);
- }
- }
- }
-
- for (uint32_t i = 0; i < nExtensions; ++i) {
- printf("Using instance extension: %s\n", extensions[i]);
- }
-
- for (uint32_t i = 0; i < nLayers; ++i) {
- printf("Using instance layer: %s\n", layers[i]);
- }
-
- const VkInstanceCreateInfo createInfo = {
- VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
- NULL,
- 0,
- &appInfo,
- COUNTED(nLayers, layers),
- COUNTED(nExtensions, extensions),
- };
-
- if ((vr = vkCreateInstance(&createInfo, ALLOC_VK, &app->vk.instance))) {
- logError("Could not create Vulkan Instance: %d\n", vr);
- }
-
- free(layers);
- free(extensions);
- free(layerProps);
- free(extProps);
-
- return vr;
+ const VkApplicationInfo appInfo = {
+ VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ NULL,
+ "Pugl Vulkan Test",
+ VK_MAKE_VERSION(0, 1, 0),
+ "Pugl Vulkan Test Engine",
+ VK_MAKE_VERSION(0, 1, 0),
+ VK_MAKE_VERSION(1, 0, 0),
+ };
+
+ // Get the number of supported extensions and layers
+ VkResult vr = VK_SUCCESS;
+ uint32_t nExtProps = 0;
+ uint32_t nLayerProps = 0;
+ if ((vr = vkEnumerateInstanceLayerProperties(&nLayerProps, NULL)) ||
+ (vr = vkEnumerateInstanceExtensionProperties(NULL, &nExtProps, NULL))) {
+ return vr;
+ }
+
+ // Get properties of supported extensions
+ VkExtensionProperties* extProps = AALLOC(nExtProps, VkExtensionProperties);
+ vkEnumerateInstanceExtensionProperties(NULL, &nExtProps, extProps);
+
+ uint32_t nExtensions = 0;
+ const char** extensions = NULL;
+
+ // Add extensions required by pugl
+ uint32_t nPuglExts = 0;
+ const char* const* puglExts = puglGetInstanceExtensions(&nPuglExts);
+ for (uint32_t i = 0; i < nPuglExts; ++i) {
+ pushString(&extensions, &nExtensions, puglExts[i]);
+ }
+
+ // Add extra extensions we want to use if they are supported
+ if (hasExtension("VK_EXT_debug_report", extProps, nExtProps)) {
+ pushString(&extensions, &nExtensions, "VK_EXT_debug_report");
+ }
+
+ // Get properties of supported layers
+ VkLayerProperties* layerProps = AALLOC(nLayerProps, VkLayerProperties);
+ vkEnumerateInstanceLayerProperties(&nLayerProps, layerProps);
+
+ // Add validation layers if error checking is enabled
+ uint32_t nLayers = 0;
+ const char** layers = NULL;
+ if (app->opts.errorChecking) {
+ const char* debugLayers[] = {"VK_LAYER_KHRONOS_validation",
+ "VK_LAYER_LUNARG_standard_validation",
+ NULL};
+
+ for (const char** l = debugLayers; *l; ++l) {
+ if (hasLayer(*l, layerProps, nLayerProps)) {
+ pushString(&layers, &nLayers, *l);
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < nExtensions; ++i) {
+ printf("Using instance extension: %s\n", extensions[i]);
+ }
+
+ for (uint32_t i = 0; i < nLayers; ++i) {
+ printf("Using instance layer: %s\n", layers[i]);
+ }
+
+ const VkInstanceCreateInfo createInfo = {
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ NULL,
+ 0,
+ &appInfo,
+ COUNTED(nLayers, layers),
+ COUNTED(nExtensions, extensions),
+ };
+
+ if ((vr = vkCreateInstance(&createInfo, ALLOC_VK, &app->vk.instance))) {
+ logError("Could not create Vulkan Instance: %d\n", vr);
+ }
+
+ free(layers);
+ free(extensions);
+ free(layerProps);
+ free(extProps);
+
+ return vr;
}
static VkResult
enableDebugging(VulkanState* const vk)
{
- vk->api.vkCreateDebugReportCallbackEXT =
- (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
- vk->instance, "vkCreateDebugReportCallbackEXT");
-
- vk->api.vkDestroyDebugReportCallbackEXT =
- (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
- vk->instance, "vkDestroyDebugReportCallbackEXT");
-
- if (vk->api.vkCreateDebugReportCallbackEXT) {
- const VkDebugReportCallbackCreateInfoEXT info = {
- VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
- NULL,
- VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
- debugCallback,
- NULL,
- };
-
- VkResult vr = VK_SUCCESS;
- if ((vr = vk->api.vkCreateDebugReportCallbackEXT(
- vk->instance, &info, ALLOC_VK, &vk->debugCallback))) {
- logError("Could not create debug reporter: %d\n", vr);
- return vr;
- }
- }
-
- return VK_SUCCESS;
+ vk->api.vkCreateDebugReportCallbackEXT =
+ (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
+ vk->instance, "vkCreateDebugReportCallbackEXT");
+
+ vk->api.vkDestroyDebugReportCallbackEXT =
+ (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
+ vk->instance, "vkDestroyDebugReportCallbackEXT");
+
+ if (vk->api.vkCreateDebugReportCallbackEXT) {
+ const VkDebugReportCallbackCreateInfoEXT info = {
+ VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
+ NULL,
+ VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
+ debugCallback,
+ NULL,
+ };
+
+ VkResult vr = VK_SUCCESS;
+ if ((vr = vk->api.vkCreateDebugReportCallbackEXT(
+ vk->instance, &info, ALLOC_VK, &vk->debugCallback))) {
+ logError("Could not create debug reporter: %d\n", vr);
+ return vr;
+ }
+ }
+
+ return VK_SUCCESS;
}
static VkResult
@@ -297,52 +297,51 @@ getGraphicsQueueIndex(VkSurfaceKHR surface,
VkPhysicalDevice device,
uint32_t* graphicsIndex)
{
- VkResult r = VK_SUCCESS;
-
- uint32_t nProps = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(device, &nProps, NULL);
-
- VkQueueFamilyProperties* props = AALLOC(nProps, VkQueueFamilyProperties);
- vkGetPhysicalDeviceQueueFamilyProperties(device, &nProps, props);
-
- for (uint32_t q = 0; q < nProps; ++q) {
- if (props[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
- VkBool32 supported = false;
- if ((r = vkGetPhysicalDeviceSurfaceSupportKHR(
- device, q, surface, &supported))) {
- free(props);
- return r;
- } else if (supported) {
- *graphicsIndex = q;
- free(props);
- return VK_SUCCESS;
- }
- }
- }
-
- free(props);
- return VK_ERROR_FEATURE_NOT_PRESENT;
+ VkResult r = VK_SUCCESS;
+
+ uint32_t nProps = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(device, &nProps, NULL);
+
+ VkQueueFamilyProperties* props = AALLOC(nProps, VkQueueFamilyProperties);
+ vkGetPhysicalDeviceQueueFamilyProperties(device, &nProps, props);
+
+ for (uint32_t q = 0; q < nProps; ++q) {
+ if (props[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ VkBool32 supported = false;
+ if ((r = vkGetPhysicalDeviceSurfaceSupportKHR(
+ device, q, surface, &supported))) {
+ free(props);
+ return r;
+ } else if (supported) {
+ *graphicsIndex = q;
+ free(props);
+ return VK_SUCCESS;
+ }
+ }
+ }
+
+ free(props);
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
static bool
supportsRequiredExtensions(const VkPhysicalDevice device)
{
- uint32_t nExtProps = 0;
- vkEnumerateDeviceExtensionProperties(device, NULL, &nExtProps, NULL);
-
- VkExtensionProperties* extProps = AALLOC(nExtProps, VkExtensionProperties);
- vkEnumerateDeviceExtensionProperties(device, NULL, &nExtProps, extProps);
-
- for (uint32_t i = 0; i < nExtProps; ++i) {
- if (!strcmp(extProps[i].extensionName,
- VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
- free(extProps);
- return true;
- }
- }
-
- free(extProps);
- return false;
+ uint32_t nExtProps = 0;
+ vkEnumerateDeviceExtensionProperties(device, NULL, &nExtProps, NULL);
+
+ VkExtensionProperties* extProps = AALLOC(nExtProps, VkExtensionProperties);
+ vkEnumerateDeviceExtensionProperties(device, NULL, &nExtProps, extProps);
+
+ for (uint32_t i = 0; i < nExtProps; ++i) {
+ if (!strcmp(extProps[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
+ free(extProps);
+ return true;
+ }
+ }
+
+ free(extProps);
+ return false;
}
static bool
@@ -350,12 +349,12 @@ isDeviceSuitable(const VulkanState* const vk,
const VkPhysicalDevice device,
uint32_t* const graphicsIndex)
{
- if (!supportsRequiredExtensions(device) ||
- getGraphicsQueueIndex(vk->surface, device, graphicsIndex)) {
- return false;
- }
+ if (!supportsRequiredExtensions(device) ||
+ getGraphicsQueueIndex(vk->surface, device, graphicsIndex)) {
+ return false;
+ }
- return true;
+ return true;
}
/**
@@ -366,134 +365,134 @@ isDeviceSuitable(const VulkanState* const vk,
static VkResult
selectPhysicalDevice(VulkanState* const vk)
{
- VkResult vr = VK_SUCCESS;
- if (!vk->surface) {
- logError("Cannot select a physical device without a surface\n");
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
- uint32_t nDevices = 0;
- if ((vr = vkEnumeratePhysicalDevices(vk->instance, &nDevices, NULL))) {
- logError("Failed to get count of physical devices: %d\n", vr);
- return vr;
- }
-
- if (!nDevices) {
- logError("No physical devices found\n");
- return VK_ERROR_DEVICE_LOST;
- }
-
- VkPhysicalDevice* devices = AALLOC(nDevices, VkPhysicalDevice);
- if ((vr = vkEnumeratePhysicalDevices(vk->instance, &nDevices, devices))) {
- logError("Failed to enumerate physical devices: %d\n", vr);
- free(devices);
- return vr;
- }
-
- uint32_t i = 0;
- for (i = 0; i < nDevices; ++i) {
- VkPhysicalDeviceProperties deviceProps = {0};
- vkGetPhysicalDeviceProperties(devices[i], &deviceProps);
-
- uint32_t graphicsIndex = 0;
- if (isDeviceSuitable(vk, devices[i], &graphicsIndex)) {
- printf("Using device %u/%u: \"%s\"\n",
- i + 1,
- nDevices,
- deviceProps.deviceName);
- vk->deviceProperties = deviceProps;
- vk->physicalDevice = devices[i];
- vk->graphicsIndex = graphicsIndex;
- printf("Using graphics queue family: %u\n", vk->graphicsIndex);
- break;
- }
-
- printf("Device \"%s\" not suitable\n", deviceProps.deviceName);
- }
-
- if (i >= nDevices) {
- logError("No suitable devices found\n");
- vr = VK_ERROR_DEVICE_LOST;
- }
-
- free(devices);
- return vr;
+ VkResult vr = VK_SUCCESS;
+ if (!vk->surface) {
+ logError("Cannot select a physical device without a surface\n");
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+
+ uint32_t nDevices = 0;
+ if ((vr = vkEnumeratePhysicalDevices(vk->instance, &nDevices, NULL))) {
+ logError("Failed to get count of physical devices: %d\n", vr);
+ return vr;
+ }
+
+ if (!nDevices) {
+ logError("No physical devices found\n");
+ return VK_ERROR_DEVICE_LOST;
+ }
+
+ VkPhysicalDevice* devices = AALLOC(nDevices, VkPhysicalDevice);
+ if ((vr = vkEnumeratePhysicalDevices(vk->instance, &nDevices, devices))) {
+ logError("Failed to enumerate physical devices: %d\n", vr);
+ free(devices);
+ return vr;
+ }
+
+ uint32_t i = 0;
+ for (i = 0; i < nDevices; ++i) {
+ VkPhysicalDeviceProperties deviceProps = {0};
+ vkGetPhysicalDeviceProperties(devices[i], &deviceProps);
+
+ uint32_t graphicsIndex = 0;
+ if (isDeviceSuitable(vk, devices[i], &graphicsIndex)) {
+ printf("Using device %u/%u: \"%s\"\n",
+ i + 1,
+ nDevices,
+ deviceProps.deviceName);
+ vk->deviceProperties = deviceProps;
+ vk->physicalDevice = devices[i];
+ vk->graphicsIndex = graphicsIndex;
+ printf("Using graphics queue family: %u\n", vk->graphicsIndex);
+ break;
+ }
+
+ printf("Device \"%s\" not suitable\n", deviceProps.deviceName);
+ }
+
+ if (i >= nDevices) {
+ logError("No suitable devices found\n");
+ vr = VK_ERROR_DEVICE_LOST;
+ }
+
+ free(devices);
+ return vr;
}
/// Opens the logical device and sets up the queue and command pool
static VkResult
openDevice(VulkanState* const vk)
{
- if (vk->device) {
- logError("Renderer already has an opened device\n");
- return VK_NOT_READY;
- }
-
- const float graphicsQueuePriority = 1.0f;
- const char* const swapchainName = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
-
- const VkDeviceQueueCreateInfo queueCreateInfo = {
- VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
- NULL,
- 0,
- vk->graphicsIndex,
- COUNTED(1, &graphicsQueuePriority),
- };
-
- const VkDeviceCreateInfo createInfo = {
- VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- NULL,
- 0,
- COUNTED(1, &queueCreateInfo),
- COUNTED(0, NULL),
- COUNTED(1, &swapchainName),
- NULL,
- };
-
- VkDevice device = NULL;
- VkResult vr = VK_SUCCESS;
- if ((vr = vkCreateDevice(
- vk->physicalDevice, &createInfo, ALLOC_VK, &device))) {
- logError("Could not open device \"%s\": %d\n",
- vk->deviceProperties.deviceName,
- vr);
- return vr;
- }
-
- vk->device = device;
- vkGetDeviceQueue(vk->device, vk->graphicsIndex, 0, &vk->graphicsQueue);
-
- const VkCommandPoolCreateInfo commandInfo = {
- VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
- NULL,
- 0,
- vk->graphicsIndex,
- };
-
- if ((vr = vkCreateCommandPool(
- vk->device, &commandInfo, ALLOC_VK, &vk->commandPool))) {
- logError("Could not create command pool: %d\n", vr);
- return vr;
- }
-
- return VK_SUCCESS;
+ if (vk->device) {
+ logError("Renderer already has an opened device\n");
+ return VK_NOT_READY;
+ }
+
+ const float graphicsQueuePriority = 1.0f;
+ const char* const swapchainName = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+
+ const VkDeviceQueueCreateInfo queueCreateInfo = {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ NULL,
+ 0,
+ vk->graphicsIndex,
+ COUNTED(1, &graphicsQueuePriority),
+ };
+
+ const VkDeviceCreateInfo createInfo = {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ NULL,
+ 0,
+ COUNTED(1, &queueCreateInfo),
+ COUNTED(0, NULL),
+ COUNTED(1, &swapchainName),
+ NULL,
+ };
+
+ VkDevice device = NULL;
+ VkResult vr = VK_SUCCESS;
+ if ((vr =
+ vkCreateDevice(vk->physicalDevice, &createInfo, ALLOC_VK, &device))) {
+ logError("Could not open device \"%s\": %d\n",
+ vk->deviceProperties.deviceName,
+ vr);
+ return vr;
+ }
+
+ vk->device = device;
+ vkGetDeviceQueue(vk->device, vk->graphicsIndex, 0, &vk->graphicsQueue);
+
+ const VkCommandPoolCreateInfo commandInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ NULL,
+ 0,
+ vk->graphicsIndex,
+ };
+
+ if ((vr = vkCreateCommandPool(
+ vk->device, &commandInfo, ALLOC_VK, &vk->commandPool))) {
+ logError("Could not create command pool: %d\n", vr);
+ return vr;
+ }
+
+ return VK_SUCCESS;
}
static const char*
presentModeString(const VkPresentModeKHR presentMode)
{
- switch (presentMode) {
- case VK_PRESENT_MODE_IMMEDIATE_KHR:
- return "Immediate";
- case VK_PRESENT_MODE_MAILBOX_KHR:
- return "Mailbox";
- case VK_PRESENT_MODE_FIFO_KHR:
- return "FIFO";
- case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
- return "FIFO relaxed";
- default:
- return "Other";
- }
+ switch (presentMode) {
+ case VK_PRESENT_MODE_IMMEDIATE_KHR:
+ return "Immediate";
+ case VK_PRESENT_MODE_MAILBOX_KHR:
+ return "Mailbox";
+ case VK_PRESENT_MODE_FIFO_KHR:
+ return "FIFO";
+ case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+ return "FIFO relaxed";
+ default:
+ return "Other";
+ }
}
static bool
@@ -501,90 +500,82 @@ hasPresentMode(const VkPresentModeKHR mode,
const VkPresentModeKHR* const presentModes,
const uint32_t nPresentModes)
{
- for (uint32_t i = 0; i < nPresentModes; ++i) {
- if (presentModes[i] == mode) {
- return true;
- }
- }
+ for (uint32_t i = 0; i < nPresentModes; ++i) {
+ if (presentModes[i] == mode) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
/// Configure the surface for the currently opened device
static VkResult
configureSurface(VulkanState* const vk)
{
- uint32_t nFormats = 0;
- vkGetPhysicalDeviceSurfaceFormatsKHR(vk->physicalDevice,
- vk->surface,
- &nFormats,
- NULL);
- if (!nFormats) {
- logError("No surface formats available\n");
- return VK_ERROR_FORMAT_NOT_SUPPORTED;
- }
-
- VkSurfaceFormatKHR* surfaceFormats = AALLOC(nFormats, VkSurfaceFormatKHR);
- vkGetPhysicalDeviceSurfaceFormatsKHR(vk->physicalDevice,
- vk->surface,
- &nFormats,
- surfaceFormats);
-
- const VkSurfaceFormatKHR want = {VK_FORMAT_B8G8R8A8_UNORM,
- VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
-
- uint32_t formatIndex = 0;
- for (formatIndex = 0; formatIndex < nFormats; ++formatIndex) {
- if (surfaceFormats[formatIndex].format == want.format &&
- surfaceFormats[formatIndex].colorSpace == want.colorSpace) {
- vk->surfaceFormat = want;
- break;
- }
- }
- free(surfaceFormats);
- if (formatIndex >= nFormats) {
- logError("Could not find a suitable surface format\n");
- return VK_ERROR_FORMAT_NOT_SUPPORTED;
- }
-
- uint32_t nPresentModes = 0;
- vkGetPhysicalDeviceSurfacePresentModesKHR(vk->physicalDevice,
- vk->surface,
- &nPresentModes,
- NULL);
- if (!nPresentModes) {
- logError("No present modes available\n");
- return VK_ERROR_FORMAT_NOT_SUPPORTED;
- }
-
- VkPresentModeKHR* presentModes = AALLOC(nPresentModes, VkPresentModeKHR);
- vkGetPhysicalDeviceSurfacePresentModesKHR(vk->physicalDevice,
- vk->surface,
- &nPresentModes,
- presentModes);
-
- const VkPresentModeKHR tryModes[] = {
- VK_PRESENT_MODE_MAILBOX_KHR,
- VK_PRESENT_MODE_FIFO_RELAXED_KHR,
- VK_PRESENT_MODE_FIFO_KHR,
- VK_PRESENT_MODE_IMMEDIATE_KHR,
- };
-
- VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
- for (uint32_t i = 0; i < sizeof(tryModes) / sizeof(VkPresentModeKHR); ++i) {
- if (hasPresentMode(tryModes[i], presentModes, nPresentModes)) {
- presentMode = tryModes[i];
- break;
- }
- }
-
- free(presentModes);
- vk->presentMode = presentMode;
- printf("Using present mode: \"%s\" (%u)\n",
- presentModeString(presentMode),
- presentMode);
-
- return VK_SUCCESS;
+ uint32_t nFormats = 0;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(
+ vk->physicalDevice, vk->surface, &nFormats, NULL);
+ if (!nFormats) {
+ logError("No surface formats available\n");
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ }
+
+ VkSurfaceFormatKHR* surfaceFormats = AALLOC(nFormats, VkSurfaceFormatKHR);
+ vkGetPhysicalDeviceSurfaceFormatsKHR(
+ vk->physicalDevice, vk->surface, &nFormats, surfaceFormats);
+
+ const VkSurfaceFormatKHR want = {VK_FORMAT_B8G8R8A8_UNORM,
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
+
+ uint32_t formatIndex = 0;
+ for (formatIndex = 0; formatIndex < nFormats; ++formatIndex) {
+ if (surfaceFormats[formatIndex].format == want.format &&
+ surfaceFormats[formatIndex].colorSpace == want.colorSpace) {
+ vk->surfaceFormat = want;
+ break;
+ }
+ }
+ free(surfaceFormats);
+ if (formatIndex >= nFormats) {
+ logError("Could not find a suitable surface format\n");
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ }
+
+ uint32_t nPresentModes = 0;
+ vkGetPhysicalDeviceSurfacePresentModesKHR(
+ vk->physicalDevice, vk->surface, &nPresentModes, NULL);
+ if (!nPresentModes) {
+ logError("No present modes available\n");
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ }
+
+ VkPresentModeKHR* presentModes = AALLOC(nPresentModes, VkPresentModeKHR);
+ vkGetPhysicalDeviceSurfacePresentModesKHR(
+ vk->physicalDevice, vk->surface, &nPresentModes, presentModes);
+
+ const VkPresentModeKHR tryModes[] = {
+ VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+ VK_PRESENT_MODE_FIFO_KHR,
+ VK_PRESENT_MODE_IMMEDIATE_KHR,
+ };
+
+ VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ for (uint32_t i = 0; i < sizeof(tryModes) / sizeof(VkPresentModeKHR); ++i) {
+ if (hasPresentMode(tryModes[i], presentModes, nPresentModes)) {
+ presentMode = tryModes[i];
+ break;
+ }
+ }
+
+ free(presentModes);
+ vk->presentMode = presentMode;
+ printf("Using present mode: \"%s\" (%u)\n",
+ presentModeString(presentMode),
+ presentMode);
+
+ return VK_SUCCESS;
}
static VkResult
@@ -592,140 +583,137 @@ createRawSwapchain(VulkanState* const vk,
const uint32_t width,
const uint32_t height)
{
- VkSurfaceCapabilitiesKHR surfaceCapabilities;
- VkResult vr = VK_SUCCESS;
- if ((vr = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
- vk->physicalDevice, vk->surface, &surfaceCapabilities))) {
- logError("Could not get surface capabilities: %d\n", vr);
- return vr;
- }
-
- /* There is a known race condition with window/surface sizes, so we clamp
- to what Vulkan reports and hope for the best. */
-
- vk->swapchain->extent.width =
- CLAMP(width,
- surfaceCapabilities.minImageExtent.width,
- surfaceCapabilities.maxImageExtent.width);
-
- vk->swapchain->extent.height =
- CLAMP(height,
- surfaceCapabilities.minImageExtent.height,
- surfaceCapabilities.maxImageExtent.height);
-
- vk->swapchain->nImages = surfaceCapabilities.minImageCount;
-
- const VkSwapchainCreateInfoKHR createInfo = {
- VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
- NULL,
- 0,
- vk->surface,
- vk->swapchain->nImages,
- vk->surfaceFormat.format,
- VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
- vk->swapchain->extent,
- 1,
- (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
- VK_SHARING_MODE_EXCLUSIVE,
- COUNTED(0, NULL),
- surfaceCapabilities.currentTransform,
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
- vk->presentMode,
- VK_TRUE,
- 0,
- };
-
- if ((vr = vkCreateSwapchainKHR(vk->device,
- &createInfo,
- ALLOC_VK,
- &vk->swapchain->rawSwapchain))) {
- logError("Could not create swapchain: %d\n", vr);
- return vr;
- }
-
- return VK_SUCCESS;
+ VkSurfaceCapabilitiesKHR surfaceCapabilities;
+ VkResult vr = VK_SUCCESS;
+ if ((vr = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ vk->physicalDevice, vk->surface, &surfaceCapabilities))) {
+ logError("Could not get surface capabilities: %d\n", vr);
+ return vr;
+ }
+
+ /* There is a known race condition with window/surface sizes, so we clamp
+ to what Vulkan reports and hope for the best. */
+
+ vk->swapchain->extent.width = CLAMP(width,
+ surfaceCapabilities.minImageExtent.width,
+ surfaceCapabilities.maxImageExtent.width);
+
+ vk->swapchain->extent.height =
+ CLAMP(height,
+ surfaceCapabilities.minImageExtent.height,
+ surfaceCapabilities.maxImageExtent.height);
+
+ vk->swapchain->nImages = surfaceCapabilities.minImageCount;
+
+ const VkSwapchainCreateInfoKHR createInfo = {
+ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ NULL,
+ 0,
+ vk->surface,
+ vk->swapchain->nImages,
+ vk->surfaceFormat.format,
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ vk->swapchain->extent,
+ 1,
+ (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
+ VK_SHARING_MODE_EXCLUSIVE,
+ COUNTED(0, NULL),
+ surfaceCapabilities.currentTransform,
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ vk->presentMode,
+ VK_TRUE,
+ 0,
+ };
+
+ if ((vr = vkCreateSwapchainKHR(
+ vk->device, &createInfo, ALLOC_VK, &vk->swapchain->rawSwapchain))) {
+ logError("Could not create swapchain: %d\n", vr);
+ return vr;
+ }
+
+ return VK_SUCCESS;
}
static VkResult
recordCommandBuffers(VulkanState* const vk)
{
- const VkClearColorValue clearValue = {{
- 0xA4 / (float)0x100, // R
- 0x1E / (float)0x100, // G
- 0x22 / (float)0x100, // B
- 0xFF / (float)0x100, // A
- }};
-
- const VkImageSubresourceRange range = {
- VK_IMAGE_ASPECT_COLOR_BIT,
- 0,
- 1,
- 0,
- 1,
- };
-
- const VkCommandBufferBeginInfo beginInfo = {
- VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- NULL,
- VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
- NULL,
- };
-
- for (uint32_t i = 0; i < vk->swapchain->nImages; ++i) {
- const VkImageMemoryBarrier toClearBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
- NULL,
- VK_ACCESS_MEMORY_READ_BIT,
- VK_ACCESS_TRANSFER_WRITE_BIT,
- VK_IMAGE_LAYOUT_UNDEFINED,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- vk->graphicsIndex,
- vk->graphicsIndex,
- vk->swapchain->images[i],
- range,
- };
-
- const VkImageMemoryBarrier toPresentBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
- NULL,
- VK_ACCESS_TRANSFER_WRITE_BIT,
- VK_ACCESS_MEMORY_READ_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
- vk->graphicsIndex,
- vk->graphicsIndex,
- vk->swapchain->images[i],
- range,
- };
-
- vkBeginCommandBuffer(vk->swapchain->commandBuffers[i], &beginInfo);
-
- vkCmdPipelineBarrier(vk->swapchain->commandBuffers[i],
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- 0,
- COUNTED(0, NULL),
- COUNTED(0, NULL),
- COUNTED(1, &toClearBarrier));
-
- vkCmdClearColorImage(vk->swapchain->commandBuffers[i],
- vk->swapchain->images[i],
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- &clearValue,
- COUNTED(1, &range));
-
- vkCmdPipelineBarrier(vk->swapchain->commandBuffers[i],
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
- 0,
- COUNTED(0, NULL),
- COUNTED(0, NULL),
- COUNTED(1, &toPresentBarrier));
-
- vkEndCommandBuffer(vk->swapchain->commandBuffers[i]);
- }
-
- return VK_SUCCESS;
+ const VkClearColorValue clearValue = {{
+ 0xA4 / (float)0x100, // R
+ 0x1E / (float)0x100, // G
+ 0x22 / (float)0x100, // B
+ 0xFF / (float)0x100, // A
+ }};
+
+ const VkImageSubresourceRange range = {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 0,
+ 1,
+ 0,
+ 1,
+ };
+
+ const VkCommandBufferBeginInfo beginInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ NULL,
+ VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
+ NULL,
+ };
+
+ for (uint32_t i = 0; i < vk->swapchain->nImages; ++i) {
+ const VkImageMemoryBarrier toClearBarrier = {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ NULL,
+ VK_ACCESS_MEMORY_READ_BIT,
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ vk->graphicsIndex,
+ vk->graphicsIndex,
+ vk->swapchain->images[i],
+ range,
+ };
+
+ const VkImageMemoryBarrier toPresentBarrier = {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ NULL,
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ VK_ACCESS_MEMORY_READ_BIT,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ vk->graphicsIndex,
+ vk->graphicsIndex,
+ vk->swapchain->images[i],
+ range,
+ };
+
+ vkBeginCommandBuffer(vk->swapchain->commandBuffers[i], &beginInfo);
+
+ vkCmdPipelineBarrier(vk->swapchain->commandBuffers[i],
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0,
+ COUNTED(0, NULL),
+ COUNTED(0, NULL),
+ COUNTED(1, &toClearBarrier));
+
+ vkCmdClearColorImage(vk->swapchain->commandBuffers[i],
+ vk->swapchain->images[i],
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ &clearValue,
+ COUNTED(1, &range));
+
+ vkCmdPipelineBarrier(vk->swapchain->commandBuffers[i],
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ 0,
+ COUNTED(0, NULL),
+ COUNTED(0, NULL),
+ COUNTED(1, &toPresentBarrier));
+
+ vkEndCommandBuffer(vk->swapchain->commandBuffers[i]);
+ }
+
+ return VK_SUCCESS;
}
static VkResult
@@ -733,204 +721,200 @@ createSwapchain(VulkanState* const vk,
const uint32_t width,
const uint32_t height)
{
- VkResult vr = VK_SUCCESS;
-
- vk->swapchain = AALLOC(1, Swapchain);
- if ((vr = createRawSwapchain(vk, width, height))) {
- return vr;
- }
-
- if ((vr = vkGetSwapchainImagesKHR(vk->device,
- vk->swapchain->rawSwapchain,
- &vk->swapchain->nImages,
- NULL))) {
- logError("Failed to query swapchain images: %d\n", vr);
- return vr;
- }
-
- vk->swapchain->images = AALLOC(vk->swapchain->nImages, VkImage);
- if ((vr = vkGetSwapchainImagesKHR(vk->device,
- vk->swapchain->rawSwapchain,
- &vk->swapchain->nImages,
- vk->swapchain->images))) {
- logError("Failed to get swapchain images: %d\n", vr);
- return vr;
- }
-
- const VkCommandBufferAllocateInfo allocInfo = {
- VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- NULL,
- vk->commandPool,
- VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- vk->swapchain->nImages,
- };
-
- vk->swapchain->commandBuffers = AALLOC(vk->swapchain->nImages,
- VkCommandBuffer);
-
- if ((vr = vkAllocateCommandBuffers(vk->device,
- &allocInfo,
- vk->swapchain->commandBuffers))) {
- logError("Could not allocate command buffers: %d\n", vr);
- return vr;
- }
-
- const VkFenceCreateInfo fenceInfo = {
- VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
- NULL,
- VK_FENCE_CREATE_SIGNALED_BIT,
- };
- vk->swapchain->fences = AALLOC(vk->swapchain->nImages, VkFence);
-
- for (uint32_t i = 0; i < vk->swapchain->nImages; ++i) {
- if ((vr = vkCreateFence(vk->device,
- &fenceInfo,
- ALLOC_VK,
- &vk->swapchain->fences[i]))) {
- logError("Could not create render finished fence: %d\n", vr);
- return vr;
- }
- }
-
- if ((vr = recordCommandBuffers(vk))) {
- logError("Failed to record command buffers\n");
- return vr;
- }
-
- return VK_SUCCESS;
+ VkResult vr = VK_SUCCESS;
+
+ vk->swapchain = AALLOC(1, Swapchain);
+ if ((vr = createRawSwapchain(vk, width, height))) {
+ return vr;
+ }
+
+ if ((vr = vkGetSwapchainImagesKHR(vk->device,
+ vk->swapchain->rawSwapchain,
+ &vk->swapchain->nImages,
+ NULL))) {
+ logError("Failed to query swapchain images: %d\n", vr);
+ return vr;
+ }
+
+ vk->swapchain->images = AALLOC(vk->swapchain->nImages, VkImage);
+ if ((vr = vkGetSwapchainImagesKHR(vk->device,
+ vk->swapchain->rawSwapchain,
+ &vk->swapchain->nImages,
+ vk->swapchain->images))) {
+ logError("Failed to get swapchain images: %d\n", vr);
+ return vr;
+ }
+
+ const VkCommandBufferAllocateInfo allocInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ NULL,
+ vk->commandPool,
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ vk->swapchain->nImages,
+ };
+
+ vk->swapchain->commandBuffers =
+ AALLOC(vk->swapchain->nImages, VkCommandBuffer);
+
+ if ((vr = vkAllocateCommandBuffers(
+ vk->device, &allocInfo, vk->swapchain->commandBuffers))) {
+ logError("Could not allocate command buffers: %d\n", vr);
+ return vr;
+ }
+
+ const VkFenceCreateInfo fenceInfo = {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ NULL,
+ VK_FENCE_CREATE_SIGNALED_BIT,
+ };
+ vk->swapchain->fences = AALLOC(vk->swapchain->nImages, VkFence);
+
+ for (uint32_t i = 0; i < vk->swapchain->nImages; ++i) {
+ if ((vr = vkCreateFence(
+ vk->device, &fenceInfo, ALLOC_VK, &vk->swapchain->fences[i]))) {
+ logError("Could not create render finished fence: %d\n", vr);
+ return vr;
+ }
+ }
+
+ if ((vr = recordCommandBuffers(vk))) {
+ logError("Failed to record command buffers\n");
+ return vr;
+ }
+
+ return VK_SUCCESS;
}
static void
destroySwapchain(VulkanState* const vk, Swapchain* const swapchain)
{
- if (!swapchain) {
- return;
- }
-
- for (uint32_t i = 0; i < swapchain->nImages; ++i) {
- if (swapchain->fences[i]) {
- vkDestroyFence(vk->device, swapchain->fences[i], ALLOC_VK);
- }
-
- if (swapchain->imageViews && swapchain->imageViews[i]) {
- vkDestroyImageView(vk->device, swapchain->imageViews[i], ALLOC_VK);
- }
- }
-
- free(swapchain->fences);
- swapchain->fences = NULL;
- free(swapchain->imageViews);
- swapchain->imageViews = NULL;
-
- if (swapchain->images) {
- free(swapchain->images);
- swapchain->images = NULL;
- }
-
- if (swapchain->commandBuffers) {
- vkFreeCommandBuffers(vk->device,
- vk->commandPool,
- swapchain->nImages,
- swapchain->commandBuffers);
- free(swapchain->commandBuffers);
- }
-
- if (swapchain->rawSwapchain) {
- vkDestroySwapchainKHR(vk->device, swapchain->rawSwapchain, ALLOC_VK);
- }
-
- free(swapchain);
+ if (!swapchain) {
+ return;
+ }
+
+ for (uint32_t i = 0; i < swapchain->nImages; ++i) {
+ if (swapchain->fences[i]) {
+ vkDestroyFence(vk->device, swapchain->fences[i], ALLOC_VK);
+ }
+
+ if (swapchain->imageViews && swapchain->imageViews[i]) {
+ vkDestroyImageView(vk->device, swapchain->imageViews[i], ALLOC_VK);
+ }
+ }
+
+ free(swapchain->fences);
+ swapchain->fences = NULL;
+ free(swapchain->imageViews);
+ swapchain->imageViews = NULL;
+
+ if (swapchain->images) {
+ free(swapchain->images);
+ swapchain->images = NULL;
+ }
+
+ if (swapchain->commandBuffers) {
+ vkFreeCommandBuffers(vk->device,
+ vk->commandPool,
+ swapchain->nImages,
+ swapchain->commandBuffers);
+ free(swapchain->commandBuffers);
+ }
+
+ if (swapchain->rawSwapchain) {
+ vkDestroySwapchainKHR(vk->device, swapchain->rawSwapchain, ALLOC_VK);
+ }
+
+ free(swapchain);
}
static VkResult
createSyncObjects(VulkanState* const vk)
{
- const VkSemaphoreCreateInfo info = {
- VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
- NULL,
- 0,
- };
-
- vkCreateSemaphore(vk->device, &info, ALLOC_VK, &vk->sync.presentComplete);
- vkCreateSemaphore(vk->device, &info, ALLOC_VK, &vk->sync.renderFinished);
- return VK_SUCCESS;
+ const VkSemaphoreCreateInfo info = {
+ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ NULL,
+ 0,
+ };
+
+ vkCreateSemaphore(vk->device, &info, ALLOC_VK, &vk->sync.presentComplete);
+ vkCreateSemaphore(vk->device, &info, ALLOC_VK, &vk->sync.renderFinished);
+ return VK_SUCCESS;
}
static void
destroySyncObjects(VulkanState* const vk)
{
- if (vk->sync.renderFinished) {
- vkDestroySemaphore(vk->device, vk->sync.renderFinished, ALLOC_VK);
- vk->sync.renderFinished = VK_NULL_HANDLE;
- }
- if (vk->sync.presentComplete) {
- vkDestroySemaphore(vk->device, vk->sync.presentComplete, ALLOC_VK);
- vk->sync.presentComplete = VK_NULL_HANDLE;
- }
+ if (vk->sync.renderFinished) {
+ vkDestroySemaphore(vk->device, vk->sync.renderFinished, ALLOC_VK);
+ vk->sync.renderFinished = VK_NULL_HANDLE;
+ }
+ if (vk->sync.presentComplete) {
+ vkDestroySemaphore(vk->device, vk->sync.presentComplete, ALLOC_VK);
+ vk->sync.presentComplete = VK_NULL_HANDLE;
+ }
}
static void
closeDevice(VulkanState* const vk)
{
- if (vk->device) {
- vkDeviceWaitIdle(vk->device);
- destroySyncObjects(vk);
- destroySwapchain(vk, vk->swapchain);
- if (vk->commandPool) {
- vkDestroyCommandPool(vk->device, vk->commandPool, ALLOC_VK);
- vk->commandPool = VK_NULL_HANDLE;
- }
- vk->graphicsQueue = VK_NULL_HANDLE;
- vkDestroyDevice(vk->device, ALLOC_VK);
- vk->device = VK_NULL_HANDLE;
- }
+ if (vk->device) {
+ vkDeviceWaitIdle(vk->device);
+ destroySyncObjects(vk);
+ destroySwapchain(vk, vk->swapchain);
+ if (vk->commandPool) {
+ vkDestroyCommandPool(vk->device, vk->commandPool, ALLOC_VK);
+ vk->commandPool = VK_NULL_HANDLE;
+ }
+ vk->graphicsQueue = VK_NULL_HANDLE;
+ vkDestroyDevice(vk->device, ALLOC_VK);
+ vk->device = VK_NULL_HANDLE;
+ }
}
static void
destroyWorld(VulkanApp* const app)
{
- VulkanState* vk = &app->vk;
-
- if (vk) {
- closeDevice(vk);
-
- if (app->view) {
- puglHide(app->view);
- puglFreeView(app->view);
- app->view = NULL;
- }
- if (vk->debugCallback && vk->api.vkDestroyDebugReportCallbackEXT) {
- vk->api.vkDestroyDebugReportCallbackEXT(vk->instance,
- vk->debugCallback,
- ALLOC_VK);
- vk->debugCallback = VK_NULL_HANDLE;
- }
- if (vk->surface) {
- vkDestroySurfaceKHR(vk->instance, vk->surface, ALLOC_VK);
- vk->surface = VK_NULL_HANDLE;
- }
- if (vk->instance) {
- fflush(stderr);
- vkDestroyInstance(vk->instance, ALLOC_VK);
- vk->instance = VK_NULL_HANDLE;
- }
- if (app->world) {
- puglFreeWorld(app->world);
- app->world = NULL;
- }
- }
+ VulkanState* vk = &app->vk;
+
+ if (vk) {
+ closeDevice(vk);
+
+ if (app->view) {
+ puglHide(app->view);
+ puglFreeView(app->view);
+ app->view = NULL;
+ }
+ if (vk->debugCallback && vk->api.vkDestroyDebugReportCallbackEXT) {
+ vk->api.vkDestroyDebugReportCallbackEXT(
+ vk->instance, vk->debugCallback, ALLOC_VK);
+ vk->debugCallback = VK_NULL_HANDLE;
+ }
+ if (vk->surface) {
+ vkDestroySurfaceKHR(vk->instance, vk->surface, ALLOC_VK);
+ vk->surface = VK_NULL_HANDLE;
+ }
+ if (vk->instance) {
+ fflush(stderr);
+ vkDestroyInstance(vk->instance, ALLOC_VK);
+ vk->instance = VK_NULL_HANDLE;
+ }
+ if (app->world) {
+ puglFreeWorld(app->world);
+ app->world = NULL;
+ }
+ }
}
static PuglStatus
onConfigure(PuglView* const view, const double width, const double height)
{
- VulkanApp* const app = (VulkanApp*)puglGetHandle(view);
+ VulkanApp* const app = (VulkanApp*)puglGetHandle(view);
- // We just record the size here and lazily resize the surface when exposed
- app->width = (uint32_t)width;
- app->height = (uint32_t)height;
+ // We just record the size here and lazily resize the surface when exposed
+ app->width = (uint32_t)width;
+ app->height = (uint32_t)height;
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
@@ -938,202 +922,202 @@ recreateSwapchain(VulkanState* const vk,
const uint32_t width,
const uint32_t height)
{
- vkDeviceWaitIdle(vk->device);
- destroySwapchain(vk, vk->swapchain);
+ vkDeviceWaitIdle(vk->device);
+ destroySwapchain(vk, vk->swapchain);
- if (createSwapchain(vk, width, height)) {
- logError("Failed to recreate swapchain\n");
- return PUGL_UNKNOWN_ERROR;
- }
+ if (createSwapchain(vk, width, height)) {
+ logError("Failed to recreate swapchain\n");
+ return PUGL_UNKNOWN_ERROR;
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
onExpose(PuglView* const view)
{
- VulkanApp* app = (VulkanApp*)puglGetHandle(view);
- VulkanState* vk = &app->vk;
- uint32_t imageIndex = 0;
- VkResult result = VK_SUCCESS;
-
- // Recreate swapchain if the window size has changed
- const Swapchain* swapchain = vk->swapchain;
- if (swapchain->extent.width != app->width ||
- swapchain->extent.height != app->height) {
- recreateSwapchain(vk, app->width, app->height);
- }
-
- // Acquire the next image to render, rebuilding if necessary
- while ((result = vkAcquireNextImageKHR(vk->device,
- vk->swapchain->rawSwapchain,
- UINT64_MAX,
- vk->sync.presentComplete,
- VK_NULL_HANDLE,
- &imageIndex))) {
- switch (result) {
- case VK_SUCCESS:
- break;
- case VK_SUBOPTIMAL_KHR:
- case VK_ERROR_OUT_OF_DATE_KHR:
- recreateSwapchain(vk, app->width, app->height);
- continue;
- default:
- logError("Could not acquire swapchain image: %d\n", result);
- return PUGL_UNKNOWN_ERROR;
- }
- }
-
- // Wait until we can start rendering this frame
- vkWaitForFences(vk->device,
- COUNTED(1, &vk->swapchain->fences[imageIndex]),
- VK_TRUE,
- UINT64_MAX);
- vkResetFences(vk->device, 1, &vk->swapchain->fences[imageIndex]);
-
- const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
-
- // Submit command buffer to render this frame
- const VkSubmitInfo submitInfo = {
- VK_STRUCTURE_TYPE_SUBMIT_INFO,
- NULL,
- COUNTED(1, &vk->sync.presentComplete),
- &waitStage,
- COUNTED(1, &vk->swapchain->commandBuffers[imageIndex]),
- COUNTED(1, &vk->sync.renderFinished)};
- if ((result = vkQueueSubmit(vk->graphicsQueue,
- 1,
- &submitInfo,
- vk->swapchain->fences[imageIndex]))) {
- logError("Could not submit to queue: %d\n", result);
- return PUGL_FAILURE;
- }
-
- // Present this frame
- const VkPresentInfoKHR presentInfo = {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
- NULL,
- COUNTED(1, &vk->sync.renderFinished),
- COUNTED(1, &vk->swapchain->rawSwapchain, &imageIndex, NULL),
- };
- if ((result = vkQueuePresentKHR(vk->graphicsQueue, &presentInfo))) {
- logError("Could not present image: %d\n", result);
- }
-
- if (app->opts.continuous) {
- ++app->framesDrawn;
- }
-
- return PUGL_SUCCESS;
+ VulkanApp* app = (VulkanApp*)puglGetHandle(view);
+ VulkanState* vk = &app->vk;
+ uint32_t imageIndex = 0;
+ VkResult result = VK_SUCCESS;
+
+ // Recreate swapchain if the window size has changed
+ const Swapchain* swapchain = vk->swapchain;
+ if (swapchain->extent.width != app->width ||
+ swapchain->extent.height != app->height) {
+ recreateSwapchain(vk, app->width, app->height);
+ }
+
+ // Acquire the next image to render, rebuilding if necessary
+ while ((result = vkAcquireNextImageKHR(vk->device,
+ vk->swapchain->rawSwapchain,
+ UINT64_MAX,
+ vk->sync.presentComplete,
+ VK_NULL_HANDLE,
+ &imageIndex))) {
+ switch (result) {
+ case VK_SUCCESS:
+ break;
+ case VK_SUBOPTIMAL_KHR:
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ recreateSwapchain(vk, app->width, app->height);
+ continue;
+ default:
+ logError("Could not acquire swapchain image: %d\n", result);
+ return PUGL_UNKNOWN_ERROR;
+ }
+ }
+
+ // Wait until we can start rendering this frame
+ vkWaitForFences(vk->device,
+ COUNTED(1, &vk->swapchain->fences[imageIndex]),
+ VK_TRUE,
+ UINT64_MAX);
+ vkResetFences(vk->device, 1, &vk->swapchain->fences[imageIndex]);
+
+ const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+
+ // Submit command buffer to render this frame
+ const VkSubmitInfo submitInfo = {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ NULL,
+ COUNTED(1, &vk->sync.presentComplete),
+ &waitStage,
+ COUNTED(1, &vk->swapchain->commandBuffers[imageIndex]),
+ COUNTED(1, &vk->sync.renderFinished)};
+ if ((result = vkQueueSubmit(vk->graphicsQueue,
+ 1,
+ &submitInfo,
+ vk->swapchain->fences[imageIndex]))) {
+ logError("Could not submit to queue: %d\n", result);
+ return PUGL_FAILURE;
+ }
+
+ // Present this frame
+ const VkPresentInfoKHR presentInfo = {
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ NULL,
+ COUNTED(1, &vk->sync.renderFinished),
+ COUNTED(1, &vk->swapchain->rawSwapchain, &imageIndex, NULL),
+ };
+ if ((result = vkQueuePresentKHR(vk->graphicsQueue, &presentInfo))) {
+ logError("Could not present image: %d\n", result);
+ }
+
+ if (app->opts.continuous) {
+ ++app->framesDrawn;
+ }
+
+ return PUGL_SUCCESS;
}
static PuglStatus
onEvent(PuglView* const view, const PuglEvent* const e)
{
- VulkanApp* const app = (VulkanApp*)puglGetHandle(view);
-
- printEvent(e, "Event: ", app->opts.verbose);
-
- switch (e->type) {
- case PUGL_EXPOSE:
- return onExpose(view);
- case PUGL_CONFIGURE:
- return onConfigure(view, e->configure.width, e->configure.height);
- case PUGL_CLOSE:
- app->quit = 1;
- break;
- case PUGL_KEY_PRESS:
- switch (e->key.key) {
- case PUGL_KEY_ESCAPE:
- case 'q':
- app->quit = 1;
- break;
- }
- break;
- default:
- break;
- }
- return PUGL_SUCCESS;
+ VulkanApp* const app = (VulkanApp*)puglGetHandle(view);
+
+ printEvent(e, "Event: ", app->opts.verbose);
+
+ switch (e->type) {
+ case PUGL_EXPOSE:
+ return onExpose(view);
+ case PUGL_CONFIGURE:
+ return onConfigure(view, e->configure.width, e->configure.height);
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ case PUGL_KEY_PRESS:
+ switch (e->key.key) {
+ case PUGL_KEY_ESCAPE:
+ case 'q':
+ app->quit = 1;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- VulkanApp app = {0};
- VulkanState* vk = &app.vk;
- const uint32_t defaultWidth = 640;
- const uint32_t defaultHeight = 360;
- const PuglRect frame = {0, 0, defaultWidth, defaultHeight};
-
- // Parse command line options
- app.opts = puglParseTestOptions(&argc, &argv);
- if (app.opts.help) {
- puglPrintTestUsage(argv[0], "");
- return 0;
- }
-
- // Create world and view
- if (!(app.world = puglNewWorld(PUGL_PROGRAM, PUGL_WORLD_THREADS))) {
- return logError("Failed to create world\n");
- } else if (!(app.view = puglNewView(app.world))) {
- puglFreeWorld(app.world);
- return logError("Failed to create Pugl World and View\n");
- }
-
- // Create Vulkan instance
- if (createInstance(&app)) {
- puglFreeWorld(app.world);
- return logError("Failed to create instance\n");
- }
-
- // Create window
- puglSetWindowTitle(app.view, "Pugl Vulkan");
- puglSetFrame(app.view, frame);
- puglSetHandle(app.view, &app);
- puglSetBackend(app.view, puglVulkanBackend());
- puglSetViewHint(app.view, PUGL_RESIZABLE, app.opts.resizable);
- puglSetEventFunc(app.view, onEvent);
- const PuglStatus st = puglRealize(app.view);
- if (st) {
- puglFreeWorld(app.world);
- puglFreeView(app.view);
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
-
- // Create Vulkan surface for Window
- PuglVulkanLoader* loader = puglNewVulkanLoader(app.world);
- if (puglCreateSurface(puglGetInstanceProcAddrFunc(loader),
- app.view,
- vk->instance,
- ALLOC_VK,
- &vk->surface)) {
- return logError("Failed to create surface\n");
- }
-
- // Set up Vulkan
- VkResult vr = VK_SUCCESS;
- if ((vr = enableDebugging(vk)) || //
- (vr = selectPhysicalDevice(vk)) || //
- (vr = openDevice(vk)) || //
- (vr = configureSurface(vk)) || //
- (vr = createSwapchain(vk, defaultWidth, defaultHeight)) || //
- (vr = createSyncObjects(vk))) {
- destroyWorld(&app);
- return logError("Failed to set up graphics (%d)\n", vr);
- }
-
- printf("Swapchain images: %u\n", app.vk.swapchain->nImages);
-
- PuglFpsPrinter fpsPrinter = {puglGetTime(app.world)};
- puglShow(app.view);
- while (!app.quit) {
- puglUpdate(app.world, -1.0);
-
- if (app.opts.continuous) {
- puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
- }
- }
-
- destroyWorld(&app);
- return 0;
+ VulkanApp app = {0};
+ VulkanState* vk = &app.vk;
+ const uint32_t defaultWidth = 640;
+ const uint32_t defaultHeight = 360;
+ const PuglRect frame = {0, 0, defaultWidth, defaultHeight};
+
+ // Parse command line options
+ app.opts = puglParseTestOptions(&argc, &argv);
+ if (app.opts.help) {
+ puglPrintTestUsage(argv[0], "");
+ return 0;
+ }
+
+ // Create world and view
+ if (!(app.world = puglNewWorld(PUGL_PROGRAM, PUGL_WORLD_THREADS))) {
+ return logError("Failed to create world\n");
+ } else if (!(app.view = puglNewView(app.world))) {
+ puglFreeWorld(app.world);
+ return logError("Failed to create Pugl World and View\n");
+ }
+
+ // Create Vulkan instance
+ if (createInstance(&app)) {
+ puglFreeWorld(app.world);
+ return logError("Failed to create instance\n");
+ }
+
+ // Create window
+ puglSetWindowTitle(app.view, "Pugl Vulkan");
+ puglSetFrame(app.view, frame);
+ puglSetHandle(app.view, &app);
+ puglSetBackend(app.view, puglVulkanBackend());
+ puglSetViewHint(app.view, PUGL_RESIZABLE, app.opts.resizable);
+ puglSetEventFunc(app.view, onEvent);
+ const PuglStatus st = puglRealize(app.view);
+ if (st) {
+ puglFreeWorld(app.world);
+ puglFreeView(app.view);
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
+
+ // Create Vulkan surface for Window
+ PuglVulkanLoader* loader = puglNewVulkanLoader(app.world);
+ if (puglCreateSurface(puglGetInstanceProcAddrFunc(loader),
+ app.view,
+ vk->instance,
+ ALLOC_VK,
+ &vk->surface)) {
+ return logError("Failed to create surface\n");
+ }
+
+ // Set up Vulkan
+ VkResult vr = VK_SUCCESS;
+ if ((vr = enableDebugging(vk)) || //
+ (vr = selectPhysicalDevice(vk)) || //
+ (vr = openDevice(vk)) || //
+ (vr = configureSurface(vk)) || //
+ (vr = createSwapchain(vk, defaultWidth, defaultHeight)) || //
+ (vr = createSyncObjects(vk))) {
+ destroyWorld(&app);
+ return logError("Failed to set up graphics (%d)\n", vr);
+ }
+
+ printf("Swapchain images: %u\n", app.vk.swapchain->nImages);
+
+ PuglFpsPrinter fpsPrinter = {puglGetTime(app.world)};
+ puglShow(app.view);
+ while (!app.quit) {
+ puglUpdate(app.world, -1.0);
+
+ if (app.opts.continuous) {
+ puglPrintFps(app.world, &fpsPrinter, &app.framesDrawn);
+ }
+ }
+
+ destroyWorld(&app);
+ return 0;
}
diff --git a/examples/pugl_window_demo.c b/examples/pugl_window_demo.c
index 3dfc39a..be320dd 100644
--- a/examples/pugl_window_demo.c
+++ b/examples/pugl_window_demo.c
@@ -30,22 +30,22 @@
#include <string.h>
typedef struct {
- PuglView* view;
- double xAngle;
- double yAngle;
- double lastMouseX;
- double lastMouseY;
- double lastDrawTime;
- float dist;
- bool entered;
+ PuglView* view;
+ double xAngle;
+ double yAngle;
+ double lastMouseX;
+ double lastMouseY;
+ double lastDrawTime;
+ float dist;
+ bool entered;
} CubeView;
typedef struct {
- PuglWorld* world;
- CubeView cubes[2];
- int quit;
- bool continuous;
- bool verbose;
+ PuglWorld* world;
+ CubeView cubes[2];
+ int quit;
+ bool continuous;
+ bool verbose;
} PuglTestApp;
static const double pad = 64.0;
@@ -53,207 +53,201 @@ static const double pad = 64.0;
static void
onDisplay(PuglView* view)
{
- PuglWorld* world = puglGetWorld(view);
- PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
- CubeView* cube = (CubeView*)puglGetHandle(view);
+ PuglWorld* world = puglGetWorld(view);
+ PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
+ CubeView* cube = (CubeView*)puglGetHandle(view);
- const double thisTime = puglGetTime(app->world);
- if (app->continuous) {
- const double dTime = thisTime - cube->lastDrawTime;
+ const double thisTime = puglGetTime(app->world);
+ if (app->continuous) {
+ const double dTime = thisTime - cube->lastDrawTime;
- cube->xAngle = fmod(cube->xAngle + dTime * 100.0, 360.0);
- cube->yAngle = fmod(cube->yAngle + dTime * 100.0, 360.0);
- }
+ cube->xAngle = fmod(cube->xAngle + dTime * 100.0, 360.0);
+ cube->yAngle = fmod(cube->yAngle + dTime * 100.0, 360.0);
+ }
- displayCube(view,
- cube->dist,
- (float)cube->xAngle,
- (float)cube->yAngle,
- cube->entered);
+ displayCube(
+ view, cube->dist, (float)cube->xAngle, (float)cube->yAngle, cube->entered);
- cube->lastDrawTime = thisTime;
+ cube->lastDrawTime = thisTime;
}
static void
onKeyPress(PuglView* view, const PuglEventKey* event)
{
- PuglWorld* world = puglGetWorld(view);
- PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
- PuglRect frame = puglGetFrame(view);
-
- if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) {
- app->quit = 1;
- } else if (event->state & PUGL_MOD_SHIFT) {
- if (event->key == PUGL_KEY_UP) {
- frame.height += 10;
- } else if (event->key == PUGL_KEY_DOWN) {
- frame.height -= 10;
- } else if (event->key == PUGL_KEY_LEFT) {
- frame.width -= 10;
- } else if (event->key == PUGL_KEY_RIGHT) {
- frame.width += 10;
- } else {
- return;
- }
- puglSetFrame(view, frame);
- } else {
- if (event->key == PUGL_KEY_UP) {
- frame.y -= 10;
- } else if (event->key == PUGL_KEY_DOWN) {
- frame.y += 10;
- } else if (event->key == PUGL_KEY_LEFT) {
- frame.x -= 10;
- } else if (event->key == PUGL_KEY_RIGHT) {
- frame.x += 10;
- } else {
- return;
- }
- puglSetFrame(view, frame);
- }
+ PuglWorld* world = puglGetWorld(view);
+ PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
+ PuglRect frame = puglGetFrame(view);
+
+ if (event->key == 'q' || event->key == PUGL_KEY_ESCAPE) {
+ app->quit = 1;
+ } else if (event->state & PUGL_MOD_SHIFT) {
+ if (event->key == PUGL_KEY_UP) {
+ frame.height += 10;
+ } else if (event->key == PUGL_KEY_DOWN) {
+ frame.height -= 10;
+ } else if (event->key == PUGL_KEY_LEFT) {
+ frame.width -= 10;
+ } else if (event->key == PUGL_KEY_RIGHT) {
+ frame.width += 10;
+ } else {
+ return;
+ }
+ puglSetFrame(view, frame);
+ } else {
+ if (event->key == PUGL_KEY_UP) {
+ frame.y -= 10;
+ } else if (event->key == PUGL_KEY_DOWN) {
+ frame.y += 10;
+ } else if (event->key == PUGL_KEY_LEFT) {
+ frame.x -= 10;
+ } else if (event->key == PUGL_KEY_RIGHT) {
+ frame.x += 10;
+ } else {
+ return;
+ }
+ puglSetFrame(view, frame);
+ }
}
static void
redisplayView(PuglTestApp* app, PuglView* view)
{
- if (!app->continuous) {
- puglPostRedisplay(view);
- }
+ if (!app->continuous) {
+ puglPostRedisplay(view);
+ }
}
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglWorld* world = puglGetWorld(view);
- PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
- CubeView* cube = (CubeView*)puglGetHandle(view);
-
- const char* const prefix = cube == &app->cubes[0] ? "View 1: " : "View 2: ";
- printEvent(event, prefix, app->verbose);
-
- switch (event->type) {
- case PUGL_CONFIGURE:
- reshapeCube((float)event->configure.width,
- (float)event->configure.height);
- break;
- case PUGL_UPDATE:
- if (app->continuous) {
- puglPostRedisplay(view);
- }
- break;
- case PUGL_EXPOSE:
- onDisplay(view);
- break;
- case PUGL_CLOSE:
- app->quit = 1;
- break;
- case PUGL_KEY_PRESS:
- onKeyPress(view, &event->key);
- break;
- case PUGL_MOTION:
- cube->xAngle -= event->motion.x - cube->lastMouseX;
- cube->yAngle += event->motion.y - cube->lastMouseY;
- cube->lastMouseX = event->motion.x;
- cube->lastMouseY = event->motion.y;
- redisplayView(app, view);
- break;
- case PUGL_SCROLL:
- cube->dist = fmaxf(10.0f, cube->dist + (float)event->scroll.dy);
- redisplayView(app, view);
- break;
- case PUGL_POINTER_IN:
- cube->entered = true;
- redisplayView(app, view);
- break;
- case PUGL_POINTER_OUT:
- cube->entered = false;
- redisplayView(app, view);
- break;
- case PUGL_FOCUS_IN:
- case PUGL_FOCUS_OUT:
- redisplayView(app, view);
- break;
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglWorld* world = puglGetWorld(view);
+ PuglTestApp* app = (PuglTestApp*)puglGetWorldHandle(world);
+ CubeView* cube = (CubeView*)puglGetHandle(view);
+
+ const char* const prefix = cube == &app->cubes[0] ? "View 1: " : "View 2: ";
+ printEvent(event, prefix, app->verbose);
+
+ switch (event->type) {
+ case PUGL_CONFIGURE:
+ reshapeCube((float)event->configure.width, (float)event->configure.height);
+ break;
+ case PUGL_UPDATE:
+ if (app->continuous) {
+ puglPostRedisplay(view);
+ }
+ break;
+ case PUGL_EXPOSE:
+ onDisplay(view);
+ break;
+ case PUGL_CLOSE:
+ app->quit = 1;
+ break;
+ case PUGL_KEY_PRESS:
+ onKeyPress(view, &event->key);
+ break;
+ case PUGL_MOTION:
+ cube->xAngle -= event->motion.x - cube->lastMouseX;
+ cube->yAngle += event->motion.y - cube->lastMouseY;
+ cube->lastMouseX = event->motion.x;
+ cube->lastMouseY = event->motion.y;
+ redisplayView(app, view);
+ break;
+ case PUGL_SCROLL:
+ cube->dist = fmaxf(10.0f, cube->dist + (float)event->scroll.dy);
+ redisplayView(app, view);
+ break;
+ case PUGL_POINTER_IN:
+ cube->entered = true;
+ redisplayView(app, view);
+ break;
+ case PUGL_POINTER_OUT:
+ cube->entered = false;
+ redisplayView(app, view);
+ break;
+ case PUGL_FOCUS_IN:
+ case PUGL_FOCUS_OUT:
+ redisplayView(app, view);
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTestApp app = {0};
-
- const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
- if (opts.help) {
- puglPrintTestUsage(argv[0], "");
- return 1;
- }
-
- app.continuous = opts.continuous;
- app.verbose = opts.verbose;
-
- app.world = puglNewWorld(PUGL_PROGRAM, 0);
- app.cubes[0].view = puglNewView(app.world);
- app.cubes[1].view = puglNewView(app.world);
-
- puglSetWorldHandle(app.world, &app);
- puglSetClassName(app.world, "Pugl Test");
-
- PuglStatus st = PUGL_SUCCESS;
- for (unsigned i = 0; i < 2; ++i) {
- CubeView* cube = &app.cubes[i];
- PuglView* view = cube->view;
- const PuglRect frame = {pad + (128.0 + pad) * i,
- pad + (128.0 + pad) * i,
- 512.0,
- 512.0};
-
- cube->dist = 10;
-
- puglSetWindowTitle(view, "Pugl Window Demo");
- puglSetFrame(view, frame);
- puglSetDefaultSize(view, 512, 512);
- puglSetMinSize(view, 128, 128);
- puglSetBackend(view, puglGlBackend());
-
- puglSetViewHint(view, PUGL_USE_DEBUG_CONTEXT, opts.errorChecking);
- puglSetViewHint(view, PUGL_RESIZABLE, opts.resizable);
- puglSetViewHint(view, PUGL_SAMPLES, opts.samples);
- puglSetViewHint(view, PUGL_DOUBLE_BUFFER, opts.doubleBuffer);
- puglSetViewHint(view, PUGL_SWAP_INTERVAL, opts.sync);
- puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, opts.ignoreKeyRepeat);
- puglSetHandle(view, cube);
- puglSetEventFunc(view, onEvent);
-
- if (i == 1) {
- puglSetTransientFor(app.cubes[1].view,
- puglGetNativeWindow(app.cubes[0].view));
- }
-
- if ((st = puglRealize(view))) {
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
-
- puglShow(view);
- }
-
- PuglFpsPrinter fpsPrinter = {puglGetTime(app.world)};
- unsigned framesDrawn = 0;
- while (!app.quit) {
- puglUpdate(app.world, app.continuous ? 0.0 : -1.0);
- ++framesDrawn;
-
- if (app.continuous) {
- puglPrintFps(app.world, &fpsPrinter, &framesDrawn);
- }
- }
-
- for (size_t i = 0; i < 2; ++i) {
- puglFreeView(app.cubes[i].view);
- }
-
- puglFreeWorld(app.world);
-
- return 0;
+ PuglTestApp app = {0};
+
+ const PuglTestOptions opts = puglParseTestOptions(&argc, &argv);
+ if (opts.help) {
+ puglPrintTestUsage(argv[0], "");
+ return 1;
+ }
+
+ app.continuous = opts.continuous;
+ app.verbose = opts.verbose;
+
+ app.world = puglNewWorld(PUGL_PROGRAM, 0);
+ app.cubes[0].view = puglNewView(app.world);
+ app.cubes[1].view = puglNewView(app.world);
+
+ puglSetWorldHandle(app.world, &app);
+ puglSetClassName(app.world, "Pugl Test");
+
+ PuglStatus st = PUGL_SUCCESS;
+ for (unsigned i = 0; i < 2; ++i) {
+ CubeView* cube = &app.cubes[i];
+ PuglView* view = cube->view;
+ const PuglRect frame = {
+ pad + (128.0 + pad) * i, pad + (128.0 + pad) * i, 512.0, 512.0};
+
+ cube->dist = 10;
+
+ puglSetWindowTitle(view, "Pugl Window Demo");
+ puglSetFrame(view, frame);
+ puglSetDefaultSize(view, 512, 512);
+ puglSetMinSize(view, 128, 128);
+ puglSetBackend(view, puglGlBackend());
+
+ puglSetViewHint(view, PUGL_USE_DEBUG_CONTEXT, opts.errorChecking);
+ puglSetViewHint(view, PUGL_RESIZABLE, opts.resizable);
+ puglSetViewHint(view, PUGL_SAMPLES, opts.samples);
+ puglSetViewHint(view, PUGL_DOUBLE_BUFFER, opts.doubleBuffer);
+ puglSetViewHint(view, PUGL_SWAP_INTERVAL, opts.sync);
+ puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, opts.ignoreKeyRepeat);
+ puglSetHandle(view, cube);
+ puglSetEventFunc(view, onEvent);
+
+ if (i == 1) {
+ puglSetTransientFor(app.cubes[1].view,
+ puglGetNativeWindow(app.cubes[0].view));
+ }
+
+ if ((st = puglRealize(view))) {
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
+
+ puglShow(view);
+ }
+
+ PuglFpsPrinter fpsPrinter = {puglGetTime(app.world)};
+ unsigned framesDrawn = 0;
+ while (!app.quit) {
+ puglUpdate(app.world, app.continuous ? 0.0 : -1.0);
+ ++framesDrawn;
+
+ if (app.continuous) {
+ puglPrintFps(app.world, &fpsPrinter, &framesDrawn);
+ }
+ }
+
+ for (size_t i = 0; i < 2; ++i) {
+ puglFreeView(app.cubes[i].view);
+ }
+
+ puglFreeWorld(app.world);
+
+ return 0;
}
diff --git a/examples/rects.h b/examples/rects.h
index 3537a5b..b99d9f0 100644
--- a/examples/rects.h
+++ b/examples/rects.h
@@ -23,16 +23,16 @@
typedef float vec2[2];
typedef struct {
- float pos[2];
- float size[2];
- float fillColor[4];
+ float pos[2];
+ float size[2];
+ float fillColor[4];
} Rect;
static const vec2 rectVertices[] = {
- {0.0f, 0.0f}, // TL
- {1.0f, 0.0f}, // TR
- {0.0f, 1.0f}, // BL
- {1.0f, 1.0f} // BR
+ {0.0f, 0.0f}, // TL
+ {1.0f, 0.0f}, // TR
+ {0.0f, 1.0f}, // BL
+ {1.0f, 1.0f} // BR
};
static const unsigned rectIndices[4] = {0, 1, 2, 3};
@@ -41,19 +41,19 @@ static const unsigned rectIndices[4] = {0, 1, 2, 3};
static inline Rect
makeRect(const size_t index, const float frameWidth)
{
- static const float alpha = 0.3f;
- const float minSize = frameWidth / 64.0f;
- const float maxSize = frameWidth / 6.0f;
- const float s = (sinf((float)index) / 2.0f + 0.5f);
- const float c = (cosf((float)index) / 2.0f + 0.5f);
+ static const float alpha = 0.3f;
+ const float minSize = frameWidth / 64.0f;
+ const float maxSize = frameWidth / 6.0f;
+ const float s = (sinf((float)index) / 2.0f + 0.5f);
+ const float c = (cosf((float)index) / 2.0f + 0.5f);
- const Rect rect = {
- {0.0f, 0.0f}, // Position is set later during expose
- {minSize + s * maxSize, minSize + c * maxSize},
- {0.0f, s / 2.0f + 0.25f, c / 2.0f + 0.25f, alpha},
- };
+ const Rect rect = {
+ {0.0f, 0.0f}, // Position is set later during expose
+ {minSize + s * maxSize, minSize + c * maxSize},
+ {0.0f, s / 2.0f + 0.25f, c / 2.0f + 0.25f, alpha},
+ };
- return rect;
+ return rect;
}
/// Move `rect` with the given index around in an arbitrary way that looks cool
@@ -65,15 +65,15 @@ moveRect(Rect* const rect,
const float frameHeight,
const double time)
{
- const float normal = (float)index / (float)numRects;
- const float offset[2] = {normal * 128.0f, normal * 128.0f};
+ const float normal = (float)index / (float)numRects;
+ const float offset[2] = {normal * 128.0f, normal * 128.0f};
- rect->pos[0] = (frameWidth - rect->size[0] + offset[0]) *
- (sinf((float)time * rect->size[0] / 64.0f + normal) + 1.0f) /
- 2.0f;
- rect->pos[1] = (frameHeight - rect->size[1] + offset[1]) *
- (cosf((float)time * rect->size[1] / 64.0f + normal) + 1.0f) /
- 2.0f;
+ rect->pos[0] = (frameWidth - rect->size[0] + offset[0]) *
+ (sinf((float)time * rect->size[0] / 64.0f + normal) + 1.0f) /
+ 2.0f;
+ rect->pos[1] = (frameHeight - rect->size[1] + offset[1]) *
+ (cosf((float)time * rect->size[1] / 64.0f + normal) + 1.0f) /
+ 2.0f;
}
#endif // EXAMPLES_RECTS_H
diff --git a/examples/shader_utils.h b/examples/shader_utils.h
index 217ba47..2575f47 100644
--- a/examples/shader_utils.h
+++ b/examples/shader_utils.h
@@ -23,45 +23,44 @@
#include <stdlib.h>
#include <string.h>
-typedef struct
-{
- GLuint vertexShader;
- GLuint fragmentShader;
- GLuint program;
+typedef struct {
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint program;
} Program;
static GLuint
compileShader(const char* header, const char* source, const GLenum type)
{
- const GLchar* sources[] = {header, source};
- const GLint lengths[] = {(GLint)strlen(header), (GLint)strlen(source)};
- GLuint shader = glCreateShader(type);
- glShaderSource(shader, 2, sources, lengths);
- glCompileShader(shader);
-
- int status = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if (status == GL_FALSE) {
- GLint length = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
-
- char* log = (char*)calloc(1, (size_t)length);
- glGetShaderInfoLog(shader, length, &length, log);
- fprintf(stderr, "error: Failed to compile shader (%s)\n", log);
- free(log);
-
- return 0;
- }
-
- return shader;
+ const GLchar* sources[] = {header, source};
+ const GLint lengths[] = {(GLint)strlen(header), (GLint)strlen(source)};
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 2, sources, lengths);
+ glCompileShader(shader);
+
+ int status = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLint length = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
+
+ char* log = (char*)calloc(1, (size_t)length);
+ glGetShaderInfoLog(shader, length, &length, log);
+ fprintf(stderr, "error: Failed to compile shader (%s)\n", log);
+ free(log);
+
+ return 0;
+ }
+
+ return shader;
}
static void
deleteProgram(Program program)
{
- glDeleteShader(program.vertexShader);
- glDeleteShader(program.fragmentShader);
- glDeleteProgram(program.program);
+ glDeleteShader(program.vertexShader);
+ glDeleteShader(program.fragmentShader);
+ glDeleteProgram(program.program);
}
static Program
@@ -69,39 +68,39 @@ compileProgram(const char* headerSource,
const char* vertexSource,
const char* fragmentSource)
{
- static const Program nullProgram = {0, 0, 0};
-
- Program program = {
- compileShader(headerSource, vertexSource, GL_VERTEX_SHADER),
- compileShader(headerSource, fragmentSource, GL_FRAGMENT_SHADER),
- glCreateProgram(),
- };
-
- if (!program.vertexShader || !program.fragmentShader || !program.program) {
- deleteProgram(program);
- return nullProgram;
- }
-
- glAttachShader(program.program, program.vertexShader);
- glAttachShader(program.program, program.fragmentShader);
- glLinkProgram(program.program);
-
- GLint status = 0;
- glGetProgramiv(program.program, GL_LINK_STATUS, &status);
- if (status == GL_FALSE) {
- GLint length = 0;
- glGetProgramiv(program.program, GL_INFO_LOG_LENGTH, &length);
-
- char* log = (char*)calloc(1, (size_t)length);
- glGetProgramInfoLog(program.program, length, &length, &log[0]);
- fprintf(stderr, "error: Failed to link program (%s)\n", log);
- free(log);
-
- deleteProgram(program);
- return nullProgram;
- }
-
- return program;
+ static const Program nullProgram = {0, 0, 0};
+
+ Program program = {
+ compileShader(headerSource, vertexSource, GL_VERTEX_SHADER),
+ compileShader(headerSource, fragmentSource, GL_FRAGMENT_SHADER),
+ glCreateProgram(),
+ };
+
+ if (!program.vertexShader || !program.fragmentShader || !program.program) {
+ deleteProgram(program);
+ return nullProgram;
+ }
+
+ glAttachShader(program.program, program.vertexShader);
+ glAttachShader(program.program, program.fragmentShader);
+ glLinkProgram(program.program);
+
+ GLint status = 0;
+ glGetProgramiv(program.program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ GLint length = 0;
+ glGetProgramiv(program.program, GL_INFO_LOG_LENGTH, &length);
+
+ char* log = (char*)calloc(1, (size_t)length);
+ glGetProgramInfoLog(program.program, length, &length, &log[0]);
+ fprintf(stderr, "error: Failed to link program (%s)\n", log);
+ free(log);
+
+ deleteProgram(program);
+ return nullProgram;
+ }
+
+ return program;
}
#endif // EXAMPLES_SHADER_UTILS_H
diff --git a/examples/shaders/header_330.glsl b/examples/shaders/header_330.glsl
index bfe7a00..59d5f6f 100644
--- a/examples/shaders/header_330.glsl
+++ b/examples/shaders/header_330.glsl
@@ -2,4 +2,3 @@
#define INTER(qualifiers)
#define UBO(qualifiers) layout(std140)
-
diff --git a/examples/shaders/header_420.glsl b/examples/shaders/header_420.glsl
index 55fbe8a..2beaad0 100644
--- a/examples/shaders/header_420.glsl
+++ b/examples/shaders/header_420.glsl
@@ -2,4 +2,3 @@
#define INTER(qualifiers) layout(qualifiers)
#define UBO(qualifiers) layout(std140, qualifiers)
-
diff --git a/examples/shaders/rect.frag b/examples/shaders/rect.frag
index ecec50d..33bfbb2 100644
--- a/examples/shaders/rect.frag
+++ b/examples/shaders/rect.frag
@@ -17,17 +17,17 @@ layout(location = 0) out vec4 FragColor;
void
main()
{
- const float borderWidth = 2.0;
+ const float borderWidth = 2.0;
- vec4 borderColor = f_fillColor + vec4(0.0, 0.4, 0.4, 0.0);
- float t = step(borderWidth, f_uv[1]);
- float r = step(borderWidth, f_size.x - f_uv[0]);
- float b = step(borderWidth, f_size.y - f_uv[1]);
- float l = step(borderWidth, f_uv[0]);
- float fillMix = t * r * b * l;
- float borderMix = 1.0 - fillMix;
- vec4 fill = fillMix * f_fillColor;
- vec4 border = borderMix * borderColor;
+ vec4 borderColor = f_fillColor + vec4(0.0, 0.4, 0.4, 0.0);
+ float t = step(borderWidth, f_uv[1]);
+ float r = step(borderWidth, f_size.x - f_uv[0]);
+ float b = step(borderWidth, f_size.y - f_uv[1]);
+ float l = step(borderWidth, f_uv[0]);
+ float fillMix = t * r * b * l;
+ float borderMix = 1.0 - fillMix;
+ vec4 fill = fillMix * f_fillColor;
+ vec4 border = borderMix * borderColor;
- FragColor = fill + border;
+ FragColor = fill + border;
}
diff --git a/examples/shaders/rect.vert b/examples/shaders/rect.vert
index 09f1917..2c7b5f1 100644
--- a/examples/shaders/rect.vert
+++ b/examples/shaders/rect.vert
@@ -3,8 +3,9 @@
UBO(binding = 0) uniform UniformBufferObject
{
- mat4 projection;
-} ubo;
+ mat4 projection;
+}
+ubo;
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec2 v_origin;
@@ -18,18 +19,18 @@ INTER(location = 2) noperspective out vec4 f_fillColor;
void
main()
{
- // clang-format off
- mat4 m = mat4(v_size[0], 0.0, 0.0, 0.0,
- 0.0, v_size[1], 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- v_origin[0], v_origin[1], 0.0, 1.0);
- // clang-format on
+ // clang-format off
+ mat4 m = mat4(v_size[0], 0.0, 0.0, 0.0,
+ 0.0, v_size[1], 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ v_origin[0], v_origin[1], 0.0, 1.0);
+ // clang-format on
- mat4 MVP = ubo.projection * m;
+ mat4 MVP = ubo.projection * m;
- f_uv = v_position * v_size;
- f_size = v_size;
- f_fillColor = v_fillColor;
+ f_uv = v_position * v_size;
+ f_size = v_size;
+ f_fillColor = v_fillColor;
- gl_Position = MVP * vec4(v_position, 0.0, 1.0);
+ gl_Position = MVP * vec4(v_position, 0.0, 1.0);
}
diff --git a/examples/sybok.hpp b/examples/sybok.hpp
index 8985547..05b2c3d 100644
--- a/examples/sybok.hpp
+++ b/examples/sybok.hpp
@@ -66,13 +66,13 @@
#define VK_NO_PROTOTYPES
// On 64-bit platforms, all handles are "dispatchable" pointers
-#if defined(__LP64__) || defined(_WIN64) || \
- (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || \
- defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || \
- defined(__powerpc64__)
+#if defined(__LP64__) || defined(_WIN64) || \
+ (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || \
+ defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || \
+ defined(__powerpc64__)
-# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) \
- typedef struct object##_T* object;
+# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) \
+ typedef struct object##_T* object;
// On 32-bit platforms, some "non-dispatchable" handles are 64 bit integers
#else
@@ -80,14 +80,14 @@
/// Trivial wrapper class for a 64-bit integer handle for type safety
template<class Tag>
struct NonDispatchableHandle {
- explicit operator uint64_t() const noexcept { return handle; }
- explicit operator bool() const noexcept { return handle; }
+ explicit operator uint64_t() const noexcept { return handle; }
+ explicit operator bool() const noexcept { return handle; }
- uint64_t handle;
+ uint64_t handle;
};
-# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) \
- using object = NonDispatchableHandle<struct Sk##object##Tag>;
+# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) \
+ using object = NonDispatchableHandle<struct Sk##object##Tag>;
#endif
@@ -101,11 +101,11 @@ struct NonDispatchableHandle {
#include <utility>
#if __cplusplus >= 201703L
-# define SYBOK_NODISCARD [[nodiscard]]
+# define SYBOK_NODISCARD [[nodiscard]]
#elif defined(__GNUC__)
-# define SYBOK_NODISCARD [[gnu::warn_unused_result]]
+# define SYBOK_NODISCARD [[gnu::warn_unused_result]]
#else
-# define SYBOK_NODISCARD
+# define SYBOK_NODISCARD
#endif
/// Helper macro to make array arguments format nicely
@@ -119,295 +119,294 @@ class RenderCommandScope;
static inline const char*
string(const VkResult result)
{
- switch (result) {
- case VK_SUCCESS:
- return "Success";
- case VK_NOT_READY:
- return "Not Ready";
- case VK_TIMEOUT:
- return "Timeout";
- case VK_EVENT_SET:
- return "Event set";
- case VK_EVENT_RESET:
- return "Event reset";
- case VK_INCOMPLETE:
- return "Incomplete";
- case VK_ERROR_OUT_OF_HOST_MEMORY:
- return "Out of host memory";
- case VK_ERROR_OUT_OF_DEVICE_MEMORY:
- return "Out of device memory";
- case VK_ERROR_INITIALIZATION_FAILED:
- return "Initialization failed";
- case VK_ERROR_DEVICE_LOST:
- return "Device lost";
- case VK_ERROR_MEMORY_MAP_FAILED:
- return "Memory map failed";
- case VK_ERROR_LAYER_NOT_PRESENT:
- return "Layer not present";
- case VK_ERROR_EXTENSION_NOT_PRESENT:
- return "Extension not present";
- case VK_ERROR_FEATURE_NOT_PRESENT:
- return "Feature not present";
- case VK_ERROR_INCOMPATIBLE_DRIVER:
- return "Incompatible driver";
- case VK_ERROR_TOO_MANY_OBJECTS:
- return "Too many objects";
- case VK_ERROR_FORMAT_NOT_SUPPORTED:
- return "Format not supported";
- case VK_ERROR_FRAGMENTED_POOL:
- return "Fragmented pool";
- case VK_ERROR_OUT_OF_POOL_MEMORY: // Vulkan 1.1
- return "Out of pool memory";
- case VK_ERROR_INVALID_EXTERNAL_HANDLE: // Vulkan 1.1
- return "Invalid external handle";
- case VK_ERROR_SURFACE_LOST_KHR: // VK_KHR_surface
- return "Surface lost";
- case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: // VK_KHR_surface
- return "Native window in use";
- case VK_SUBOPTIMAL_KHR: // VK_KHR_swapchain
- return "Suboptimal";
- case VK_ERROR_OUT_OF_DATE_KHR: // VK_KHR_swapchain
- return "Out of date";
- case VK_ERROR_VALIDATION_FAILED_EXT: // VK_EXT_debug_report
- return "Validation failed";
- default:
- break;
- }
-
- return "Unknown error";
+ switch (result) {
+ case VK_SUCCESS:
+ return "Success";
+ case VK_NOT_READY:
+ return "Not Ready";
+ case VK_TIMEOUT:
+ return "Timeout";
+ case VK_EVENT_SET:
+ return "Event set";
+ case VK_EVENT_RESET:
+ return "Event reset";
+ case VK_INCOMPLETE:
+ return "Incomplete";
+ case VK_ERROR_OUT_OF_HOST_MEMORY:
+ return "Out of host memory";
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+ return "Out of device memory";
+ case VK_ERROR_INITIALIZATION_FAILED:
+ return "Initialization failed";
+ case VK_ERROR_DEVICE_LOST:
+ return "Device lost";
+ case VK_ERROR_MEMORY_MAP_FAILED:
+ return "Memory map failed";
+ case VK_ERROR_LAYER_NOT_PRESENT:
+ return "Layer not present";
+ case VK_ERROR_EXTENSION_NOT_PRESENT:
+ return "Extension not present";
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ return "Feature not present";
+ case VK_ERROR_INCOMPATIBLE_DRIVER:
+ return "Incompatible driver";
+ case VK_ERROR_TOO_MANY_OBJECTS:
+ return "Too many objects";
+ case VK_ERROR_FORMAT_NOT_SUPPORTED:
+ return "Format not supported";
+ case VK_ERROR_FRAGMENTED_POOL:
+ return "Fragmented pool";
+ case VK_ERROR_OUT_OF_POOL_MEMORY: // Vulkan 1.1
+ return "Out of pool memory";
+ case VK_ERROR_INVALID_EXTERNAL_HANDLE: // Vulkan 1.1
+ return "Invalid external handle";
+ case VK_ERROR_SURFACE_LOST_KHR: // VK_KHR_surface
+ return "Surface lost";
+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: // VK_KHR_surface
+ return "Native window in use";
+ case VK_SUBOPTIMAL_KHR: // VK_KHR_swapchain
+ return "Suboptimal";
+ case VK_ERROR_OUT_OF_DATE_KHR: // VK_KHR_swapchain
+ return "Out of date";
+ case VK_ERROR_VALIDATION_FAILED_EXT: // VK_EXT_debug_report
+ return "Validation failed";
+ default:
+ break;
+ }
+
+ return "Unknown error";
}
static inline const char*
string(const VkPresentModeKHR presentMode)
{
- switch (presentMode) {
- case VK_PRESENT_MODE_IMMEDIATE_KHR:
- return "Immediate";
- case VK_PRESENT_MODE_MAILBOX_KHR:
- return "Mailbox";
- case VK_PRESENT_MODE_FIFO_KHR:
- return "FIFO";
- case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
- return "Relaxed FIFO";
- default:
- break;
- }
-
- return "Unknown present mode";
+ switch (presentMode) {
+ case VK_PRESENT_MODE_IMMEDIATE_KHR:
+ return "Immediate";
+ case VK_PRESENT_MODE_MAILBOX_KHR:
+ return "Mailbox";
+ case VK_PRESENT_MODE_FIFO_KHR:
+ return "FIFO";
+ case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+ return "Relaxed FIFO";
+ default:
+ break;
+ }
+
+ return "Unknown present mode";
}
static inline const char*
string(const VkDebugReportFlagBitsEXT flag)
{
- switch (flag) {
- case VK_DEBUG_REPORT_INFORMATION_BIT_EXT:
- return "Information";
- case VK_DEBUG_REPORT_WARNING_BIT_EXT:
- return "Warning";
- case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT:
- return "Performance Warning";
- case VK_DEBUG_REPORT_ERROR_BIT_EXT:
- return "Error";
- case VK_DEBUG_REPORT_DEBUG_BIT_EXT:
- return "Debug";
- default:
- break;
- }
-
- return "Unknown report";
+ switch (flag) {
+ case VK_DEBUG_REPORT_INFORMATION_BIT_EXT:
+ return "Information";
+ case VK_DEBUG_REPORT_WARNING_BIT_EXT:
+ return "Warning";
+ case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT:
+ return "Performance Warning";
+ case VK_DEBUG_REPORT_ERROR_BIT_EXT:
+ return "Error";
+ case VK_DEBUG_REPORT_DEBUG_BIT_EXT:
+ return "Debug";
+ default:
+ break;
+ }
+
+ return "Unknown report";
}
template<class T>
class GlobalDeleter
{
public:
- using DestroyFunc = void (*)(T, const VkAllocationCallbacks*);
+ using DestroyFunc = void (*)(T, const VkAllocationCallbacks*);
- GlobalDeleter() = default;
- ~GlobalDeleter() = default;
+ GlobalDeleter() = default;
+ ~GlobalDeleter() = default;
- GlobalDeleter(DestroyFunc destroyFunc) noexcept
- : _destroyFunc{destroyFunc}
- {}
+ GlobalDeleter(DestroyFunc destroyFunc) noexcept
+ : _destroyFunc{destroyFunc}
+ {}
- GlobalDeleter(const GlobalDeleter&) = delete;
- GlobalDeleter& operator=(const GlobalDeleter&) = delete;
+ GlobalDeleter(const GlobalDeleter&) = delete;
+ GlobalDeleter& operator=(const GlobalDeleter&) = delete;
- GlobalDeleter(GlobalDeleter&& other) noexcept
- {
- std::swap(_destroyFunc, other._destroyFunc);
- }
+ GlobalDeleter(GlobalDeleter&& other) noexcept
+ {
+ std::swap(_destroyFunc, other._destroyFunc);
+ }
- GlobalDeleter& operator=(GlobalDeleter&& other) noexcept
- {
- std::swap(_destroyFunc, other._destroyFunc);
- return *this;
- }
+ GlobalDeleter& operator=(GlobalDeleter&& other) noexcept
+ {
+ std::swap(_destroyFunc, other._destroyFunc);
+ return *this;
+ }
- void operator()(T handle) noexcept
- {
- if (_destroyFunc && handle) {
- _destroyFunc(handle, nullptr);
- }
- }
+ void operator()(T handle) noexcept
+ {
+ if (_destroyFunc && handle) {
+ _destroyFunc(handle, nullptr);
+ }
+ }
private:
- DestroyFunc _destroyFunc{};
+ DestroyFunc _destroyFunc{};
};
template<class T, class Parent>
class DependantDeleter
{
public:
- using DestroyFunc = void (*)(Parent, T, const VkAllocationCallbacks*);
+ using DestroyFunc = void (*)(Parent, T, const VkAllocationCallbacks*);
- DependantDeleter() = default;
- ~DependantDeleter() = default;
+ DependantDeleter() = default;
+ ~DependantDeleter() = default;
- DependantDeleter(Parent parent, DestroyFunc destroyFunc) noexcept
- : _parent{parent}
- , _destroyFunc{destroyFunc}
- {}
+ DependantDeleter(Parent parent, DestroyFunc destroyFunc) noexcept
+ : _parent{parent}
+ , _destroyFunc{destroyFunc}
+ {}
- DependantDeleter(const DependantDeleter&) = delete;
- DependantDeleter& operator=(const DependantDeleter&) = delete;
+ DependantDeleter(const DependantDeleter&) = delete;
+ DependantDeleter& operator=(const DependantDeleter&) = delete;
- DependantDeleter(DependantDeleter&& other) noexcept { swap(other); }
+ DependantDeleter(DependantDeleter&& other) noexcept { swap(other); }
- DependantDeleter& operator=(DependantDeleter&& other) noexcept
- {
- swap(other);
- return *this;
- }
+ DependantDeleter& operator=(DependantDeleter&& other) noexcept
+ {
+ swap(other);
+ return *this;
+ }
- void operator()(T handle) noexcept
- {
- if (_parent && _destroyFunc && handle) {
- _destroyFunc(_parent, handle, nullptr);
- }
- }
+ void operator()(T handle) noexcept
+ {
+ if (_parent && _destroyFunc && handle) {
+ _destroyFunc(_parent, handle, nullptr);
+ }
+ }
private:
- void swap(DependantDeleter& other) noexcept
- {
- std::swap(_parent, other._parent);
- std::swap(_destroyFunc, other._destroyFunc);
- }
-
- Parent _parent{};
- DestroyFunc _destroyFunc{};
+ void swap(DependantDeleter& other) noexcept
+ {
+ std::swap(_parent, other._parent);
+ std::swap(_destroyFunc, other._destroyFunc);
+ }
+
+ Parent _parent{};
+ DestroyFunc _destroyFunc{};
};
template<class T, class Pool, class FreeFuncResult>
class PoolDeleter
{
public:
- using FreeFunc = FreeFuncResult (*)(VkDevice, Pool, uint32_t, const T*);
-
- PoolDeleter() noexcept = default;
- ~PoolDeleter() noexcept = default;
-
- PoolDeleter(VkDevice device,
- Pool pool,
- uint32_t count,
- FreeFunc freeFunc) noexcept
- : _device{device}
- , _pool{pool}
- , _count{count}
- , _freeFunc{freeFunc}
- {}
-
- PoolDeleter(const PoolDeleter&) = delete;
- PoolDeleter& operator=(const PoolDeleter&) = delete;
-
- PoolDeleter(PoolDeleter&& other) noexcept { swap(other); }
-
- PoolDeleter& operator=(PoolDeleter&& other) noexcept
- {
- swap(other);
- return *this;
- }
-
- void operator()(T* handle) noexcept
- {
- if (_device && _pool && handle) {
- _freeFunc(_device, _pool, _count, handle);
- }
- }
+ using FreeFunc = FreeFuncResult (*)(VkDevice, Pool, uint32_t, const T*);
+
+ PoolDeleter() noexcept = default;
+ ~PoolDeleter() noexcept = default;
+
+ PoolDeleter(VkDevice device,
+ Pool pool,
+ uint32_t count,
+ FreeFunc freeFunc) noexcept
+ : _device{device}
+ , _pool{pool}
+ , _count{count}
+ , _freeFunc{freeFunc}
+ {}
+
+ PoolDeleter(const PoolDeleter&) = delete;
+ PoolDeleter& operator=(const PoolDeleter&) = delete;
+
+ PoolDeleter(PoolDeleter&& other) noexcept { swap(other); }
+
+ PoolDeleter& operator=(PoolDeleter&& other) noexcept
+ {
+ swap(other);
+ return *this;
+ }
+
+ void operator()(T* handle) noexcept
+ {
+ if (_device && _pool && handle) {
+ _freeFunc(_device, _pool, _count, handle);
+ }
+ }
private:
- void swap(PoolDeleter& other) noexcept
- {
- std::swap(_device, other._device);
- std::swap(_pool, other._pool);
- std::swap(_count, other._count);
- std::swap(_freeFunc, other._freeFunc);
- }
-
- VkDevice _device{};
- Pool _pool{};
- uint32_t _count{};
- FreeFunc _freeFunc{};
+ void swap(PoolDeleter& other) noexcept
+ {
+ std::swap(_device, other._device);
+ std::swap(_pool, other._pool);
+ std::swap(_count, other._count);
+ std::swap(_freeFunc, other._freeFunc);
+ }
+
+ VkDevice _device{};
+ Pool _pool{};
+ uint32_t _count{};
+ FreeFunc _freeFunc{};
};
template<class T, class TDeleter>
class UniqueDispatchableHandle
{
public:
- using Deleter = TDeleter;
- using Handle = T;
+ using Deleter = TDeleter;
+ using Handle = T;
- static_assert(std::is_pointer<T>::value, "");
+ static_assert(std::is_pointer<T>::value, "");
- UniqueDispatchableHandle() = default;
+ UniqueDispatchableHandle() = default;
- UniqueDispatchableHandle(Handle handle, Deleter deleter) noexcept
- : _handle{handle}
- , _deleter{std::move(deleter)}
- {}
+ UniqueDispatchableHandle(Handle handle, Deleter deleter) noexcept
+ : _handle{handle}
+ , _deleter{std::move(deleter)}
+ {}
- ~UniqueDispatchableHandle() noexcept
- {
- if (_handle) {
- _deleter(_handle);
- }
- }
+ ~UniqueDispatchableHandle() noexcept
+ {
+ if (_handle) {
+ _deleter(_handle);
+ }
+ }
- UniqueDispatchableHandle(const UniqueDispatchableHandle&) noexcept = delete;
- UniqueDispatchableHandle&
- operator=(const UniqueDispatchableHandle&) noexcept = delete;
+ UniqueDispatchableHandle(const UniqueDispatchableHandle&) noexcept = delete;
+ UniqueDispatchableHandle& operator =(
+ const UniqueDispatchableHandle&) noexcept = delete;
- UniqueDispatchableHandle(UniqueDispatchableHandle&& other) noexcept
- {
- swap(other);
- }
+ UniqueDispatchableHandle(UniqueDispatchableHandle&& other) noexcept
+ {
+ swap(other);
+ }
- UniqueDispatchableHandle&
- operator=(UniqueDispatchableHandle&& other) noexcept
- {
- swap(other);
- return *this;
- }
+ UniqueDispatchableHandle& operator=(UniqueDispatchableHandle&& other) noexcept
+ {
+ swap(other);
+ return *this;
+ }
- const Handle& get() const noexcept { return _handle; }
+ const Handle& get() const noexcept { return _handle; }
- operator Handle() const noexcept { return _handle; }
+ operator Handle() const noexcept { return _handle; }
private:
- void swap(UniqueDispatchableHandle& other) noexcept
- {
- std::swap(_handle, other._handle);
- std::swap(_deleter, other._deleter);
- }
-
- Handle _handle{};
- Deleter _deleter{};
+ void swap(UniqueDispatchableHandle& other) noexcept
+ {
+ std::swap(_handle, other._handle);
+ std::swap(_deleter, other._deleter);
+ }
+
+ Handle _handle{};
+ Deleter _deleter{};
};
-#if defined(__LP64__) || defined(_WIN64) || \
- (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || \
- defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || \
- defined(__powerpc64__)
+#if defined(__LP64__) || defined(_WIN64) || \
+ (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || \
+ defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || \
+ defined(__powerpc64__)
template<class T, class TDeleter>
using UniqueNonDispatchableHandle = UniqueDispatchableHandle<T, TDeleter>;
@@ -418,55 +417,55 @@ template<class T, class TDeleter>
class UniqueNonDispatchableHandle
{
public:
- using Deleter = TDeleter;
- using Handle = T;
-
- UniqueNonDispatchableHandle() = default;
-
- UniqueNonDispatchableHandle(T handle, Deleter deleter) noexcept
- : _handle{handle}
- , _deleter{std::move(deleter)}
- {
- assert(handle);
- }
-
- ~UniqueNonDispatchableHandle() noexcept
- {
- if (_handle) {
- _deleter(_handle);
- }
- }
-
- UniqueNonDispatchableHandle(const UniqueNonDispatchableHandle&) noexcept =
- delete;
- UniqueNonDispatchableHandle&
- operator=(const UniqueNonDispatchableHandle&) noexcept = delete;
-
- UniqueNonDispatchableHandle(UniqueNonDispatchableHandle&& other) noexcept
- {
- swap(other);
- }
-
- UniqueNonDispatchableHandle&
- operator=(UniqueNonDispatchableHandle&& other) noexcept
- {
- swap(other);
- return *this;
- }
-
- const Handle& get() const noexcept { return _handle; }
-
- operator Handle() const noexcept { return _handle; }
+ using Deleter = TDeleter;
+ using Handle = T;
+
+ UniqueNonDispatchableHandle() = default;
+
+ UniqueNonDispatchableHandle(T handle, Deleter deleter) noexcept
+ : _handle{handle}
+ , _deleter{std::move(deleter)}
+ {
+ assert(handle);
+ }
+
+ ~UniqueNonDispatchableHandle() noexcept
+ {
+ if (_handle) {
+ _deleter(_handle);
+ }
+ }
+
+ UniqueNonDispatchableHandle(const UniqueNonDispatchableHandle&) noexcept =
+ delete;
+ UniqueNonDispatchableHandle& operator =(
+ const UniqueNonDispatchableHandle&) noexcept = delete;
+
+ UniqueNonDispatchableHandle(UniqueNonDispatchableHandle&& other) noexcept
+ {
+ swap(other);
+ }
+
+ UniqueNonDispatchableHandle& operator=(
+ UniqueNonDispatchableHandle&& other) noexcept
+ {
+ swap(other);
+ return *this;
+ }
+
+ const Handle& get() const noexcept { return _handle; }
+
+ operator Handle() const noexcept { return _handle; }
private:
- void swap(UniqueNonDispatchableHandle& other) noexcept
- {
- std::swap(_handle, other._handle);
- std::swap(_deleter, other._deleter);
- }
-
- T _handle{};
- Deleter _deleter{};
+ void swap(UniqueNonDispatchableHandle& other) noexcept
+ {
+ std::swap(_handle, other._handle);
+ std::swap(_deleter, other._deleter);
+ }
+
+ T _handle{};
+ Deleter _deleter{};
};
#endif
@@ -475,83 +474,83 @@ template<class Vector, class Deleter>
class UniqueArrayHandle
{
public:
- using T = typename Vector::value_type;
+ using T = typename Vector::value_type;
- UniqueArrayHandle() = default;
+ UniqueArrayHandle() = default;
- UniqueArrayHandle(uint32_t size, Vector&& array, Deleter deleter) noexcept
- : _array{std::move(array)}
- , _deleter{std::move(deleter)}
- , _size{size}
- {
- assert(!_array.empty());
- }
+ UniqueArrayHandle(uint32_t size, Vector&& array, Deleter deleter) noexcept
+ : _array{std::move(array)}
+ , _deleter{std::move(deleter)}
+ , _size{size}
+ {
+ assert(!_array.empty());
+ }
- ~UniqueArrayHandle() noexcept
- {
- if (!_array.empty()) {
- _deleter(_array.data());
- }
- }
+ ~UniqueArrayHandle() noexcept
+ {
+ if (!_array.empty()) {
+ _deleter(_array.data());
+ }
+ }
- UniqueArrayHandle(const UniqueArrayHandle&) noexcept = delete;
- UniqueArrayHandle& operator=(const UniqueArrayHandle&) noexcept = delete;
+ UniqueArrayHandle(const UniqueArrayHandle&) noexcept = delete;
+ UniqueArrayHandle& operator=(const UniqueArrayHandle&) noexcept = delete;
- UniqueArrayHandle(UniqueArrayHandle&& other) noexcept { swap(other); }
+ UniqueArrayHandle(UniqueArrayHandle&& other) noexcept { swap(other); }
- UniqueArrayHandle& operator=(UniqueArrayHandle&& other) noexcept
- {
- swap(other);
- return *this;
- }
+ UniqueArrayHandle& operator=(UniqueArrayHandle&& other) noexcept
+ {
+ swap(other);
+ return *this;
+ }
- const T& operator[](const size_t index) const noexcept
- {
- return _array[index];
- }
+ const T& operator[](const size_t index) const noexcept
+ {
+ return _array[index];
+ }
- T& operator[](const size_t index) noexcept { return _array[index]; }
+ T& operator[](const size_t index) noexcept { return _array[index]; }
- const T* get() const noexcept { return _array.data(); }
- T* get() noexcept { return _array.data(); }
+ const T* get() const noexcept { return _array.data(); }
+ T* get() noexcept { return _array.data(); }
private:
- void swap(UniqueArrayHandle& other) noexcept
- {
- std::swap(_array, other._array);
- std::swap(_deleter, other._deleter);
- std::swap(_size, other._size);
- }
-
- Vector _array{};
- Deleter _deleter{};
- uint32_t _size{};
+ void swap(UniqueArrayHandle& other) noexcept
+ {
+ std::swap(_array, other._array);
+ std::swap(_deleter, other._deleter);
+ std::swap(_size, other._size);
+ }
+
+ Vector _array{};
+ Deleter _deleter{};
+ uint32_t _size{};
};
template<typename T>
class OptionalParameter
{
public:
- using Handle = typename T::Handle;
+ using Handle = typename T::Handle;
- OptionalParameter(const T& value) noexcept
- : _handle{value.get()}
- {}
+ OptionalParameter(const T& value) noexcept
+ : _handle{value.get()}
+ {}
- OptionalParameter() noexcept
- : _handle{}
- {}
+ OptionalParameter() noexcept
+ : _handle{}
+ {}
- OptionalParameter(const OptionalParameter&) = delete;
- OptionalParameter& operator=(const OptionalParameter&) = delete;
+ OptionalParameter(const OptionalParameter&) = delete;
+ OptionalParameter& operator=(const OptionalParameter&) = delete;
- OptionalParameter(OptionalParameter&&) = delete;
- OptionalParameter& operator=(OptionalParameter&&) = delete;
+ OptionalParameter(OptionalParameter&&) = delete;
+ OptionalParameter& operator=(OptionalParameter&&) = delete;
- const Handle get() const noexcept { return _handle; }
+ const Handle get() const noexcept { return _handle; }
private:
- Handle _handle{};
+ Handle _handle{};
};
template<typename T>
@@ -559,20 +558,20 @@ using GlobalObject = UniqueDispatchableHandle<T, GlobalDeleter<T>>;
template<typename T>
using InstanceChild =
- UniqueNonDispatchableHandle<T, DependantDeleter<T, VkInstance>>;
+ UniqueNonDispatchableHandle<T, DependantDeleter<T, VkInstance>>;
template<typename T>
using DispatchableDeviceChild =
- UniqueDispatchableHandle<T, DependantDeleter<T, VkDevice>>;
+ UniqueDispatchableHandle<T, DependantDeleter<T, VkDevice>>;
template<typename T>
using NonDispatchableDeviceChild =
- UniqueNonDispatchableHandle<T, DependantDeleter<T, VkDevice>>;
+ UniqueNonDispatchableHandle<T, DependantDeleter<T, VkDevice>>;
template<typename Vector, typename Pool, typename FreeFuncResult>
using PoolChild = UniqueArrayHandle<
- Vector,
- PoolDeleter<typename Vector::value_type, Pool, FreeFuncResult>>;
+ Vector,
+ PoolDeleter<typename Vector::value_type, Pool, FreeFuncResult>>;
using Device = GlobalObject<VkDevice>;
using Instance = GlobalObject<VkInstance>;
@@ -606,7 +605,7 @@ using CommandBuffers = PoolChild<VkCommandBufferVector, VkCommandPool, void>;
template<class VkDescriptorSetVector>
using DescriptorSets =
- PoolChild<VkDescriptorSetVector, VkDescriptorPool, VkResult>;
+ PoolChild<VkDescriptorSetVector, VkDescriptorPool, VkResult>;
// VK_KHR_swapchain
using SwapchainKHR = NonDispatchableDeviceChild<VkSwapchainKHR>;
@@ -622,11 +621,11 @@ struct IndexSequence {};
template<size_t N, size_t... Next>
struct IndexSequenceHelper
- : public IndexSequenceHelper<N - 1U, N - 1U, Next...> {};
+ : public IndexSequenceHelper<N - 1U, N - 1U, Next...> {};
template<size_t... Next>
struct IndexSequenceHelper<0U, Next...> {
- using type = IndexSequence<Next...>;
+ using type = IndexSequence<Next...>;
};
template<size_t N>
@@ -639,7 +638,7 @@ make_handle_array_h(Parent parent,
std::array<typename T::Handle, count> handles,
IndexSequence<Is...>) noexcept
{
- return {T{handles[Is], {parent, destroyFunc}}...};
+ return {T{handles[Is], {parent, destroyFunc}}...};
}
template<class T, class Parent, class DestroyFunc, size_t count>
@@ -648,8 +647,8 @@ make_handle_array(Parent parent,
DestroyFunc destroyFunc,
std::array<typename T::Handle, count> handles) noexcept
{
- return make_handle_array_h<T, Parent, DestroyFunc, count>(
- parent, destroyFunc, handles, makeIndexSequence<count>());
+ return make_handle_array_h<T, Parent, DestroyFunc, count>(
+ parent, destroyFunc, handles, makeIndexSequence<count>());
}
namespace detail {
@@ -658,20 +657,20 @@ template<class Value, class Vector, class Func, class... Args>
inline VkResult
wrapVectorAccessor(Vector& vector, Func func, Args... args) noexcept
{
- uint32_t count = 0u;
- VkResult r = func(args..., &count, nullptr);
- if (r > VK_INCOMPLETE) {
- vector.clear();
- return r;
- }
-
- vector = Vector(count);
- if ((r = func(args..., &count, vector.data()))) {
- vector.clear();
- return r;
- }
-
- return VK_SUCCESS;
+ uint32_t count = 0u;
+ VkResult r = func(args..., &count, nullptr);
+ if (r > VK_INCOMPLETE) {
+ vector.clear();
+ return r;
+ }
+
+ vector = Vector(count);
+ if ((r = func(args..., &count, vector.data()))) {
+ vector.clear();
+ return r;
+ }
+
+ return VK_SUCCESS;
}
} // namespace detail
@@ -679,148 +678,147 @@ wrapVectorAccessor(Vector& vector, Func func, Args... args) noexcept
class VulkanApi;
struct MappedMemory {
- MappedMemory() noexcept = default;
-
- MappedMemory(const VulkanApi& api,
- VkDevice device,
- VkDeviceMemory memory,
- void* data) noexcept
- : _api{&api}
- , _device{device}
- , _memory{memory}
- , _data{data}
- {}
-
- MappedMemory(const MappedMemory&) = delete;
- MappedMemory& operator=(const MappedMemory&) = delete;
-
- MappedMemory(MappedMemory&& mappedMemory) noexcept
- : _api{mappedMemory._api}
- , _device{mappedMemory._device}
- , _memory{mappedMemory._memory}
- , _data{mappedMemory._data}
- {
- mappedMemory._device = {};
- mappedMemory._memory = {};
- mappedMemory._data = {};
- }
-
- MappedMemory& operator=(MappedMemory&& mappedMemory) noexcept
- {
- std::swap(_api, mappedMemory._api);
- std::swap(_device, mappedMemory._device);
- std::swap(_memory, mappedMemory._memory);
- std::swap(_data, mappedMemory._data);
- return *this;
- }
-
- ~MappedMemory() noexcept;
-
- const void* get() const noexcept { return _data; }
- void* get() noexcept { return _data; }
+ MappedMemory() noexcept = default;
+
+ MappedMemory(const VulkanApi& api,
+ VkDevice device,
+ VkDeviceMemory memory,
+ void* data) noexcept
+ : _api{&api}
+ , _device{device}
+ , _memory{memory}
+ , _data{data}
+ {}
+
+ MappedMemory(const MappedMemory&) = delete;
+ MappedMemory& operator=(const MappedMemory&) = delete;
+
+ MappedMemory(MappedMemory&& mappedMemory) noexcept
+ : _api{mappedMemory._api}
+ , _device{mappedMemory._device}
+ , _memory{mappedMemory._memory}
+ , _data{mappedMemory._data}
+ {
+ mappedMemory._device = {};
+ mappedMemory._memory = {};
+ mappedMemory._data = {};
+ }
+
+ MappedMemory& operator=(MappedMemory&& mappedMemory) noexcept
+ {
+ std::swap(_api, mappedMemory._api);
+ std::swap(_device, mappedMemory._device);
+ std::swap(_memory, mappedMemory._memory);
+ std::swap(_data, mappedMemory._data);
+ return *this;
+ }
+
+ ~MappedMemory() noexcept;
+
+ const void* get() const noexcept { return _data; }
+ void* get() noexcept { return _data; }
private:
- const VulkanApi* _api{};
- VkDevice _device{};
- VkDeviceMemory _memory{};
- void* _data{};
+ const VulkanApi* _api{};
+ VkDevice _device{};
+ VkDeviceMemory _memory{};
+ void* _data{};
};
class VulkanInitApi
{
public:
- template<typename NotFoundFunc>
- VkResult init(PFN_vkGetInstanceProcAddr pGetInstanceProcAddr,
- NotFoundFunc notFound) noexcept
- {
-#define SK_INIT(name) \
- do { \
- if (!(name = PFN_##name(getInstanceProcAddr(NULL, #name)))) { \
- notFound(#name); \
- } \
- } while (0)
-
- vkGetInstanceProcAddr = pGetInstanceProcAddr;
- SK_INIT(vkCreateInstance);
- vkDestroyInstance = {}; // Loaded after we create an instance
- SK_INIT(vkEnumerateInstanceExtensionProperties);
- SK_INIT(vkEnumerateInstanceLayerProperties);
-
- if (!vkCreateInstance || !vkEnumerateInstanceExtensionProperties ||
- !vkEnumerateInstanceLayerProperties) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- return VK_SUCCESS;
+ template<typename NotFoundFunc>
+ VkResult init(PFN_vkGetInstanceProcAddr pGetInstanceProcAddr,
+ NotFoundFunc notFound) noexcept
+ {
+#define SK_INIT(name) \
+ do { \
+ if (!(name = PFN_##name(getInstanceProcAddr(NULL, #name)))) { \
+ notFound(#name); \
+ } \
+ } while (0)
+
+ vkGetInstanceProcAddr = pGetInstanceProcAddr;
+ SK_INIT(vkCreateInstance);
+ vkDestroyInstance = {}; // Loaded after we create an instance
+ SK_INIT(vkEnumerateInstanceExtensionProperties);
+ SK_INIT(vkEnumerateInstanceLayerProperties);
+
+ if (!vkCreateInstance || !vkEnumerateInstanceExtensionProperties ||
+ !vkEnumerateInstanceLayerProperties) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ return VK_SUCCESS;
#undef SK_INIT
- }
-
- VkResult init(PFN_vkGetInstanceProcAddr pGetInstanceProcAddr) noexcept
- {
- return init(pGetInstanceProcAddr, [](const char*) {});
- }
-
- PFN_vkVoidFunction
- getInstanceProcAddr(VkInstance instance,
- const char* const name) const noexcept
- {
- return vkGetInstanceProcAddr(instance, name);
- }
-
- VkResult createInstance(const VkInstanceCreateInfo& createInfo,
- Instance& instance) noexcept
- {
- VkInstance h = {};
- if (const VkResult r = vkCreateInstance(&createInfo, nullptr, &h)) {
- return r;
- } else if (!h) {
- // Shouldn't actually happen, but this lets the compiler know that
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- if (!vkDestroyInstance) {
- vkDestroyInstance = PFN_vkDestroyInstance(
- getInstanceProcAddr(instance, "vkDestroyInstance"));
- }
-
- instance = {h, {vkDestroyInstance}};
- return VK_SUCCESS;
- }
-
- template<class Vector>
- VkResult
- enumerateInstanceExtensionProperties(Vector& properties) const noexcept
- {
- return detail::wrapVectorAccessor<VkExtensionProperties>(
- properties, vkEnumerateInstanceExtensionProperties, nullptr);
- }
-
- template<class Vector>
- VkResult
- enumerateInstanceExtensionProperties(const char* const layerName,
- Vector& properties) const noexcept
- {
- return detail::wrapVectorAccessor<VkExtensionProperties>(
- properties, vkEnumerateInstanceExtensionProperties, layerName);
- }
-
- template<class Vector>
- VkResult enumerateInstanceLayerProperties(Vector& properties) const noexcept
- {
- return detail::wrapVectorAccessor<VkLayerProperties>(
- properties, vkEnumerateInstanceLayerProperties);
- }
+ }
+
+ VkResult init(PFN_vkGetInstanceProcAddr pGetInstanceProcAddr) noexcept
+ {
+ return init(pGetInstanceProcAddr, [](const char*) {});
+ }
+
+ PFN_vkVoidFunction getInstanceProcAddr(VkInstance instance,
+ const char* const name) const noexcept
+ {
+ return vkGetInstanceProcAddr(instance, name);
+ }
+
+ VkResult createInstance(const VkInstanceCreateInfo& createInfo,
+ Instance& instance) noexcept
+ {
+ VkInstance h = {};
+ if (const VkResult r = vkCreateInstance(&createInfo, nullptr, &h)) {
+ return r;
+ } else if (!h) {
+ // Shouldn't actually happen, but this lets the compiler know that
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (!vkDestroyInstance) {
+ vkDestroyInstance = PFN_vkDestroyInstance(
+ getInstanceProcAddr(instance, "vkDestroyInstance"));
+ }
+
+ instance = {h, {vkDestroyInstance}};
+ return VK_SUCCESS;
+ }
+
+ template<class Vector>
+ VkResult enumerateInstanceExtensionProperties(
+ Vector& properties) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkExtensionProperties>(
+ properties, vkEnumerateInstanceExtensionProperties, nullptr);
+ }
+
+ template<class Vector>
+ VkResult enumerateInstanceExtensionProperties(
+ const char* const layerName,
+ Vector& properties) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkExtensionProperties>(
+ properties, vkEnumerateInstanceExtensionProperties, layerName);
+ }
+
+ template<class Vector>
+ VkResult enumerateInstanceLayerProperties(Vector& properties) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkLayerProperties>(
+ properties, vkEnumerateInstanceLayerProperties);
+ }
private:
- PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
#define SK_FUNC(name) \
- PFN_##name name {}
+ PFN_##name name {}
- SK_FUNC(vkCreateInstance);
- SK_FUNC(vkDestroyInstance);
- SK_FUNC(vkEnumerateInstanceExtensionProperties);
- SK_FUNC(vkEnumerateInstanceLayerProperties);
+ SK_FUNC(vkCreateInstance);
+ SK_FUNC(vkDestroyInstance);
+ SK_FUNC(vkEnumerateInstanceExtensionProperties);
+ SK_FUNC(vkEnumerateInstanceLayerProperties);
#undef SK_FUNC
};
@@ -828,1529 +826,1472 @@ private:
class VulkanApi
{
public:
- template<typename NotFoundFunc>
- VkResult init(const VulkanInitApi& initApi,
- const Instance& instance,
- NotFoundFunc notFound) noexcept
- {
- VkResult r = VK_SUCCESS;
-
- const auto notFoundWrapper = [&r, notFound](const char* name) {
- r = VK_INCOMPLETE;
- notFound(name);
- };
-
-#define SK_INIT(name) \
- do { \
- if (!(name = PFN_##name( \
- initApi.getInstanceProcAddr(instance, #name)))) { \
- notFoundWrapper(#name); \
- } \
- } while (0)
-
- SK_INIT(vkAllocateCommandBuffers);
- SK_INIT(vkAllocateDescriptorSets);
- SK_INIT(vkAllocateMemory);
- SK_INIT(vkBeginCommandBuffer);
- SK_INIT(vkBindBufferMemory);
- SK_INIT(vkBindImageMemory);
- SK_INIT(vkCmdBeginQuery);
- SK_INIT(vkCmdBeginRenderPass);
- SK_INIT(vkCmdBindDescriptorSets);
- SK_INIT(vkCmdBindIndexBuffer);
- SK_INIT(vkCmdBindPipeline);
- SK_INIT(vkCmdBindVertexBuffers);
- SK_INIT(vkCmdBlitImage);
- SK_INIT(vkCmdClearAttachments);
- SK_INIT(vkCmdClearColorImage);
- SK_INIT(vkCmdClearDepthStencilImage);
- SK_INIT(vkCmdCopyBuffer);
- SK_INIT(vkCmdCopyBufferToImage);
- SK_INIT(vkCmdCopyImage);
- SK_INIT(vkCmdCopyImageToBuffer);
- SK_INIT(vkCmdCopyQueryPoolResults);
- SK_INIT(vkCmdDispatch);
- SK_INIT(vkCmdDispatchIndirect);
- SK_INIT(vkCmdDraw);
- SK_INIT(vkCmdDrawIndexed);
- SK_INIT(vkCmdDrawIndexedIndirect);
- SK_INIT(vkCmdDrawIndirect);
- SK_INIT(vkCmdEndQuery);
- SK_INIT(vkCmdEndRenderPass);
- SK_INIT(vkCmdExecuteCommands);
- SK_INIT(vkCmdFillBuffer);
- SK_INIT(vkCmdNextSubpass);
- SK_INIT(vkCmdPipelineBarrier);
- SK_INIT(vkCmdPushConstants);
- SK_INIT(vkCmdResetEvent);
- SK_INIT(vkCmdResetQueryPool);
- SK_INIT(vkCmdResolveImage);
- SK_INIT(vkCmdSetBlendConstants);
- SK_INIT(vkCmdSetDepthBias);
- SK_INIT(vkCmdSetDepthBounds);
- SK_INIT(vkCmdSetEvent);
- SK_INIT(vkCmdSetLineWidth);
- SK_INIT(vkCmdSetScissor);
- SK_INIT(vkCmdSetStencilCompareMask);
- SK_INIT(vkCmdSetStencilReference);
- SK_INIT(vkCmdSetStencilWriteMask);
- SK_INIT(vkCmdSetViewport);
- SK_INIT(vkCmdUpdateBuffer);
- SK_INIT(vkCmdWaitEvents);
- SK_INIT(vkCmdWriteTimestamp);
- SK_INIT(vkCreateBuffer);
- SK_INIT(vkCreateBufferView);
- SK_INIT(vkCreateCommandPool);
- SK_INIT(vkCreateComputePipelines);
- SK_INIT(vkCreateDescriptorPool);
- SK_INIT(vkCreateDescriptorSetLayout);
- SK_INIT(vkCreateDevice);
- SK_INIT(vkCreateEvent);
- SK_INIT(vkCreateFence);
- SK_INIT(vkCreateFramebuffer);
- SK_INIT(vkCreateGraphicsPipelines);
- SK_INIT(vkCreateImage);
- SK_INIT(vkCreateImageView);
- SK_INIT(vkCreateInstance);
- SK_INIT(vkCreatePipelineCache);
- SK_INIT(vkCreatePipelineLayout);
- SK_INIT(vkCreateQueryPool);
- SK_INIT(vkCreateRenderPass);
- SK_INIT(vkCreateSampler);
- SK_INIT(vkCreateSemaphore);
- SK_INIT(vkCreateShaderModule);
- SK_INIT(vkDestroyBuffer);
- SK_INIT(vkDestroyBufferView);
- SK_INIT(vkDestroyCommandPool);
- SK_INIT(vkDestroyDescriptorPool);
- SK_INIT(vkDestroyDescriptorSetLayout);
- SK_INIT(vkDestroyDevice);
- SK_INIT(vkDestroyEvent);
- SK_INIT(vkDestroyFence);
- SK_INIT(vkDestroyFramebuffer);
- SK_INIT(vkDestroyImage);
- SK_INIT(vkDestroyImageView);
- SK_INIT(vkDestroyPipeline);
- SK_INIT(vkDestroyPipelineCache);
- SK_INIT(vkDestroyPipelineLayout);
- SK_INIT(vkDestroyQueryPool);
- SK_INIT(vkDestroyRenderPass);
- SK_INIT(vkDestroySampler);
- SK_INIT(vkDestroySemaphore);
- SK_INIT(vkDestroyShaderModule);
- SK_INIT(vkDeviceWaitIdle);
- SK_INIT(vkEndCommandBuffer);
- SK_INIT(vkEnumerateDeviceExtensionProperties);
- SK_INIT(vkEnumerateDeviceLayerProperties);
- SK_INIT(vkEnumeratePhysicalDevices);
- SK_INIT(vkFlushMappedMemoryRanges);
- SK_INIT(vkFreeCommandBuffers);
- SK_INIT(vkFreeDescriptorSets);
- SK_INIT(vkFreeMemory);
- SK_INIT(vkGetBufferMemoryRequirements);
- SK_INIT(vkGetDeviceMemoryCommitment);
- SK_INIT(vkGetDeviceProcAddr);
- SK_INIT(vkGetDeviceQueue);
- SK_INIT(vkGetEventStatus);
- SK_INIT(vkGetFenceStatus);
- SK_INIT(vkGetImageMemoryRequirements);
- SK_INIT(vkGetImageSparseMemoryRequirements);
- SK_INIT(vkGetImageSubresourceLayout);
- SK_INIT(vkGetInstanceProcAddr);
- SK_INIT(vkGetPhysicalDeviceFeatures);
- SK_INIT(vkGetPhysicalDeviceFormatProperties);
- SK_INIT(vkGetPhysicalDeviceImageFormatProperties);
- SK_INIT(vkGetPhysicalDeviceMemoryProperties);
- SK_INIT(vkGetPhysicalDeviceProperties);
- SK_INIT(vkGetPhysicalDeviceQueueFamilyProperties);
- SK_INIT(vkGetPhysicalDeviceSparseImageFormatProperties);
- SK_INIT(vkGetPipelineCacheData);
- SK_INIT(vkGetQueryPoolResults);
- SK_INIT(vkGetRenderAreaGranularity);
- SK_INIT(vkInvalidateMappedMemoryRanges);
- SK_INIT(vkMapMemory);
- SK_INIT(vkMergePipelineCaches);
- SK_INIT(vkQueueBindSparse);
- SK_INIT(vkQueueSubmit);
- SK_INIT(vkQueueWaitIdle);
- SK_INIT(vkResetCommandBuffer);
- SK_INIT(vkResetCommandPool);
- SK_INIT(vkResetDescriptorPool);
- SK_INIT(vkResetEvent);
- SK_INIT(vkResetFences);
- SK_INIT(vkSetEvent);
- SK_INIT(vkUnmapMemory);
- SK_INIT(vkUpdateDescriptorSets);
- SK_INIT(vkWaitForFences);
-
- // VK_EXT_debug_report
- SK_INIT(vkCreateDebugReportCallbackEXT);
- SK_INIT(vkDebugReportMessageEXT);
- SK_INIT(vkDestroyDebugReportCallbackEXT);
-
- // VK_KHR_surface
- SK_INIT(vkDestroySurfaceKHR);
- SK_INIT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
- SK_INIT(vkGetPhysicalDeviceSurfaceFormatsKHR);
- SK_INIT(vkGetPhysicalDeviceSurfacePresentModesKHR);
- SK_INIT(vkGetPhysicalDeviceSurfaceSupportKHR);
-
- // VK_KHR_swapchain
- SK_INIT(vkAcquireNextImageKHR);
- SK_INIT(vkCreateSwapchainKHR);
- SK_INIT(vkDestroySwapchainKHR);
- SK_INIT(vkGetDeviceGroupPresentCapabilitiesKHR);
- SK_INIT(vkGetDeviceGroupSurfacePresentModesKHR);
- SK_INIT(vkGetPhysicalDevicePresentRectanglesKHR);
- SK_INIT(vkGetSwapchainImagesKHR);
- SK_INIT(vkQueuePresentKHR);
+ template<typename NotFoundFunc>
+ VkResult init(const VulkanInitApi& initApi,
+ const Instance& instance,
+ NotFoundFunc notFound) noexcept
+ {
+ VkResult r = VK_SUCCESS;
+
+ const auto notFoundWrapper = [&r, notFound](const char* name) {
+ r = VK_INCOMPLETE;
+ notFound(name);
+ };
+
+#define SK_INIT(name) \
+ do { \
+ if (!(name = PFN_##name(initApi.getInstanceProcAddr(instance, #name)))) { \
+ notFoundWrapper(#name); \
+ } \
+ } while (0)
+
+ SK_INIT(vkAllocateCommandBuffers);
+ SK_INIT(vkAllocateDescriptorSets);
+ SK_INIT(vkAllocateMemory);
+ SK_INIT(vkBeginCommandBuffer);
+ SK_INIT(vkBindBufferMemory);
+ SK_INIT(vkBindImageMemory);
+ SK_INIT(vkCmdBeginQuery);
+ SK_INIT(vkCmdBeginRenderPass);
+ SK_INIT(vkCmdBindDescriptorSets);
+ SK_INIT(vkCmdBindIndexBuffer);
+ SK_INIT(vkCmdBindPipeline);
+ SK_INIT(vkCmdBindVertexBuffers);
+ SK_INIT(vkCmdBlitImage);
+ SK_INIT(vkCmdClearAttachments);
+ SK_INIT(vkCmdClearColorImage);
+ SK_INIT(vkCmdClearDepthStencilImage);
+ SK_INIT(vkCmdCopyBuffer);
+ SK_INIT(vkCmdCopyBufferToImage);
+ SK_INIT(vkCmdCopyImage);
+ SK_INIT(vkCmdCopyImageToBuffer);
+ SK_INIT(vkCmdCopyQueryPoolResults);
+ SK_INIT(vkCmdDispatch);
+ SK_INIT(vkCmdDispatchIndirect);
+ SK_INIT(vkCmdDraw);
+ SK_INIT(vkCmdDrawIndexed);
+ SK_INIT(vkCmdDrawIndexedIndirect);
+ SK_INIT(vkCmdDrawIndirect);
+ SK_INIT(vkCmdEndQuery);
+ SK_INIT(vkCmdEndRenderPass);
+ SK_INIT(vkCmdExecuteCommands);
+ SK_INIT(vkCmdFillBuffer);
+ SK_INIT(vkCmdNextSubpass);
+ SK_INIT(vkCmdPipelineBarrier);
+ SK_INIT(vkCmdPushConstants);
+ SK_INIT(vkCmdResetEvent);
+ SK_INIT(vkCmdResetQueryPool);
+ SK_INIT(vkCmdResolveImage);
+ SK_INIT(vkCmdSetBlendConstants);
+ SK_INIT(vkCmdSetDepthBias);
+ SK_INIT(vkCmdSetDepthBounds);
+ SK_INIT(vkCmdSetEvent);
+ SK_INIT(vkCmdSetLineWidth);
+ SK_INIT(vkCmdSetScissor);
+ SK_INIT(vkCmdSetStencilCompareMask);
+ SK_INIT(vkCmdSetStencilReference);
+ SK_INIT(vkCmdSetStencilWriteMask);
+ SK_INIT(vkCmdSetViewport);
+ SK_INIT(vkCmdUpdateBuffer);
+ SK_INIT(vkCmdWaitEvents);
+ SK_INIT(vkCmdWriteTimestamp);
+ SK_INIT(vkCreateBuffer);
+ SK_INIT(vkCreateBufferView);
+ SK_INIT(vkCreateCommandPool);
+ SK_INIT(vkCreateComputePipelines);
+ SK_INIT(vkCreateDescriptorPool);
+ SK_INIT(vkCreateDescriptorSetLayout);
+ SK_INIT(vkCreateDevice);
+ SK_INIT(vkCreateEvent);
+ SK_INIT(vkCreateFence);
+ SK_INIT(vkCreateFramebuffer);
+ SK_INIT(vkCreateGraphicsPipelines);
+ SK_INIT(vkCreateImage);
+ SK_INIT(vkCreateImageView);
+ SK_INIT(vkCreateInstance);
+ SK_INIT(vkCreatePipelineCache);
+ SK_INIT(vkCreatePipelineLayout);
+ SK_INIT(vkCreateQueryPool);
+ SK_INIT(vkCreateRenderPass);
+ SK_INIT(vkCreateSampler);
+ SK_INIT(vkCreateSemaphore);
+ SK_INIT(vkCreateShaderModule);
+ SK_INIT(vkDestroyBuffer);
+ SK_INIT(vkDestroyBufferView);
+ SK_INIT(vkDestroyCommandPool);
+ SK_INIT(vkDestroyDescriptorPool);
+ SK_INIT(vkDestroyDescriptorSetLayout);
+ SK_INIT(vkDestroyDevice);
+ SK_INIT(vkDestroyEvent);
+ SK_INIT(vkDestroyFence);
+ SK_INIT(vkDestroyFramebuffer);
+ SK_INIT(vkDestroyImage);
+ SK_INIT(vkDestroyImageView);
+ SK_INIT(vkDestroyPipeline);
+ SK_INIT(vkDestroyPipelineCache);
+ SK_INIT(vkDestroyPipelineLayout);
+ SK_INIT(vkDestroyQueryPool);
+ SK_INIT(vkDestroyRenderPass);
+ SK_INIT(vkDestroySampler);
+ SK_INIT(vkDestroySemaphore);
+ SK_INIT(vkDestroyShaderModule);
+ SK_INIT(vkDeviceWaitIdle);
+ SK_INIT(vkEndCommandBuffer);
+ SK_INIT(vkEnumerateDeviceExtensionProperties);
+ SK_INIT(vkEnumerateDeviceLayerProperties);
+ SK_INIT(vkEnumeratePhysicalDevices);
+ SK_INIT(vkFlushMappedMemoryRanges);
+ SK_INIT(vkFreeCommandBuffers);
+ SK_INIT(vkFreeDescriptorSets);
+ SK_INIT(vkFreeMemory);
+ SK_INIT(vkGetBufferMemoryRequirements);
+ SK_INIT(vkGetDeviceMemoryCommitment);
+ SK_INIT(vkGetDeviceProcAddr);
+ SK_INIT(vkGetDeviceQueue);
+ SK_INIT(vkGetEventStatus);
+ SK_INIT(vkGetFenceStatus);
+ SK_INIT(vkGetImageMemoryRequirements);
+ SK_INIT(vkGetImageSparseMemoryRequirements);
+ SK_INIT(vkGetImageSubresourceLayout);
+ SK_INIT(vkGetInstanceProcAddr);
+ SK_INIT(vkGetPhysicalDeviceFeatures);
+ SK_INIT(vkGetPhysicalDeviceFormatProperties);
+ SK_INIT(vkGetPhysicalDeviceImageFormatProperties);
+ SK_INIT(vkGetPhysicalDeviceMemoryProperties);
+ SK_INIT(vkGetPhysicalDeviceProperties);
+ SK_INIT(vkGetPhysicalDeviceQueueFamilyProperties);
+ SK_INIT(vkGetPhysicalDeviceSparseImageFormatProperties);
+ SK_INIT(vkGetPipelineCacheData);
+ SK_INIT(vkGetQueryPoolResults);
+ SK_INIT(vkGetRenderAreaGranularity);
+ SK_INIT(vkInvalidateMappedMemoryRanges);
+ SK_INIT(vkMapMemory);
+ SK_INIT(vkMergePipelineCaches);
+ SK_INIT(vkQueueBindSparse);
+ SK_INIT(vkQueueSubmit);
+ SK_INIT(vkQueueWaitIdle);
+ SK_INIT(vkResetCommandBuffer);
+ SK_INIT(vkResetCommandPool);
+ SK_INIT(vkResetDescriptorPool);
+ SK_INIT(vkResetEvent);
+ SK_INIT(vkResetFences);
+ SK_INIT(vkSetEvent);
+ SK_INIT(vkUnmapMemory);
+ SK_INIT(vkUpdateDescriptorSets);
+ SK_INIT(vkWaitForFences);
+
+ // VK_EXT_debug_report
+ SK_INIT(vkCreateDebugReportCallbackEXT);
+ SK_INIT(vkDebugReportMessageEXT);
+ SK_INIT(vkDestroyDebugReportCallbackEXT);
+
+ // VK_KHR_surface
+ SK_INIT(vkDestroySurfaceKHR);
+ SK_INIT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
+ SK_INIT(vkGetPhysicalDeviceSurfaceFormatsKHR);
+ SK_INIT(vkGetPhysicalDeviceSurfacePresentModesKHR);
+ SK_INIT(vkGetPhysicalDeviceSurfaceSupportKHR);
+
+ // VK_KHR_swapchain
+ SK_INIT(vkAcquireNextImageKHR);
+ SK_INIT(vkCreateSwapchainKHR);
+ SK_INIT(vkDestroySwapchainKHR);
+ SK_INIT(vkGetDeviceGroupPresentCapabilitiesKHR);
+ SK_INIT(vkGetDeviceGroupSurfacePresentModesKHR);
+ SK_INIT(vkGetPhysicalDevicePresentRectanglesKHR);
+ SK_INIT(vkGetSwapchainImagesKHR);
+ SK_INIT(vkQueuePresentKHR);
#undef SK_INIT
- return r;
- }
-
- VkResult
- init(const VulkanInitApi& initApi, const Instance& instance) noexcept
- {
- return init(initApi, instance, [](const char*) {});
- }
-
- template<class VkCommandBufferVector>
- VkResult allocateCommandBuffers(
- const Device& device,
- const VkCommandBufferAllocateInfo& allocateInfo,
- CommandBuffers<VkCommandBufferVector>& commandBuffers) const noexcept
- {
- VkCommandBufferVector rawCommandBuffers = VkCommandBufferVector(
- allocateInfo.commandBufferCount);
-
- if (const VkResult r = vkAllocateCommandBuffers(
- device, &allocateInfo, rawCommandBuffers.data())) {
- return r;
- }
-
- commandBuffers = CommandBuffers<VkCommandBufferVector>{
- allocateInfo.commandBufferCount,
- std::move(rawCommandBuffers),
- PoolDeleter<VkCommandBuffer, VkCommandPool, void>{
- device,
- allocateInfo.commandPool,
- allocateInfo.commandBufferCount,
- vkFreeCommandBuffers}};
- return VK_SUCCESS;
- }
-
- template<class VkDescriptorSetVector>
- VkResult allocateDescriptorSets(
- const Device& device,
- const VkDescriptorSetAllocateInfo& allocateInfo,
- DescriptorSets<VkDescriptorSetVector>& descriptorSets) const noexcept
- {
- auto descriptorSetVector = VkDescriptorSetVector(
- allocateInfo.descriptorSetCount);
-
- if (const VkResult r = vkAllocateDescriptorSets(
- device, &allocateInfo, descriptorSetVector.data())) {
- return r;
- }
-
- descriptorSets = DescriptorSets<VkDescriptorSetVector>{
- allocateInfo.descriptorSetCount,
- std::move(descriptorSetVector),
- PoolDeleter<VkDescriptorSet, VkDescriptorPool, VkResult>{
- device,
- allocateInfo.descriptorPool,
- allocateInfo.descriptorSetCount,
- vkFreeDescriptorSets}};
- return VK_SUCCESS;
- }
-
- VkResult bindBufferMemory(const Device& device,
- const Buffer& buffer,
- const DeviceMemory& memory,
- VkDeviceSize memoryOffset) const noexcept
- {
- return vkBindBufferMemory
- ? vkBindBufferMemory(device, buffer, memory, memoryOffset)
- : VK_ERROR_FEATURE_NOT_PRESENT;
- }
-
- VkResult createBuffer(const Device& device,
- const VkBufferCreateInfo& createInfo,
- Buffer& buffer) const noexcept
- {
- VkBuffer h = {};
- const VkResult r = vkCreateBuffer(device, &createInfo, nullptr, &h);
- return wrapResult(r, h, {device, vkDestroyBuffer}, buffer);
- }
-
- VkResult createBufferView(const Device& device,
- const VkBufferViewCreateInfo& createInfo,
- BufferView& bufferView) const noexcept
- {
- VkBufferView h = {};
- const VkResult r = vkCreateBufferView(device, &createInfo, nullptr, &h);
- return wrapResult(r, h, {device, vkDestroyBufferView}, bufferView);
- }
-
- VkResult createCommandPool(const Device& device,
- const VkCommandPoolCreateInfo& createInfo,
- CommandPool& commandPool) const noexcept
- {
- VkCommandPool h = {};
- const VkResult r =
- vkCreateCommandPool(device, &createInfo, nullptr, &h);
- return wrapResult(r, h, {device, vkDestroyCommandPool}, commandPool);
- }
-
- VkResult createDescriptorPool(const Device& device,
- const VkDescriptorPoolCreateInfo& createInfo,
- DescriptorPool& descriptorPool) const noexcept
- {
- VkDescriptorPool h = {};
- const VkResult r =
- vkCreateDescriptorPool(device, &createInfo, nullptr, &h);
-
- return wrapResult(r,
- h,
- {device, vkDestroyDescriptorPool},
- descriptorPool);
- }
-
- VkResult createDescriptorSetLayout(
- const Device& device,
- const VkDescriptorSetLayoutCreateInfo& createInfo,
- DescriptorSetLayout& descriptorSetLayout) const noexcept
- {
- VkDescriptorSetLayout h = {};
- const VkResult r =
- vkCreateDescriptorSetLayout(device, &createInfo, nullptr, &h);
-
- return wrapResult(r,
- h,
- {device, vkDestroyDescriptorSetLayout},
- descriptorSetLayout);
- }
-
- VkResult createDevice(const PhysicalDevice& physicalDevice,
- const VkDeviceCreateInfo& createInfo,
- Device& result) const noexcept
- {
- VkDevice h = {};
- const VkResult r =
- vkCreateDevice(physicalDevice, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {vkDestroyDevice}, result);
- }
-
- VkResult createEvent(const Device& device,
- const VkEventCreateInfo& createInfo,
- Event& event) const noexcept
- {
- VkEvent h = {};
- const VkResult r = vkCreateEvent(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyEvent}, event);
- }
-
- VkResult createFence(const Device& device,
- const VkFenceCreateInfo& createInfo,
- Fence& fence) const noexcept
- {
- VkFence h = {};
- const VkResult r = vkCreateFence(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyFence}, fence);
- }
-
- VkResult createFramebuffer(const Device& device,
- const VkFramebufferCreateInfo& createInfo,
- Framebuffer& framebuffer) const noexcept
- {
- VkFramebuffer h = {};
- const VkResult r =
- vkCreateFramebuffer(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyFramebuffer}, framebuffer);
- }
-
- VkResult createImage(const Device& device,
- const VkImageCreateInfo& createInfo,
- Image& image) const noexcept
- {
- VkImage h = {};
- const VkResult r = vkCreateImage(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyImage}, image);
- }
-
- VkResult createImageView(const Device& device,
- const VkImageViewCreateInfo& createInfo,
- ImageView& imageView) const noexcept
- {
- VkImageView h = {};
- const VkResult r = vkCreateImageView(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyImageView}, imageView);
- }
-
- template<size_t count>
- VkResult createGraphicsPipelines(
- const Device& device,
- const OptionalParameter<PipelineCache>& pipelineCache,
- const std::array<VkGraphicsPipelineCreateInfo, count>& createInfos,
- std::array<Pipeline, count>& pipelines) const noexcept
- {
- std::array<VkPipeline, count> pipelineHandles{};
-
- if (const VkResult r = vkCreateGraphicsPipelines(
- device,
- pipelineCache.get(),
- static_cast<uint32_t>(createInfos.size()),
- createInfos.data(),
- nullptr,
- pipelineHandles.data())) {
- return r;
- }
-
- pipelines = make_handle_array<Pipeline>(device.get(),
- vkDestroyPipeline,
- pipelineHandles);
- return VK_SUCCESS;
- }
-
- VkResult createPipelineCache(const Device& device,
- const VkPipelineCacheCreateInfo& createInfo,
- PipelineCache& pipelineCache) const noexcept
- {
- VkPipelineCache h = {};
- const VkResult r =
- vkCreatePipelineCache(device, &createInfo, nullptr, &h);
-
- return wrapResult(r,
- h,
- {device, vkDestroyPipelineCache},
- pipelineCache);
- }
-
- VkResult createPipelineLayout(const Device& device,
- const VkPipelineLayoutCreateInfo& createInfo,
- PipelineLayout& pipelineLayout) const noexcept
- {
- VkPipelineLayout h = {};
- const VkResult r =
- vkCreatePipelineLayout(device, &createInfo, nullptr, &h);
-
- return wrapResult(r,
- h,
- {device, vkDestroyPipelineLayout},
- pipelineLayout);
- }
-
- VkResult createQueryPool(const Device& device,
- const VkQueryPoolCreateInfo& createInfo,
- QueryPool& queryPool) const noexcept
- {
- VkQueryPool h = {};
- const VkResult r = vkCreateQueryPool(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyQueryPool}, queryPool);
- }
-
- VkResult createRenderPass(const Device& device,
- const VkRenderPassCreateInfo& createInfo,
- RenderPass& renderPass) const noexcept
- {
- VkRenderPass h = {};
- const VkResult r = vkCreateRenderPass(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyRenderPass}, renderPass);
- }
-
- VkResult createSampler(const Device& device,
- const VkSamplerCreateInfo& createInfo,
- Sampler& sampler) const noexcept
- {
- VkSampler h = {};
- const VkResult r = vkCreateSampler(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroySampler}, sampler);
- }
-
- VkResult createSemaphore(const Device& device,
- const VkSemaphoreCreateInfo& createInfo,
- Semaphore& semaphore) const noexcept
- {
- VkSemaphore h = {};
- const VkResult r = vkCreateSemaphore(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroySemaphore}, semaphore);
- }
-
- VkResult createShaderModule(const Device& device,
- const VkShaderModuleCreateInfo& createInfo,
- ShaderModule& shaderModule) const noexcept
- {
- VkShaderModule h = {};
- const VkResult r =
- vkCreateShaderModule(device, &createInfo, nullptr, &h);
-
- return wrapResult(r, h, {device, vkDestroyShaderModule}, shaderModule);
- }
-
- VkResult deviceWaitIdle(const Device& device) const noexcept
- {
- return vkDeviceWaitIdle(device);
- }
-
- template<class Vector>
- VkResult
- enumerateDeviceExtensionProperties(const PhysicalDevice& physicalDevice,
- const char* const layerName,
- Vector& properties) const noexcept
- {
- return detail::wrapVectorAccessor<VkExtensionProperties>(
- properties,
- vkEnumerateDeviceExtensionProperties,
- physicalDevice,
- layerName);
- }
-
- template<class Vector>
- VkResult
- enumerateDeviceExtensionProperties(const PhysicalDevice& physicalDevice,
- Vector& properties) const noexcept
- {
- return detail::wrapVectorAccessor<VkExtensionProperties>(
- properties,
- vkEnumerateDeviceExtensionProperties,
- physicalDevice,
- nullptr);
- }
-
- template<class Vector>
- VkResult enumeratePhysicalDevices(const Instance& instance,
- Vector& physicalDevices) const noexcept
- {
- uint32_t count = 0u;
- VkResult r = vkEnumeratePhysicalDevices(instance, &count, nullptr);
- if (r > VK_INCOMPLETE) {
- return r;
- }
-
- physicalDevices = Vector(count);
- if ((r = vkEnumeratePhysicalDevices(instance,
- &count,
- physicalDevices.data()))) {
- return r;
- }
-
- return VK_SUCCESS;
- }
-
- sk::Queue getDeviceQueue(const Device& device,
- const uint32_t queueFamilyIndex,
- const uint32_t queueIndex) const noexcept
- {
- VkQueue queue{};
- vkGetDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
- return sk::Queue{queue};
- }
-
- VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties(
- VkPhysicalDevice physicalDevice) const noexcept
- {
- VkPhysicalDeviceMemoryProperties properties{};
- vkGetPhysicalDeviceMemoryProperties(physicalDevice, &properties);
- return properties;
- }
-
- VkPhysicalDeviceProperties getPhysicalDeviceProperties(
- const PhysicalDevice& physicalDevice) const noexcept
- {
- VkPhysicalDeviceProperties properties{};
- vkGetPhysicalDeviceProperties(physicalDevice, &properties);
- return properties;
- }
-
- template<class Vector>
- VkResult getPhysicalDeviceQueueFamilyProperties(
- const PhysicalDevice& physicalDevice,
- Vector& queueFamilyProperties) const noexcept
- {
- uint32_t count = 0u;
- vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice,
- &count,
- nullptr);
-
- queueFamilyProperties = Vector(count);
- vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice,
- &count,
- queueFamilyProperties.data());
-
- return VK_SUCCESS;
- }
-
- VkMemoryRequirements
- getBufferMemoryRequirements(const Device& device,
- const Buffer& buffer) const noexcept
- {
- VkMemoryRequirements requirements;
- vkGetBufferMemoryRequirements(device, buffer, &requirements);
- return requirements;
- }
-
- VkResult allocateMemory(const Device& device,
- const VkMemoryAllocateInfo& info,
- DeviceMemory& memory) const noexcept
- {
- VkDeviceMemory h = {};
- if (const VkResult r = vkAllocateMemory(device, &info, nullptr, &h)) {
- return r;
- } else if (!h) {
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
-
- memory = DeviceMemory{h, {device, vkFreeMemory}};
- return VK_SUCCESS;
- }
-
- VkResult mapMemory(const Device& device,
- const DeviceMemory& memory,
- VkDeviceSize offset,
- VkDeviceSize size,
- VkMemoryMapFlags flags,
- MappedMemory& mappedMemory) const noexcept
- {
- void* data = nullptr;
- if (const VkResult r =
- vkMapMemory(device, memory, offset, size, flags, &data)) {
- return r;
- }
-
- mappedMemory = MappedMemory{*this, device, memory, data};
- return VK_SUCCESS;
- }
-
- VkResult queueSubmit(const Queue& queue,
- uint32_t submitCount,
- const VkSubmitInfo& submits,
- const Fence& fence) const noexcept
- {
- return vkQueueSubmit(queue, submitCount, &submits, fence);
- }
-
- VkResult queueSubmit(const Queue& queue,
- const VkSubmitInfo& submit,
- const Fence& fence) const noexcept
- {
- return vkQueueSubmit(queue, 1u, &submit, fence);
- }
-
- template<size_t descriptorWriteCount, size_t descriptorCopyCount>
- void updateDescriptorSets(
- const Device& device,
- std::array<VkWriteDescriptorSet, descriptorWriteCount> descriptorWrites,
- std::array<VkCopyDescriptorSet, descriptorCopyCount> descriptorCopies)
- const noexcept
- {
- vkUpdateDescriptorSets(device,
- static_cast<uint32_t>(descriptorWrites.size()),
- descriptorWrites.data(),
- static_cast<uint32_t>(descriptorCopies.size()),
- descriptorCopies.data());
- }
-
- VkResult resetFence(const Device& device, const Fence& fence) const noexcept
- {
- VkFence h = fence;
- return vkResetFences(device, 1u, &h);
- }
-
- VkResult waitForFence(const Device& device,
- const Fence& fence,
- uint64_t timeout) const noexcept
- {
- VkFence h = fence;
- return vkWaitForFences(device, 1u, &h, VK_TRUE, timeout);
- }
-
- VkResult
- waitForFence(const Device& device, const Fence& fence) const noexcept
- {
- VkFence h = fence;
- return vkWaitForFences(device, 1u, &h, VK_TRUE, UINT64_MAX);
- }
-
- // Scoped command buffer interface
- SYBOK_NODISCARD
- CommandScope
- beginCommandBuffer(VkCommandBuffer commandBuffer,
- VkCommandBufferBeginInfo beginInfo) const noexcept;
-
- // VK_EXT_debug_report
-
- VkResult createDebugReportCallbackEXT(
- const Instance& instance,
- const VkDebugReportCallbackCreateInfoEXT& createInfo,
- DebugReportCallbackEXT& callback) const noexcept
- {
- VkDebugReportCallbackEXT h = {};
-
- if (const VkResult r = vkCreateDebugReportCallbackEXT(
- instance, &createInfo, nullptr, &h)) {
- return r;
- } else if (!h) {
- return VK_ERROR_FEATURE_NOT_PRESENT;
- }
-
- callback = {h, {instance, vkDestroyDebugReportCallbackEXT}};
- return VK_SUCCESS;
- }
-
- // VK_KHR_surface
-
- VkResult getPhysicalDeviceSurfaceCapabilitiesKHR(
- const PhysicalDevice& physicalDevice,
- const SurfaceKHR& surface,
- VkSurfaceCapabilitiesKHR& capabilities) const noexcept
- {
- return vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice,
- surface,
- &capabilities);
- }
-
- template<typename Vector>
- VkResult
- getPhysicalDeviceSurfaceFormatsKHR(const PhysicalDevice& physicalDevice,
- const SurfaceKHR& surface,
- Vector& surfaceFormats) const noexcept
- {
- return detail::wrapVectorAccessor<VkSurfaceFormatKHR>(
- surfaceFormats,
- vkGetPhysicalDeviceSurfaceFormatsKHR,
- physicalDevice,
- surface.get());
- }
-
- template<typename Vector>
- VkResult getPhysicalDeviceSurfacePresentModesKHR(
- const PhysicalDevice& physicalDevice,
- const SurfaceKHR& surface,
- Vector& presentModes) const noexcept
- {
- return detail::wrapVectorAccessor<VkPresentModeKHR>(
- presentModes,
- vkGetPhysicalDeviceSurfacePresentModesKHR,
- physicalDevice,
- surface.get());
- }
-
- VkResult
- getPhysicalDeviceSurfaceSupportKHR(const PhysicalDevice& physicalDevice,
- uint32_t queueFamilyIndex,
- const SurfaceKHR& surface,
- bool& supported) const noexcept
- {
- VkBool32 s = {};
-
- if (VkResult r = vkGetPhysicalDeviceSurfaceSupportKHR(
- physicalDevice, queueFamilyIndex, surface, &s)) {
- return r;
- }
-
- supported = s;
- return VK_SUCCESS;
- }
-
- // VK_KHR_swapchain
-
- VkResult acquireNextImageKHR(const Device& device,
- const SwapchainKHR& swapchain,
- uint64_t timeout,
- const Semaphore& semaphore,
- const OptionalParameter<Fence>& fence,
- uint32_t* pImageIndex) const noexcept
- {
- return vkAcquireNextImageKHR(
- device, swapchain, timeout, semaphore, fence.get(), pImageIndex);
- }
-
- template<class Vector>
- VkResult getSwapchainImagesKHR(const Device& device,
- const SwapchainKHR& swapchain,
- Vector& images) const noexcept
- {
- return detail::wrapVectorAccessor<VkImage>(images,
- vkGetSwapchainImagesKHR,
- device.get(),
- swapchain.get());
- }
-
- VkResult createSwapchainKHR(const Device& device,
- const VkSwapchainCreateInfoKHR& createInfo,
- SwapchainKHR& swapchain) const noexcept
- {
- VkSwapchainKHR h = {};
- const VkResult r =
- vkCreateSwapchainKHR(device, &createInfo, nullptr, &h);
-
- if (r) {
- return r;
- } else if (!h) {
- return VK_ERROR_INCOMPATIBLE_DRIVER;
- }
-
- swapchain = {h, {device, vkDestroySwapchainKHR}};
- return VK_SUCCESS;
- }
-
- VkResult queuePresentKHR(const Queue& queue,
- const VkPresentInfoKHR& presentInfo) const noexcept
- {
- return vkQueuePresentKHR(queue, &presentInfo);
- }
+ return r;
+ }
+
+ VkResult init(const VulkanInitApi& initApi, const Instance& instance) noexcept
+ {
+ return init(initApi, instance, [](const char*) {});
+ }
+
+ template<class VkCommandBufferVector>
+ VkResult allocateCommandBuffers(
+ const Device& device,
+ const VkCommandBufferAllocateInfo& allocateInfo,
+ CommandBuffers<VkCommandBufferVector>& commandBuffers) const noexcept
+ {
+ VkCommandBufferVector rawCommandBuffers =
+ VkCommandBufferVector(allocateInfo.commandBufferCount);
+
+ if (const VkResult r = vkAllocateCommandBuffers(
+ device, &allocateInfo, rawCommandBuffers.data())) {
+ return r;
+ }
+
+ commandBuffers = CommandBuffers<VkCommandBufferVector>{
+ allocateInfo.commandBufferCount,
+ std::move(rawCommandBuffers),
+ PoolDeleter<VkCommandBuffer, VkCommandPool, void>{
+ device,
+ allocateInfo.commandPool,
+ allocateInfo.commandBufferCount,
+ vkFreeCommandBuffers}};
+ return VK_SUCCESS;
+ }
+
+ template<class VkDescriptorSetVector>
+ VkResult allocateDescriptorSets(
+ const Device& device,
+ const VkDescriptorSetAllocateInfo& allocateInfo,
+ DescriptorSets<VkDescriptorSetVector>& descriptorSets) const noexcept
+ {
+ auto descriptorSetVector =
+ VkDescriptorSetVector(allocateInfo.descriptorSetCount);
+
+ if (const VkResult r = vkAllocateDescriptorSets(
+ device, &allocateInfo, descriptorSetVector.data())) {
+ return r;
+ }
+
+ descriptorSets = DescriptorSets<VkDescriptorSetVector>{
+ allocateInfo.descriptorSetCount,
+ std::move(descriptorSetVector),
+ PoolDeleter<VkDescriptorSet, VkDescriptorPool, VkResult>{
+ device,
+ allocateInfo.descriptorPool,
+ allocateInfo.descriptorSetCount,
+ vkFreeDescriptorSets}};
+ return VK_SUCCESS;
+ }
+
+ VkResult bindBufferMemory(const Device& device,
+ const Buffer& buffer,
+ const DeviceMemory& memory,
+ VkDeviceSize memoryOffset) const noexcept
+ {
+ return vkBindBufferMemory
+ ? vkBindBufferMemory(device, buffer, memory, memoryOffset)
+ : VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ VkResult createBuffer(const Device& device,
+ const VkBufferCreateInfo& createInfo,
+ Buffer& buffer) const noexcept
+ {
+ VkBuffer h = {};
+ const VkResult r = vkCreateBuffer(device, &createInfo, nullptr, &h);
+ return wrapResult(r, h, {device, vkDestroyBuffer}, buffer);
+ }
+
+ VkResult createBufferView(const Device& device,
+ const VkBufferViewCreateInfo& createInfo,
+ BufferView& bufferView) const noexcept
+ {
+ VkBufferView h = {};
+ const VkResult r = vkCreateBufferView(device, &createInfo, nullptr, &h);
+ return wrapResult(r, h, {device, vkDestroyBufferView}, bufferView);
+ }
+
+ VkResult createCommandPool(const Device& device,
+ const VkCommandPoolCreateInfo& createInfo,
+ CommandPool& commandPool) const noexcept
+ {
+ VkCommandPool h = {};
+ const VkResult r = vkCreateCommandPool(device, &createInfo, nullptr, &h);
+ return wrapResult(r, h, {device, vkDestroyCommandPool}, commandPool);
+ }
+
+ VkResult createDescriptorPool(const Device& device,
+ const VkDescriptorPoolCreateInfo& createInfo,
+ DescriptorPool& descriptorPool) const noexcept
+ {
+ VkDescriptorPool h = {};
+ const VkResult r = vkCreateDescriptorPool(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyDescriptorPool}, descriptorPool);
+ }
+
+ VkResult createDescriptorSetLayout(
+ const Device& device,
+ const VkDescriptorSetLayoutCreateInfo& createInfo,
+ DescriptorSetLayout& descriptorSetLayout) const noexcept
+ {
+ VkDescriptorSetLayout h = {};
+ const VkResult r =
+ vkCreateDescriptorSetLayout(device, &createInfo, nullptr, &h);
+
+ return wrapResult(
+ r, h, {device, vkDestroyDescriptorSetLayout}, descriptorSetLayout);
+ }
+
+ VkResult createDevice(const PhysicalDevice& physicalDevice,
+ const VkDeviceCreateInfo& createInfo,
+ Device& result) const noexcept
+ {
+ VkDevice h = {};
+ const VkResult r = vkCreateDevice(physicalDevice, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {vkDestroyDevice}, result);
+ }
+
+ VkResult createEvent(const Device& device,
+ const VkEventCreateInfo& createInfo,
+ Event& event) const noexcept
+ {
+ VkEvent h = {};
+ const VkResult r = vkCreateEvent(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyEvent}, event);
+ }
+
+ VkResult createFence(const Device& device,
+ const VkFenceCreateInfo& createInfo,
+ Fence& fence) const noexcept
+ {
+ VkFence h = {};
+ const VkResult r = vkCreateFence(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyFence}, fence);
+ }
+
+ VkResult createFramebuffer(const Device& device,
+ const VkFramebufferCreateInfo& createInfo,
+ Framebuffer& framebuffer) const noexcept
+ {
+ VkFramebuffer h = {};
+ const VkResult r = vkCreateFramebuffer(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyFramebuffer}, framebuffer);
+ }
+
+ VkResult createImage(const Device& device,
+ const VkImageCreateInfo& createInfo,
+ Image& image) const noexcept
+ {
+ VkImage h = {};
+ const VkResult r = vkCreateImage(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyImage}, image);
+ }
+
+ VkResult createImageView(const Device& device,
+ const VkImageViewCreateInfo& createInfo,
+ ImageView& imageView) const noexcept
+ {
+ VkImageView h = {};
+ const VkResult r = vkCreateImageView(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyImageView}, imageView);
+ }
+
+ template<size_t count>
+ VkResult createGraphicsPipelines(
+ const Device& device,
+ const OptionalParameter<PipelineCache>& pipelineCache,
+ const std::array<VkGraphicsPipelineCreateInfo, count>& createInfos,
+ std::array<Pipeline, count>& pipelines) const noexcept
+ {
+ std::array<VkPipeline, count> pipelineHandles{};
+
+ if (const VkResult r =
+ vkCreateGraphicsPipelines(device,
+ pipelineCache.get(),
+ static_cast<uint32_t>(createInfos.size()),
+ createInfos.data(),
+ nullptr,
+ pipelineHandles.data())) {
+ return r;
+ }
+
+ pipelines = make_handle_array<Pipeline>(
+ device.get(), vkDestroyPipeline, pipelineHandles);
+ return VK_SUCCESS;
+ }
+
+ VkResult createPipelineCache(const Device& device,
+ const VkPipelineCacheCreateInfo& createInfo,
+ PipelineCache& pipelineCache) const noexcept
+ {
+ VkPipelineCache h = {};
+ const VkResult r = vkCreatePipelineCache(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyPipelineCache}, pipelineCache);
+ }
+
+ VkResult createPipelineLayout(const Device& device,
+ const VkPipelineLayoutCreateInfo& createInfo,
+ PipelineLayout& pipelineLayout) const noexcept
+ {
+ VkPipelineLayout h = {};
+ const VkResult r = vkCreatePipelineLayout(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyPipelineLayout}, pipelineLayout);
+ }
+
+ VkResult createQueryPool(const Device& device,
+ const VkQueryPoolCreateInfo& createInfo,
+ QueryPool& queryPool) const noexcept
+ {
+ VkQueryPool h = {};
+ const VkResult r = vkCreateQueryPool(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyQueryPool}, queryPool);
+ }
+
+ VkResult createRenderPass(const Device& device,
+ const VkRenderPassCreateInfo& createInfo,
+ RenderPass& renderPass) const noexcept
+ {
+ VkRenderPass h = {};
+ const VkResult r = vkCreateRenderPass(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyRenderPass}, renderPass);
+ }
+
+ VkResult createSampler(const Device& device,
+ const VkSamplerCreateInfo& createInfo,
+ Sampler& sampler) const noexcept
+ {
+ VkSampler h = {};
+ const VkResult r = vkCreateSampler(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroySampler}, sampler);
+ }
+
+ VkResult createSemaphore(const Device& device,
+ const VkSemaphoreCreateInfo& createInfo,
+ Semaphore& semaphore) const noexcept
+ {
+ VkSemaphore h = {};
+ const VkResult r = vkCreateSemaphore(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroySemaphore}, semaphore);
+ }
+
+ VkResult createShaderModule(const Device& device,
+ const VkShaderModuleCreateInfo& createInfo,
+ ShaderModule& shaderModule) const noexcept
+ {
+ VkShaderModule h = {};
+ const VkResult r = vkCreateShaderModule(device, &createInfo, nullptr, &h);
+
+ return wrapResult(r, h, {device, vkDestroyShaderModule}, shaderModule);
+ }
+
+ VkResult deviceWaitIdle(const Device& device) const noexcept
+ {
+ return vkDeviceWaitIdle(device);
+ }
+
+ template<class Vector>
+ VkResult enumerateDeviceExtensionProperties(
+ const PhysicalDevice& physicalDevice,
+ const char* const layerName,
+ Vector& properties) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkExtensionProperties>(
+ properties,
+ vkEnumerateDeviceExtensionProperties,
+ physicalDevice,
+ layerName);
+ }
+
+ template<class Vector>
+ VkResult enumerateDeviceExtensionProperties(
+ const PhysicalDevice& physicalDevice,
+ Vector& properties) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkExtensionProperties>(
+ properties,
+ vkEnumerateDeviceExtensionProperties,
+ physicalDevice,
+ nullptr);
+ }
+
+ template<class Vector>
+ VkResult enumeratePhysicalDevices(const Instance& instance,
+ Vector& physicalDevices) const noexcept
+ {
+ uint32_t count = 0u;
+ VkResult r = vkEnumeratePhysicalDevices(instance, &count, nullptr);
+ if (r > VK_INCOMPLETE) {
+ return r;
+ }
+
+ physicalDevices = Vector(count);
+ if ((r = vkEnumeratePhysicalDevices(
+ instance, &count, physicalDevices.data()))) {
+ return r;
+ }
+
+ return VK_SUCCESS;
+ }
+
+ sk::Queue getDeviceQueue(const Device& device,
+ const uint32_t queueFamilyIndex,
+ const uint32_t queueIndex) const noexcept
+ {
+ VkQueue queue{};
+ vkGetDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
+ return sk::Queue{queue};
+ }
+
+ VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties(
+ VkPhysicalDevice physicalDevice) const noexcept
+ {
+ VkPhysicalDeviceMemoryProperties properties{};
+ vkGetPhysicalDeviceMemoryProperties(physicalDevice, &properties);
+ return properties;
+ }
+
+ VkPhysicalDeviceProperties getPhysicalDeviceProperties(
+ const PhysicalDevice& physicalDevice) const noexcept
+ {
+ VkPhysicalDeviceProperties properties{};
+ vkGetPhysicalDeviceProperties(physicalDevice, &properties);
+ return properties;
+ }
+
+ template<class Vector>
+ VkResult getPhysicalDeviceQueueFamilyProperties(
+ const PhysicalDevice& physicalDevice,
+ Vector& queueFamilyProperties) const noexcept
+ {
+ uint32_t count = 0u;
+ vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
+
+ queueFamilyProperties = Vector(count);
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &count, queueFamilyProperties.data());
+
+ return VK_SUCCESS;
+ }
+
+ VkMemoryRequirements getBufferMemoryRequirements(
+ const Device& device,
+ const Buffer& buffer) const noexcept
+ {
+ VkMemoryRequirements requirements;
+ vkGetBufferMemoryRequirements(device, buffer, &requirements);
+ return requirements;
+ }
+
+ VkResult allocateMemory(const Device& device,
+ const VkMemoryAllocateInfo& info,
+ DeviceMemory& memory) const noexcept
+ {
+ VkDeviceMemory h = {};
+ if (const VkResult r = vkAllocateMemory(device, &info, nullptr, &h)) {
+ return r;
+ } else if (!h) {
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ memory = DeviceMemory{h, {device, vkFreeMemory}};
+ return VK_SUCCESS;
+ }
+
+ VkResult mapMemory(const Device& device,
+ const DeviceMemory& memory,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ MappedMemory& mappedMemory) const noexcept
+ {
+ void* data = nullptr;
+ if (const VkResult r =
+ vkMapMemory(device, memory, offset, size, flags, &data)) {
+ return r;
+ }
+
+ mappedMemory = MappedMemory{*this, device, memory, data};
+ return VK_SUCCESS;
+ }
+
+ VkResult queueSubmit(const Queue& queue,
+ uint32_t submitCount,
+ const VkSubmitInfo& submits,
+ const Fence& fence) const noexcept
+ {
+ return vkQueueSubmit(queue, submitCount, &submits, fence);
+ }
+
+ VkResult queueSubmit(const Queue& queue,
+ const VkSubmitInfo& submit,
+ const Fence& fence) const noexcept
+ {
+ return vkQueueSubmit(queue, 1u, &submit, fence);
+ }
+
+ template<size_t descriptorWriteCount, size_t descriptorCopyCount>
+ void updateDescriptorSets(
+ const Device& device,
+ std::array<VkWriteDescriptorSet, descriptorWriteCount> descriptorWrites,
+ std::array<VkCopyDescriptorSet, descriptorCopyCount> descriptorCopies)
+ const noexcept
+ {
+ vkUpdateDescriptorSets(device,
+ static_cast<uint32_t>(descriptorWrites.size()),
+ descriptorWrites.data(),
+ static_cast<uint32_t>(descriptorCopies.size()),
+ descriptorCopies.data());
+ }
+
+ VkResult resetFence(const Device& device, const Fence& fence) const noexcept
+ {
+ VkFence h = fence;
+ return vkResetFences(device, 1u, &h);
+ }
+
+ VkResult waitForFence(const Device& device,
+ const Fence& fence,
+ uint64_t timeout) const noexcept
+ {
+ VkFence h = fence;
+ return vkWaitForFences(device, 1u, &h, VK_TRUE, timeout);
+ }
+
+ VkResult waitForFence(const Device& device, const Fence& fence) const noexcept
+ {
+ VkFence h = fence;
+ return vkWaitForFences(device, 1u, &h, VK_TRUE, UINT64_MAX);
+ }
+
+ // Scoped command buffer interface
+ SYBOK_NODISCARD
+ CommandScope beginCommandBuffer(
+ VkCommandBuffer commandBuffer,
+ VkCommandBufferBeginInfo beginInfo) const noexcept;
+
+ // VK_EXT_debug_report
+
+ VkResult createDebugReportCallbackEXT(
+ const Instance& instance,
+ const VkDebugReportCallbackCreateInfoEXT& createInfo,
+ DebugReportCallbackEXT& callback) const noexcept
+ {
+ VkDebugReportCallbackEXT h = {};
+
+ if (const VkResult r =
+ vkCreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &h)) {
+ return r;
+ } else if (!h) {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ callback = {h, {instance, vkDestroyDebugReportCallbackEXT}};
+ return VK_SUCCESS;
+ }
+
+ // VK_KHR_surface
+
+ VkResult getPhysicalDeviceSurfaceCapabilitiesKHR(
+ const PhysicalDevice& physicalDevice,
+ const SurfaceKHR& surface,
+ VkSurfaceCapabilitiesKHR& capabilities) const noexcept
+ {
+ return vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ physicalDevice, surface, &capabilities);
+ }
+
+ template<typename Vector>
+ VkResult getPhysicalDeviceSurfaceFormatsKHR(
+ const PhysicalDevice& physicalDevice,
+ const SurfaceKHR& surface,
+ Vector& surfaceFormats) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkSurfaceFormatKHR>(
+ surfaceFormats,
+ vkGetPhysicalDeviceSurfaceFormatsKHR,
+ physicalDevice,
+ surface.get());
+ }
+
+ template<typename Vector>
+ VkResult getPhysicalDeviceSurfacePresentModesKHR(
+ const PhysicalDevice& physicalDevice,
+ const SurfaceKHR& surface,
+ Vector& presentModes) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkPresentModeKHR>(
+ presentModes,
+ vkGetPhysicalDeviceSurfacePresentModesKHR,
+ physicalDevice,
+ surface.get());
+ }
+
+ VkResult getPhysicalDeviceSurfaceSupportKHR(
+ const PhysicalDevice& physicalDevice,
+ uint32_t queueFamilyIndex,
+ const SurfaceKHR& surface,
+ bool& supported) const noexcept
+ {
+ VkBool32 s = {};
+
+ if (VkResult r = vkGetPhysicalDeviceSurfaceSupportKHR(
+ physicalDevice, queueFamilyIndex, surface, &s)) {
+ return r;
+ }
+
+ supported = s;
+ return VK_SUCCESS;
+ }
+
+ // VK_KHR_swapchain
+
+ VkResult acquireNextImageKHR(const Device& device,
+ const SwapchainKHR& swapchain,
+ uint64_t timeout,
+ const Semaphore& semaphore,
+ const OptionalParameter<Fence>& fence,
+ uint32_t* pImageIndex) const noexcept
+ {
+ return vkAcquireNextImageKHR(
+ device, swapchain, timeout, semaphore, fence.get(), pImageIndex);
+ }
+
+ template<class Vector>
+ VkResult getSwapchainImagesKHR(const Device& device,
+ const SwapchainKHR& swapchain,
+ Vector& images) const noexcept
+ {
+ return detail::wrapVectorAccessor<VkImage>(
+ images, vkGetSwapchainImagesKHR, device.get(), swapchain.get());
+ }
+
+ VkResult createSwapchainKHR(const Device& device,
+ const VkSwapchainCreateInfoKHR& createInfo,
+ SwapchainKHR& swapchain) const noexcept
+ {
+ VkSwapchainKHR h = {};
+ const VkResult r = vkCreateSwapchainKHR(device, &createInfo, nullptr, &h);
+
+ if (r) {
+ return r;
+ } else if (!h) {
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ swapchain = {h, {device, vkDestroySwapchainKHR}};
+ return VK_SUCCESS;
+ }
+
+ VkResult queuePresentKHR(const Queue& queue,
+ const VkPresentInfoKHR& presentInfo) const noexcept
+ {
+ return vkQueuePresentKHR(queue, &presentInfo);
+ }
#define SK_FUNC(name) \
- PFN_##name name {} // NOLINT
-
- // Vulkan 1.0 Core
- SK_FUNC(vkAllocateCommandBuffers);
- SK_FUNC(vkAllocateDescriptorSets);
- SK_FUNC(vkAllocateMemory);
- SK_FUNC(vkBeginCommandBuffer);
- SK_FUNC(vkBindBufferMemory);
- SK_FUNC(vkBindImageMemory);
- SK_FUNC(vkCmdBeginQuery);
- SK_FUNC(vkCmdBeginRenderPass);
- SK_FUNC(vkCmdBindDescriptorSets);
- SK_FUNC(vkCmdBindIndexBuffer);
- SK_FUNC(vkCmdBindPipeline);
- SK_FUNC(vkCmdBindVertexBuffers);
- SK_FUNC(vkCmdBlitImage);
- SK_FUNC(vkCmdClearAttachments);
- SK_FUNC(vkCmdClearColorImage);
- SK_FUNC(vkCmdClearDepthStencilImage);
- SK_FUNC(vkCmdCopyBuffer);
- SK_FUNC(vkCmdCopyBufferToImage);
- SK_FUNC(vkCmdCopyImage);
- SK_FUNC(vkCmdCopyImageToBuffer);
- SK_FUNC(vkCmdCopyQueryPoolResults);
- SK_FUNC(vkCmdDispatch);
- SK_FUNC(vkCmdDispatchIndirect);
- SK_FUNC(vkCmdDraw);
- SK_FUNC(vkCmdDrawIndexed);
- SK_FUNC(vkCmdDrawIndexedIndirect);
- SK_FUNC(vkCmdDrawIndirect);
- SK_FUNC(vkCmdEndQuery);
- SK_FUNC(vkCmdEndRenderPass);
- SK_FUNC(vkCmdExecuteCommands);
- SK_FUNC(vkCmdFillBuffer);
- SK_FUNC(vkCmdNextSubpass);
- SK_FUNC(vkCmdPipelineBarrier);
- SK_FUNC(vkCmdPushConstants);
- SK_FUNC(vkCmdResetEvent);
- SK_FUNC(vkCmdResetQueryPool);
- SK_FUNC(vkCmdResolveImage);
- SK_FUNC(vkCmdSetBlendConstants);
- SK_FUNC(vkCmdSetDepthBias);
- SK_FUNC(vkCmdSetDepthBounds);
- SK_FUNC(vkCmdSetEvent);
- SK_FUNC(vkCmdSetLineWidth);
- SK_FUNC(vkCmdSetScissor);
- SK_FUNC(vkCmdSetStencilCompareMask);
- SK_FUNC(vkCmdSetStencilReference);
- SK_FUNC(vkCmdSetStencilWriteMask);
- SK_FUNC(vkCmdSetViewport);
- SK_FUNC(vkCmdUpdateBuffer);
- SK_FUNC(vkCmdWaitEvents);
- SK_FUNC(vkCmdWriteTimestamp);
- SK_FUNC(vkCreateBuffer);
- SK_FUNC(vkCreateBufferView);
- SK_FUNC(vkCreateCommandPool);
- SK_FUNC(vkCreateComputePipelines);
- SK_FUNC(vkCreateDescriptorPool);
- SK_FUNC(vkCreateDescriptorSetLayout);
- SK_FUNC(vkCreateDevice);
- SK_FUNC(vkCreateEvent);
- SK_FUNC(vkCreateFence);
- SK_FUNC(vkCreateFramebuffer);
- SK_FUNC(vkCreateGraphicsPipelines);
- SK_FUNC(vkCreateImage);
- SK_FUNC(vkCreateImageView);
- SK_FUNC(vkCreateInstance);
- SK_FUNC(vkCreatePipelineCache);
- SK_FUNC(vkCreatePipelineLayout);
- SK_FUNC(vkCreateQueryPool);
- SK_FUNC(vkCreateRenderPass);
- SK_FUNC(vkCreateSampler);
- SK_FUNC(vkCreateSemaphore);
- SK_FUNC(vkCreateShaderModule);
- SK_FUNC(vkDestroyBuffer);
- SK_FUNC(vkDestroyBufferView);
- SK_FUNC(vkDestroyCommandPool);
- SK_FUNC(vkDestroyDescriptorPool);
- SK_FUNC(vkDestroyDescriptorSetLayout);
- SK_FUNC(vkDestroyDevice);
- SK_FUNC(vkDestroyEvent);
- SK_FUNC(vkDestroyFence);
- SK_FUNC(vkDestroyFramebuffer);
- SK_FUNC(vkDestroyImage);
- SK_FUNC(vkDestroyImageView);
- SK_FUNC(vkDestroyPipeline);
- SK_FUNC(vkDestroyPipelineCache);
- SK_FUNC(vkDestroyPipelineLayout);
- SK_FUNC(vkDestroyQueryPool);
- SK_FUNC(vkDestroyRenderPass);
- SK_FUNC(vkDestroySampler);
- SK_FUNC(vkDestroySemaphore);
- SK_FUNC(vkDestroyShaderModule);
- SK_FUNC(vkDeviceWaitIdle);
- SK_FUNC(vkEndCommandBuffer);
- SK_FUNC(vkEnumerateDeviceExtensionProperties);
- SK_FUNC(vkEnumerateDeviceLayerProperties);
- SK_FUNC(vkEnumeratePhysicalDevices);
- SK_FUNC(vkFlushMappedMemoryRanges);
- SK_FUNC(vkFreeCommandBuffers);
- SK_FUNC(vkFreeDescriptorSets);
- SK_FUNC(vkFreeMemory);
- SK_FUNC(vkGetBufferMemoryRequirements);
- SK_FUNC(vkGetDeviceMemoryCommitment);
- SK_FUNC(vkGetDeviceProcAddr);
- SK_FUNC(vkGetDeviceQueue);
- SK_FUNC(vkGetEventStatus);
- SK_FUNC(vkGetFenceStatus);
- SK_FUNC(vkGetImageMemoryRequirements);
- SK_FUNC(vkGetImageSparseMemoryRequirements);
- SK_FUNC(vkGetImageSubresourceLayout);
- SK_FUNC(vkGetInstanceProcAddr);
- SK_FUNC(vkGetPhysicalDeviceFeatures);
- SK_FUNC(vkGetPhysicalDeviceFormatProperties);
- SK_FUNC(vkGetPhysicalDeviceImageFormatProperties);
- SK_FUNC(vkGetPhysicalDeviceMemoryProperties);
- SK_FUNC(vkGetPhysicalDeviceProperties);
- SK_FUNC(vkGetPhysicalDeviceQueueFamilyProperties);
- SK_FUNC(vkGetPhysicalDeviceSparseImageFormatProperties);
- SK_FUNC(vkGetPipelineCacheData);
- SK_FUNC(vkGetQueryPoolResults);
- SK_FUNC(vkGetRenderAreaGranularity);
- SK_FUNC(vkInvalidateMappedMemoryRanges);
- SK_FUNC(vkMapMemory);
- SK_FUNC(vkMergePipelineCaches);
- SK_FUNC(vkQueueBindSparse);
- SK_FUNC(vkQueueSubmit);
- SK_FUNC(vkQueueWaitIdle);
- SK_FUNC(vkResetCommandBuffer);
- SK_FUNC(vkResetCommandPool);
- SK_FUNC(vkResetDescriptorPool);
- SK_FUNC(vkResetEvent);
- SK_FUNC(vkResetFences);
- SK_FUNC(vkSetEvent);
- SK_FUNC(vkUnmapMemory);
- SK_FUNC(vkUpdateDescriptorSets);
- SK_FUNC(vkWaitForFences);
-
- // VK_EXT_debug_report
- SK_FUNC(vkCreateDebugReportCallbackEXT);
- SK_FUNC(vkDebugReportMessageEXT);
- SK_FUNC(vkDestroyDebugReportCallbackEXT);
-
- // VK_KHR_surface
- SK_FUNC(vkDestroySurfaceKHR);
- SK_FUNC(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
- SK_FUNC(vkGetPhysicalDeviceSurfaceFormatsKHR);
- SK_FUNC(vkGetPhysicalDeviceSurfacePresentModesKHR);
- SK_FUNC(vkGetPhysicalDeviceSurfaceSupportKHR);
-
- // VK_KHR_swapchain
- SK_FUNC(vkAcquireNextImageKHR);
- SK_FUNC(vkCreateSwapchainKHR);
- SK_FUNC(vkDestroySwapchainKHR);
- SK_FUNC(vkGetDeviceGroupPresentCapabilitiesKHR);
- SK_FUNC(vkGetDeviceGroupSurfacePresentModesKHR);
- SK_FUNC(vkGetPhysicalDevicePresentRectanglesKHR);
- SK_FUNC(vkGetSwapchainImagesKHR);
- SK_FUNC(vkQueuePresentKHR);
+ PFN_##name name {} // NOLINT
+
+ // Vulkan 1.0 Core
+ SK_FUNC(vkAllocateCommandBuffers);
+ SK_FUNC(vkAllocateDescriptorSets);
+ SK_FUNC(vkAllocateMemory);
+ SK_FUNC(vkBeginCommandBuffer);
+ SK_FUNC(vkBindBufferMemory);
+ SK_FUNC(vkBindImageMemory);
+ SK_FUNC(vkCmdBeginQuery);
+ SK_FUNC(vkCmdBeginRenderPass);
+ SK_FUNC(vkCmdBindDescriptorSets);
+ SK_FUNC(vkCmdBindIndexBuffer);
+ SK_FUNC(vkCmdBindPipeline);
+ SK_FUNC(vkCmdBindVertexBuffers);
+ SK_FUNC(vkCmdBlitImage);
+ SK_FUNC(vkCmdClearAttachments);
+ SK_FUNC(vkCmdClearColorImage);
+ SK_FUNC(vkCmdClearDepthStencilImage);
+ SK_FUNC(vkCmdCopyBuffer);
+ SK_FUNC(vkCmdCopyBufferToImage);
+ SK_FUNC(vkCmdCopyImage);
+ SK_FUNC(vkCmdCopyImageToBuffer);
+ SK_FUNC(vkCmdCopyQueryPoolResults);
+ SK_FUNC(vkCmdDispatch);
+ SK_FUNC(vkCmdDispatchIndirect);
+ SK_FUNC(vkCmdDraw);
+ SK_FUNC(vkCmdDrawIndexed);
+ SK_FUNC(vkCmdDrawIndexedIndirect);
+ SK_FUNC(vkCmdDrawIndirect);
+ SK_FUNC(vkCmdEndQuery);
+ SK_FUNC(vkCmdEndRenderPass);
+ SK_FUNC(vkCmdExecuteCommands);
+ SK_FUNC(vkCmdFillBuffer);
+ SK_FUNC(vkCmdNextSubpass);
+ SK_FUNC(vkCmdPipelineBarrier);
+ SK_FUNC(vkCmdPushConstants);
+ SK_FUNC(vkCmdResetEvent);
+ SK_FUNC(vkCmdResetQueryPool);
+ SK_FUNC(vkCmdResolveImage);
+ SK_FUNC(vkCmdSetBlendConstants);
+ SK_FUNC(vkCmdSetDepthBias);
+ SK_FUNC(vkCmdSetDepthBounds);
+ SK_FUNC(vkCmdSetEvent);
+ SK_FUNC(vkCmdSetLineWidth);
+ SK_FUNC(vkCmdSetScissor);
+ SK_FUNC(vkCmdSetStencilCompareMask);
+ SK_FUNC(vkCmdSetStencilReference);
+ SK_FUNC(vkCmdSetStencilWriteMask);
+ SK_FUNC(vkCmdSetViewport);
+ SK_FUNC(vkCmdUpdateBuffer);
+ SK_FUNC(vkCmdWaitEvents);
+ SK_FUNC(vkCmdWriteTimestamp);
+ SK_FUNC(vkCreateBuffer);
+ SK_FUNC(vkCreateBufferView);
+ SK_FUNC(vkCreateCommandPool);
+ SK_FUNC(vkCreateComputePipelines);
+ SK_FUNC(vkCreateDescriptorPool);
+ SK_FUNC(vkCreateDescriptorSetLayout);
+ SK_FUNC(vkCreateDevice);
+ SK_FUNC(vkCreateEvent);
+ SK_FUNC(vkCreateFence);
+ SK_FUNC(vkCreateFramebuffer);
+ SK_FUNC(vkCreateGraphicsPipelines);
+ SK_FUNC(vkCreateImage);
+ SK_FUNC(vkCreateImageView);
+ SK_FUNC(vkCreateInstance);
+ SK_FUNC(vkCreatePipelineCache);
+ SK_FUNC(vkCreatePipelineLayout);
+ SK_FUNC(vkCreateQueryPool);
+ SK_FUNC(vkCreateRenderPass);
+ SK_FUNC(vkCreateSampler);
+ SK_FUNC(vkCreateSemaphore);
+ SK_FUNC(vkCreateShaderModule);
+ SK_FUNC(vkDestroyBuffer);
+ SK_FUNC(vkDestroyBufferView);
+ SK_FUNC(vkDestroyCommandPool);
+ SK_FUNC(vkDestroyDescriptorPool);
+ SK_FUNC(vkDestroyDescriptorSetLayout);
+ SK_FUNC(vkDestroyDevice);
+ SK_FUNC(vkDestroyEvent);
+ SK_FUNC(vkDestroyFence);
+ SK_FUNC(vkDestroyFramebuffer);
+ SK_FUNC(vkDestroyImage);
+ SK_FUNC(vkDestroyImageView);
+ SK_FUNC(vkDestroyPipeline);
+ SK_FUNC(vkDestroyPipelineCache);
+ SK_FUNC(vkDestroyPipelineLayout);
+ SK_FUNC(vkDestroyQueryPool);
+ SK_FUNC(vkDestroyRenderPass);
+ SK_FUNC(vkDestroySampler);
+ SK_FUNC(vkDestroySemaphore);
+ SK_FUNC(vkDestroyShaderModule);
+ SK_FUNC(vkDeviceWaitIdle);
+ SK_FUNC(vkEndCommandBuffer);
+ SK_FUNC(vkEnumerateDeviceExtensionProperties);
+ SK_FUNC(vkEnumerateDeviceLayerProperties);
+ SK_FUNC(vkEnumeratePhysicalDevices);
+ SK_FUNC(vkFlushMappedMemoryRanges);
+ SK_FUNC(vkFreeCommandBuffers);
+ SK_FUNC(vkFreeDescriptorSets);
+ SK_FUNC(vkFreeMemory);
+ SK_FUNC(vkGetBufferMemoryRequirements);
+ SK_FUNC(vkGetDeviceMemoryCommitment);
+ SK_FUNC(vkGetDeviceProcAddr);
+ SK_FUNC(vkGetDeviceQueue);
+ SK_FUNC(vkGetEventStatus);
+ SK_FUNC(vkGetFenceStatus);
+ SK_FUNC(vkGetImageMemoryRequirements);
+ SK_FUNC(vkGetImageSparseMemoryRequirements);
+ SK_FUNC(vkGetImageSubresourceLayout);
+ SK_FUNC(vkGetInstanceProcAddr);
+ SK_FUNC(vkGetPhysicalDeviceFeatures);
+ SK_FUNC(vkGetPhysicalDeviceFormatProperties);
+ SK_FUNC(vkGetPhysicalDeviceImageFormatProperties);
+ SK_FUNC(vkGetPhysicalDeviceMemoryProperties);
+ SK_FUNC(vkGetPhysicalDeviceProperties);
+ SK_FUNC(vkGetPhysicalDeviceQueueFamilyProperties);
+ SK_FUNC(vkGetPhysicalDeviceSparseImageFormatProperties);
+ SK_FUNC(vkGetPipelineCacheData);
+ SK_FUNC(vkGetQueryPoolResults);
+ SK_FUNC(vkGetRenderAreaGranularity);
+ SK_FUNC(vkInvalidateMappedMemoryRanges);
+ SK_FUNC(vkMapMemory);
+ SK_FUNC(vkMergePipelineCaches);
+ SK_FUNC(vkQueueBindSparse);
+ SK_FUNC(vkQueueSubmit);
+ SK_FUNC(vkQueueWaitIdle);
+ SK_FUNC(vkResetCommandBuffer);
+ SK_FUNC(vkResetCommandPool);
+ SK_FUNC(vkResetDescriptorPool);
+ SK_FUNC(vkResetEvent);
+ SK_FUNC(vkResetFences);
+ SK_FUNC(vkSetEvent);
+ SK_FUNC(vkUnmapMemory);
+ SK_FUNC(vkUpdateDescriptorSets);
+ SK_FUNC(vkWaitForFences);
+
+ // VK_EXT_debug_report
+ SK_FUNC(vkCreateDebugReportCallbackEXT);
+ SK_FUNC(vkDebugReportMessageEXT);
+ SK_FUNC(vkDestroyDebugReportCallbackEXT);
+
+ // VK_KHR_surface
+ SK_FUNC(vkDestroySurfaceKHR);
+ SK_FUNC(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
+ SK_FUNC(vkGetPhysicalDeviceSurfaceFormatsKHR);
+ SK_FUNC(vkGetPhysicalDeviceSurfacePresentModesKHR);
+ SK_FUNC(vkGetPhysicalDeviceSurfaceSupportKHR);
+
+ // VK_KHR_swapchain
+ SK_FUNC(vkAcquireNextImageKHR);
+ SK_FUNC(vkCreateSwapchainKHR);
+ SK_FUNC(vkDestroySwapchainKHR);
+ SK_FUNC(vkGetDeviceGroupPresentCapabilitiesKHR);
+ SK_FUNC(vkGetDeviceGroupSurfacePresentModesKHR);
+ SK_FUNC(vkGetPhysicalDevicePresentRectanglesKHR);
+ SK_FUNC(vkGetSwapchainImagesKHR);
+ SK_FUNC(vkQueuePresentKHR);
#undef SK_FUNC
private:
- template<class T>
- static inline VkResult wrapResult(const VkResult r,
- const typename T::Handle handle,
- typename T::Deleter&& deleter,
- T& result) noexcept
- {
- if (r) {
- return r;
- } else if (!handle) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- result = T{handle, std::move(deleter)};
- return VK_SUCCESS;
- }
+ template<class T>
+ static inline VkResult wrapResult(const VkResult r,
+ const typename T::Handle handle,
+ typename T::Deleter&& deleter,
+ T& result) noexcept
+ {
+ if (r) {
+ return r;
+ } else if (!handle) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ result = T{handle, std::move(deleter)};
+ return VK_SUCCESS;
+ }
};
/// Scope for commands that work both inside and outside a render pass
class CommonCommandScope
{
public:
- CommonCommandScope(const VulkanApi& api,
- VkCommandBuffer commandBuffer,
- VkResult result) noexcept
- : _api{api}
- , _commandBuffer{commandBuffer}
- , _result{result}
- {}
-
- CommonCommandScope(const CommonCommandScope&) noexcept = delete;
- CommonCommandScope& operator=(const CommonCommandScope&) noexcept = delete;
-
- CommonCommandScope(CommonCommandScope&& scope) noexcept
- : _api{scope._api}
- , _commandBuffer{scope._commandBuffer}
- {
- scope._commandBuffer = {};
- }
-
- CommonCommandScope& operator=(CommonCommandScope&&) = delete;
-
- ~CommonCommandScope() noexcept = default;
-
- explicit operator bool() const noexcept { return _result == VK_SUCCESS; }
-
- VkResult error() const noexcept { return _result; }
-
- void bindPipeline(VkPipelineBindPoint pipelineBindPoint,
- VkPipeline pipeline) const noexcept
- {
- _api.vkCmdBindPipeline(_commandBuffer, pipelineBindPoint, pipeline);
- }
-
- void setViewport(uint32_t firstViewport,
- uint32_t viewportCount,
- const VkViewport* pViewports) const noexcept
- {
- _api.vkCmdSetViewport(_commandBuffer,
- firstViewport,
- viewportCount,
- pViewports);
- }
-
- void setScissor(uint32_t firstScissor,
- uint32_t scissorCount,
- const VkRect2D* pScissors) const noexcept
- {
- _api.vkCmdSetScissor(_commandBuffer,
- firstScissor,
- scissorCount,
- pScissors);
- }
-
- void setLineWidth(float lineWidth) const noexcept
- {
- _api.vkCmdSetLineWidth(_commandBuffer, lineWidth);
- }
-
- void setDepthBias(float depthBiasConstantFactor,
- float depthBiasClamp,
- float depthBiasSlopeFactor) const noexcept
- {
- _api.vkCmdSetDepthBias(_commandBuffer,
- depthBiasConstantFactor,
- depthBiasClamp,
- depthBiasSlopeFactor);
- }
-
- void setBlendConstants(const float blendConstants[4]) const noexcept
- {
- _api.vkCmdSetBlendConstants(_commandBuffer, blendConstants);
- }
-
- void
- setDepthBounds(float minDepthBounds, float maxDepthBounds) const noexcept
- {
- _api.vkCmdSetDepthBounds(_commandBuffer,
- minDepthBounds,
- maxDepthBounds);
- }
-
- void setStencilCompareMask(VkStencilFaceFlags faceMask,
- uint32_t compareMask) const noexcept
- {
- _api.vkCmdSetStencilCompareMask(_commandBuffer, faceMask, compareMask);
- }
-
- void setStencilWriteMask(VkStencilFaceFlags faceMask,
- uint32_t writeMask) const noexcept
- {
- _api.vkCmdSetStencilWriteMask(_commandBuffer, faceMask, writeMask);
- }
-
- void setStencilReference(VkStencilFaceFlags faceMask,
- uint32_t reference) const noexcept
- {
- _api.vkCmdSetStencilReference(_commandBuffer, faceMask, reference);
- }
-
- void bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
- VkPipelineLayout layout,
- uint32_t firstSet,
- uint32_t descriptorSetCount,
- const VkDescriptorSet* pDescriptorSets,
- uint32_t dynamicOffsetCount,
- const uint32_t* pDynamicOffsets) const noexcept
- {
- _api.vkCmdBindDescriptorSets(_commandBuffer,
- pipelineBindPoint,
- layout,
- firstSet,
- descriptorSetCount,
- pDescriptorSets,
- dynamicOffsetCount,
- pDynamicOffsets);
- }
-
- void bindIndexBuffer(VkBuffer buffer,
- VkDeviceSize offset,
- VkIndexType indexType) const noexcept
- {
- _api.vkCmdBindIndexBuffer(_commandBuffer, buffer, offset, indexType);
- }
-
- void bindVertexBuffers(uint32_t firstBinding,
- uint32_t bindingCount,
- const VkBuffer* pBuffers,
- const VkDeviceSize* pOffsets) const noexcept
- {
- _api.vkCmdBindVertexBuffers(
- _commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
- }
-
- void
- waitEvents(uint32_t eventCount,
- const VkEvent* pEvents,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier* pMemoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier* pBufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier* pImageMemoryBarriers) const noexcept
- {
- _api.vkCmdWaitEvents(_commandBuffer,
- eventCount,
- pEvents,
- srcStageMask,
- dstStageMask,
- memoryBarrierCount,
- pMemoryBarriers,
- bufferMemoryBarrierCount,
- pBufferMemoryBarriers,
- imageMemoryBarrierCount,
- pImageMemoryBarriers);
- }
-
- void pipelineBarrier(
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- VkDependencyFlags dependencyFlags,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier* pMemoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier* pBufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier* pImageMemoryBarriers) const noexcept
- {
- _api.vkCmdPipelineBarrier(_commandBuffer,
- srcStageMask,
- dstStageMask,
- dependencyFlags,
- memoryBarrierCount,
- pMemoryBarriers,
- bufferMemoryBarrierCount,
- pBufferMemoryBarriers,
- imageMemoryBarrierCount,
- pImageMemoryBarriers);
- }
-
- void beginQuery(VkQueryPool queryPool,
- uint32_t query,
- VkQueryControlFlags flags) const noexcept
- {
- _api.vkCmdBeginQuery(_commandBuffer, queryPool, query, flags);
- }
-
- void endQuery(VkQueryPool queryPool, uint32_t query) const noexcept
- {
- _api.vkCmdEndQuery(_commandBuffer, queryPool, query);
- }
-
- void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
- VkQueryPool queryPool,
- uint32_t query) const noexcept
- {
- _api.vkCmdWriteTimestamp(_commandBuffer,
- pipelineStage,
- queryPool,
- query);
- }
-
- void pushConstants(VkPipelineLayout layout,
- VkShaderStageFlags stageFlags,
- uint32_t offset,
- uint32_t size,
- const void* pValues) const noexcept
- {
- _api.vkCmdPushConstants(
- _commandBuffer, layout, stageFlags, offset, size, pValues);
- }
-
- void executeCommands(uint32_t commandBufferCount,
- const VkCommandBuffer* pCommandBuffers) const noexcept
- {
- _api.vkCmdExecuteCommands(_commandBuffer,
- commandBufferCount,
- pCommandBuffers);
- }
+ CommonCommandScope(const VulkanApi& api,
+ VkCommandBuffer commandBuffer,
+ VkResult result) noexcept
+ : _api{api}
+ , _commandBuffer{commandBuffer}
+ , _result{result}
+ {}
+
+ CommonCommandScope(const CommonCommandScope&) noexcept = delete;
+ CommonCommandScope& operator=(const CommonCommandScope&) noexcept = delete;
+
+ CommonCommandScope(CommonCommandScope&& scope) noexcept
+ : _api{scope._api}
+ , _commandBuffer{scope._commandBuffer}
+ {
+ scope._commandBuffer = {};
+ }
+
+ CommonCommandScope& operator=(CommonCommandScope&&) = delete;
+
+ ~CommonCommandScope() noexcept = default;
+
+ explicit operator bool() const noexcept { return _result == VK_SUCCESS; }
+
+ VkResult error() const noexcept { return _result; }
+
+ void bindPipeline(VkPipelineBindPoint pipelineBindPoint,
+ VkPipeline pipeline) const noexcept
+ {
+ _api.vkCmdBindPipeline(_commandBuffer, pipelineBindPoint, pipeline);
+ }
+
+ void setViewport(uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewport* pViewports) const noexcept
+ {
+ _api.vkCmdSetViewport(
+ _commandBuffer, firstViewport, viewportCount, pViewports);
+ }
+
+ void setScissor(uint32_t firstScissor,
+ uint32_t scissorCount,
+ const VkRect2D* pScissors) const noexcept
+ {
+ _api.vkCmdSetScissor(_commandBuffer, firstScissor, scissorCount, pScissors);
+ }
+
+ void setLineWidth(float lineWidth) const noexcept
+ {
+ _api.vkCmdSetLineWidth(_commandBuffer, lineWidth);
+ }
+
+ void setDepthBias(float depthBiasConstantFactor,
+ float depthBiasClamp,
+ float depthBiasSlopeFactor) const noexcept
+ {
+ _api.vkCmdSetDepthBias(_commandBuffer,
+ depthBiasConstantFactor,
+ depthBiasClamp,
+ depthBiasSlopeFactor);
+ }
+
+ void setBlendConstants(const float blendConstants[4]) const noexcept
+ {
+ _api.vkCmdSetBlendConstants(_commandBuffer, blendConstants);
+ }
+
+ void setDepthBounds(float minDepthBounds, float maxDepthBounds) const noexcept
+ {
+ _api.vkCmdSetDepthBounds(_commandBuffer, minDepthBounds, maxDepthBounds);
+ }
+
+ void setStencilCompareMask(VkStencilFaceFlags faceMask,
+ uint32_t compareMask) const noexcept
+ {
+ _api.vkCmdSetStencilCompareMask(_commandBuffer, faceMask, compareMask);
+ }
+
+ void setStencilWriteMask(VkStencilFaceFlags faceMask,
+ uint32_t writeMask) const noexcept
+ {
+ _api.vkCmdSetStencilWriteMask(_commandBuffer, faceMask, writeMask);
+ }
+
+ void setStencilReference(VkStencilFaceFlags faceMask,
+ uint32_t reference) const noexcept
+ {
+ _api.vkCmdSetStencilReference(_commandBuffer, faceMask, reference);
+ }
+
+ void bindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet* pDescriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t* pDynamicOffsets) const noexcept
+ {
+ _api.vkCmdBindDescriptorSets(_commandBuffer,
+ pipelineBindPoint,
+ layout,
+ firstSet,
+ descriptorSetCount,
+ pDescriptorSets,
+ dynamicOffsetCount,
+ pDynamicOffsets);
+ }
+
+ void bindIndexBuffer(VkBuffer buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType) const noexcept
+ {
+ _api.vkCmdBindIndexBuffer(_commandBuffer, buffer, offset, indexType);
+ }
+
+ void bindVertexBuffers(uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer* pBuffers,
+ const VkDeviceSize* pOffsets) const noexcept
+ {
+ _api.vkCmdBindVertexBuffers(
+ _commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
+ }
+
+ void waitEvents(
+ uint32_t eventCount,
+ const VkEvent* pEvents,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier* pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier* pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier* pImageMemoryBarriers) const noexcept
+ {
+ _api.vkCmdWaitEvents(_commandBuffer,
+ eventCount,
+ pEvents,
+ srcStageMask,
+ dstStageMask,
+ memoryBarrierCount,
+ pMemoryBarriers,
+ bufferMemoryBarrierCount,
+ pBufferMemoryBarriers,
+ imageMemoryBarrierCount,
+ pImageMemoryBarriers);
+ }
+
+ void pipelineBarrier(
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier* pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier* pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier* pImageMemoryBarriers) const noexcept
+ {
+ _api.vkCmdPipelineBarrier(_commandBuffer,
+ srcStageMask,
+ dstStageMask,
+ dependencyFlags,
+ memoryBarrierCount,
+ pMemoryBarriers,
+ bufferMemoryBarrierCount,
+ pBufferMemoryBarriers,
+ imageMemoryBarrierCount,
+ pImageMemoryBarriers);
+ }
+
+ void beginQuery(VkQueryPool queryPool,
+ uint32_t query,
+ VkQueryControlFlags flags) const noexcept
+ {
+ _api.vkCmdBeginQuery(_commandBuffer, queryPool, query, flags);
+ }
+
+ void endQuery(VkQueryPool queryPool, uint32_t query) const noexcept
+ {
+ _api.vkCmdEndQuery(_commandBuffer, queryPool, query);
+ }
+
+ void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query) const noexcept
+ {
+ _api.vkCmdWriteTimestamp(_commandBuffer, pipelineStage, queryPool, query);
+ }
+
+ void pushConstants(VkPipelineLayout layout,
+ VkShaderStageFlags stageFlags,
+ uint32_t offset,
+ uint32_t size,
+ const void* pValues) const noexcept
+ {
+ _api.vkCmdPushConstants(
+ _commandBuffer, layout, stageFlags, offset, size, pValues);
+ }
+
+ void executeCommands(uint32_t commandBufferCount,
+ const VkCommandBuffer* pCommandBuffers) const noexcept
+ {
+ _api.vkCmdExecuteCommands(
+ _commandBuffer, commandBufferCount, pCommandBuffers);
+ }
protected:
- const VulkanApi& _api;
- VkCommandBuffer _commandBuffer;
- VkResult _result;
+ const VulkanApi& _api;
+ VkCommandBuffer _commandBuffer;
+ VkResult _result;
};
// Top level command scope outside a render pass
class CommandScope : public CommonCommandScope
{
public:
- CommandScope(const VulkanApi& api,
- VkCommandBuffer commandBuffer,
- VkResult result) noexcept
- : CommonCommandScope{api, commandBuffer, result}
- {}
-
- CommandScope(const CommandScope&) = delete;
- CommandScope& operator=(const CommandScope&) = delete;
-
- CommandScope(CommandScope&& scope) noexcept
- : CommonCommandScope{std::forward<CommandScope>(scope)}
- {}
-
- CommandScope& operator=(CommandScope&&) = delete;
-
- ~CommandScope() noexcept
- {
- assert(!_commandBuffer); // Buffer must be finished with end()
- }
-
- VkResult end() noexcept
- {
- if (_commandBuffer) {
- VkResult r = _api.vkEndCommandBuffer(_commandBuffer);
- _commandBuffer = {};
- return r;
- }
-
- return VK_NOT_READY;
- }
-
- void dispatch(uint32_t groupCountX,
- uint32_t groupCountY,
- uint32_t groupCountZ) const noexcept
- {
- _api.vkCmdDispatch(_commandBuffer,
- groupCountX,
- groupCountY,
- groupCountZ);
- }
-
- void dispatchIndirect(VkBuffer buffer, VkDeviceSize offset) const noexcept
- {
- _api.vkCmdDispatchIndirect(_commandBuffer, buffer, offset);
- }
-
- void copyBuffer(VkBuffer srcBuffer,
- VkBuffer dstBuffer,
- uint32_t regionCount,
- const VkBufferCopy* pRegions) const noexcept
- {
- _api.vkCmdCopyBuffer(
- _commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
- }
-
- void copyImage(VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkImage dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkImageCopy* pRegions) const noexcept
- {
- _api.vkCmdCopyImage(_commandBuffer,
- srcImage,
- srcImageLayout,
- dstImage,
- dstImageLayout,
- regionCount,
- pRegions);
- }
-
- void blitImage(VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkImage dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkImageBlit* pRegions,
- VkFilter filter) const noexcept
- {
- _api.vkCmdBlitImage(_commandBuffer,
- srcImage,
- srcImageLayout,
- dstImage,
- dstImageLayout,
- regionCount,
- pRegions,
- filter);
- }
-
- void copyBufferToImage(VkBuffer srcBuffer,
- VkImage dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkBufferImageCopy* pRegions) const noexcept
- {
- _api.vkCmdCopyBufferToImage(_commandBuffer,
- srcBuffer,
- dstImage,
- dstImageLayout,
- regionCount,
- pRegions);
- }
-
- void copyImageToBuffer(VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkBuffer dstBuffer,
- uint32_t regionCount,
- const VkBufferImageCopy* pRegions) const noexcept
- {
- _api.vkCmdCopyImageToBuffer(_commandBuffer,
- srcImage,
- srcImageLayout,
- dstBuffer,
- regionCount,
- pRegions);
- }
-
- void updateBuffer(VkBuffer dstBuffer,
- VkDeviceSize dstOffset,
- VkDeviceSize dataSize,
- const void* pData) const noexcept
- {
- _api.vkCmdUpdateBuffer(
- _commandBuffer, dstBuffer, dstOffset, dataSize, pData);
- }
-
- void fillBuffer(VkBuffer dstBuffer,
- VkDeviceSize dstOffset,
- VkDeviceSize size,
- uint32_t data) const noexcept
- {
- _api.vkCmdFillBuffer(_commandBuffer, dstBuffer, dstOffset, size, data);
- }
-
- void clearColorImage(VkImage image,
- VkImageLayout imageLayout,
- const VkClearColorValue& color,
- uint32_t rangeCount,
- const VkImageSubresourceRange* pRanges) const noexcept
- {
- _api.vkCmdClearColorImage(
- _commandBuffer, image, imageLayout, &color, rangeCount, pRanges);
- }
-
- void clearDepthStencilImage(
- VkImage image,
- VkImageLayout imageLayout,
- const VkClearDepthStencilValue& depthStencil,
- uint32_t rangeCount,
- const VkImageSubresourceRange* pRanges) const noexcept
- {
- _api.vkCmdClearDepthStencilImage(_commandBuffer,
- image,
- imageLayout,
- &depthStencil,
- rangeCount,
- pRanges);
- }
-
- void resolveImage(VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkImage dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkImageResolve* pRegions) const noexcept
- {
- _api.vkCmdResolveImage(_commandBuffer,
- srcImage,
- srcImageLayout,
- dstImage,
- dstImageLayout,
- regionCount,
- pRegions);
- }
-
- void setEvent(VkEvent event, VkPipelineStageFlags stageMask) const noexcept
- {
- _api.vkCmdSetEvent(_commandBuffer, event, stageMask);
- }
-
- void
- resetEvent(VkEvent event, VkPipelineStageFlags stageMask) const noexcept
- {
- _api.vkCmdResetEvent(_commandBuffer, event, stageMask);
- }
-
- void resetQueryPool(VkQueryPool queryPool,
- uint32_t firstQuery,
- uint32_t queryCount) const noexcept
- {
- _api.vkCmdResetQueryPool(_commandBuffer,
- queryPool,
- firstQuery,
- queryCount);
- }
-
- void copyQueryPoolResults(VkQueryPool queryPool,
- uint32_t firstQuery,
- uint32_t queryCount,
- VkBuffer dstBuffer,
- VkDeviceSize dstOffset,
- VkDeviceSize stride,
- VkQueryResultFlags flags) const noexcept
- {
- _api.vkCmdCopyQueryPoolResults(_commandBuffer,
- queryPool,
- firstQuery,
- queryCount,
- dstBuffer,
- dstOffset,
- stride,
- flags);
- }
-
- SYBOK_NODISCARD
- RenderCommandScope
- beginRenderPass(const VkRenderPassBeginInfo& renderPassBegin,
- VkSubpassContents contents) const noexcept;
+ CommandScope(const VulkanApi& api,
+ VkCommandBuffer commandBuffer,
+ VkResult result) noexcept
+ : CommonCommandScope{api, commandBuffer, result}
+ {}
+
+ CommandScope(const CommandScope&) = delete;
+ CommandScope& operator=(const CommandScope&) = delete;
+
+ CommandScope(CommandScope&& scope) noexcept
+ : CommonCommandScope{std::forward<CommandScope>(scope)}
+ {}
+
+ CommandScope& operator=(CommandScope&&) = delete;
+
+ ~CommandScope() noexcept
+ {
+ assert(!_commandBuffer); // Buffer must be finished with end()
+ }
+
+ VkResult end() noexcept
+ {
+ if (_commandBuffer) {
+ VkResult r = _api.vkEndCommandBuffer(_commandBuffer);
+ _commandBuffer = {};
+ return r;
+ }
+
+ return VK_NOT_READY;
+ }
+
+ void dispatch(uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ) const noexcept
+ {
+ _api.vkCmdDispatch(_commandBuffer, groupCountX, groupCountY, groupCountZ);
+ }
+
+ void dispatchIndirect(VkBuffer buffer, VkDeviceSize offset) const noexcept
+ {
+ _api.vkCmdDispatchIndirect(_commandBuffer, buffer, offset);
+ }
+
+ void copyBuffer(VkBuffer srcBuffer,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy* pRegions) const noexcept
+ {
+ _api.vkCmdCopyBuffer(
+ _commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
+ }
+
+ void copyImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy* pRegions) const noexcept
+ {
+ _api.vkCmdCopyImage(_commandBuffer,
+ srcImage,
+ srcImageLayout,
+ dstImage,
+ dstImageLayout,
+ regionCount,
+ pRegions);
+ }
+
+ void blitImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit* pRegions,
+ VkFilter filter) const noexcept
+ {
+ _api.vkCmdBlitImage(_commandBuffer,
+ srcImage,
+ srcImageLayout,
+ dstImage,
+ dstImageLayout,
+ regionCount,
+ pRegions,
+ filter);
+ }
+
+ void copyBufferToImage(VkBuffer srcBuffer,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions) const noexcept
+ {
+ _api.vkCmdCopyBufferToImage(_commandBuffer,
+ srcBuffer,
+ dstImage,
+ dstImageLayout,
+ regionCount,
+ pRegions);
+ }
+
+ void copyImageToBuffer(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions) const noexcept
+ {
+ _api.vkCmdCopyImageToBuffer(_commandBuffer,
+ srcImage,
+ srcImageLayout,
+ dstBuffer,
+ regionCount,
+ pRegions);
+ }
+
+ void updateBuffer(VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize dataSize,
+ const void* pData) const noexcept
+ {
+ _api.vkCmdUpdateBuffer(
+ _commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+ }
+
+ void fillBuffer(VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize size,
+ uint32_t data) const noexcept
+ {
+ _api.vkCmdFillBuffer(_commandBuffer, dstBuffer, dstOffset, size, data);
+ }
+
+ void clearColorImage(VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue& color,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges) const noexcept
+ {
+ _api.vkCmdClearColorImage(
+ _commandBuffer, image, imageLayout, &color, rangeCount, pRanges);
+ }
+
+ void clearDepthStencilImage(
+ VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue& depthStencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges) const noexcept
+ {
+ _api.vkCmdClearDepthStencilImage(
+ _commandBuffer, image, imageLayout, &depthStencil, rangeCount, pRanges);
+ }
+
+ void resolveImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageResolve* pRegions) const noexcept
+ {
+ _api.vkCmdResolveImage(_commandBuffer,
+ srcImage,
+ srcImageLayout,
+ dstImage,
+ dstImageLayout,
+ regionCount,
+ pRegions);
+ }
+
+ void setEvent(VkEvent event, VkPipelineStageFlags stageMask) const noexcept
+ {
+ _api.vkCmdSetEvent(_commandBuffer, event, stageMask);
+ }
+
+ void resetEvent(VkEvent event, VkPipelineStageFlags stageMask) const noexcept
+ {
+ _api.vkCmdResetEvent(_commandBuffer, event, stageMask);
+ }
+
+ void resetQueryPool(VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount) const noexcept
+ {
+ _api.vkCmdResetQueryPool(_commandBuffer, queryPool, firstQuery, queryCount);
+ }
+
+ void copyQueryPoolResults(VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize stride,
+ VkQueryResultFlags flags) const noexcept
+ {
+ _api.vkCmdCopyQueryPoolResults(_commandBuffer,
+ queryPool,
+ firstQuery,
+ queryCount,
+ dstBuffer,
+ dstOffset,
+ stride,
+ flags);
+ }
+
+ SYBOK_NODISCARD
+ RenderCommandScope beginRenderPass(
+ const VkRenderPassBeginInfo& renderPassBegin,
+ VkSubpassContents contents) const noexcept;
};
class RenderCommandScope : public CommonCommandScope
{
public:
- RenderCommandScope(const VulkanApi& api,
- VkCommandBuffer commandBuffer) noexcept
- : CommonCommandScope{api, commandBuffer, VK_SUCCESS}
- {}
-
- RenderCommandScope(const RenderCommandScope&) = delete;
- RenderCommandScope& operator=(const RenderCommandScope&) = delete;
-
- RenderCommandScope(RenderCommandScope&& scope) noexcept
- : CommonCommandScope{std::forward<RenderCommandScope>(scope)}
- {}
-
- RenderCommandScope& operator=(RenderCommandScope&&) = delete;
-
- ~RenderCommandScope() noexcept { _api.vkCmdEndRenderPass(_commandBuffer); }
-
- void draw(uint32_t vertexCount,
- uint32_t instanceCount,
- uint32_t firstVertex,
- uint32_t firstInstance) const noexcept
- {
- _api.vkCmdDraw(_commandBuffer,
- vertexCount,
- instanceCount,
- firstVertex,
- firstInstance);
- }
-
- void drawIndexed(uint32_t indexCount,
- uint32_t instanceCount,
- uint32_t firstIndex,
- int32_t vertexOffset,
- uint32_t firstInstance) const noexcept
- {
- _api.vkCmdDrawIndexed(_commandBuffer,
- indexCount,
- instanceCount,
- firstIndex,
- vertexOffset,
- firstInstance);
- }
-
- void drawIndirect(VkBuffer buffer,
- VkDeviceSize offset,
- uint32_t drawCount,
- uint32_t stride) const noexcept
- {
- _api.vkCmdDrawIndirect(
- _commandBuffer, buffer, offset, drawCount, stride);
- }
-
- void drawIndexedIndirect(VkBuffer buffer,
- VkDeviceSize offset,
- uint32_t drawCount,
- uint32_t stride) const noexcept
- {
- _api.vkCmdDrawIndexedIndirect(
- _commandBuffer, buffer, offset, drawCount, stride);
- }
-
- void clearAttachments(uint32_t attachmentCount,
- const VkClearAttachment& attachments,
- uint32_t rectCount,
- const VkClearRect* pRects) const noexcept
- {
- _api.vkCmdClearAttachments(
- _commandBuffer, attachmentCount, &attachments, rectCount, pRects);
- }
-
- void nextSubpass(VkSubpassContents contents) const noexcept
- {
- _api.vkCmdNextSubpass(_commandBuffer, contents);
- }
+ RenderCommandScope(const VulkanApi& api,
+ VkCommandBuffer commandBuffer) noexcept
+ : CommonCommandScope{api, commandBuffer, VK_SUCCESS}
+ {}
+
+ RenderCommandScope(const RenderCommandScope&) = delete;
+ RenderCommandScope& operator=(const RenderCommandScope&) = delete;
+
+ RenderCommandScope(RenderCommandScope&& scope) noexcept
+ : CommonCommandScope{std::forward<RenderCommandScope>(scope)}
+ {}
+
+ RenderCommandScope& operator=(RenderCommandScope&&) = delete;
+
+ ~RenderCommandScope() noexcept { _api.vkCmdEndRenderPass(_commandBuffer); }
+
+ void draw(uint32_t vertexCount,
+ uint32_t instanceCount,
+ uint32_t firstVertex,
+ uint32_t firstInstance) const noexcept
+ {
+ _api.vkCmdDraw(
+ _commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
+ }
+
+ void drawIndexed(uint32_t indexCount,
+ uint32_t instanceCount,
+ uint32_t firstIndex,
+ int32_t vertexOffset,
+ uint32_t firstInstance) const noexcept
+ {
+ _api.vkCmdDrawIndexed(_commandBuffer,
+ indexCount,
+ instanceCount,
+ firstIndex,
+ vertexOffset,
+ firstInstance);
+ }
+
+ void drawIndirect(VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride) const noexcept
+ {
+ _api.vkCmdDrawIndirect(_commandBuffer, buffer, offset, drawCount, stride);
+ }
+
+ void drawIndexedIndirect(VkBuffer buffer,
+ VkDeviceSize offset,
+ uint32_t drawCount,
+ uint32_t stride) const noexcept
+ {
+ _api.vkCmdDrawIndexedIndirect(
+ _commandBuffer, buffer, offset, drawCount, stride);
+ }
+
+ void clearAttachments(uint32_t attachmentCount,
+ const VkClearAttachment& attachments,
+ uint32_t rectCount,
+ const VkClearRect* pRects) const noexcept
+ {
+ _api.vkCmdClearAttachments(
+ _commandBuffer, attachmentCount, &attachments, rectCount, pRects);
+ }
+
+ void nextSubpass(VkSubpassContents contents) const noexcept
+ {
+ _api.vkCmdNextSubpass(_commandBuffer, contents);
+ }
};
CommandScope
VulkanApi::beginCommandBuffer(
- VkCommandBuffer commandBuffer,
- const VkCommandBufferBeginInfo beginInfo) const noexcept
+ VkCommandBuffer commandBuffer,
+ const VkCommandBufferBeginInfo beginInfo) const noexcept
{
- if (const VkResult r = vkBeginCommandBuffer(commandBuffer, &beginInfo)) {
- return {*this, nullptr, r};
- }
+ if (const VkResult r = vkBeginCommandBuffer(commandBuffer, &beginInfo)) {
+ return {*this, nullptr, r};
+ }
- return {*this, commandBuffer, VK_SUCCESS};
+ return {*this, commandBuffer, VK_SUCCESS};
}
inline RenderCommandScope
CommandScope::beginRenderPass(const VkRenderPassBeginInfo& renderPassBegin,
VkSubpassContents contents) const noexcept
{
- _api.vkCmdBeginRenderPass(_commandBuffer, &renderPassBegin, contents);
+ _api.vkCmdBeginRenderPass(_commandBuffer, &renderPassBegin, contents);
- return {_api, _commandBuffer};
+ return {_api, _commandBuffer};
}
inline MappedMemory::~MappedMemory() noexcept
{
- if (_api && _memory) {
- _api->vkUnmapMemory(_device, _memory);
- }
+ if (_api && _memory) {
+ _api->vkUnmapMemory(_device, _memory);
+ }
}
} // namespace sk
diff --git a/include/pugl/cairo.h b/include/pugl/cairo.h
index d72580d..9909682 100644
--- a/include/pugl/cairo.h
+++ b/include/pugl/cairo.h
@@ -33,7 +33,9 @@ PUGL_BEGIN_DECLS
Pass the returned value to puglSetBackend() to draw to a view with Cairo.
*/
-PUGL_API PUGL_CONST_FUNC const PuglBackend*
+PUGL_API
+PUGL_CONST_FUNC
+const PuglBackend*
puglCairoBackend(void);
/**
diff --git a/include/pugl/gl.h b/include/pugl/gl.h
index eb86c3d..a311416 100644
--- a/include/pugl/gl.h
+++ b/include/pugl/gl.h
@@ -25,25 +25,25 @@
enable pure portable programs. */
#ifndef PUGL_NO_INCLUDE_GL_H
-# ifdef __APPLE__
-# include "OpenGL/gl.h"
-# else
-# ifdef _WIN32
-# include <windows.h>
-# endif
-# include "GL/gl.h"
-# endif
+# ifdef __APPLE__
+# include "OpenGL/gl.h"
+# else
+# ifdef _WIN32
+# include <windows.h>
+# endif
+# include "GL/gl.h"
+# endif
#endif
#ifndef PUGL_NO_INCLUDE_GLU_H
-# ifdef __APPLE__
-# include "OpenGL/glu.h"
-# else
-# ifdef _WIN32
-# include <windows.h>
-# endif
-# include "GL/glu.h"
-# endif
+# ifdef __APPLE__
+# include "OpenGL/glu.h"
+# else
+# ifdef _WIN32
+# include <windows.h>
+# endif
+# include "GL/glu.h"
+# endif
#endif
// IWYU pragma: end_exports
@@ -65,7 +65,8 @@ typedef void (*PuglGlFunc)(void);
/**
Return the address of an OpenGL extension function.
*/
-PUGL_API PuglGlFunc
+PUGL_API
+PuglGlFunc
puglGetProcAddress(const char* name);
/**
@@ -75,7 +76,8 @@ puglGetProcAddress(const char* name);
doing things like loading textures. Note that this must not be used for
drawing, which may only be done while processing an expose event.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglEnterContext(PuglView* view);
/**
@@ -83,7 +85,8 @@ puglEnterContext(PuglView* view);
This must only be called after puglEnterContext().
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglLeaveContext(PuglView* view);
/**
@@ -91,7 +94,9 @@ puglLeaveContext(PuglView* view);
Pass the returned value to puglSetBackend() to draw to a view with OpenGL.
*/
-PUGL_API PUGL_CONST_FUNC const PuglBackend*
+PUGL_API
+PUGL_CONST_FUNC
+const PuglBackend*
puglGlBackend(void);
PUGL_END_DECLS
diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h
index 9ddc1ec..bb21a29 100644
--- a/include/pugl/pugl.h
+++ b/include/pugl/pugl.h
@@ -22,44 +22,44 @@
#include <stdint.h>
#ifdef PUGL_SHARED
-# ifdef _WIN32
-# define PUGL_LIB_IMPORT __declspec(dllimport)
-# define PUGL_LIB_EXPORT __declspec(dllexport)
-# else
-# define PUGL_LIB_IMPORT __attribute__((visibility("default")))
-# define PUGL_LIB_EXPORT __attribute__((visibility("default")))
-# endif
-# ifdef PUGL_INTERNAL
-# define PUGL_API PUGL_LIB_EXPORT
-# else
-# define PUGL_API PUGL_LIB_IMPORT
-# endif
+# ifdef _WIN32
+# define PUGL_LIB_IMPORT __declspec(dllimport)
+# define PUGL_LIB_EXPORT __declspec(dllexport)
+# else
+# define PUGL_LIB_IMPORT __attribute__((visibility("default")))
+# define PUGL_LIB_EXPORT __attribute__((visibility("default")))
+# endif
+# ifdef PUGL_INTERNAL
+# define PUGL_API PUGL_LIB_EXPORT
+# else
+# define PUGL_API PUGL_LIB_IMPORT
+# endif
#else
-# define PUGL_API
+# define PUGL_API
#endif
#ifndef PUGL_DISABLE_DEPRECATED
-# if defined(__clang__)
-# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("", rep)))
-# elif defined(__GNUC__)
-# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("Use " rep)))
-# else
-# define PUGL_DEPRECATED_BY(rep)
-# endif
+# if defined(__clang__)
+# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("", rep)))
+# elif defined(__GNUC__)
+# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("Use " rep)))
+# else
+# define PUGL_DEPRECATED_BY(rep)
+# endif
#endif
#if defined(__GNUC__)
-# define PUGL_CONST_FUNC __attribute__((const))
+# define PUGL_CONST_FUNC __attribute__((const))
#else
-# define PUGL_CONST_FUNC
+# define PUGL_CONST_FUNC
#endif
#ifdef __cplusplus
-# define PUGL_BEGIN_DECLS extern "C" {
-# define PUGL_END_DECLS }
+# define PUGL_BEGIN_DECLS extern "C" {
+# define PUGL_END_DECLS }
#else
-# define PUGL_BEGIN_DECLS
-# define PUGL_END_DECLS
+# define PUGL_BEGIN_DECLS
+# define PUGL_END_DECLS
#endif
PUGL_BEGIN_DECLS
@@ -77,10 +77,10 @@ PUGL_BEGIN_DECLS
uses coordinates where the top left corner is 0,0.
*/
typedef struct {
- double x;
- double y;
- double width;
- double height;
+ double x;
+ double y;
+ double width;
+ double height;
} PuglRect;
/**
@@ -96,10 +96,10 @@ typedef struct {
/// Keyboard modifier flags
typedef enum {
- PUGL_MOD_SHIFT = 1u << 0u, ///< Shift key
- PUGL_MOD_CTRL = 1u << 1u, ///< Control key
- PUGL_MOD_ALT = 1u << 2u, ///< Alt/Option key
- PUGL_MOD_SUPER = 1u << 3u ///< Mod4/Command/Windows key
+ PUGL_MOD_SHIFT = 1u << 0u, ///< Shift key
+ PUGL_MOD_CTRL = 1u << 1u, ///< Control key
+ PUGL_MOD_ALT = 1u << 2u, ///< Alt/Option key
+ PUGL_MOD_SUPER = 1u << 3u ///< Mod4/Command/Windows key
} PuglMod;
/// Bitwise OR of #PuglMod values
@@ -120,92 +120,92 @@ typedef uint32_t PuglMods;
mapping used here is arbitrary and specific to Pugl.
*/
typedef enum {
- // ASCII control codes
- PUGL_KEY_BACKSPACE = 0x08,
- PUGL_KEY_ESCAPE = 0x1B,
- PUGL_KEY_DELETE = 0x7F,
-
- // Unicode Private Use Area
- PUGL_KEY_F1 = 0xE000,
- 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_SHIFT_L = PUGL_KEY_SHIFT,
- PUGL_KEY_SHIFT_R,
- PUGL_KEY_CTRL,
- PUGL_KEY_CTRL_L = PUGL_KEY_CTRL,
- PUGL_KEY_CTRL_R,
- PUGL_KEY_ALT,
- PUGL_KEY_ALT_L = PUGL_KEY_ALT,
- PUGL_KEY_ALT_R,
- PUGL_KEY_SUPER,
- PUGL_KEY_SUPER_L = PUGL_KEY_SUPER,
- PUGL_KEY_SUPER_R,
- PUGL_KEY_MENU,
- PUGL_KEY_CAPS_LOCK,
- PUGL_KEY_SCROLL_LOCK,
- PUGL_KEY_NUM_LOCK,
- PUGL_KEY_PRINT_SCREEN,
- PUGL_KEY_PAUSE
+ // ASCII control codes
+ PUGL_KEY_BACKSPACE = 0x08,
+ PUGL_KEY_ESCAPE = 0x1B,
+ PUGL_KEY_DELETE = 0x7F,
+
+ // Unicode Private Use Area
+ PUGL_KEY_F1 = 0xE000,
+ 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_SHIFT_L = PUGL_KEY_SHIFT,
+ PUGL_KEY_SHIFT_R,
+ PUGL_KEY_CTRL,
+ PUGL_KEY_CTRL_L = PUGL_KEY_CTRL,
+ PUGL_KEY_CTRL_R,
+ PUGL_KEY_ALT,
+ PUGL_KEY_ALT_L = PUGL_KEY_ALT,
+ PUGL_KEY_ALT_R,
+ PUGL_KEY_SUPER,
+ PUGL_KEY_SUPER_L = PUGL_KEY_SUPER,
+ PUGL_KEY_SUPER_R,
+ PUGL_KEY_MENU,
+ PUGL_KEY_CAPS_LOCK,
+ PUGL_KEY_SCROLL_LOCK,
+ PUGL_KEY_NUM_LOCK,
+ PUGL_KEY_PRINT_SCREEN,
+ PUGL_KEY_PAUSE
} PuglKey;
/// The type of a PuglEvent
typedef enum {
- PUGL_NOTHING, ///< No event
- PUGL_CREATE, ///< View created, a #PuglEventCreate
- PUGL_DESTROY, ///< View destroyed, a #PuglEventDestroy
- PUGL_CONFIGURE, ///< View moved/resized, a #PuglEventConfigure
- PUGL_MAP, ///< View made visible, a #PuglEventMap
- PUGL_UNMAP, ///< View made invisible, a #PuglEventUnmap
- PUGL_UPDATE, ///< View ready to draw, a #PuglEventUpdate
- PUGL_EXPOSE, ///< View must be drawn, a #PuglEventExpose
- PUGL_CLOSE, ///< View will be closed, a #PuglEventClose
- PUGL_FOCUS_IN, ///< Keyboard focus entered view, a #PuglEventFocus
- PUGL_FOCUS_OUT, ///< Keyboard focus left view, a #PuglEventFocus
- PUGL_KEY_PRESS, ///< Key pressed, a #PuglEventKey
- PUGL_KEY_RELEASE, ///< Key released, a #PuglEventKey
- PUGL_TEXT, ///< Character entered, a #PuglEventText
- PUGL_POINTER_IN, ///< Pointer entered view, a #PuglEventCrossing
- PUGL_POINTER_OUT, ///< Pointer left view, a #PuglEventCrossing
- PUGL_BUTTON_PRESS, ///< Mouse button pressed, a #PuglEventButton
- PUGL_BUTTON_RELEASE, ///< Mouse button released, a #PuglEventButton
- PUGL_MOTION, ///< Pointer moved, a #PuglEventMotion
- PUGL_SCROLL, ///< Scrolled, a #PuglEventScroll
- PUGL_CLIENT, ///< Custom client message, a #PuglEventClient
- PUGL_TIMER, ///< Timer triggered, a #PuglEventTimer
- PUGL_LOOP_ENTER, ///< Recursive loop entered, a #PuglEventLoopEnter
- PUGL_LOOP_LEAVE, ///< Recursive loop left, a #PuglEventLoopLeave
+ PUGL_NOTHING, ///< No event
+ PUGL_CREATE, ///< View created, a #PuglEventCreate
+ PUGL_DESTROY, ///< View destroyed, a #PuglEventDestroy
+ PUGL_CONFIGURE, ///< View moved/resized, a #PuglEventConfigure
+ PUGL_MAP, ///< View made visible, a #PuglEventMap
+ PUGL_UNMAP, ///< View made invisible, a #PuglEventUnmap
+ PUGL_UPDATE, ///< View ready to draw, a #PuglEventUpdate
+ PUGL_EXPOSE, ///< View must be drawn, a #PuglEventExpose
+ PUGL_CLOSE, ///< View will be closed, a #PuglEventClose
+ PUGL_FOCUS_IN, ///< Keyboard focus entered view, a #PuglEventFocus
+ PUGL_FOCUS_OUT, ///< Keyboard focus left view, a #PuglEventFocus
+ PUGL_KEY_PRESS, ///< Key pressed, a #PuglEventKey
+ PUGL_KEY_RELEASE, ///< Key released, a #PuglEventKey
+ PUGL_TEXT, ///< Character entered, a #PuglEventText
+ PUGL_POINTER_IN, ///< Pointer entered view, a #PuglEventCrossing
+ PUGL_POINTER_OUT, ///< Pointer left view, a #PuglEventCrossing
+ PUGL_BUTTON_PRESS, ///< Mouse button pressed, a #PuglEventButton
+ PUGL_BUTTON_RELEASE, ///< Mouse button released, a #PuglEventButton
+ PUGL_MOTION, ///< Pointer moved, a #PuglEventMotion
+ PUGL_SCROLL, ///< Scrolled, a #PuglEventScroll
+ PUGL_CLIENT, ///< Custom client message, a #PuglEventClient
+ PUGL_TIMER, ///< Timer triggered, a #PuglEventTimer
+ PUGL_LOOP_ENTER, ///< Recursive loop entered, a #PuglEventLoopEnter
+ PUGL_LOOP_LEAVE, ///< Recursive loop left, a #PuglEventLoopLeave
#ifndef PUGL_DISABLE_DEPRECATED
- PUGL_ENTER_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_IN") = PUGL_POINTER_IN,
- PUGL_LEAVE_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_OUT") = PUGL_POINTER_OUT,
- PUGL_MOTION_NOTIFY PUGL_DEPRECATED_BY("PUGL_MOTION") = PUGL_MOTION,
+ PUGL_ENTER_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_IN") = PUGL_POINTER_IN,
+ PUGL_LEAVE_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_OUT") = PUGL_POINTER_OUT,
+ PUGL_MOTION_NOTIFY PUGL_DEPRECATED_BY("PUGL_MOTION") = PUGL_MOTION,
#endif
} PuglEventType;
/// Common flags for all event types
typedef enum {
- PUGL_IS_SEND_EVENT = 1, ///< Event is synthetic
- PUGL_IS_HINT = 2 ///< Event is a hint (not direct user input)
+ PUGL_IS_SEND_EVENT = 1, ///< Event is synthetic
+ PUGL_IS_HINT = 2 ///< Event is a hint (not direct user input)
} PuglEventFlag;
/// Bitwise OR of #PuglEventFlag values
@@ -213,9 +213,9 @@ typedef uint32_t PuglEventFlags;
/// Reason for a PuglEventCrossing
typedef enum {
- PUGL_CROSSING_NORMAL, ///< Crossing due to pointer motion
- PUGL_CROSSING_GRAB, ///< Crossing due to a grab
- PUGL_CROSSING_UNGRAB ///< Crossing due to a grab release
+ PUGL_CROSSING_NORMAL, ///< Crossing due to pointer motion
+ PUGL_CROSSING_GRAB, ///< Crossing due to a grab
+ PUGL_CROSSING_UNGRAB ///< Crossing due to a grab release
} PuglCrossingMode;
/**
@@ -227,17 +227,17 @@ typedef enum {
arbitrary scroll direction freedom, like some touchpads.
*/
typedef enum {
- PUGL_SCROLL_UP, ///< Scroll up
- PUGL_SCROLL_DOWN, ///< Scroll down
- PUGL_SCROLL_LEFT, ///< Scroll left
- PUGL_SCROLL_RIGHT, ///< Scroll right
- PUGL_SCROLL_SMOOTH ///< Smooth scroll in any direction
+ PUGL_SCROLL_UP, ///< Scroll up
+ PUGL_SCROLL_DOWN, ///< Scroll down
+ PUGL_SCROLL_LEFT, ///< Scroll left
+ PUGL_SCROLL_RIGHT, ///< Scroll right
+ PUGL_SCROLL_SMOOTH ///< Smooth scroll in any direction
} PuglScrollDirection;
/// Common header for all event structs
typedef struct {
- PuglEventType type; ///< Event type
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ PuglEventType type; ///< Event type
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
} PuglEventAny;
/**
@@ -275,12 +275,12 @@ typedef PuglEventAny PuglEventDestroy;
otherwise configure the context, but not to draw anything.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_CONFIGURE
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double x; ///< New parent-relative X coordinate
- double y; ///< New parent-relative Y coordinate
- double width; ///< New width
- double height; ///< New height
+ PuglEventType type; ///< #PUGL_CONFIGURE
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double x; ///< New parent-relative X coordinate
+ double y; ///< New parent-relative Y coordinate
+ double width; ///< New width
+ double height; ///< New height
} PuglEventConfigure;
/**
@@ -321,12 +321,12 @@ typedef PuglEventAny PuglEventUpdate;
undefined, there is no preservation of anything drawn previously.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_EXPOSE
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double width; ///< Width of exposed region
- double height; ///< Height of exposed region
+ PuglEventType type; ///< #PUGL_EXPOSE
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double width; ///< Width of exposed region
+ double height; ///< Height of exposed region
} PuglEventExpose;
/**
@@ -346,9 +346,9 @@ typedef PuglEventAny PuglEventClose;
view with the keyboard focus will receive any key press or release events.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_FOCUS_IN or #PUGL_FOCUS_OUT
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- PuglCrossingMode mode; ///< Reason for focus change
+ PuglEventType type; ///< #PUGL_FOCUS_IN or #PUGL_FOCUS_OUT
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ PuglCrossingMode mode; ///< Reason for focus change
} PuglEventFocus;
/**
@@ -369,16 +369,16 @@ typedef struct {
and hardware.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_KEY_PRESS or #PUGL_KEY_RELEASE
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double time; ///< Time in seconds
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double xRoot; ///< Root-relative X coordinate
- double yRoot; ///< Root-relative Y coordinate
- PuglMods state; ///< Bitwise OR of #PuglMod flags
- uint32_t keycode; ///< Raw key code
- uint32_t key; ///< Unshifted Unicode character code, or 0
+ PuglEventType type; ///< #PUGL_KEY_PRESS or #PUGL_KEY_RELEASE
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double time; ///< Time in seconds
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double xRoot; ///< Root-relative X coordinate
+ double yRoot; ///< Root-relative Y coordinate
+ PuglMods state; ///< Bitwise OR of #PuglMod flags
+ uint32_t keycode; ///< Raw key code
+ uint32_t key; ///< Unshifted Unicode character code, or 0
} PuglEventKey;
/**
@@ -393,17 +393,17 @@ typedef struct {
presses will generate a single character.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_TEXT
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double time; ///< Time in seconds
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double xRoot; ///< Root-relative X coordinate
- double yRoot; ///< Root-relative Y coordinate
- PuglMods state; ///< Bitwise OR of #PuglMod flags
- uint32_t keycode; ///< Raw key code
- uint32_t character; ///< Unicode character code
- char string[8]; ///< UTF-8 string
+ PuglEventType type; ///< #PUGL_TEXT
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double time; ///< Time in seconds
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double xRoot; ///< Root-relative X coordinate
+ double yRoot; ///< Root-relative Y coordinate
+ PuglMods state; ///< Bitwise OR of #PuglMod flags
+ uint32_t keycode; ///< Raw key code
+ uint32_t character; ///< Unicode character code
+ char string[8]; ///< UTF-8 string
} PuglEventText;
/**
@@ -414,44 +414,44 @@ typedef struct {
window edge), as described by the `mode` field.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_POINTER_IN or #PUGL_POINTER_OUT
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double time; ///< Time in seconds
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double xRoot; ///< Root-relative X coordinate
- double yRoot; ///< Root-relative Y coordinate
- PuglMods state; ///< Bitwise OR of #PuglMod flags
- PuglCrossingMode mode; ///< Reason for crossing
+ PuglEventType type; ///< #PUGL_POINTER_IN or #PUGL_POINTER_OUT
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double time; ///< Time in seconds
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double xRoot; ///< Root-relative X coordinate
+ double yRoot; ///< Root-relative Y coordinate
+ PuglMods state; ///< Bitwise OR of #PuglMod flags
+ PuglCrossingMode mode; ///< Reason for crossing
} PuglEventCrossing;
/**
Button press or release event.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_BUTTON_PRESS or #PUGL_BUTTON_RELEASE
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double time; ///< Time in seconds
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double xRoot; ///< Root-relative X coordinate
- double yRoot; ///< Root-relative Y coordinate
- PuglMods state; ///< Bitwise OR of #PuglMod flags
- uint32_t button; ///< Button number starting from 1
+ PuglEventType type; ///< #PUGL_BUTTON_PRESS or #PUGL_BUTTON_RELEASE
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double time; ///< Time in seconds
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double xRoot; ///< Root-relative X coordinate
+ double yRoot; ///< Root-relative Y coordinate
+ PuglMods state; ///< Bitwise OR of #PuglMod flags
+ uint32_t button; ///< Button number starting from 1
} PuglEventButton;
/**
Pointer motion event.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_MOTION
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double time; ///< Time in seconds
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double xRoot; ///< Root-relative X coordinate
- double yRoot; ///< Root-relative Y coordinate
- PuglMods state; ///< Bitwise OR of #PuglMod flags
+ PuglEventType type; ///< #PUGL_MOTION
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double time; ///< Time in seconds
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double xRoot; ///< Root-relative X coordinate
+ double yRoot; ///< Root-relative Y coordinate
+ PuglMods state; ///< Bitwise OR of #PuglMod flags
} PuglEventMotion;
/**
@@ -464,17 +464,17 @@ typedef struct {
gracefully.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_SCROLL
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- double time; ///< Time in seconds
- double x; ///< View-relative X coordinate
- double y; ///< View-relative Y coordinate
- double xRoot; ///< Root-relative X coordinate
- double yRoot; ///< Root-relative Y coordinate
- PuglMods state; ///< Bitwise OR of #PuglMod flags
- PuglScrollDirection direction; ///< Scroll direction
- double dx; ///< Scroll X distance in lines
- double dy; ///< Scroll Y distance in lines
+ PuglEventType type; ///< #PUGL_SCROLL
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ double time; ///< Time in seconds
+ double x; ///< View-relative X coordinate
+ double y; ///< View-relative Y coordinate
+ double xRoot; ///< Root-relative X coordinate
+ double yRoot; ///< Root-relative Y coordinate
+ PuglMods state; ///< Bitwise OR of #PuglMod flags
+ PuglScrollDirection direction; ///< Scroll direction
+ double dx; ///< Scroll X distance in lines
+ double dy; ///< Scroll Y distance in lines
} PuglEventScroll;
/**
@@ -485,10 +485,10 @@ typedef struct {
things, this makes it possible to wake up the event loop for any reason.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_CLIENT
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- uintptr_t data1; ///< Client-specific data
- uintptr_t data2; ///< Client-specific data
+ PuglEventType type; ///< #PUGL_CLIENT
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ uintptr_t data1; ///< Client-specific data
+ uintptr_t data2; ///< Client-specific data
} PuglEventClient;
/**
@@ -502,9 +502,9 @@ typedef struct {
event handler, even in applications that register only one timer.
*/
typedef struct {
- PuglEventType type; ///< #PUGL_TIMER
- PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
- uintptr_t id; ///< Timer ID
+ PuglEventType type; ///< #PUGL_TIMER
+ PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
+ uintptr_t id; ///< Timer ID
} PuglEventTimer;
/**
@@ -551,19 +551,19 @@ typedef PuglEventAny PuglEventLoopLeave;
and #PUGL_EXPOSE, but only enabled for drawing for #PUGL_EXPOSE.
*/
typedef union {
- PuglEventAny any; ///< Valid for all event types
- PuglEventType type; ///< Event type
- PuglEventButton button; ///< #PUGL_BUTTON_PRESS, #PUGL_BUTTON_RELEASE
- PuglEventConfigure configure; ///< #PUGL_CONFIGURE
- PuglEventExpose expose; ///< #PUGL_EXPOSE
- PuglEventKey key; ///< #PUGL_KEY_PRESS, #PUGL_KEY_RELEASE
- PuglEventText text; ///< #PUGL_TEXT
- PuglEventCrossing crossing; ///< #PUGL_POINTER_IN, #PUGL_POINTER_OUT
- PuglEventMotion motion; ///< #PUGL_MOTION
- PuglEventScroll scroll; ///< #PUGL_SCROLL
- PuglEventFocus focus; ///< #PUGL_FOCUS_IN, #PUGL_FOCUS_OUT
- PuglEventClient client; ///< #PUGL_CLIENT
- PuglEventTimer timer; ///< #PUGL_TIMER
+ PuglEventAny any; ///< Valid for all event types
+ PuglEventType type; ///< Event type
+ PuglEventButton button; ///< #PUGL_BUTTON_PRESS, #PUGL_BUTTON_RELEASE
+ PuglEventConfigure configure; ///< #PUGL_CONFIGURE
+ PuglEventExpose expose; ///< #PUGL_EXPOSE
+ PuglEventKey key; ///< #PUGL_KEY_PRESS, #PUGL_KEY_RELEASE
+ PuglEventText text; ///< #PUGL_TEXT
+ PuglEventCrossing crossing; ///< #PUGL_POINTER_IN, #PUGL_POINTER_OUT
+ PuglEventMotion motion; ///< #PUGL_MOTION
+ PuglEventScroll scroll; ///< #PUGL_SCROLL
+ PuglEventFocus focus; ///< #PUGL_FOCUS_IN, #PUGL_FOCUS_OUT
+ PuglEventClient client; ///< #PUGL_CLIENT
+ PuglEventTimer timer; ///< #PUGL_TIMER
} PuglEvent;
/**
@@ -577,22 +577,23 @@ typedef union {
/// Return status code
typedef enum {
- PUGL_SUCCESS, ///< Success
- PUGL_FAILURE, ///< Non-fatal failure
- PUGL_UNKNOWN_ERROR, ///< Unknown system error
- PUGL_BAD_BACKEND, ///< Invalid or missing backend
- PUGL_BAD_CONFIGURATION, ///< Invalid view configuration
- PUGL_BAD_PARAMETER, ///< Invalid parameter
- PUGL_BACKEND_FAILED, ///< Backend initialization failed
- PUGL_REGISTRATION_FAILED, ///< Class registration failed
- PUGL_REALIZE_FAILED, ///< System view realization failed
- PUGL_SET_FORMAT_FAILED, ///< Failed to set pixel format
- PUGL_CREATE_CONTEXT_FAILED, ///< Failed to create drawing context
- PUGL_UNSUPPORTED_TYPE, ///< Unsupported data type
+ PUGL_SUCCESS, ///< Success
+ PUGL_FAILURE, ///< Non-fatal failure
+ PUGL_UNKNOWN_ERROR, ///< Unknown system error
+ PUGL_BAD_BACKEND, ///< Invalid or missing backend
+ PUGL_BAD_CONFIGURATION, ///< Invalid view configuration
+ PUGL_BAD_PARAMETER, ///< Invalid parameter
+ PUGL_BACKEND_FAILED, ///< Backend initialization failed
+ PUGL_REGISTRATION_FAILED, ///< Class registration failed
+ PUGL_REALIZE_FAILED, ///< System view realization failed
+ PUGL_SET_FORMAT_FAILED, ///< Failed to set pixel format
+ PUGL_CREATE_CONTEXT_FAILED, ///< Failed to create drawing context
+ PUGL_UNSUPPORTED_TYPE, ///< Unsupported data type
} PuglStatus;
/// Return a string describing a status code
-PUGL_API PUGL_CONST_FUNC
+PUGL_API
+PUGL_CONST_FUNC
const char*
puglStrerror(PuglStatus status);
@@ -625,18 +626,18 @@ typedef void* PuglWorldHandle;
/// The type of a World
typedef enum {
- PUGL_PROGRAM, ///< Top-level application
- PUGL_MODULE ///< Plugin or module within a larger application
+ PUGL_PROGRAM, ///< Top-level application
+ PUGL_MODULE ///< Plugin or module within a larger application
} PuglWorldType;
/// World flags
typedef enum {
- /**
- Set up support for threads if necessary.
+ /**
+ Set up support for threads if necessary.
- - X11: Calls XInitThreads() which is required for some drivers.
- */
- PUGL_WORLD_THREADS = 1u << 0u
+ - X11: Calls XInitThreads() which is required for some drivers.
+ */
+ PUGL_WORLD_THREADS = 1u << 0u
} PuglWorldFlag;
/// Bitwise OR of #PuglWorldFlag values
@@ -649,11 +650,13 @@ typedef uint32_t PuglWorldFlags;
@param flags Flags to control world features.
@return A new world, which must be later freed with puglFreeWorld().
*/
-PUGL_API PuglWorld*
+PUGL_API
+PuglWorld*
puglNewWorld(PuglWorldType type, PuglWorldFlags flags);
/// Free a world allocated with puglNewWorld()
-PUGL_API void
+PUGL_API
+void
puglFreeWorld(PuglWorld* world);
/**
@@ -664,11 +667,13 @@ puglFreeWorld(PuglWorld* world);
The handle is opaque to Pugl and is not interpreted in any way.
*/
-PUGL_API void
+PUGL_API
+void
puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle);
/// Get the user data for the world
-PUGL_API PuglWorldHandle
+PUGL_API
+PuglWorldHandle
puglGetWorldHandle(PuglWorld* world);
/**
@@ -680,7 +685,8 @@ puglGetWorldHandle(PuglWorld* world);
Windows: Returns the `HMODULE` of the calling process.
*/
-PUGL_API void*
+PUGL_API
+void*
puglGetNativeWorld(PuglWorld* world);
/**
@@ -692,7 +698,8 @@ puglGetNativeWorld(PuglWorld* world);
for every instance of the application, but different from other
applications.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetClassName(PuglWorld* world, const char* name);
/**
@@ -702,7 +709,8 @@ puglSetClassName(PuglWorld* world, const char* name);
time is only useful to compare against other times returned by this
function, its absolute value has no meaning.
*/
-PUGL_API double
+PUGL_API
+double
puglGetTime(const PuglWorld* world);
/**
@@ -726,7 +734,8 @@ puglGetTime(const PuglWorld* world);
@return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if not, or an error.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglUpdate(PuglWorld* world, double timeout);
/**
@@ -775,31 +784,31 @@ typedef void* PuglHandle;
/// A hint for configuring a view
typedef enum {
- PUGL_USE_COMPAT_PROFILE, ///< Use compatible (not core) OpenGL profile
- PUGL_USE_DEBUG_CONTEXT, ///< True to use a debug OpenGL context
- PUGL_CONTEXT_VERSION_MAJOR, ///< OpenGL context major version
- PUGL_CONTEXT_VERSION_MINOR, ///< OpenGL context minor version
- PUGL_RED_BITS, ///< Number of bits for red channel
- PUGL_GREEN_BITS, ///< Number of bits for green channel
- PUGL_BLUE_BITS, ///< Number of bits for blue channel
- PUGL_ALPHA_BITS, ///< Number of bits for alpha channel
- PUGL_DEPTH_BITS, ///< Number of bits for depth buffer
- PUGL_STENCIL_BITS, ///< Number of bits for stencil buffer
- PUGL_SAMPLES, ///< Number of samples per pixel (AA)
- PUGL_DOUBLE_BUFFER, ///< True if double buffering should be used
- PUGL_SWAP_INTERVAL, ///< Number of frames between buffer swaps
- PUGL_RESIZABLE, ///< True if view should be resizable
- PUGL_IGNORE_KEY_REPEAT, ///< True if key repeat events are ignored
- PUGL_REFRESH_RATE, ///< Refresh rate in Hz
-
- PUGL_NUM_VIEW_HINTS
+ PUGL_USE_COMPAT_PROFILE, ///< Use compatible (not core) OpenGL profile
+ PUGL_USE_DEBUG_CONTEXT, ///< True to use a debug OpenGL context
+ PUGL_CONTEXT_VERSION_MAJOR, ///< OpenGL context major version
+ PUGL_CONTEXT_VERSION_MINOR, ///< OpenGL context minor version
+ PUGL_RED_BITS, ///< Number of bits for red channel
+ PUGL_GREEN_BITS, ///< Number of bits for green channel
+ PUGL_BLUE_BITS, ///< Number of bits for blue channel
+ PUGL_ALPHA_BITS, ///< Number of bits for alpha channel
+ PUGL_DEPTH_BITS, ///< Number of bits for depth buffer
+ PUGL_STENCIL_BITS, ///< Number of bits for stencil buffer
+ PUGL_SAMPLES, ///< Number of samples per pixel (AA)
+ PUGL_DOUBLE_BUFFER, ///< True if double buffering should be used
+ PUGL_SWAP_INTERVAL, ///< Number of frames between buffer swaps
+ PUGL_RESIZABLE, ///< True if view should be resizable
+ PUGL_IGNORE_KEY_REPEAT, ///< True if key repeat events are ignored
+ PUGL_REFRESH_RATE, ///< Refresh rate in Hz
+
+ PUGL_NUM_VIEW_HINTS
} PuglViewHint;
/// A special view hint value
typedef enum {
- PUGL_DONT_CARE = -1, ///< Use best available value
- PUGL_FALSE = 0, ///< Explicitly false
- PUGL_TRUE = 1 ///< Explicitly true
+ PUGL_DONT_CARE = -1, ///< Use best available value
+ PUGL_FALSE = 0, ///< Explicitly false
+ PUGL_TRUE = 1 ///< Explicitly true
} PuglViewHintValue;
/// A function called when an event occurs
@@ -818,15 +827,18 @@ typedef PuglStatus (*PuglEventFunc)(PuglView* view, const PuglEvent* event);
It must first be configured, then the system view can be created with
puglRealize().
*/
-PUGL_API PuglView*
+PUGL_API
+PuglView*
puglNewView(PuglWorld* world);
/// Free a view created with puglNewView()
-PUGL_API void
+PUGL_API
+void
puglFreeView(PuglView* view);
/// Return the world that `view` is a part of
-PUGL_API PuglWorld*
+PUGL_API
+PuglWorld*
puglGetWorld(PuglView* view);
/**
@@ -838,11 +850,13 @@ puglGetWorld(PuglView* view);
The handle is opaque to Pugl and is not interpreted in any way.
*/
-PUGL_API void
+PUGL_API
+void
puglSetHandle(PuglView* view, PuglHandle handle);
/// Get the user data for a view
-PUGL_API PuglHandle
+PUGL_API
+PuglHandle
puglGetHandle(PuglView* view);
/**
@@ -862,11 +876,13 @@ puglGetHandle(PuglView* view);
applications must link against the appropriate backend library, or be sure
to compile in the appropriate code if using a local copy of Pugl.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetBackend(PuglView* view, const PuglBackend* backend);
/// Set the function to call when an event occurs
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
/**
@@ -874,7 +890,8 @@ puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
This only has an effect when called before puglRealize().
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetViewHint(PuglView* view, PuglViewHint hint, int value);
/**
@@ -884,7 +901,8 @@ puglSetViewHint(PuglView* view, PuglViewHint hint, int value);
hint which was initially set to PUGL_DONT_CARE, or has been adjusted from
the suggested value.
*/
-PUGL_API int
+PUGL_API
+int
puglGetViewHint(const PuglView* view, PuglViewHint hint);
/**
@@ -899,7 +917,8 @@ puglGetViewHint(const PuglView* view, PuglViewHint hint);
The position is in screen coordinates with an upper left origin.
*/
-PUGL_API PuglRect
+PUGL_API
+PuglRect
puglGetFrame(const PuglView* view);
/**
@@ -910,7 +929,8 @@ puglGetFrame(const PuglView* view);
@return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is
unchanged.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetFrame(PuglView* view, PuglRect frame);
/**
@@ -923,7 +943,8 @@ puglSetFrame(PuglView* view, PuglRect frame);
@return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
not yet realized.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetDefaultSize(PuglView* view, int width, int height);
/**
@@ -935,7 +956,8 @@ puglSetDefaultSize(PuglView* view, int width, int height);
@return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
not yet realized.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetMinSize(PuglView* view, int width, int height);
/**
@@ -947,7 +969,8 @@ puglSetMinSize(PuglView* view, int width, int height);
@return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
not yet realized.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetMaxSize(PuglView* view, int width, int height);
/**
@@ -966,7 +989,8 @@ puglSetMaxSize(PuglView* view, int width, int height);
@return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
not yet realized.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetAspectRatio(PuglView* view, int minX, int minY, int maxX, int maxY);
/**
@@ -983,7 +1007,8 @@ puglSetAspectRatio(PuglView* view, int minX, int minY, int maxX, int maxY);
top-level window, and sets the title, typically displayed in the title bar
or in window switchers.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetWindowTitle(PuglView* view, const char* title);
/**
@@ -991,7 +1016,8 @@ puglSetWindowTitle(PuglView* view, const char* title);
This must be called before puglRealize(), reparenting is not supported.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetParentWindow(PuglView* view, PuglNativeView parent);
/**
@@ -1004,7 +1030,8 @@ puglSetParentWindow(PuglView* view, PuglNativeView parent);
A view can either have a parent (for embedding) or a transient parent (for
top-level windows like dialogs), but not both.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetTransientFor(PuglView* view, PuglNativeView parent);
/**
@@ -1018,7 +1045,8 @@ puglSetTransientFor(PuglView* view, PuglNativeView parent);
The view should be fully configured using the above functions before this is
called. This function may only be called once per view.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglRealize(PuglView* view);
/**
@@ -1030,19 +1058,23 @@ puglRealize(PuglView* view);
If the view is currently hidden, it will be shown and possibly raised to the
top depending on the platform.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglShow(PuglView* view);
/// Hide the current window
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglHide(PuglView* view);
/// Return true iff the view is currently visible
-PUGL_API bool
+PUGL_API
+bool
puglGetVisible(const PuglView* view);
/// Return the native window handle
-PUGL_API PuglNativeView
+PUGL_API
+PuglNativeView
puglGetNativeWindow(PuglView* view);
/**
@@ -1063,7 +1095,8 @@ puglGetNativeWindow(PuglView* view);
All other backends: returns null.
*/
-PUGL_API void*
+PUGL_API
+void*
puglGetContext(PuglView* view);
/**
@@ -1075,7 +1108,8 @@ puglGetContext(PuglView* view);
platforms. If called elsewhere, an expose will be enqueued to be processed
in the next event loop iteration.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglPostRedisplay(PuglView* view);
/**
@@ -1084,7 +1118,8 @@ puglPostRedisplay(PuglView* view);
This has the same semantics as puglPostRedisplay(), but allows giving a
precise region for redrawing only a portion of the view.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglPostRedisplayRect(PuglView* view, PuglRect rect);
/**
@@ -1101,21 +1136,23 @@ puglPostRedisplayRect(PuglView* view, PuglRect rect);
Windows.
*/
typedef enum {
- PUGL_CURSOR_ARROW, ///< Default pointing arrow
- PUGL_CURSOR_CARET, ///< Caret (I-Beam) for text entry
- PUGL_CURSOR_CROSSHAIR, ///< Cross-hair
- PUGL_CURSOR_HAND, ///< Hand with a pointing finger
- PUGL_CURSOR_NO, ///< Operation not allowed
- PUGL_CURSOR_LEFT_RIGHT, ///< Left/right arrow for horizontal resize
- PUGL_CURSOR_UP_DOWN, ///< Up/down arrow for vertical resize
+ PUGL_CURSOR_ARROW, ///< Default pointing arrow
+ PUGL_CURSOR_CARET, ///< Caret (I-Beam) for text entry
+ PUGL_CURSOR_CROSSHAIR, ///< Cross-hair
+ PUGL_CURSOR_HAND, ///< Hand with a pointing finger
+ PUGL_CURSOR_NO, ///< Operation not allowed
+ PUGL_CURSOR_LEFT_RIGHT, ///< Left/right arrow for horizontal resize
+ PUGL_CURSOR_UP_DOWN, ///< Up/down arrow for vertical resize
} PuglCursor;
/// Grab the keyboard input focus
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglGrabFocus(PuglView* view);
/// Return whether `view` has the keyboard input focus
-PUGL_API bool
+PUGL_API
+bool
puglHasFocus(const PuglView* view);
/**
@@ -1129,7 +1166,8 @@ puglHasFocus(const PuglView* view);
@param data The data to copy to the clipboard.
@param len The length of data in bytes (including terminator if necessary).
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetClipboard(PuglView* view,
const char* type,
const void* data,
@@ -1146,7 +1184,8 @@ puglSetClipboard(PuglView* view,
@param[out] len Set to the length of the data in bytes.
@return The clipboard contents, or `NULL`.
*/
-PUGL_API const void*
+PUGL_API
+const void*
puglGetClipboard(PuglView* view, const char** type, size_t* len);
/**
@@ -1160,7 +1199,8 @@ puglGetClipboard(PuglView* view, const char** type, size_t* len);
- #PUGL_BAD_PARAMETER if the given cursor is invalid.
- #PUGL_FAILURE if the cursor isknown but loading it from the system fails.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSetCursor(PuglView* view, PuglCursor cursor);
/**
@@ -1170,7 +1210,8 @@ puglSetCursor(PuglView* view, PuglCursor cursor);
from the user. The exact effect depends on the platform, but is usually
something like a flashing task bar entry or bouncing application icon.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglRequestAttention(PuglView* view);
/**
@@ -1200,7 +1241,8 @@ puglRequestAttention(PuglView* view);
- #PUGL_FAILURE if timers are not supported by this system or build.
- #PUGL_UNKNOWN_ERROR if setting the timer failed.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglStartTimer(PuglView* view, uintptr_t id, double timeout);
/**
@@ -1213,7 +1255,8 @@ puglStartTimer(PuglView* view, uintptr_t id, double timeout);
- #PUGL_FAILURE if timers are not supported by this system or build.
- #PUGL_UNKNOWN_ERROR if stopping the timer failed.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglStopTimer(PuglView* view, uintptr_t id);
/**
@@ -1233,7 +1276,8 @@ puglStopTimer(PuglView* view, uintptr_t id);
- #PUGL_UNSUPPORTED_TYPE if sending events of this type is not supported.
- #PUGL_UNKNOWN_ERROR if sending the event failed.
*/
-PUGL_API PuglStatus
+PUGL_API
+PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event);
/**
@@ -1271,13 +1315,14 @@ typedef uintptr_t PuglNativeWindow;
@param argv Arguments (currently unused).
@return A newly created view.
*/
-static inline PUGL_DEPRECATED_BY("puglNewView") PuglView*
+static inline PUGL_DEPRECATED_BY("puglNewView")
+PuglView*
puglInit(const int* pargc, char** argv)
{
- (void)pargc;
- (void)argv;
+ (void)pargc;
+ (void)argv;
- return puglNewView(puglNewWorld(PUGL_MODULE, 0));
+ return puglNewView(puglNewWorld(PUGL_MODULE, 0));
}
/**
@@ -1285,22 +1330,24 @@ puglInit(const int* pargc, char** argv)
@deprecated Use puglFreeApp() and puglFreeView().
*/
-static inline PUGL_DEPRECATED_BY("puglFreeView") void
+static inline PUGL_DEPRECATED_BY("puglFreeView")
+void
puglDestroy(PuglView* view)
{
- PuglWorld* const world = puglGetWorld(view);
+ PuglWorld* const world = puglGetWorld(view);
- puglFreeView(view);
- puglFreeWorld(world);
+ puglFreeView(view);
+ puglFreeWorld(world);
}
/**
Set the window class name before creating a window.
*/
-static inline PUGL_DEPRECATED_BY("puglSetClassName") void
+static inline PUGL_DEPRECATED_BY("puglSetClassName")
+void
puglInitWindowClass(PuglView* view, const char* name)
{
- puglSetClassName(puglGetWorld(view), name);
+ puglSetClassName(puglGetWorld(view), name);
}
/**
@@ -1308,24 +1355,26 @@ puglInitWindowClass(PuglView* view, const char* name)
@deprecated Use puglSetFrame().
*/
-static inline PUGL_DEPRECATED_BY("puglSetFrame") void
+static inline PUGL_DEPRECATED_BY("puglSetFrame")
+void
puglInitWindowSize(PuglView* view, int width, int height)
{
- PuglRect frame = puglGetFrame(view);
+ PuglRect frame = puglGetFrame(view);
- frame.width = width;
- frame.height = height;
+ frame.width = width;
+ frame.height = height;
- puglSetFrame(view, frame);
+ puglSetFrame(view, frame);
}
/**
Set the minimum window size before creating a window.
*/
-static inline PUGL_DEPRECATED_BY("puglSetMinSize") void
+static inline PUGL_DEPRECATED_BY("puglSetMinSize")
+void
puglInitWindowMinSize(PuglView* view, int width, int height)
{
- puglSetMinSize(view, width, height);
+ puglSetMinSize(view, width, height);
}
/**
@@ -1338,14 +1387,15 @@ puglInitWindowMinSize(PuglView* view, int width, int height)
currenty work on MacOS (the minimum is used), so only setting a fixed aspect
ratio works properly across all platforms.
*/
-static inline PUGL_DEPRECATED_BY("puglSetAspectRatio") void
+static inline PUGL_DEPRECATED_BY("puglSetAspectRatio")
+void
puglInitWindowAspectRatio(PuglView* view,
int minX,
int minY,
int maxX,
int maxY)
{
- puglSetAspectRatio(view, minX, minY, maxX, maxY);
+ puglSetAspectRatio(view, minX, minY, maxX, maxY);
}
/**
@@ -1354,10 +1404,11 @@ puglInitWindowAspectRatio(PuglView* view,
On X11, parent must be a Window.
On OSX, parent must be an NSView*.
*/
-static inline PUGL_DEPRECATED_BY("puglSetTransientFor") void
+static inline PUGL_DEPRECATED_BY("puglSetTransientFor")
+void
puglInitTransientFor(PuglView* view, uintptr_t parent)
{
- puglSetTransientFor(view, (PuglNativeWindow)parent);
+ puglSetTransientFor(view, (PuglNativeWindow)parent);
}
/**
@@ -1365,10 +1416,11 @@ puglInitTransientFor(PuglView* view, uintptr_t parent)
@deprecated Use puglSetViewHint() with #PUGL_RESIZABLE.
*/
-static inline PUGL_DEPRECATED_BY("puglSetViewHint") void
+static inline PUGL_DEPRECATED_BY("puglSetViewHint")
+void
puglInitResizable(PuglView* view, bool resizable)
{
- puglSetViewHint(view, PUGL_RESIZABLE, resizable);
+ puglSetViewHint(view, PUGL_RESIZABLE, resizable);
}
/**
@@ -1377,13 +1429,14 @@ puglInitResizable(PuglView* view, bool resizable)
@deprecated Use puglGetFrame().
*/
-static inline PUGL_DEPRECATED_BY("puglGetFrame") void
+static inline PUGL_DEPRECATED_BY("puglGetFrame")
+void
puglGetSize(PuglView* view, int* width, int* height)
{
- const PuglRect frame = puglGetFrame(view);
+ const PuglRect frame = puglGetFrame(view);
- *width = (int)frame.width;
- *height = (int)frame.height;
+ *width = (int)frame.width;
+ *height = (int)frame.height;
}
/**
@@ -1391,10 +1444,11 @@ puglGetSize(PuglView* view, int* width, int* height)
@deprecated Use puglSetViewHint() with #PUGL_IGNORE_KEY_REPEAT.
*/
-static inline PUGL_DEPRECATED_BY("puglSetViewHint") void
+static inline PUGL_DEPRECATED_BY("puglSetViewHint")
+void
puglIgnoreKeyRepeat(PuglView* view, bool ignore)
{
- puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, ignore);
+ puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, ignore);
}
/**
@@ -1402,10 +1456,11 @@ puglIgnoreKeyRepeat(PuglView* view, bool ignore)
@deprecated Use puglSetWindowHint().
*/
-static inline PUGL_DEPRECATED_BY("puglSetViewHint") void
+static inline PUGL_DEPRECATED_BY("puglSetViewHint")
+void
puglInitWindowHint(PuglView* view, PuglViewHint hint, int value)
{
- puglSetViewHint(view, hint, value);
+ puglSetViewHint(view, hint, value);
}
/**
@@ -1413,10 +1468,11 @@ puglInitWindowHint(PuglView* view, PuglViewHint hint, int value)
@deprecated Use puglSetWindowParent().
*/
-static inline PUGL_DEPRECATED_BY("puglSetParentWindow") void
+static inline PUGL_DEPRECATED_BY("puglSetParentWindow")
+void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
{
- puglSetParentWindow(view, parent);
+ puglSetParentWindow(view, parent);
}
/**
@@ -1424,10 +1480,11 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
@deprecated Use puglSetBackend().
*/
-static inline PUGL_DEPRECATED_BY("puglSetBackend") int
+static inline PUGL_DEPRECATED_BY("puglSetBackend")
+int
puglInitBackend(PuglView* view, const PuglBackend* backend)
{
- return (int)puglSetBackend(view, backend);
+ return (int)puglSetBackend(view, backend);
}
/**
@@ -1438,11 +1495,12 @@ puglInitBackend(PuglView* view, const PuglBackend* backend)
@deprecated Use puglRealize(), or just show the view.
*/
-static inline PUGL_DEPRECATED_BY("puglRealize") PuglStatus
+static inline PUGL_DEPRECATED_BY("puglRealize")
+PuglStatus
puglCreateWindow(PuglView* view, const char* title)
{
- puglSetWindowTitle(view, title);
- return puglRealize(view);
+ puglSetWindowTitle(view, title);
+ return puglRealize(view);
}
/**
@@ -1455,7 +1513,9 @@ puglCreateWindow(PuglView* view, const char* title)
@deprecated Use puglPollEvents().
*/
-PUGL_API PUGL_DEPRECATED_BY("puglPollEvents") PuglStatus
+PUGL_API
+PUGL_DEPRECATED_BY("puglPollEvents")
+PuglStatus
puglWaitForEvent(PuglView* view);
/**
@@ -1467,7 +1527,9 @@ puglWaitForEvent(PuglView* view);
@deprecated Use puglDispatchEvents().
*/
-PUGL_API PUGL_DEPRECATED_BY("puglDispatchEvents") PuglStatus
+PUGL_API
+PUGL_DEPRECATED_BY("puglDispatchEvents")
+PuglStatus
puglProcessEvents(PuglView* view);
/**
@@ -1485,7 +1547,9 @@ puglProcessEvents(PuglView* view);
@deprecated Use puglUpdate().
*/
-PUGL_API PUGL_DEPRECATED_BY("puglUpdate") PuglStatus
+PUGL_API
+PUGL_DEPRECATED_BY("puglUpdate")
+PuglStatus
puglPollEvents(PuglWorld* world, double timeout);
/**
@@ -1498,13 +1562,19 @@ puglPollEvents(PuglWorld* world, double timeout);
@deprecated Use puglUpdate().
*/
-PUGL_API PUGL_DEPRECATED_BY("puglUpdate") PuglStatus
+PUGL_API
+PUGL_DEPRECATED_BY("puglUpdate")
+PuglStatus
puglDispatchEvents(PuglWorld* world);
-PUGL_API PUGL_DEPRECATED_BY("puglShow") PuglStatus
+PUGL_API
+PUGL_DEPRECATED_BY("puglShow")
+PuglStatus
puglShowWindow(PuglView* view);
-PUGL_API PUGL_DEPRECATED_BY("puglHide") PuglStatus
+PUGL_API
+PUGL_DEPRECATED_BY("puglHide")
+PuglStatus
puglHideWindow(PuglView* view);
#endif // PUGL_DISABLE_DEPRECATED
diff --git a/include/pugl/stub.h b/include/pugl/stub.h
index d2d1236..46e0e96 100644
--- a/include/pugl/stub.h
+++ b/include/pugl/stub.h
@@ -34,7 +34,8 @@ PUGL_BEGIN_DECLS
This backend just creates a simple native window without setting up any
portable graphics API.
*/
-PUGL_API PUGL_CONST_FUNC
+PUGL_API
+PUGL_CONST_FUNC
const PuglBackend*
puglStubBackend(void);
diff --git a/include/pugl/vulkan.h b/include/pugl/vulkan.h
index bd4ad8e..15f834c 100644
--- a/include/pugl/vulkan.h
+++ b/include/pugl/vulkan.h
@@ -66,11 +66,13 @@ typedef struct PuglVulkanLoaderImpl PuglVulkanLoader;
/**
Create a new dynamic loader for Vulkan functions.
- This dynamically loads the Vulkan library and gets the load functions from it.
+ This dynamically loads the Vulkan library and gets the load functions from
+ it.
@return A new Vulkan loader, or null on failure.
*/
-PUGL_API PuglVulkanLoader*
+PUGL_API
+PuglVulkanLoader*
puglNewVulkanLoader(PuglWorld* world);
/**
@@ -79,7 +81,8 @@ puglNewVulkanLoader(PuglWorld* world);
Note that this closes the Vulkan library, so no Vulkan objects or API may be
used after this is called.
*/
-PUGL_API void
+PUGL_API
+void
puglFreeVulkanLoader(PuglVulkanLoader* loader);
/**
@@ -88,7 +91,8 @@ puglFreeVulkanLoader(PuglVulkanLoader* loader);
@return Null if the Vulkan library does not contain this function (which is
unlikely and indicates a broken system).
*/
-PUGL_API PFN_vkGetInstanceProcAddr
+PUGL_API
+PFN_vkGetInstanceProcAddr
puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader);
/**
@@ -97,7 +101,8 @@ puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader);
@return Null if the Vulkan library does not contain this function (which is
unlikely and indicates a broken system).
*/
-PUGL_API PFN_vkGetDeviceProcAddr
+PUGL_API
+PFN_vkGetDeviceProcAddr
puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader);
/**
@@ -109,7 +114,8 @@ puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader);
@param[out] count The number of extensions in the returned array.
@return An array of extension name strings.
*/
-PUGL_API const char* const*
+PUGL_API
+const char* const*
puglGetInstanceExtensions(uint32_t* count);
/**
@@ -122,7 +128,8 @@ puglGetInstanceExtensions(uint32_t* count);
@param[out] surface Pointed to a newly created Vulkan surface.
@return `VK_SUCCESS` on success, or a Vulkan error code.
*/
-PUGL_API VkResult
+PUGL_API
+VkResult
puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
PuglView* view,
VkInstance instance,
@@ -134,7 +141,9 @@ puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
Pass the returned value to puglSetBackend() to draw to a view with Vulkan.
*/
-PUGL_API PUGL_CONST_FUNC const PuglBackend*
+PUGL_API
+PUGL_CONST_FUNC
+const PuglBackend*
puglVulkanBackend(void);
/**
diff --git a/src/implementation.c b/src/implementation.c
index e842e13..a6d8393 100644
--- a/src/implementation.c
+++ b/src/implementation.c
@@ -26,248 +26,249 @@
const char*
puglStrerror(const PuglStatus status)
{
- // clang-format off
- switch (status) {
- case PUGL_SUCCESS: return "Success";
- case PUGL_FAILURE: return "Non-fatal failure";
- case PUGL_UNKNOWN_ERROR: return "Unknown system error";
- case PUGL_BAD_BACKEND: return "Invalid or missing backend";
- case PUGL_BAD_CONFIGURATION: return "Invalid view configuration";
- case PUGL_BAD_PARAMETER: return "Invalid parameter";
- case PUGL_BACKEND_FAILED: return "Backend initialisation failed";
- case PUGL_REGISTRATION_FAILED: return "Class registration failed";
- case PUGL_REALIZE_FAILED: return "View creation failed";
- case PUGL_SET_FORMAT_FAILED: return "Failed to set pixel format";
- case PUGL_CREATE_CONTEXT_FAILED: return "Failed to create drawing context";
- case PUGL_UNSUPPORTED_TYPE: return "Unsupported data type";
- }
- // clang-format on
-
- return "Unknown error";
+ // clang-format off
+ switch (status) {
+ case PUGL_SUCCESS: return "Success";
+ case PUGL_FAILURE: return "Non-fatal failure";
+ case PUGL_UNKNOWN_ERROR: return "Unknown system error";
+ case PUGL_BAD_BACKEND: return "Invalid or missing backend";
+ case PUGL_BAD_CONFIGURATION: return "Invalid view configuration";
+ case PUGL_BAD_PARAMETER: return "Invalid parameter";
+ case PUGL_BACKEND_FAILED: return "Backend initialisation failed";
+ case PUGL_REGISTRATION_FAILED: return "Class registration failed";
+ case PUGL_REALIZE_FAILED: return "View creation failed";
+ case PUGL_SET_FORMAT_FAILED: return "Failed to set pixel format";
+ case PUGL_CREATE_CONTEXT_FAILED: return "Failed to create drawing context";
+ case PUGL_UNSUPPORTED_TYPE: return "Unsupported data type";
+ }
+ // clang-format on
+
+ return "Unknown error";
}
void
puglSetString(char** dest, const char* string)
{
- if (*dest != string) {
- const size_t len = strlen(string);
+ if (*dest != string) {
+ const size_t len = strlen(string);
- *dest = (char*)realloc(*dest, len + 1);
- strncpy(*dest, string, len + 1);
- }
+ *dest = (char*)realloc(*dest, len + 1);
+ strncpy(*dest, string, len + 1);
+ }
}
void
puglSetBlob(PuglBlob* const dest, const void* const data, const size_t len)
{
- if (data) {
- dest->len = len;
- dest->data = realloc(dest->data, len + 1);
- memcpy(dest->data, data, len);
- ((char*)dest->data)[len] = 0;
- } else {
- dest->len = 0;
- dest->data = NULL;
- }
+ if (data) {
+ dest->len = len;
+ dest->data = realloc(dest->data, len + 1);
+ memcpy(dest->data, data, len);
+ ((char*)dest->data)[len] = 0;
+ } else {
+ dest->len = 0;
+ dest->data = NULL;
+ }
}
static void
puglSetDefaultHints(PuglHints hints)
{
- hints[PUGL_USE_COMPAT_PROFILE] = PUGL_TRUE;
- hints[PUGL_CONTEXT_VERSION_MAJOR] = 2;
- hints[PUGL_CONTEXT_VERSION_MINOR] = 0;
- hints[PUGL_RED_BITS] = 8;
- hints[PUGL_GREEN_BITS] = 8;
- hints[PUGL_BLUE_BITS] = 8;
- hints[PUGL_ALPHA_BITS] = 8;
- hints[PUGL_DEPTH_BITS] = 0;
- hints[PUGL_STENCIL_BITS] = 0;
- hints[PUGL_SAMPLES] = 0;
- hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE;
- hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE;
- hints[PUGL_RESIZABLE] = PUGL_FALSE;
- hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE;
- hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE;
+ hints[PUGL_USE_COMPAT_PROFILE] = PUGL_TRUE;
+ hints[PUGL_CONTEXT_VERSION_MAJOR] = 2;
+ hints[PUGL_CONTEXT_VERSION_MINOR] = 0;
+ hints[PUGL_RED_BITS] = 8;
+ hints[PUGL_GREEN_BITS] = 8;
+ hints[PUGL_BLUE_BITS] = 8;
+ hints[PUGL_ALPHA_BITS] = 8;
+ hints[PUGL_DEPTH_BITS] = 0;
+ hints[PUGL_STENCIL_BITS] = 0;
+ hints[PUGL_SAMPLES] = 0;
+ hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE;
+ hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE;
+ hints[PUGL_RESIZABLE] = PUGL_FALSE;
+ hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE;
+ hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE;
}
PuglWorld*
puglNewWorld(PuglWorldType type, PuglWorldFlags flags)
{
- PuglWorld* world = (PuglWorld*)calloc(1, sizeof(PuglWorld));
- if (!world || !(world->impl = puglInitWorldInternals(type, flags))) {
- free(world);
- return NULL;
- }
+ PuglWorld* world = (PuglWorld*)calloc(1, sizeof(PuglWorld));
+ if (!world || !(world->impl = puglInitWorldInternals(type, flags))) {
+ free(world);
+ return NULL;
+ }
- world->startTime = puglGetTime(world);
+ world->startTime = puglGetTime(world);
- puglSetString(&world->className, "Pugl");
+ puglSetString(&world->className, "Pugl");
- return world;
+ return world;
}
void
puglFreeWorld(PuglWorld* const world)
{
- puglFreeWorldInternals(world);
- free(world->className);
- free(world->views);
- free(world);
+ puglFreeWorldInternals(world);
+ free(world->className);
+ free(world->views);
+ free(world);
}
void
puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle)
{
- world->handle = handle;
+ world->handle = handle;
}
PuglWorldHandle
puglGetWorldHandle(PuglWorld* world)
{
- return world->handle;
+ return world->handle;
}
PuglStatus
puglSetClassName(PuglWorld* const world, const char* const name)
{
- puglSetString(&world->className, name);
- return PUGL_SUCCESS;
+ puglSetString(&world->className, name);
+ return PUGL_SUCCESS;
}
PuglView*
puglNewView(PuglWorld* const world)
{
- PuglView* view = (PuglView*)calloc(1, sizeof(PuglView));
- if (!view || !(view->impl = puglInitViewInternals())) {
- free(view);
- return NULL;
- }
+ PuglView* view = (PuglView*)calloc(1, sizeof(PuglView));
+ if (!view || !(view->impl = puglInitViewInternals())) {
+ free(view);
+ return NULL;
+ }
- view->world = world;
- view->minWidth = 1;
- view->minHeight = 1;
+ view->world = world;
+ view->minWidth = 1;
+ view->minHeight = 1;
- puglSetDefaultHints(view->hints);
+ puglSetDefaultHints(view->hints);
- // Add to world view list
- ++world->numViews;
- world->views = (PuglView**)realloc(world->views,
- world->numViews * sizeof(PuglView*));
+ // Add to world view list
+ ++world->numViews;
+ world->views =
+ (PuglView**)realloc(world->views, world->numViews * sizeof(PuglView*));
- world->views[world->numViews - 1] = view;
+ world->views[world->numViews - 1] = view;
- return view;
+ return view;
}
void
puglFreeView(PuglView* view)
{
- puglDispatchSimpleEvent(view, PUGL_DESTROY);
-
- // Remove from world view list
- PuglWorld* world = view->world;
- for (size_t i = 0; i < world->numViews; ++i) {
- if (world->views[i] == view) {
- if (i == world->numViews - 1) {
- world->views[i] = NULL;
- } else {
- memmove(world->views + i, world->views + i + 1,
- sizeof(PuglView*) * (world->numViews - i - 1));
- world->views[world->numViews - 1] = NULL;
- }
- --world->numViews;
- }
- }
-
- free(view->title);
- free(view->clipboard.data);
- puglFreeViewInternals(view);
- free(view);
+ puglDispatchSimpleEvent(view, PUGL_DESTROY);
+
+ // Remove from world view list
+ PuglWorld* world = view->world;
+ for (size_t i = 0; i < world->numViews; ++i) {
+ if (world->views[i] == view) {
+ if (i == world->numViews - 1) {
+ world->views[i] = NULL;
+ } else {
+ memmove(world->views + i,
+ world->views + i + 1,
+ sizeof(PuglView*) * (world->numViews - i - 1));
+ world->views[world->numViews - 1] = NULL;
+ }
+ --world->numViews;
+ }
+ }
+
+ free(view->title);
+ free(view->clipboard.data);
+ puglFreeViewInternals(view);
+ free(view);
}
PuglWorld*
puglGetWorld(PuglView* view)
{
- return view->world;
+ return view->world;
}
PuglStatus
puglSetViewHint(PuglView* view, PuglViewHint hint, int value)
{
- if (value == PUGL_DONT_CARE) {
- switch (hint) {
- case PUGL_USE_COMPAT_PROFILE:
- case PUGL_USE_DEBUG_CONTEXT:
- case PUGL_CONTEXT_VERSION_MAJOR:
- case PUGL_CONTEXT_VERSION_MINOR:
- case PUGL_SWAP_INTERVAL:
- return PUGL_BAD_PARAMETER;
- default:
- break;
- }
- }
+ if (value == PUGL_DONT_CARE) {
+ switch (hint) {
+ case PUGL_USE_COMPAT_PROFILE:
+ case PUGL_USE_DEBUG_CONTEXT:
+ case PUGL_CONTEXT_VERSION_MAJOR:
+ case PUGL_CONTEXT_VERSION_MINOR:
+ case PUGL_SWAP_INTERVAL:
+ return PUGL_BAD_PARAMETER;
+ default:
+ break;
+ }
+ }
- if (hint < PUGL_NUM_VIEW_HINTS) {
- view->hints[hint] = value;
- return PUGL_SUCCESS;
- }
+ if (hint < PUGL_NUM_VIEW_HINTS) {
+ view->hints[hint] = value;
+ return PUGL_SUCCESS;
+ }
- return PUGL_BAD_PARAMETER;
+ return PUGL_BAD_PARAMETER;
}
int
puglGetViewHint(const PuglView* view, PuglViewHint hint)
{
- if (hint < PUGL_NUM_VIEW_HINTS) {
- return view->hints[hint];
- }
+ if (hint < PUGL_NUM_VIEW_HINTS) {
+ return view->hints[hint];
+ }
- return PUGL_DONT_CARE;
+ return PUGL_DONT_CARE;
}
PuglStatus
puglSetParentWindow(PuglView* view, PuglNativeView parent)
{
- view->parent = parent;
- return PUGL_SUCCESS;
+ view->parent = parent;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetBackend(PuglView* view, const PuglBackend* backend)
{
- view->backend = backend;
- return PUGL_SUCCESS;
+ view->backend = backend;
+ return PUGL_SUCCESS;
}
void
puglSetHandle(PuglView* view, PuglHandle handle)
{
- view->handle = handle;
+ view->handle = handle;
}
PuglHandle
puglGetHandle(PuglView* view)
{
- return view->handle;
+ return view->handle;
}
bool
puglGetVisible(const PuglView* view)
{
- return view->visible;
+ return view->visible;
}
PuglRect
puglGetFrame(const PuglView* view)
{
- return view->frame;
+ return view->frame;
}
void*
puglGetContext(PuglView* view)
{
- return view->backend->getContext(view);
+ return view->backend->getContext(view);
}
#ifndef PUGL_DISABLE_DEPRECATED
@@ -275,25 +276,25 @@ puglGetContext(PuglView* view)
PuglStatus
puglPollEvents(PuglWorld* world, double timeout)
{
- return puglUpdate(world, timeout);
+ return puglUpdate(world, timeout);
}
PuglStatus
puglDispatchEvents(PuglWorld* world)
{
- return puglUpdate(world, 0.0);
+ return puglUpdate(world, 0.0);
}
PuglStatus
puglShowWindow(PuglView* view)
{
- return puglShow(view);
+ return puglShow(view);
}
PuglStatus
puglHideWindow(PuglView* view)
{
- return puglHide(view);
+ return puglHide(view);
}
#endif
@@ -301,112 +302,116 @@ puglHideWindow(PuglView* view)
PuglStatus
puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc)
{
- view->eventFunc = eventFunc;
- return PUGL_SUCCESS;
+ view->eventFunc = eventFunc;
+ return PUGL_SUCCESS;
}
/// Return the code point for buf, or the replacement character on error
uint32_t
puglDecodeUTF8(const uint8_t* buf)
{
-#define FAIL_IF(cond) do { if (cond) return 0xFFFD; } while (0)
-
- // 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] & 0xC0u) != 0x80);
- return ((uint32_t)buf[0] << 6u) + buf[1] - 0x3080u;
- } else if (buf[0] < 0xF0) {
- FAIL_IF((buf[1] & 0xC0u) != 0x80);
- FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0);
- FAIL_IF((buf[2] & 0xC0u) != 0x80);
- return ((uint32_t)buf[0] << 12u) + //
- ((uint32_t)buf[1] << 6u) + //
- ((uint32_t)buf[2] - 0xE2080u);
- } else if (buf[0] < 0xF5) {
- FAIL_IF((buf[1] & 0xC0u) != 0x80);
- FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90);
- FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90);
- FAIL_IF((buf[2] & 0xC0u) != 0x80u);
- FAIL_IF((buf[3] & 0xC0u) != 0x80u);
- return (((uint32_t)buf[0] << 18u) + //
- ((uint32_t)buf[1] << 12u) + //
- ((uint32_t)buf[2] << 6u) + //
- ((uint32_t)buf[3] - 0x3C82080u));
- }
- return 0xFFFD;
+#define FAIL_IF(cond) \
+ do { \
+ if (cond) \
+ return 0xFFFD; \
+ } while (0)
+
+ // 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] & 0xC0u) != 0x80);
+ return ((uint32_t)buf[0] << 6u) + buf[1] - 0x3080u;
+ } else if (buf[0] < 0xF0) {
+ FAIL_IF((buf[1] & 0xC0u) != 0x80);
+ FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0);
+ FAIL_IF((buf[2] & 0xC0u) != 0x80);
+ return ((uint32_t)buf[0] << 12u) + //
+ ((uint32_t)buf[1] << 6u) + //
+ ((uint32_t)buf[2] - 0xE2080u);
+ } else if (buf[0] < 0xF5) {
+ FAIL_IF((buf[1] & 0xC0u) != 0x80);
+ FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90);
+ FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90);
+ FAIL_IF((buf[2] & 0xC0u) != 0x80u);
+ FAIL_IF((buf[3] & 0xC0u) != 0x80u);
+ return (((uint32_t)buf[0] << 18u) + //
+ ((uint32_t)buf[1] << 12u) + //
+ ((uint32_t)buf[2] << 6u) + //
+ ((uint32_t)buf[3] - 0x3C82080u));
+ }
+ return 0xFFFD;
}
static inline bool
puglMustConfigure(PuglView* view, const PuglEventConfigure* configure)
{
- return memcmp(configure, &view->lastConfigure, sizeof(PuglEventConfigure));
+ return memcmp(configure, &view->lastConfigure, sizeof(PuglEventConfigure));
}
void
puglDispatchSimpleEvent(PuglView* view, const PuglEventType type)
{
- assert(type == PUGL_CREATE || type == PUGL_DESTROY || type == PUGL_MAP ||
- type == PUGL_UNMAP || type == PUGL_UPDATE || type == PUGL_CLOSE ||
- type == PUGL_LOOP_ENTER || type == PUGL_LOOP_LEAVE);
+ assert(type == PUGL_CREATE || type == PUGL_DESTROY || type == PUGL_MAP ||
+ type == PUGL_UNMAP || type == PUGL_UPDATE || type == PUGL_CLOSE ||
+ type == PUGL_LOOP_ENTER || type == PUGL_LOOP_LEAVE);
- const PuglEvent event = {{type, 0}};
- puglDispatchEvent(view, &event);
+ const PuglEvent event = {{type, 0}};
+ puglDispatchEvent(view, &event);
}
void
puglDispatchEventInContext(PuglView* view, const PuglEvent* event)
{
- if (event->type == PUGL_CONFIGURE) {
- view->frame.x = event->configure.x;
- view->frame.y = event->configure.y;
- view->frame.width = event->configure.width;
- view->frame.height = event->configure.height;
-
- if (puglMustConfigure(view, &event->configure)) {
- view->eventFunc(view, event);
- view->lastConfigure = event->configure;
- }
- } else if (event->type == PUGL_EXPOSE) {
- if (event->expose.width > 0 && event->expose.height > 0) {
- view->eventFunc(view, event);
- }
- } else {
- view->eventFunc(view, event);
- }
+ if (event->type == PUGL_CONFIGURE) {
+ view->frame.x = event->configure.x;
+ view->frame.y = event->configure.y;
+ view->frame.width = event->configure.width;
+ view->frame.height = event->configure.height;
+
+ if (puglMustConfigure(view, &event->configure)) {
+ view->eventFunc(view, event);
+ view->lastConfigure = event->configure;
+ }
+ } else if (event->type == PUGL_EXPOSE) {
+ if (event->expose.width > 0 && event->expose.height > 0) {
+ view->eventFunc(view, event);
+ }
+ } else {
+ view->eventFunc(view, event);
+ }
}
void
puglDispatchEvent(PuglView* view, const PuglEvent* event)
{
- switch (event->type) {
- case PUGL_NOTHING:
- break;
- case PUGL_CREATE:
- case PUGL_DESTROY:
- view->backend->enter(view, NULL);
- view->eventFunc(view, event);
- view->backend->leave(view, NULL);
- break;
- case PUGL_CONFIGURE:
- if (puglMustConfigure(view, &event->configure)) {
- view->backend->enter(view, NULL);
- puglDispatchEventInContext(view, event);
- view->backend->leave(view, NULL);
- }
- break;
- case PUGL_EXPOSE:
- view->backend->enter(view, &event->expose);
- puglDispatchEventInContext(view, event);
- view->backend->leave(view, &event->expose);
- break;
- default:
- view->eventFunc(view, event);
- }
+ switch (event->type) {
+ case PUGL_NOTHING:
+ break;
+ case PUGL_CREATE:
+ case PUGL_DESTROY:
+ view->backend->enter(view, NULL);
+ view->eventFunc(view, event);
+ view->backend->leave(view, NULL);
+ break;
+ case PUGL_CONFIGURE:
+ if (puglMustConfigure(view, &event->configure)) {
+ view->backend->enter(view, NULL);
+ puglDispatchEventInContext(view, event);
+ view->backend->leave(view, NULL);
+ }
+ break;
+ case PUGL_EXPOSE:
+ view->backend->enter(view, &event->expose);
+ puglDispatchEventInContext(view, event);
+ view->backend->leave(view, &event->expose);
+ break;
+ default:
+ view->eventFunc(view, event);
+ }
}
const void*
@@ -414,15 +419,15 @@ puglGetInternalClipboard(const PuglView* const view,
const char** const type,
size_t* const len)
{
- if (len) {
- *len = view->clipboard.len;
- }
+ if (len) {
+ *len = view->clipboard.len;
+ }
- if (type) {
- *type = "text/plain";
- }
+ if (type) {
+ *type = "text/plain";
+ }
- return view->clipboard.data;
+ return view->clipboard.data;
}
PuglStatus
@@ -431,11 +436,10 @@ puglSetInternalClipboard(PuglView* const view,
const void* const data,
const size_t len)
{
- if (type && strcmp(type, "text/plain")) {
- return PUGL_UNSUPPORTED_TYPE;
- }
+ if (type && strcmp(type, "text/plain")) {
+ return PUGL_UNSUPPORTED_TYPE;
+ }
- puglSetBlob(&view->clipboard, data, len);
- return PUGL_SUCCESS;
+ puglSetBlob(&view->clipboard, data, len);
+ return PUGL_SUCCESS;
}
-
diff --git a/src/mac.h b/src/mac.h
index d17c74f..35e6e0d 100644
--- a/src/mac.h
+++ b/src/mac.h
@@ -38,18 +38,18 @@
@end
struct PuglWorldInternalsImpl {
- NSApplication* app;
- NSAutoreleasePool* autoreleasePool;
+ NSApplication* app;
+ NSAutoreleasePool* autoreleasePool;
};
struct PuglInternalsImpl {
- NSApplication* app;
- PuglWrapperView* wrapperView;
- NSView* drawView;
- NSCursor* cursor;
- PuglWindow* window;
- uint32_t mods;
- bool mouseTracked;
+ NSApplication* app;
+ PuglWrapperView* wrapperView;
+ NSView* drawView;
+ NSCursor* cursor;
+ PuglWindow* window;
+ uint32_t mods;
+ bool mouseTracked;
};
#endif // PUGL_DETAIL_MAC_H
diff --git a/src/mac.m b/src/mac.m
index adac2a5..090dd0f 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -40,85 +40,85 @@ typedef NSUInteger NSWindowStyleMask;
static NSRect
rectToScreen(NSScreen* screen, NSRect rect)
{
- const double screenHeight = [screen frame].size.height;
+ const double screenHeight = [screen frame].size.height;
- rect.origin.y = screenHeight - rect.origin.y - rect.size.height;
- return rect;
+ rect.origin.y = screenHeight - rect.origin.y - rect.size.height;
+ return rect;
}
static NSScreen*
viewScreen(PuglView* view)
{
- return view->impl->window ? [view->impl->window screen] : [NSScreen mainScreen];
+ return view->impl->window ? [view->impl->window screen]
+ : [NSScreen mainScreen];
}
static NSRect
nsRectToPoints(PuglView* view, const NSRect rect)
{
- const double scaleFactor = [viewScreen(view) backingScaleFactor];
+ const double scaleFactor = [viewScreen(view) backingScaleFactor];
- return NSMakeRect(rect.origin.x / scaleFactor,
- rect.origin.y / scaleFactor,
- rect.size.width / scaleFactor,
- rect.size.height / scaleFactor);
+ return NSMakeRect(rect.origin.x / scaleFactor,
+ rect.origin.y / scaleFactor,
+ rect.size.width / scaleFactor,
+ rect.size.height / scaleFactor);
}
static NSRect
nsRectFromPoints(PuglView* view, const NSRect rect)
{
- const double scaleFactor = [viewScreen(view) backingScaleFactor];
+ const double scaleFactor = [viewScreen(view) backingScaleFactor];
- return NSMakeRect(rect.origin.x * scaleFactor,
- rect.origin.y * scaleFactor,
- rect.size.width * scaleFactor,
- rect.size.height * scaleFactor);
+ return NSMakeRect(rect.origin.x * scaleFactor,
+ rect.origin.y * scaleFactor,
+ rect.size.width * scaleFactor,
+ rect.size.height * scaleFactor);
}
static NSPoint
nsPointFromPoints(PuglView* view, const NSPoint point)
{
- const double scaleFactor = [viewScreen(view) backingScaleFactor];
+ const double scaleFactor = [viewScreen(view) backingScaleFactor];
- return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor);
+ return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor);
}
static NSRect
rectToNsRect(const PuglRect rect)
{
- return NSMakeRect(rect.x, rect.y, rect.width, rect.height);
+ return NSMakeRect(rect.x, rect.y, rect.width, rect.height);
}
static NSSize
sizePoints(PuglView* view, const double width, const double height)
{
- const double scaleFactor = [viewScreen(view) backingScaleFactor];
+ const double scaleFactor = [viewScreen(view) backingScaleFactor];
- return NSMakeSize(width / scaleFactor, height / scaleFactor);
+ return NSMakeSize(width / scaleFactor, height / scaleFactor);
}
static void
updateViewRect(PuglView* view)
{
- NSWindow* const window = view->impl->window;
- if (window) {
- const NSRect screenFramePt = [[NSScreen mainScreen] frame];
- const NSRect screenFramePx = nsRectFromPoints(view, screenFramePt);
- const NSRect framePt = [window frame];
- const NSRect contentPt = [window contentRectForFrameRect:framePt];
- const NSRect contentPx = nsRectFromPoints(view, contentPt);
- const double screenHeight = screenFramePx.size.height;
+ NSWindow* const window = view->impl->window;
+ if (window) {
+ const NSRect screenFramePt = [[NSScreen mainScreen] frame];
+ const NSRect screenFramePx = nsRectFromPoints(view, screenFramePt);
+ const NSRect framePt = [window frame];
+ const NSRect contentPt = [window contentRectForFrameRect:framePt];
+ const NSRect contentPx = nsRectFromPoints(view, contentPt);
+ const double screenHeight = screenFramePx.size.height;
- view->frame.x = contentPx.origin.x;
- view->frame.y = screenHeight - contentPx.origin.y - contentPx.size.height;
- view->frame.width = contentPx.size.width;
- view->frame.height = contentPx.size.height;
- }
+ view->frame.x = contentPx.origin.x;
+ view->frame.y = screenHeight - contentPx.origin.y - contentPx.size.height;
+ view->frame.width = contentPx.size.width;
+ view->frame.height = contentPx.size.height;
+ }
}
-@implementation PuglWindow
-{
+@implementation PuglWindow {
@public
- PuglView* puglview;
+ PuglView* puglview;
}
- (id)initWithContentRect:(NSRect)contentRect
@@ -126,617 +126,638 @@ updateViewRect(PuglView* view)
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)flag
{
- (void)flag;
+ (void)flag;
- NSWindow* result = [super initWithContentRect:contentRect
- styleMask:aStyle
- backing:bufferingType
- defer:NO];
+ NSWindow* result = [super initWithContentRect:contentRect
+ styleMask:aStyle
+ backing:bufferingType
+ defer:NO];
- [result setAcceptsMouseMovedEvents:YES];
- return (PuglWindow*)result;
+ [result setAcceptsMouseMovedEvents:YES];
+ return (PuglWindow*)result;
}
- (void)setPuglview:(PuglView*)view
{
- puglview = view;
+ puglview = view;
- [self
- setContentSize:sizePoints(view, view->frame.width, view->frame.height)];
+ [self setContentSize:sizePoints(view, view->frame.width, view->frame.height)];
}
- (BOOL)canBecomeKeyWindow
{
- return YES;
+ return YES;
}
- (BOOL)canBecomeMainWindow
{
- return YES;
+ return YES;
}
- (void)setIsVisible:(BOOL)flag
{
- if (flag && !puglview->visible) {
- const PuglEventConfigure ev = {
- PUGL_CONFIGURE,
- 0,
- puglview->frame.x,
- puglview->frame.y,
- puglview->frame.width,
- puglview->frame.height,
- };
+ if (flag && !puglview->visible) {
+ const PuglEventConfigure ev = {
+ PUGL_CONFIGURE,
+ 0,
+ puglview->frame.x,
+ puglview->frame.y,
+ puglview->frame.width,
+ puglview->frame.height,
+ };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
- puglDispatchSimpleEvent(puglview, PUGL_MAP);
- } else if (!flag && puglview->visible) {
- puglDispatchSimpleEvent(puglview, PUGL_UNMAP);
- }
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ puglDispatchSimpleEvent(puglview, PUGL_MAP);
+ } else if (!flag && puglview->visible) {
+ puglDispatchSimpleEvent(puglview, PUGL_UNMAP);
+ }
- puglview->visible = flag;
+ puglview->visible = flag;
- [super setIsVisible:flag];
+ [super setIsVisible:flag];
}
@end
-@implementation PuglWrapperView
-{
+@implementation PuglWrapperView {
@public
- PuglView* puglview;
- NSTrackingArea* trackingArea;
- NSMutableAttributedString* markedText;
- NSMutableDictionary* userTimers;
- bool reshaped;
+ PuglView* puglview;
+ NSTrackingArea* trackingArea;
+ NSMutableAttributedString* markedText;
+ NSMutableDictionary* userTimers;
+ bool reshaped;
}
- (void)dispatchExpose:(NSRect)rect
{
- const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor];
+ const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor];
- if (reshaped) {
- updateViewRect(puglview);
+ if (reshaped) {
+ updateViewRect(puglview);
- const PuglEventConfigure ev = {
- PUGL_CONFIGURE,
- 0,
- puglview->frame.x,
- puglview->frame.y,
- puglview->frame.width,
- puglview->frame.height,
- };
+ const PuglEventConfigure ev = {
+ PUGL_CONFIGURE,
+ 0,
+ puglview->frame.x,
+ puglview->frame.y,
+ puglview->frame.width,
+ puglview->frame.height,
+ };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
- reshaped = false;
- }
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ reshaped = false;
+ }
- if (![[puglview->impl->drawView window] isVisible]) {
- return;
- }
+ if (![[puglview->impl->drawView window] isVisible]) {
+ return;
+ }
- const PuglEventExpose ev = {
- PUGL_EXPOSE,
- 0,
- rect.origin.x * scaleFactor,
- rect.origin.y * scaleFactor,
- rect.size.width * scaleFactor,
- rect.size.height * scaleFactor,
- };
+ const PuglEventExpose ev = {
+ PUGL_EXPOSE,
+ 0,
+ rect.origin.x * scaleFactor,
+ rect.origin.y * scaleFactor,
+ rect.size.width * scaleFactor,
+ rect.size.height * scaleFactor,
+ };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (NSSize)intrinsicContentSize
{
- if (puglview->defaultWidth || puglview->defaultHeight) {
- return sizePoints(puglview,
- puglview->defaultWidth,
- puglview->defaultHeight);
- }
+ if (puglview->defaultWidth || puglview->defaultHeight) {
+ return sizePoints(
+ puglview, puglview->defaultWidth, puglview->defaultHeight);
+ }
- return NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric);
+ return NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric);
}
- (BOOL)isFlipped
{
- return YES;
+ return YES;
}
- (BOOL)acceptsFirstResponder
{
- return YES;
+ return YES;
}
- (void)setReshaped
{
- reshaped = true;
+ reshaped = true;
}
static uint32_t
getModifiers(const NSEvent* const ev)
{
- const NSEventModifierFlags modifierFlags = [ev modifierFlags];
+ const NSEventModifierFlags modifierFlags = [ev modifierFlags];
- return (((modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0) |
- ((modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0) |
- ((modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0) |
- ((modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0));
+ return (((modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0) |
+ ((modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0) |
+ ((modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0) |
+ ((modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0));
}
static PuglKey
keySymToSpecial(const NSEvent* const ev)
{
- NSString* chars = [ev charactersIgnoringModifiers];
- if ([chars length] == 1) {
- switch ([chars characterAtIndex:0]) {
- case NSF1FunctionKey: return PUGL_KEY_F1;
- case NSF2FunctionKey: return PUGL_KEY_F2;
- case NSF3FunctionKey: return PUGL_KEY_F3;
- case NSF4FunctionKey: return PUGL_KEY_F4;
- case NSF5FunctionKey: return PUGL_KEY_F5;
- case NSF6FunctionKey: return PUGL_KEY_F6;
- case NSF7FunctionKey: return PUGL_KEY_F7;
- case NSF8FunctionKey: return PUGL_KEY_F8;
- case NSF9FunctionKey: return PUGL_KEY_F9;
- case NSF10FunctionKey: return PUGL_KEY_F10;
- case NSF11FunctionKey: return PUGL_KEY_F11;
- case NSF12FunctionKey: return PUGL_KEY_F12;
- case NSDeleteCharacter: return PUGL_KEY_BACKSPACE;
- case NSDeleteFunctionKey: return PUGL_KEY_DELETE;
- case NSLeftArrowFunctionKey: return PUGL_KEY_LEFT;
- case NSUpArrowFunctionKey: return PUGL_KEY_UP;
- case NSRightArrowFunctionKey: return PUGL_KEY_RIGHT;
- case NSDownArrowFunctionKey: return PUGL_KEY_DOWN;
- case NSPageUpFunctionKey: return PUGL_KEY_PAGE_UP;
- case NSPageDownFunctionKey: return PUGL_KEY_PAGE_DOWN;
- case NSHomeFunctionKey: return PUGL_KEY_HOME;
- case NSEndFunctionKey: return PUGL_KEY_END;
- case NSInsertFunctionKey: return PUGL_KEY_INSERT;
- case NSMenuFunctionKey: return PUGL_KEY_MENU;
- case NSScrollLockFunctionKey: return PUGL_KEY_SCROLL_LOCK;
- case NSClearLineFunctionKey: return PUGL_KEY_NUM_LOCK;
- case NSPrintScreenFunctionKey: return PUGL_KEY_PRINT_SCREEN;
- case NSPauseFunctionKey: return PUGL_KEY_PAUSE;
- }
- // SHIFT, CTRL, ALT, and SUPER are handled in [flagsChanged]
- }
- return (PuglKey)0;
+ NSString* chars = [ev charactersIgnoringModifiers];
+ if ([chars length] == 1) {
+ switch ([chars characterAtIndex:0]) {
+ case NSF1FunctionKey:
+ return PUGL_KEY_F1;
+ case NSF2FunctionKey:
+ return PUGL_KEY_F2;
+ case NSF3FunctionKey:
+ return PUGL_KEY_F3;
+ case NSF4FunctionKey:
+ return PUGL_KEY_F4;
+ case NSF5FunctionKey:
+ return PUGL_KEY_F5;
+ case NSF6FunctionKey:
+ return PUGL_KEY_F6;
+ case NSF7FunctionKey:
+ return PUGL_KEY_F7;
+ case NSF8FunctionKey:
+ return PUGL_KEY_F8;
+ case NSF9FunctionKey:
+ return PUGL_KEY_F9;
+ case NSF10FunctionKey:
+ return PUGL_KEY_F10;
+ case NSF11FunctionKey:
+ return PUGL_KEY_F11;
+ case NSF12FunctionKey:
+ return PUGL_KEY_F12;
+ case NSDeleteCharacter:
+ return PUGL_KEY_BACKSPACE;
+ case NSDeleteFunctionKey:
+ return PUGL_KEY_DELETE;
+ case NSLeftArrowFunctionKey:
+ return PUGL_KEY_LEFT;
+ case NSUpArrowFunctionKey:
+ return PUGL_KEY_UP;
+ case NSRightArrowFunctionKey:
+ return PUGL_KEY_RIGHT;
+ case NSDownArrowFunctionKey:
+ return PUGL_KEY_DOWN;
+ case NSPageUpFunctionKey:
+ return PUGL_KEY_PAGE_UP;
+ case NSPageDownFunctionKey:
+ return PUGL_KEY_PAGE_DOWN;
+ case NSHomeFunctionKey:
+ return PUGL_KEY_HOME;
+ case NSEndFunctionKey:
+ return PUGL_KEY_END;
+ case NSInsertFunctionKey:
+ return PUGL_KEY_INSERT;
+ case NSMenuFunctionKey:
+ return PUGL_KEY_MENU;
+ case NSScrollLockFunctionKey:
+ return PUGL_KEY_SCROLL_LOCK;
+ case NSClearLineFunctionKey:
+ return PUGL_KEY_NUM_LOCK;
+ case NSPrintScreenFunctionKey:
+ return PUGL_KEY_PRINT_SCREEN;
+ case NSPauseFunctionKey:
+ return PUGL_KEY_PAUSE;
+ }
+ // SHIFT, CTRL, ALT, and SUPER are handled in [flagsChanged]
+ }
+ return (PuglKey)0;
}
- (void)updateTrackingAreas
{
- if (trackingArea != nil) {
- [self removeTrackingArea:trackingArea];
- [trackingArea release];
- }
+ if (trackingArea != nil) {
+ [self removeTrackingArea:trackingArea];
+ [trackingArea release];
+ }
- const int opts = (NSTrackingMouseEnteredAndExited |
- NSTrackingMouseMoved |
- NSTrackingActiveAlways);
- trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
- options:opts
- owner:self
- userInfo:nil];
- [self addTrackingArea:trackingArea];
- [super updateTrackingAreas];
+ const int opts = (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
+ NSTrackingActiveAlways);
+ trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
+ options:opts
+ owner:self
+ userInfo:nil];
+ [self addTrackingArea:trackingArea];
+ [super updateTrackingAreas];
}
- (NSPoint)eventLocation:(NSEvent*)event
{
- return nsPointFromPoints(puglview,
- [self convertPoint:[event locationInWindow]
- fromView:nil]);
+ return nsPointFromPoints(
+ puglview, [self convertPoint:[event locationInWindow] fromView:nil]);
}
static void
handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
{
- const NSPoint wloc = [view eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventCrossing ev = {
- type,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- PUGL_CROSSING_NORMAL,
- };
+ const NSPoint wloc = [view eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const PuglEventCrossing ev = {
+ type,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ PUGL_CROSSING_NORMAL,
+ };
- puglDispatchEvent(view->puglview, (const PuglEvent*)&ev);
+ puglDispatchEvent(view->puglview, (const PuglEvent*)&ev);
}
- (void)mouseEntered:(NSEvent*)event
{
- handleCrossing(self, event, PUGL_POINTER_IN);
- [puglview->impl->cursor set];
- puglview->impl->mouseTracked = true;
+ handleCrossing(self, event, PUGL_POINTER_IN);
+ [puglview->impl->cursor set];
+ puglview->impl->mouseTracked = true;
}
- (void)mouseExited:(NSEvent*)event
{
- [[NSCursor arrowCursor] set];
- handleCrossing(self, event, PUGL_POINTER_OUT);
- puglview->impl->mouseTracked = false;
+ [[NSCursor arrowCursor] set];
+ handleCrossing(self, event, PUGL_POINTER_OUT);
+ puglview->impl->mouseTracked = false;
}
- (void)cursorUpdate:(NSEvent*)event
{
- (void)event;
- [puglview->impl->cursor set];
+ (void)event;
+ [puglview->impl->cursor set];
}
- (void)mouseMoved:(NSEvent*)event
{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventMotion ev = {
- PUGL_MOTION,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- };
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const PuglEventMotion ev = {
+ PUGL_MOTION,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (void)mouseDragged:(NSEvent*)event
{
- [self mouseMoved: event];
+ [self mouseMoved:event];
}
- (void)rightMouseDragged:(NSEvent*)event
{
- [self mouseMoved: event];
+ [self mouseMoved:event];
}
- (void)otherMouseDragged:(NSEvent*)event
{
- [self mouseMoved: event];
+ [self mouseMoved:event];
}
- (void)mouseDown:(NSEvent*)event
{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventButton ev = {
- PUGL_BUTTON_PRESS,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- (uint32_t)[event buttonNumber] + 1,
- };
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const PuglEventButton ev = {
+ PUGL_BUTTON_PRESS,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ (uint32_t)[event buttonNumber] + 1,
+ };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (void)mouseUp:(NSEvent*)event
{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglEventButton ev = {
- PUGL_BUTTON_RELEASE,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- (uint32_t)[event buttonNumber] + 1,
- };
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const PuglEventButton ev = {
+ PUGL_BUTTON_RELEASE,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ (uint32_t)[event buttonNumber] + 1,
+ };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (void)rightMouseDown:(NSEvent*)event
{
- [self mouseDown: event];
+ [self mouseDown:event];
}
- (void)rightMouseUp:(NSEvent*)event
{
- [self mouseUp: event];
+ [self mouseUp:event];
}
- (void)otherMouseDown:(NSEvent*)event
{
- [self mouseDown: event];
+ [self mouseDown:event];
}
- (void)otherMouseUp:(NSEvent*)event
{
- [self mouseUp: event];
+ [self mouseUp:event];
}
- (void)scrollWheel:(NSEvent*)event
{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const double dx = [event scrollingDeltaX];
- const double dy = [event scrollingDeltaY];
- const PuglScrollDirection dir =
- ((dx == 0.0 && dy > 0.0)
- ? PUGL_SCROLL_UP
- : ((dx == 0.0 && dy < 0.0)
- ? PUGL_SCROLL_DOWN
- : ((dy == 0.0 && dx > 0.0)
- ? PUGL_SCROLL_RIGHT
- : ((dy == 0.0 && dx < 0.0) ? PUGL_SCROLL_LEFT
- : PUGL_SCROLL_SMOOTH))));
-
- const PuglEventScroll ev = {
- PUGL_SCROLL,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir,
- dx,
- dy,
- };
-
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const double dx = [event scrollingDeltaX];
+ const double dy = [event scrollingDeltaY];
+ const PuglScrollDirection dir =
+ ((dx == 0.0 && dy > 0.0)
+ ? PUGL_SCROLL_UP
+ : ((dx == 0.0 && dy < 0.0)
+ ? PUGL_SCROLL_DOWN
+ : ((dy == 0.0 && dx > 0.0)
+ ? PUGL_SCROLL_RIGHT
+ : ((dy == 0.0 && dx < 0.0) ? PUGL_SCROLL_LEFT
+ : PUGL_SCROLL_SMOOTH))));
+
+ const PuglEventScroll ev = {
+ PUGL_SCROLL,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir,
+ dx,
+ dy,
+ };
+
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (void)keyDown:(NSEvent*)event
{
- if (puglview->hints[PUGL_IGNORE_KEY_REPEAT] && [event isARepeat]) {
- return;
- }
-
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglKey spec = keySymToSpecial(event);
- const NSString* chars = [event charactersIgnoringModifiers];
- const char* str = [[chars lowercaseString] UTF8String];
- const uint32_t code = (spec ? spec : puglDecodeUTF8((const uint8_t*)str));
-
- const PuglEventKey ev = {
- PUGL_KEY_PRESS,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- [event keyCode],
- (code != 0xFFFD) ? code : 0,
- };
-
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
-
- if (!spec) {
- [self interpretKeyEvents:@[event]];
- }
+ if (puglview->hints[PUGL_IGNORE_KEY_REPEAT] && [event isARepeat]) {
+ return;
+ }
+
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const PuglKey spec = keySymToSpecial(event);
+ const NSString* chars = [event charactersIgnoringModifiers];
+ const char* str = [[chars lowercaseString] UTF8String];
+ const uint32_t code = (spec ? spec : puglDecodeUTF8((const uint8_t*)str));
+
+ const PuglEventKey ev = {
+ PUGL_KEY_PRESS,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ [event keyCode],
+ (code != 0xFFFD) ? code : 0,
+ };
+
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+
+ if (!spec) {
+ [self interpretKeyEvents:@[event]];
+ }
}
- (void)keyUp:(NSEvent*)event
{
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- const PuglKey spec = keySymToSpecial(event);
- const NSString* chars = [event charactersIgnoringModifiers];
- const char* str = [[chars lowercaseString] UTF8String];
- const uint32_t code = (spec ? spec : puglDecodeUTF8((const uint8_t*)str));
-
- const PuglEventKey ev = {
- PUGL_KEY_RELEASE,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- [event keyCode],
- (code != 0xFFFD) ? code : 0,
- };
-
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ const PuglKey spec = keySymToSpecial(event);
+ const NSString* chars = [event charactersIgnoringModifiers];
+ const char* str = [[chars lowercaseString] UTF8String];
+ const uint32_t code = (spec ? spec : puglDecodeUTF8((const uint8_t*)str));
+
+ const PuglEventKey ev = {
+ PUGL_KEY_RELEASE,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ [event keyCode],
+ (code != 0xFFFD) ? code : 0,
+ };
+
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (BOOL)hasMarkedText
{
- return [markedText length] > 0;
+ return [markedText length] > 0;
}
- (NSRange)markedRange
{
- return (([markedText length] > 0)
- ? NSMakeRange(0, [markedText length] - 1)
- : NSMakeRange(NSNotFound, 0));
+ return (([markedText length] > 0) ? NSMakeRange(0, [markedText length] - 1)
+ : NSMakeRange(NSNotFound, 0));
}
- (NSRange)selectedRange
{
- return NSMakeRange(NSNotFound, 0);
+ return NSMakeRange(NSNotFound, 0);
}
- (void)setMarkedText:(id)string
selectedRange:(NSRange)selected
replacementRange:(NSRange)replacement
{
- (void)selected;
- (void)replacement;
- [markedText release];
- markedText = (
- [(NSObject*)string isKindOfClass:[NSAttributedString class]]
- ? [[NSMutableAttributedString alloc] initWithAttributedString:string]
- : [[NSMutableAttributedString alloc] initWithString:string]);
+ (void)selected;
+ (void)replacement;
+ [markedText release];
+ markedText =
+ ([(NSObject*)string isKindOfClass:[NSAttributedString class]]
+ ? [[NSMutableAttributedString alloc] initWithAttributedString:string]
+ : [[NSMutableAttributedString alloc] initWithString:string]);
}
- (void)unmarkText
{
- [[markedText mutableString] setString:@""];
+ [[markedText mutableString] setString:@""];
}
- (NSArray*)validAttributesForMarkedText
{
- return @[];
+ return @[];
}
- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
actualRange:
- (NSRangePointer)actual
+ (NSRangePointer)actual
{
- (void)range;
- (void)actual;
- return nil;
+ (void)range;
+ (void)actual;
+ return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point
{
- (void)point;
- return 0;
+ (void)point;
+ return 0;
}
- (NSRect)firstRectForCharacterRange:(NSRange)range
actualRange:(NSRangePointer)actual
{
- (void)range;
- (void)actual;
+ (void)range;
+ (void)actual;
- const NSRect frame = [self bounds];
- return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0);
+ const NSRect frame = [self bounds];
+ return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0);
}
- (void)doCommandBySelector:(SEL)selector
{
- (void)selector;
+ (void)selector;
}
- (void)insertText:(id)string replacementRange:(NSRange)replacement
{
- (void)replacement;
-
- NSEvent* const event = [NSApp currentEvent];
- NSString* const characters =
- ([(NSObject*)string isKindOfClass:[NSAttributedString class]]
- ? [(NSAttributedString*)string string]
- : (NSString*)string);
-
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- for (size_t i = 0; i < [characters length]; ++i) {
- const uint32_t code = [characters characterAtIndex:i];
- char utf8[8] = {0};
- NSUInteger len = 0;
-
- [characters getBytes:utf8
- maxLength:sizeof(utf8)
- usedLength:&len
- encoding:NSUTF8StringEncoding
- options:0
- range:NSMakeRange(i, i + 1)
- remainingRange:nil];
-
- PuglEventText ev = {
- PUGL_TEXT,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- getModifiers(event),
- [event keyCode],
- code,
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- };
-
- memcpy(ev.string, utf8, len);
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
- }
+ (void)replacement;
+
+ NSEvent* const event = [NSApp currentEvent];
+ NSString* const characters =
+ ([(NSObject*)string isKindOfClass:[NSAttributedString class]]
+ ? [(NSAttributedString*)string string]
+ : (NSString*)string);
+
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ for (size_t i = 0; i < [characters length]; ++i) {
+ const uint32_t code = [characters characterAtIndex:i];
+ char utf8[8] = {0};
+ NSUInteger len = 0;
+
+ [characters getBytes:utf8
+ maxLength:sizeof(utf8)
+ usedLength:&len
+ encoding:NSUTF8StringEncoding
+ options:0
+ range:NSMakeRange(i, i + 1)
+ remainingRange:nil];
+
+ PuglEventText ev = {
+ PUGL_TEXT,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ getModifiers(event),
+ [event keyCode],
+ code,
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ };
+
+ memcpy(ev.string, utf8, len);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ }
}
- (void)flagsChanged:(NSEvent*)event
{
- const uint32_t mods = getModifiers(event);
- PuglEventType type = PUGL_NOTHING;
- PuglKey special = (PuglKey)0;
-
- if ((mods & PUGL_MOD_SHIFT) != (puglview->impl->mods & PUGL_MOD_SHIFT)) {
- type = mods & PUGL_MOD_SHIFT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
- special = PUGL_KEY_SHIFT;
- } else if ((mods & PUGL_MOD_CTRL) != (puglview->impl->mods & PUGL_MOD_CTRL)) {
- type = mods & PUGL_MOD_CTRL ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
- special = PUGL_KEY_CTRL;
- } else if ((mods & PUGL_MOD_ALT) != (puglview->impl->mods & PUGL_MOD_ALT)) {
- type = mods & PUGL_MOD_ALT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
- special = PUGL_KEY_ALT;
- } else if ((mods & PUGL_MOD_SUPER) != (puglview->impl->mods & PUGL_MOD_SUPER)) {
- type = mods & PUGL_MOD_SUPER ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
- special = PUGL_KEY_SUPER;
- }
-
- if (special != 0) {
- const NSPoint wloc = [self eventLocation:event];
- const NSPoint rloc = [NSEvent mouseLocation];
- PuglEventKey ev = {
- type,
- 0,
- [event timestamp],
- wloc.x,
- wloc.y,
- rloc.x,
- [[NSScreen mainScreen] frame].size.height - rloc.y,
- mods,
- [event keyCode],
- special
- };
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
- }
-
- puglview->impl->mods = mods;
+ const uint32_t mods = getModifiers(event);
+ PuglEventType type = PUGL_NOTHING;
+ PuglKey special = (PuglKey)0;
+
+ if ((mods & PUGL_MOD_SHIFT) != (puglview->impl->mods & PUGL_MOD_SHIFT)) {
+ type = mods & PUGL_MOD_SHIFT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
+ special = PUGL_KEY_SHIFT;
+ } else if ((mods & PUGL_MOD_CTRL) != (puglview->impl->mods & PUGL_MOD_CTRL)) {
+ type = mods & PUGL_MOD_CTRL ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
+ special = PUGL_KEY_CTRL;
+ } else if ((mods & PUGL_MOD_ALT) != (puglview->impl->mods & PUGL_MOD_ALT)) {
+ type = mods & PUGL_MOD_ALT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
+ special = PUGL_KEY_ALT;
+ } else if ((mods & PUGL_MOD_SUPER) !=
+ (puglview->impl->mods & PUGL_MOD_SUPER)) {
+ type = mods & PUGL_MOD_SUPER ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
+ special = PUGL_KEY_SUPER;
+ }
+
+ if (special != 0) {
+ const NSPoint wloc = [self eventLocation:event];
+ const NSPoint rloc = [NSEvent mouseLocation];
+ PuglEventKey ev = {type,
+ 0,
+ [event timestamp],
+ wloc.x,
+ wloc.y,
+ rloc.x,
+ [[NSScreen mainScreen] frame].size.height - rloc.y,
+ mods,
+ [event keyCode],
+ special};
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ }
+
+ puglview->impl->mods = mods;
}
- (BOOL)preservesContentInLiveResize
{
- return NO;
+ return NO;
}
- (void)viewWillStartLiveResize
{
- puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER);
+ puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER);
}
- (void)viewWillDraw
{
- puglDispatchSimpleEvent(puglview, PUGL_UPDATE);
- [super viewWillDraw];
+ puglDispatchSimpleEvent(puglview, PUGL_UPDATE);
+ [super viewWillDraw];
}
- (void)resizeTick
{
- puglPostRedisplay(puglview);
+ puglPostRedisplay(puglview);
}
- (void)timerTick:(NSTimer*)userTimer
{
- const NSNumber* userInfo = userTimer.userInfo;
- const PuglEventTimer ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue};
+ const NSNumber* userInfo = userTimer.userInfo;
+ const PuglEventTimer ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue};
- puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
}
- (void)viewDidEndLiveResize
{
- puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE);
+ puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE);
}
@end
@@ -747,51 +768,50 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
@end
-@implementation PuglWindowDelegate
-{
- PuglWindow* window;
+@implementation PuglWindowDelegate {
+ PuglWindow* window;
}
- (instancetype)initWithPuglWindow:(PuglWindow*)puglWindow
{
- if ((self = [super init])) {
- window = puglWindow;
- }
+ if ((self = [super init])) {
+ window = puglWindow;
+ }
- return self;
+ return self;
}
- (BOOL)windowShouldClose:(id)sender
{
- (void)sender;
+ (void)sender;
- puglDispatchSimpleEvent(window->puglview, PUGL_CLOSE);
- return YES;
+ puglDispatchSimpleEvent(window->puglview, PUGL_CLOSE);
+ return YES;
}
- (void)windowDidMove:(NSNotification*)notification
{
- (void)notification;
+ (void)notification;
- updateViewRect(window->puglview);
+ updateViewRect(window->puglview);
}
- (void)windowDidBecomeKey:(NSNotification*)notification
{
- (void)notification;
+ (void)notification;
- PuglEvent ev = {{PUGL_FOCUS_IN, 0}};
- ev.focus.mode = PUGL_CROSSING_NORMAL;
- puglDispatchEvent(window->puglview, &ev);
+ PuglEvent ev = {{PUGL_FOCUS_IN, 0}};
+ ev.focus.mode = PUGL_CROSSING_NORMAL;
+ puglDispatchEvent(window->puglview, &ev);
}
- (void)windowDidResignKey:(NSNotification*)notification
{
- (void)notification;
+ (void)notification;
- PuglEvent ev = {{PUGL_FOCUS_OUT, 0}};
- ev.focus.mode = PUGL_CROSSING_NORMAL;
- puglDispatchEvent(window->puglview, &ev);
+ PuglEvent ev = {{PUGL_FOCUS_OUT, 0}};
+ ev.focus.mode = PUGL_CROSSING_NORMAL;
+ puglDispatchEvent(window->puglview, &ev);
}
@end
@@ -799,532 +819,526 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
PuglWorldInternals*
puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags))
{
- PuglWorldInternals* impl = (PuglWorldInternals*)calloc(
- 1, sizeof(PuglWorldInternals));
+ PuglWorldInternals* impl =
+ (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals));
- impl->app = [NSApplication sharedApplication];
+ impl->app = [NSApplication sharedApplication];
- if (type == PUGL_PROGRAM) {
- impl->autoreleasePool = [NSAutoreleasePool new];
- }
+ if (type == PUGL_PROGRAM) {
+ impl->autoreleasePool = [NSAutoreleasePool new];
+ }
- return impl;
+ return impl;
}
void
puglFreeWorldInternals(PuglWorld* world)
{
- if (world->impl->autoreleasePool) {
- [world->impl->autoreleasePool drain];
- }
+ if (world->impl->autoreleasePool) {
+ [world->impl->autoreleasePool drain];
+ }
- free(world->impl);
+ free(world->impl);
}
void*
puglGetNativeWorld(PuglWorld* PUGL_UNUSED(world))
{
- return NULL;
+ return NULL;
}
PuglInternals*
puglInitViewInternals(void)
{
- PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
- impl->cursor = [NSCursor arrowCursor];
+ impl->cursor = [NSCursor arrowCursor];
- return impl;
+ return impl;
}
static NSLayoutConstraint*
puglConstraint(id item, NSLayoutAttribute attribute, float constant)
{
- return [NSLayoutConstraint
- constraintWithItem: item
- attribute: attribute
- relatedBy: NSLayoutRelationGreaterThanOrEqual
- toItem: nil
- attribute: NSLayoutAttributeNotAnAttribute
- multiplier: 1.0
- constant: (CGFloat)constant];
+ return
+ [NSLayoutConstraint constraintWithItem:item
+ attribute:attribute
+ relatedBy:NSLayoutRelationGreaterThanOrEqual
+ toItem:nil
+ attribute:NSLayoutAttributeNotAnAttribute
+ multiplier:1.0
+ constant:(CGFloat)constant];
}
PuglStatus
puglRealize(PuglView* view)
{
- PuglInternals* impl = view->impl;
- if (impl->wrapperView) {
- return PUGL_FAILURE;
- }
-
- 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;
- }
-
- CGDirectDisplayID displayId = CGMainDisplayID();
- CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
-
- // Try to get refresh rate from mode (usually fails)
- view->hints[PUGL_REFRESH_RATE] = (int)CGDisplayModeGetRefreshRate(mode);
-
- CGDisplayModeRelease(mode);
- if (view->hints[PUGL_REFRESH_RATE] == 0) {
- // Get refresh rate from a display link
- // TODO: Keep and actually use the display link for something?
- CVDisplayLinkRef link;
- CVDisplayLinkCreateWithCGDisplay(displayId, &link);
-
- const CVTime p = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
- const double r = p.timeScale / (double)p.timeValue;
- view->hints[PUGL_REFRESH_RATE] = (int)lrint(r);
-
- CVDisplayLinkRelease(link);
- }
-
- if (view->frame.width == 0.0 && view->frame.height == 0.0) {
- if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) {
- return PUGL_BAD_CONFIGURATION;
- }
-
- const double screenWidthPx = [screen frame].size.width * scaleFactor;
- const double screenHeightPx = [screen frame].size.height * scaleFactor;
-
- view->frame.width = view->defaultWidth;
- view->frame.height = view->defaultHeight;
- view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0;
- view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0;
- }
-
- const NSRect framePx = rectToNsRect(view->frame);
- const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor,
- framePx.origin.y / scaleFactor,
- framePx.size.width / scaleFactor,
- framePx.size.height / scaleFactor);
-
- // Create wrapper view to handle input
- impl->wrapperView = [PuglWrapperView alloc];
- impl->wrapperView->puglview = view;
- impl->wrapperView->userTimers = [[NSMutableDictionary alloc] init];
- impl->wrapperView->markedText = [[NSMutableAttributedString alloc] init];
- [impl->wrapperView setAutoresizesSubviews:YES];
- [impl->wrapperView initWithFrame:framePt];
- [impl->wrapperView addConstraint:
- puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, view->minWidth)];
- [impl->wrapperView addConstraint:
- puglConstraint(impl->wrapperView, NSLayoutAttributeHeight, view->minHeight)];
-
- // Create draw view to be rendered to
- PuglStatus st = PUGL_SUCCESS;
- if ((st = view->backend->configure(view)) ||
- (st = view->backend->create(view))) {
- return st;
- }
-
- // Add draw view to wrapper view
- [impl->wrapperView addSubview:impl->drawView];
- [impl->wrapperView setHidden:NO];
- [impl->drawView setHidden:NO];
-
- if (view->parent) {
- NSView* pview = (NSView*)view->parent;
- [pview addSubview:impl->wrapperView];
- [impl->drawView setHidden:NO];
- [[impl->drawView window] makeFirstResponder:impl->wrapperView];
- } else {
- unsigned style = (NSClosableWindowMask |
- NSTitledWindowMask |
- NSMiniaturizableWindowMask );
- if (view->hints[PUGL_RESIZABLE]) {
- style |= NSResizableWindowMask;
- }
-
- PuglWindow* window = [[[PuglWindow alloc]
- initWithContentRect:rectToScreen([NSScreen mainScreen], framePt)
- styleMask:style
- backing:NSBackingStoreBuffered
- defer:NO
- ] retain];
- [window setPuglview:view];
-
- if (view->title) {
- NSString* titleString = [[NSString alloc]
- initWithBytes:view->title
- length:strlen(view->title)
- encoding:NSUTF8StringEncoding];
-
- [window setTitle:titleString];
- }
-
- if (view->minWidth || view->minHeight) {
- [window setContentMinSize:sizePoints(view,
- view->minWidth,
- view->minHeight)];
- }
- impl->window = window;
-
- ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc]
- initWithPuglWindow:window];
-
- if (view->minAspectX && view->minAspectY) {
- [window setContentAspectRatio:sizePoints(view,
- view->minAspectX,
- view->minAspectY)];
- }
-
- puglSetFrame(view, view->frame);
-
- [window setContentView:impl->wrapperView];
- [view->world->impl->app activateIgnoringOtherApps:YES];
- [window makeFirstResponder:impl->wrapperView];
- [window makeKeyAndOrderFront:window];
- [impl->window setIsVisible:NO];
- }
-
- [impl->wrapperView updateTrackingAreas];
-
- puglDispatchSimpleEvent(view, PUGL_CREATE);
-
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+ if (impl->wrapperView) {
+ return PUGL_FAILURE;
+ }
+
+ 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;
+ }
+
+ CGDirectDisplayID displayId = CGMainDisplayID();
+ CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
+
+ // Try to get refresh rate from mode (usually fails)
+ view->hints[PUGL_REFRESH_RATE] = (int)CGDisplayModeGetRefreshRate(mode);
+
+ CGDisplayModeRelease(mode);
+ if (view->hints[PUGL_REFRESH_RATE] == 0) {
+ // Get refresh rate from a display link
+ // TODO: Keep and actually use the display link for something?
+ CVDisplayLinkRef link;
+ CVDisplayLinkCreateWithCGDisplay(displayId, &link);
+
+ const CVTime p = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
+ const double r = p.timeScale / (double)p.timeValue;
+ view->hints[PUGL_REFRESH_RATE] = (int)lrint(r);
+
+ CVDisplayLinkRelease(link);
+ }
+
+ if (view->frame.width == 0.0 && view->frame.height == 0.0) {
+ if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) {
+ return PUGL_BAD_CONFIGURATION;
+ }
+
+ const double screenWidthPx = [screen frame].size.width * scaleFactor;
+ const double screenHeightPx = [screen frame].size.height * scaleFactor;
+
+ view->frame.width = view->defaultWidth;
+ view->frame.height = view->defaultHeight;
+ view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0;
+ view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0;
+ }
+
+ const NSRect framePx = rectToNsRect(view->frame);
+ const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor,
+ framePx.origin.y / scaleFactor,
+ framePx.size.width / scaleFactor,
+ framePx.size.height / scaleFactor);
+
+ // Create wrapper view to handle input
+ impl->wrapperView = [PuglWrapperView alloc];
+ impl->wrapperView->puglview = view;
+ impl->wrapperView->userTimers = [[NSMutableDictionary alloc] init];
+ impl->wrapperView->markedText = [[NSMutableAttributedString alloc] init];
+ [impl->wrapperView setAutoresizesSubviews:YES];
+ [impl->wrapperView initWithFrame:framePt];
+ [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView,
+ NSLayoutAttributeWidth,
+ view->minWidth)];
+ [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView,
+ NSLayoutAttributeHeight,
+ view->minHeight)];
+
+ // Create draw view to be rendered to
+ PuglStatus st = PUGL_SUCCESS;
+ if ((st = view->backend->configure(view)) ||
+ (st = view->backend->create(view))) {
+ return st;
+ }
+
+ // Add draw view to wrapper view
+ [impl->wrapperView addSubview:impl->drawView];
+ [impl->wrapperView setHidden:NO];
+ [impl->drawView setHidden:NO];
+
+ if (view->parent) {
+ NSView* pview = (NSView*)view->parent;
+ [pview addSubview:impl->wrapperView];
+ [impl->drawView setHidden:NO];
+ [[impl->drawView window] makeFirstResponder:impl->wrapperView];
+ } else {
+ unsigned style =
+ (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask);
+ if (view->hints[PUGL_RESIZABLE]) {
+ style |= NSResizableWindowMask;
+ }
+
+ PuglWindow* window = [[[PuglWindow alloc]
+ initWithContentRect:rectToScreen([NSScreen mainScreen], framePt)
+ styleMask:style
+ backing:NSBackingStoreBuffered
+ defer:NO] retain];
+ [window setPuglview:view];
+
+ if (view->title) {
+ NSString* titleString =
+ [[NSString alloc] initWithBytes:view->title
+ length:strlen(view->title)
+ encoding:NSUTF8StringEncoding];
+
+ [window setTitle:titleString];
+ }
+
+ if (view->minWidth || view->minHeight) {
+ [window
+ setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)];
+ }
+ impl->window = window;
+
+ ((NSWindow*)window).delegate =
+ [[PuglWindowDelegate alloc] initWithPuglWindow:window];
+
+ if (view->minAspectX && view->minAspectY) {
+ [window setContentAspectRatio:sizePoints(view,
+ view->minAspectX,
+ view->minAspectY)];
+ }
+
+ puglSetFrame(view, view->frame);
+
+ [window setContentView:impl->wrapperView];
+ [view->world->impl->app activateIgnoringOtherApps:YES];
+ [window makeFirstResponder:impl->wrapperView];
+ [window makeKeyAndOrderFront:window];
+ [impl->window setIsVisible:NO];
+ }
+
+ [impl->wrapperView updateTrackingAreas];
+
+ puglDispatchSimpleEvent(view, PUGL_CREATE);
+
+ return PUGL_SUCCESS;
}
PuglStatus
puglShow(PuglView* view)
{
- if (!view->impl->wrapperView) {
- const PuglStatus st = puglRealize(view);
- if (st) {
- return st;
- }
- }
+ if (!view->impl->wrapperView) {
+ const PuglStatus st = puglRealize(view);
+ if (st) {
+ return st;
+ }
+ }
- if (![view->impl->window isVisible]) {
- [view->impl->window setIsVisible:YES];
- [view->impl->drawView setNeedsDisplay: YES];
- updateViewRect(view);
- }
+ if (![view->impl->window isVisible]) {
+ [view->impl->window setIsVisible:YES];
+ [view->impl->drawView setNeedsDisplay:YES];
+ updateViewRect(view);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglHide(PuglView* view)
{
- [view->impl->window setIsVisible:NO];
- return PUGL_SUCCESS;
+ [view->impl->window setIsVisible:NO];
+ return PUGL_SUCCESS;
}
void
puglFreeViewInternals(PuglView* view)
{
- if (view) {
- if (view->backend) {
- view->backend->destroy(view);
- }
-
- if (view->impl) {
- [view->impl->wrapperView removeFromSuperview];
- view->impl->wrapperView->puglview = NULL;
- if (view->impl->window) {
- [view->impl->window close];
- }
- [view->impl->wrapperView release];
- if (view->impl->window) {
- [view->impl->window release];
- }
- free(view->impl);
- }
- }
+ if (view) {
+ if (view->backend) {
+ view->backend->destroy(view);
+ }
+
+ if (view->impl) {
+ [view->impl->wrapperView removeFromSuperview];
+ view->impl->wrapperView->puglview = NULL;
+ if (view->impl->window) {
+ [view->impl->window close];
+ }
+ [view->impl->wrapperView release];
+ if (view->impl->window) {
+ [view->impl->window release];
+ }
+ free(view->impl);
+ }
+ }
}
PuglStatus
puglGrabFocus(PuglView* view)
{
- NSWindow* window = [view->impl->wrapperView window];
+ NSWindow* window = [view->impl->wrapperView window];
- [window makeKeyWindow];
- [window makeFirstResponder:view->impl->wrapperView];
- return PUGL_SUCCESS;
+ [window makeKeyWindow];
+ [window makeFirstResponder:view->impl->wrapperView];
+ return PUGL_SUCCESS;
}
bool
puglHasFocus(const PuglView* view)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* const impl = view->impl;
- return ([[impl->wrapperView window] isKeyWindow] &&
- [[impl->wrapperView window] firstResponder] == impl->wrapperView);
+ return ([[impl->wrapperView window] isKeyWindow] &&
+ [[impl->wrapperView window] firstResponder] == impl->wrapperView);
}
PuglStatus
puglRequestAttention(PuglView* view)
{
- if (![view->impl->window isKeyWindow]) {
- [view->world->impl->app requestUserAttention:NSInformationalRequest];
- }
+ if (![view->impl->window isKeyWindow]) {
+ [view->world->impl->app requestUserAttention:NSInformationalRequest];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglStartTimer(PuglView* view, uintptr_t id, double timeout)
{
- puglStopTimer(view, id);
+ puglStopTimer(view, id);
- NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id];
+ NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id];
- NSTimer* timer = [NSTimer timerWithTimeInterval:timeout
- target:view->impl->wrapperView
- selector:@selector(timerTick:)
- userInfo:idNumber
- repeats:YES];
+ NSTimer* timer = [NSTimer timerWithTimeInterval:timeout
+ target:view->impl->wrapperView
+ selector:@selector(timerTick:)
+ userInfo:idNumber
+ repeats:YES];
- [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
+ [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
- view->impl->wrapperView->userTimers[idNumber] = timer;
+ view->impl->wrapperView->userTimers[idNumber] = timer;
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglStopTimer(PuglView* view, uintptr_t id)
{
- NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id];
- NSTimer* timer = view->impl->wrapperView->userTimers[idNumber];
+ NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id];
+ NSTimer* timer = view->impl->wrapperView->userTimers[idNumber];
- if (timer) {
- [view->impl->wrapperView->userTimers removeObjectForKey:timer];
- [timer invalidate];
- return PUGL_SUCCESS;
- }
+ if (timer) {
+ [view->impl->wrapperView->userTimers removeObjectForKey:timer];
+ [timer invalidate];
+ return PUGL_SUCCESS;
+ }
- return PUGL_UNKNOWN_ERROR;
+ return PUGL_UNKNOWN_ERROR;
}
PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event)
{
- if (event->type == PUGL_CLIENT) {
- PuglWrapperView* wrapper = view->impl->wrapperView;
- const NSWindow* window = [wrapper window];
- const NSRect rect = [wrapper frame];
- const NSPoint center = {NSMidX(rect), NSMidY(rect)};
-
- NSEvent* nsevent = [NSEvent
- otherEventWithType:NSApplicationDefined
- location:center
- modifierFlags:0
- timestamp:[[NSProcessInfo processInfo] systemUptime]
- windowNumber:window.windowNumber
- context:nil
- subtype:PUGL_CLIENT
- data1:(NSInteger)event->client.data1
- data2:(NSInteger)event->client.data2];
-
- [view->world->impl->app postEvent:nsevent atStart:false];
- return PUGL_SUCCESS;
- }
+ if (event->type == PUGL_CLIENT) {
+ PuglWrapperView* wrapper = view->impl->wrapperView;
+ const NSWindow* window = [wrapper window];
+ const NSRect rect = [wrapper frame];
+ const NSPoint center = {NSMidX(rect), NSMidY(rect)};
+
+ NSEvent* nsevent =
+ [NSEvent otherEventWithType:NSApplicationDefined
+ location:center
+ modifierFlags:0
+ timestamp:[[NSProcessInfo processInfo] systemUptime]
+ windowNumber:window.windowNumber
+ context:nil
+ subtype:PUGL_CLIENT
+ data1:(NSInteger)event->client.data1
+ data2:(NSInteger)event->client.data2];
- return PUGL_UNSUPPORTED_TYPE;
+ [view->world->impl->app postEvent:nsevent atStart:false];
+ return PUGL_SUCCESS;
+ }
+
+ return PUGL_UNSUPPORTED_TYPE;
}
#ifndef PUGL_DISABLE_DEPRECATED
PuglStatus
puglWaitForEvent(PuglView* view)
{
- return puglPollEvents(view->world, -1.0);
+ return puglPollEvents(view->world, -1.0);
}
#endif
static void
dispatchClientEvent(PuglWorld* world, NSEvent* ev)
{
- NSWindow* win = [ev window];
- NSPoint loc = [ev locationInWindow];
- for (size_t i = 0; i < world->numViews; ++i) {
- PuglView* view = world->views[i];
- PuglWrapperView* wrapper = view->impl->wrapperView;
- if ([wrapper window] == win && NSPointInRect(loc, [wrapper frame])) {
- const PuglEventClient event = {PUGL_CLIENT,
- 0,
- (uintptr_t)[ev data1],
- (uintptr_t)[ev data2]};
+ NSWindow* win = [ev window];
+ NSPoint loc = [ev locationInWindow];
+ for (size_t i = 0; i < world->numViews; ++i) {
+ PuglView* view = world->views[i];
+ PuglWrapperView* wrapper = view->impl->wrapperView;
+ if ([wrapper window] == win && NSPointInRect(loc, [wrapper frame])) {
+ const PuglEventClient event = {
+ PUGL_CLIENT, 0, (uintptr_t)[ev data1], (uintptr_t)[ev data2]};
- puglDispatchEvent(view, (const PuglEvent*)&event);
- }
- }
+ puglDispatchEvent(view, (const PuglEvent*)&event);
+ }
+ }
}
PuglStatus
puglUpdate(PuglWorld* world, const double timeout)
{
- NSDate* date = ((timeout < 0)
- ? [NSDate distantFuture]
- : [NSDate dateWithTimeIntervalSinceNow:timeout]);
-
- for (NSEvent* ev = NULL;
- (ev = [world->impl->app nextEventMatchingMask:NSAnyEventMask
- untilDate:date
- inMode:NSDefaultRunLoopMode
- dequeue:YES]);) {
-
- if ([ev type] == NSApplicationDefined && [ev subtype] == PUGL_CLIENT) {
- dispatchClientEvent(world, ev);
- }
+ NSDate* date =
+ ((timeout < 0) ? [NSDate distantFuture]
+ : [NSDate dateWithTimeIntervalSinceNow:timeout]);
+
+ for (NSEvent* ev = NULL;
+ (ev = [world->impl->app nextEventMatchingMask:NSAnyEventMask
+ untilDate:date
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES]);) {
+ if ([ev type] == NSApplicationDefined && [ev subtype] == PUGL_CLIENT) {
+ dispatchClientEvent(world, ev);
+ }
- [world->impl->app sendEvent: ev];
+ [world->impl->app sendEvent:ev];
- if (timeout < 0) {
- // Now that we've waited and got an event, set the date to now to
- // avoid looping forever
- date = [NSDate date];
- }
- }
+ if (timeout < 0) {
+ // Now that we've waited and got an event, set the date to now to
+ // avoid looping forever
+ date = [NSDate date];
+ }
+ }
- for (size_t i = 0; i < world->numViews; ++i) {
- PuglView* const view = world->views[i];
+ for (size_t i = 0; i < world->numViews; ++i) {
+ PuglView* const view = world->views[i];
- if ([[view->impl->drawView window] isVisible]) {
- puglDispatchSimpleEvent(view, PUGL_UPDATE);
- }
+ if ([[view->impl->drawView window] isVisible]) {
+ puglDispatchSimpleEvent(view, PUGL_UPDATE);
+ }
- [view->impl->drawView displayIfNeeded];
- }
+ [view->impl->drawView displayIfNeeded];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
#ifndef PUGL_DISABLE_DEPRECATED
PuglStatus
puglProcessEvents(PuglView* view)
{
- return puglDispatchEvents(view->world);
+ return puglDispatchEvents(view->world);
}
#endif
double
puglGetTime(const PuglWorld* world)
{
- return (mach_absolute_time() / 1e9) - world->startTime;
+ return (mach_absolute_time() / 1e9) - world->startTime;
}
PuglStatus
puglPostRedisplay(PuglView* view)
{
- [view->impl->drawView setNeedsDisplay: YES];
- return PUGL_SUCCESS;
+ [view->impl->drawView setNeedsDisplay:YES];
+ return PUGL_SUCCESS;
}
PuglStatus
puglPostRedisplayRect(PuglView* view, const PuglRect rect)
{
- const NSRect rectPx = rectToNsRect(rect);
+ const NSRect rectPx = rectToNsRect(rect);
- [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)];
+ [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)];
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglNativeView
puglGetNativeWindow(PuglView* view)
{
- return (PuglNativeView)view->impl->wrapperView;
+ return (PuglNativeView)view->impl->wrapperView;
}
PuglStatus
puglSetWindowTitle(PuglView* view, const char* title)
{
- puglSetString(&view->title, title);
+ puglSetString(&view->title, title);
- if (view->impl->window) {
- NSString* titleString = [[NSString alloc]
- initWithBytes:title
- length:strlen(title)
- encoding:NSUTF8StringEncoding];
+ if (view->impl->window) {
+ NSString* titleString =
+ [[NSString alloc] initWithBytes:title
+ length:strlen(title)
+ encoding:NSUTF8StringEncoding];
- [view->impl->window setTitle:titleString];
- }
+ [view->impl->window setTitle:titleString];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* const impl = view->impl;
- // Update view frame to exactly the requested frame in Pugl coordinates
- view->frame = frame;
+ // Update view frame to exactly the requested frame in Pugl coordinates
+ view->frame = frame;
- const NSRect framePx = rectToNsRect(frame);
- const NSRect framePt = nsRectToPoints(view, framePx);
- if (impl->window) {
- // Resize window to fit new content rect
- const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
- const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
+ const NSRect framePx = rectToNsRect(frame);
+ const NSRect framePt = nsRectToPoints(view, framePx);
+ if (impl->window) {
+ // Resize window to fit new content rect
+ const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
+ const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
- [impl->window setFrame:winFrame display:NO];
- }
+ [impl->window setFrame:winFrame display:NO];
+ }
- // Resize views
- const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
- const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
+ // Resize views
+ const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
+ const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
- [impl->wrapperView setFrame:(impl->window ? sizePt : framePt)];
- [impl->drawView setFrame:sizePt];
+ [impl->wrapperView setFrame:(impl->window ? sizePt : framePt)];
+ [impl->drawView setFrame:sizePt];
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetDefaultSize(PuglView* const view, const int width, const int height)
{
- view->defaultWidth = width;
- view->defaultHeight = height;
- return PUGL_SUCCESS;
+ view->defaultWidth = width;
+ view->defaultHeight = height;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetMinSize(PuglView* const view, const int width, const int height)
{
- view->minWidth = width;
- view->minHeight = height;
+ view->minWidth = width;
+ view->minHeight = height;
- if (view->impl->window && (view->minWidth || view->minHeight)) {
- [view->impl->window setContentMinSize:sizePoints(view,
- view->minWidth,
- view->minHeight)];
- }
+ if (view->impl->window && (view->minWidth || view->minHeight)) {
+ [view->impl->window
+ setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetMaxSize(PuglView* const view, const int width, const int height)
{
- view->maxWidth = width;
- view->maxHeight = height;
+ view->maxWidth = width;
+ view->maxHeight = height;
- if (view->impl->window && (view->maxWidth || view->maxHeight)) {
- [view->impl->window setContentMaxSize:sizePoints(view,
- view->maxWidth,
- view->maxHeight)];
- }
+ if (view->impl->window && (view->maxWidth || view->maxHeight)) {
+ [view->impl->window
+ setContentMaxSize:sizePoints(view, view->maxWidth, view->maxHeight)];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
@@ -1334,35 +1348,34 @@ puglSetAspectRatio(PuglView* const view,
const int maxX,
const int maxY)
{
- view->minAspectX = minX;
- view->minAspectY = minY;
- view->maxAspectX = maxX;
- view->maxAspectY = maxY;
+ view->minAspectX = minX;
+ view->minAspectY = minY;
+ view->maxAspectX = maxX;
+ view->maxAspectY = maxY;
- if (view->impl->window && view->minAspectX && view->minAspectY) {
- [view->impl->window setContentAspectRatio:sizePoints(view,
- view->minAspectX,
- view->minAspectY)];
- }
+ if (view->impl->window && view->minAspectX && view->minAspectY) {
+ [view->impl->window setContentAspectRatio:sizePoints(view,
+ view->minAspectX,
+ view->minAspectY)];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetTransientFor(PuglView* view, PuglNativeView parent)
{
- view->transientParent = parent;
+ view->transientParent = parent;
- if (view->impl->window) {
- NSWindow* parentWindow = [(NSView*)parent window];
- if (parentWindow) {
- [parentWindow addChildWindow:view->impl->window
- ordered:NSWindowAbove];
- return PUGL_SUCCESS;
- }
- }
+ if (view->impl->window) {
+ NSWindow* parentWindow = [(NSView*)parent window];
+ if (parentWindow) {
+ [parentWindow addChildWindow:view->impl->window ordered:NSWindowAbove];
+ return PUGL_SUCCESS;
+ }
+ }
- return PUGL_FAILURE;
+ return PUGL_FAILURE;
}
const void*
@@ -1370,57 +1383,57 @@ puglGetClipboard(PuglView* const view,
const char** const type,
size_t* const len)
{
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
- if ([[pasteboard types] containsObject:NSStringPboardType]) {
- const NSString* str = [pasteboard stringForType:NSStringPboardType];
- const char* utf8 = [str UTF8String];
+ if ([[pasteboard types] containsObject:NSStringPboardType]) {
+ const NSString* str = [pasteboard stringForType:NSStringPboardType];
+ const char* utf8 = [str UTF8String];
- puglSetBlob(&view->clipboard, utf8, strlen(utf8) + 1);
- }
+ puglSetBlob(&view->clipboard, utf8, strlen(utf8) + 1);
+ }
- return puglGetInternalClipboard(view, type, len);
+ return puglGetInternalClipboard(view, type, len);
}
static NSCursor*
puglGetNsCursor(const PuglCursor cursor)
{
- switch (cursor) {
- case PUGL_CURSOR_ARROW:
- return [NSCursor arrowCursor];
- case PUGL_CURSOR_CARET:
- return [NSCursor IBeamCursor];
- case PUGL_CURSOR_CROSSHAIR:
- return [NSCursor crosshairCursor];
- case PUGL_CURSOR_HAND:
- return [NSCursor pointingHandCursor];
- case PUGL_CURSOR_NO:
- return [NSCursor operationNotAllowedCursor];
- case PUGL_CURSOR_LEFT_RIGHT:
- return [NSCursor resizeLeftRightCursor];
- case PUGL_CURSOR_UP_DOWN:
- return [NSCursor resizeUpDownCursor];
- }
-
- return NULL;
+ switch (cursor) {
+ case PUGL_CURSOR_ARROW:
+ return [NSCursor arrowCursor];
+ case PUGL_CURSOR_CARET:
+ return [NSCursor IBeamCursor];
+ case PUGL_CURSOR_CROSSHAIR:
+ return [NSCursor crosshairCursor];
+ case PUGL_CURSOR_HAND:
+ return [NSCursor pointingHandCursor];
+ case PUGL_CURSOR_NO:
+ return [NSCursor operationNotAllowedCursor];
+ case PUGL_CURSOR_LEFT_RIGHT:
+ return [NSCursor resizeLeftRightCursor];
+ case PUGL_CURSOR_UP_DOWN:
+ return [NSCursor resizeUpDownCursor];
+ }
+
+ return NULL;
}
PuglStatus
puglSetCursor(PuglView* view, PuglCursor cursor)
{
- PuglInternals* const impl = view->impl;
- NSCursor* const cur = puglGetNsCursor(cursor);
- if (!cur) {
- return PUGL_FAILURE;
- }
+ PuglInternals* const impl = view->impl;
+ NSCursor* const cur = puglGetNsCursor(cursor);
+ if (!cur) {
+ return PUGL_FAILURE;
+ }
- impl->cursor = cur;
+ impl->cursor = cur;
- if (impl->mouseTracked) {
- [cur set];
- }
+ if (impl->mouseTracked) {
+ [cur set];
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
@@ -1429,24 +1442,23 @@ puglSetClipboard(PuglView* const view,
const void* const data,
const size_t len)
{
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
- const char* const str = (const char*)data;
+ NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ const char* const str = (const char*)data;
- PuglStatus st = puglSetInternalClipboard(view, type, data, len);
- if (st) {
- return st;
- }
+ PuglStatus st = puglSetInternalClipboard(view, type, data, len);
+ if (st) {
+ return st;
+ }
- NSString* nsString = [NSString stringWithUTF8String:str];
- if (nsString) {
- [pasteboard
- declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil]
- owner:nil];
+ NSString* nsString = [NSString stringWithUTF8String:str];
+ if (nsString) {
+ [pasteboard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil]
+ owner:nil];
- [pasteboard setString:nsString forType:NSStringPboardType];
+ [pasteboard setString:nsString forType:NSStringPboardType];
- return PUGL_SUCCESS;
- }
+ return PUGL_SUCCESS;
+ }
- return PUGL_UNKNOWN_ERROR;
+ return PUGL_UNKNOWN_ERROR;
}
diff --git a/src/mac_cairo.m b/src/mac_cairo.m
index 9a46037..1c564a0 100644
--- a/src/mac_cairo.m
+++ b/src/mac_cairo.m
@@ -29,33 +29,32 @@
@interface PuglCairoView : NSView
@end
-@implementation PuglCairoView
-{
+@implementation PuglCairoView {
@public
- PuglView* puglview;
- cairo_surface_t* surface;
- cairo_t* cr;
+ PuglView* puglview;
+ cairo_surface_t* surface;
+ cairo_t* cr;
}
- (id)initWithFrame:(NSRect)frame
{
- self = [super initWithFrame:frame];
+ self = [super initWithFrame:frame];
- return self;
+ return self;
}
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [super resizeWithOldSuperviewSize:oldSize];
- [wrapper setReshaped];
+ [super resizeWithOldSuperviewSize:oldSize];
+ [wrapper setReshaped];
}
- (void)drawRect:(NSRect)rect
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [wrapper dispatchExpose:rect];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ [wrapper dispatchExpose:rect];
}
@end
@@ -63,99 +62,99 @@
static PuglStatus
puglMacCairoCreate(PuglView* view)
{
- PuglInternals* impl = view->impl;
- PuglCairoView* drawView = [PuglCairoView alloc];
-
- drawView->puglview = view;
- [drawView initWithFrame:[impl->wrapperView bounds]];
- if (view->hints[PUGL_RESIZABLE]) {
- [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- } else {
- [drawView setAutoresizingMask:NSViewNotSizable];
- }
-
- impl->drawView = drawView;
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+ PuglCairoView* drawView = [PuglCairoView alloc];
+
+ drawView->puglview = view;
+ [drawView initWithFrame:[impl->wrapperView bounds]];
+ if (view->hints[PUGL_RESIZABLE]) {
+ [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ } else {
+ [drawView setAutoresizingMask:NSViewNotSizable];
+ }
+
+ impl->drawView = drawView;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacCairoDestroy(PuglView* view)
{
- PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
- [drawView removeFromSuperview];
- [drawView release];
+ [drawView removeFromSuperview];
+ [drawView release];
- view->impl->drawView = nil;
- return PUGL_SUCCESS;
+ view->impl->drawView = nil;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacCairoEnter(PuglView* view, const PuglEventExpose* expose)
{
- PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
- if (!expose) {
- return PUGL_SUCCESS;
- }
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+ if (!expose) {
+ return PUGL_SUCCESS;
+ }
- assert(!drawView->surface);
- assert(!drawView->cr);
+ assert(!drawView->surface);
+ assert(!drawView->cr);
- const double scale = 1.0 / [[NSScreen mainScreen] backingScaleFactor];
- CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
- const CGSize sizePx = {view->frame.width, view->frame.height};
- const CGSize sizePt = CGContextConvertSizeToUserSpace(context, sizePx);
+ const double scale = 1.0 / [[NSScreen mainScreen] backingScaleFactor];
+ CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
+ const CGSize sizePx = {view->frame.width, view->frame.height};
+ const CGSize sizePt = CGContextConvertSizeToUserSpace(context, sizePx);
- // Convert coordinates to standard Cairo space
- CGContextTranslateCTM(context, 0.0, -sizePt.height);
- CGContextScaleCTM(context, scale, -scale);
+ // Convert coordinates to standard Cairo space
+ CGContextTranslateCTM(context, 0.0, -sizePt.height);
+ CGContextScaleCTM(context, scale, -scale);
- drawView->surface = cairo_quartz_surface_create_for_cg_context(
- context, (unsigned)sizePx.width, (unsigned)sizePx.height);
+ drawView->surface = cairo_quartz_surface_create_for_cg_context(
+ context, (unsigned)sizePx.width, (unsigned)sizePx.height);
- drawView->cr = cairo_create(drawView->surface);
+ drawView->cr = cairo_create(drawView->surface);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacCairoLeave(PuglView* view, const PuglEventExpose* expose)
{
- PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
- if (!expose) {
- return PUGL_SUCCESS;
- }
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+ if (!expose) {
+ return PUGL_SUCCESS;
+ }
- assert(drawView->surface);
- assert(drawView->cr);
+ assert(drawView->surface);
+ assert(drawView->cr);
- CGContextRef context = cairo_quartz_surface_get_cg_context(drawView->surface);
+ CGContextRef context = cairo_quartz_surface_get_cg_context(drawView->surface);
- cairo_destroy(drawView->cr);
- cairo_surface_destroy(drawView->surface);
- drawView->cr = NULL;
- drawView->surface = NULL;
+ cairo_destroy(drawView->cr);
+ cairo_surface_destroy(drawView->surface);
+ drawView->cr = NULL;
+ drawView->surface = NULL;
- CGContextFlush(context);
+ CGContextFlush(context);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static void*
puglMacCairoGetContext(PuglView* view)
{
- return ((PuglCairoView*)view->impl->drawView)->cr;
+ return ((PuglCairoView*)view->impl->drawView)->cr;
}
const PuglBackend*
puglCairoBackend(void)
{
- static const PuglBackend backend = {puglStubConfigure,
- puglMacCairoCreate,
- puglMacCairoDestroy,
- puglMacCairoEnter,
- puglMacCairoLeave,
- puglMacCairoGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglStubConfigure,
+ puglMacCairoCreate,
+ puglMacCairoDestroy,
+ puglMacCairoEnter,
+ puglMacCairoLeave,
+ puglMacCairoGetContext};
+
+ return &backend;
}
diff --git a/src/mac_gl.m b/src/mac_gl.m
index b29221f..dd06cc0 100644
--- a/src/mac_gl.m
+++ b/src/mac_gl.m
@@ -21,95 +21,95 @@
#include "pugl/gl.h"
#ifndef __MAC_10_10
-# define NSOpenGLProfileVersion4_1Core NSOpenGLProfileVersion3_2Core
+# define NSOpenGLProfileVersion4_1Core NSOpenGLProfileVersion3_2Core
#endif
@interface PuglOpenGLView : NSOpenGLView
@end
-@implementation PuglOpenGLView
-{
+@implementation PuglOpenGLView {
@public
- PuglView* puglview;
+ PuglView* puglview;
}
- (id)initWithFrame:(NSRect)frame
{
- const bool compat = puglview->hints[PUGL_USE_COMPAT_PROFILE];
- const unsigned samples = (unsigned)puglview->hints[PUGL_SAMPLES];
- const int major = puglview->hints[PUGL_CONTEXT_VERSION_MAJOR];
- const unsigned profile = ((compat || major < 3)
- ? NSOpenGLProfileVersionLegacy
- : (major >= 4
- ? NSOpenGLProfileVersion4_1Core
- : NSOpenGLProfileVersion3_2Core));
-
- // 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, 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,
- 0};
-
- NSOpenGLPixelFormat* pixelFormat = [
- [NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs];
-
- if (pixelFormat) {
- self = [super initWithFrame:frame pixelFormat:pixelFormat];
- [pixelFormat release];
- } else {
- self = [super initWithFrame:frame];
- }
-
- [self setWantsBestResolutionOpenGLSurface:YES];
-
- if (self) {
- [[self openGLContext] makeCurrentContext];
- [self reshape];
- }
- return self;
+ const bool compat = puglview->hints[PUGL_USE_COMPAT_PROFILE];
+ const unsigned samples = (unsigned)puglview->hints[PUGL_SAMPLES];
+ const int major = puglview->hints[PUGL_CONTEXT_VERSION_MAJOR];
+ const unsigned profile =
+ ((compat || major < 3) ? NSOpenGLProfileVersionLegacy
+ : (major >= 4 ? NSOpenGLProfileVersion4_1Core
+ : NSOpenGLProfileVersion3_2Core));
+
+ // 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]);
+
+ // clang-format off
+ NSOpenGLPixelFormatAttribute pixelAttribs[17] = {
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFAOpenGLProfile, profile,
+ 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,
+ 0};
+ // clang-format on
+
+ NSOpenGLPixelFormat* pixelFormat =
+ [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs];
+
+ if (pixelFormat) {
+ self = [super initWithFrame:frame pixelFormat:pixelFormat];
+ [pixelFormat release];
+ } else {
+ self = [super initWithFrame:frame];
+ }
+
+ [self setWantsBestResolutionOpenGLSurface:YES];
+
+ if (self) {
+ [[self openGLContext] makeCurrentContext];
+ [self reshape];
+ }
+ return self;
}
- (void)reshape
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [super reshape];
- [wrapper setReshaped];
+ [super reshape];
+ [wrapper setReshaped];
}
- (void)drawRect:(NSRect)rect
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [wrapper dispatchExpose:rect];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ [wrapper dispatchExpose:rect];
}
@end
@@ -117,94 +117,94 @@
static PuglStatus
puglMacGlCreate(PuglView* view)
{
- PuglInternals* impl = view->impl;
- PuglOpenGLView* drawView = [PuglOpenGLView alloc];
-
- drawView->puglview = view;
- [drawView initWithFrame:[impl->wrapperView bounds]];
- if (view->hints[PUGL_RESIZABLE]) {
- [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- } else {
- [drawView setAutoresizingMask:NSViewNotSizable];
- }
-
- impl->drawView = drawView;
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+ PuglOpenGLView* drawView = [PuglOpenGLView alloc];
+
+ drawView->puglview = view;
+ [drawView initWithFrame:[impl->wrapperView bounds]];
+ if (view->hints[PUGL_RESIZABLE]) {
+ [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ } else {
+ [drawView setAutoresizingMask:NSViewNotSizable];
+ }
+
+ impl->drawView = drawView;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacGlDestroy(PuglView* view)
{
- PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
+ PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
- [drawView removeFromSuperview];
- [drawView release];
+ [drawView removeFromSuperview];
+ [drawView release];
- view->impl->drawView = nil;
- return PUGL_SUCCESS;
+ view->impl->drawView = nil;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacGlEnter(PuglView* view, const PuglEventExpose* PUGL_UNUSED(expose))
{
- PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
+ PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
- [[drawView openGLContext] makeCurrentContext];
- return PUGL_SUCCESS;
+ [[drawView openGLContext] makeCurrentContext];
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacGlLeave(PuglView* view, const PuglEventExpose* expose)
{
- PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
+ PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
- if (expose) {
- [[drawView openGLContext] flushBuffer];
- }
+ if (expose) {
+ [[drawView openGLContext] flushBuffer];
+ }
- [NSOpenGLContext clearCurrentContext];
+ [NSOpenGLContext clearCurrentContext];
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglGlFunc
-puglGetProcAddress(const char *name)
+puglGetProcAddress(const char* name)
{
- CFBundleRef framework =
- CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ CFBundleRef framework =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- CFStringRef symbol = CFStringCreateWithCString(
- kCFAllocatorDefault, name, kCFStringEncodingASCII);
+ CFStringRef symbol = CFStringCreateWithCString(
+ kCFAllocatorDefault, name, kCFStringEncodingASCII);
- PuglGlFunc func = (PuglGlFunc)CFBundleGetFunctionPointerForName(
- framework, symbol);
+ PuglGlFunc func =
+ (PuglGlFunc)CFBundleGetFunctionPointerForName(framework, symbol);
- CFRelease(symbol);
+ CFRelease(symbol);
- return func;
+ return func;
}
PuglStatus
puglEnterContext(PuglView* view)
{
- return view->backend->enter(view, NULL);
+ return view->backend->enter(view, NULL);
}
PuglStatus
puglLeaveContext(PuglView* view)
{
- return view->backend->leave(view, NULL);
+ return view->backend->leave(view, NULL);
}
const PuglBackend*
puglGlBackend(void)
{
- static const PuglBackend backend = {puglStubConfigure,
- puglMacGlCreate,
- puglMacGlDestroy,
- puglMacGlEnter,
- puglMacGlLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglStubConfigure,
+ puglMacGlCreate,
+ puglMacGlDestroy,
+ puglMacGlEnter,
+ puglMacGlLeave,
+ puglStubGetContext};
+
+ return &backend;
}
diff --git a/src/mac_stub.m b/src/mac_stub.m
index 404d295..ac7bfcc 100644
--- a/src/mac_stub.m
+++ b/src/mac_stub.m
@@ -25,25 +25,24 @@
@interface PuglStubView : NSView
@end
-@implementation PuglStubView
-{
+@implementation PuglStubView {
@public
- PuglView* puglview;
+ PuglView* puglview;
}
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [super resizeWithOldSuperviewSize:oldSize];
- [wrapper setReshaped];
+ [super resizeWithOldSuperviewSize:oldSize];
+ [wrapper setReshaped];
}
- (void)drawRect:(NSRect)rect
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [wrapper dispatchExpose:rect];
+ [wrapper dispatchExpose:rect];
}
@end
@@ -51,42 +50,43 @@
static PuglStatus
puglMacStubCreate(PuglView* view)
{
- PuglInternals* impl = view->impl;
- PuglStubView* drawView = [PuglStubView alloc];
-
- drawView->puglview = view;
- [drawView initWithFrame:NSMakeRect(0, 0, view->frame.width, view->frame.height)];
- if (view->hints[PUGL_RESIZABLE]) {
- [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- } else {
- [drawView setAutoresizingMask:NSViewNotSizable];
- }
-
- impl->drawView = drawView;
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+ PuglStubView* drawView = [PuglStubView alloc];
+
+ drawView->puglview = view;
+ [drawView
+ initWithFrame:NSMakeRect(0, 0, view->frame.width, view->frame.height)];
+ if (view->hints[PUGL_RESIZABLE]) {
+ [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ } else {
+ [drawView setAutoresizingMask:NSViewNotSizable];
+ }
+
+ impl->drawView = drawView;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacStubDestroy(PuglView* view)
{
- PuglStubView* const drawView = (PuglStubView*)view->impl->drawView;
+ PuglStubView* const drawView = (PuglStubView*)view->impl->drawView;
- [drawView removeFromSuperview];
- [drawView release];
+ [drawView removeFromSuperview];
+ [drawView release];
- view->impl->drawView = nil;
- return PUGL_SUCCESS;
+ view->impl->drawView = nil;
+ return PUGL_SUCCESS;
}
const PuglBackend*
puglStubBackend(void)
{
- static const PuglBackend backend = {puglStubConfigure,
- puglMacStubCreate,
- puglMacStubDestroy,
- puglStubEnter,
- puglStubLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglStubConfigure,
+ puglMacStubCreate,
+ puglMacStubDestroy,
+ puglStubEnter,
+ puglStubLeave,
+ puglStubGetContext};
+
+ return &backend;
}
diff --git a/src/mac_vulkan.m b/src/mac_vulkan.m
index c56346c..6899483 100644
--- a/src/mac_vulkan.m
+++ b/src/mac_vulkan.m
@@ -40,47 +40,45 @@
@end
-@implementation PuglVulkanView
-{
+@implementation PuglVulkanView {
@public
- PuglView* puglview;
+ PuglView* puglview;
}
- (id)initWithFrame:(NSRect)frame
{
- self = [super initWithFrame:frame];
+ self = [super initWithFrame:frame];
- if (self) {
- self.wantsLayer = YES;
- self.layerContentsRedrawPolicy =
- NSViewLayerContentsRedrawOnSetNeedsDisplay;
- }
+ if (self) {
+ self.wantsLayer = YES;
+ self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
+ }
- return self;
+ return self;
}
- (CALayer*)makeBackingLayer
{
- CAMetalLayer* layer = [CAMetalLayer layer];
- [layer setDelegate:self];
- return layer;
+ CAMetalLayer* layer = [CAMetalLayer layer];
+ [layer setDelegate:self];
+ return layer;
}
- (void)setFrameSize:(NSSize)newSize
{
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [super setFrameSize:newSize];
- [wrapper setReshaped];
+ [super setFrameSize:newSize];
+ [wrapper setReshaped];
- self.layer.frame = self.bounds;
+ self.layer.frame = self.bounds;
}
- (void)displayLayer:(CALayer*)layer
{
- (void)layer;
- PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
- [wrapper dispatchExpose:[self bounds]];
+ (void)layer;
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ [wrapper dispatchExpose:[self bounds]];
}
@end
@@ -88,105 +86,105 @@
static PuglStatus
puglMacVulkanCreate(PuglView* view)
{
- PuglInternals* impl = view->impl;
- PuglVulkanView* drawView = [PuglVulkanView alloc];
- const NSRect rect = NSMakeRect(0, 0, view->frame.width, view->frame.height);
-
- drawView->puglview = view;
- [drawView initWithFrame:rect];
- if (view->hints[PUGL_RESIZABLE]) {
- [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- } else {
- [drawView setAutoresizingMask:NSViewNotSizable];
- }
-
- impl->drawView = drawView;
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+ PuglVulkanView* drawView = [PuglVulkanView alloc];
+ const NSRect rect = NSMakeRect(0, 0, view->frame.width, view->frame.height);
+
+ drawView->puglview = view;
+ [drawView initWithFrame:rect];
+ if (view->hints[PUGL_RESIZABLE]) {
+ [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ } else {
+ [drawView setAutoresizingMask:NSViewNotSizable];
+ }
+
+ impl->drawView = drawView;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglMacVulkanDestroy(PuglView* view)
{
- PuglVulkanView* const drawView = (PuglVulkanView*)view->impl->drawView;
+ PuglVulkanView* const drawView = (PuglVulkanView*)view->impl->drawView;
- [drawView removeFromSuperview];
- [drawView release];
+ [drawView removeFromSuperview];
+ [drawView release];
- view->impl->drawView = nil;
- return PUGL_SUCCESS;
+ view->impl->drawView = nil;
+ return PUGL_SUCCESS;
}
struct PuglVulkanLoaderImpl {
- void* libvulkan;
- PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
- PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+ void* libvulkan;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
};
PuglVulkanLoader*
puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world))
{
- PuglVulkanLoader* loader = (PuglVulkanLoader*)
- calloc(1, sizeof(PuglVulkanLoader));
- if (!loader) {
- return NULL;
- }
+ PuglVulkanLoader* loader =
+ (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
+ if (!loader) {
+ return NULL;
+ }
- if (!(loader->libvulkan = dlopen("libvulkan.dylib", RTLD_LAZY))) {
- free(loader);
- return NULL;
- }
+ if (!(loader->libvulkan = dlopen("libvulkan.dylib", RTLD_LAZY))) {
+ free(loader);
+ return NULL;
+ }
- loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
- dlsym(loader->libvulkan, "vkGetInstanceProcAddr");
+ loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(
+ loader->libvulkan, "vkGetInstanceProcAddr");
- loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
- dlsym(loader->libvulkan, "vkGetDeviceProcAddr");
+ loader->vkGetDeviceProcAddr =
+ (PFN_vkGetDeviceProcAddr)dlsym(loader->libvulkan, "vkGetDeviceProcAddr");
- return loader;
+ return loader;
}
void
puglFreeVulkanLoader(PuglVulkanLoader* loader)
{
- if (loader) {
- dlclose(loader->libvulkan);
- free(loader);
- }
+ if (loader) {
+ dlclose(loader->libvulkan);
+ free(loader);
+ }
}
PFN_vkGetInstanceProcAddr
puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader)
{
- return loader->vkGetInstanceProcAddr;
+ return loader->vkGetInstanceProcAddr;
}
PFN_vkGetDeviceProcAddr
puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader)
{
- return loader->vkGetDeviceProcAddr;
+ return loader->vkGetDeviceProcAddr;
}
const PuglBackend*
puglVulkanBackend(void)
{
- static const PuglBackend backend = {puglStubConfigure,
- puglMacVulkanCreate,
- puglMacVulkanDestroy,
- puglStubEnter,
- puglStubLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglStubConfigure,
+ puglMacVulkanCreate,
+ puglMacVulkanDestroy,
+ puglStubEnter,
+ puglStubLeave,
+ puglStubGetContext};
+
+ return &backend;
}
const char* const*
puglGetInstanceExtensions(uint32_t* const count)
{
- static const char* const extensions[] = {"VK_KHR_surface",
- "VK_MVK_macos_surface"};
+ static const char* const extensions[] = {"VK_KHR_surface",
+ "VK_MVK_macos_surface"};
- *count = 2;
- return extensions;
+ *count = 2;
+ return extensions;
}
VkResult
@@ -196,18 +194,18 @@ puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
const VkAllocationCallbacks* const allocator,
VkSurfaceKHR* const surface)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* const impl = view->impl;
- PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
- (PFN_vkCreateMacOSSurfaceMVK)
- vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
+ PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
+ (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
+ instance, "vkCreateMacOSSurfaceMVK");
- const VkMacOSSurfaceCreateInfoMVK info = {
- VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
- NULL,
- 0,
- impl->drawView,
- };
+ const VkMacOSSurfaceCreateInfoMVK info = {
+ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
+ NULL,
+ 0,
+ impl->drawView,
+ };
- return vkCreateMacOSSurfaceMVK(instance, &info, allocator, surface);
+ return vkCreateMacOSSurfaceMVK(instance, &info, allocator, surface);
}
diff --git a/src/stub.h b/src/stub.h
index 36d7364..e61085c 100644
--- a/src/stub.h
+++ b/src/stub.h
@@ -24,45 +24,45 @@ PUGL_BEGIN_DECLS
static inline PuglStatus
puglStubConfigure(PuglView* view)
{
- (void)view;
- return PUGL_SUCCESS;
+ (void)view;
+ return PUGL_SUCCESS;
}
static inline PuglStatus
puglStubCreate(PuglView* view)
{
- (void)view;
- return PUGL_SUCCESS;
+ (void)view;
+ return PUGL_SUCCESS;
}
static inline PuglStatus
puglStubDestroy(PuglView* view)
{
- (void)view;
- return PUGL_SUCCESS;
+ (void)view;
+ return PUGL_SUCCESS;
}
static inline PuglStatus
puglStubEnter(PuglView* view, const PuglEventExpose* expose)
{
- (void)view;
- (void)expose;
- return PUGL_SUCCESS;
+ (void)view;
+ (void)expose;
+ return PUGL_SUCCESS;
}
static inline PuglStatus
puglStubLeave(PuglView* view, const PuglEventExpose* expose)
{
- (void)view;
- (void)expose;
- return PUGL_SUCCESS;
+ (void)view;
+ (void)expose;
+ return PUGL_SUCCESS;
}
static inline void*
puglStubGetContext(PuglView* view)
{
- (void)view;
- return NULL;
+ (void)view;
+ return NULL;
}
PUGL_END_DECLS
diff --git a/src/types.h b/src/types.h
index 4e63d43..a618e8c 100644
--- a/src/types.h
+++ b/src/types.h
@@ -25,11 +25,11 @@
// Unused parameter macro to suppresses warnings and make it impossible to use
#if defined(__cplusplus)
-# define PUGL_UNUSED(name)
+# define PUGL_UNUSED(name)
#elif defined(__GNUC__) || defined(__clang__)
-# define PUGL_UNUSED(name) name##_unused __attribute__((__unused__))
+# define PUGL_UNUSED(name) name##_unused __attribute__((__unused__))
#else
-# define PUGL_UNUSED(name) name
+# define PUGL_UNUSED(name) name
#endif
/// Platform-specific world internals
@@ -43,45 +43,45 @@ typedef int PuglHints[PUGL_NUM_VIEW_HINTS];
/// Blob of arbitrary data
typedef struct {
- void* data; ///< Dynamically allocated data
- size_t len; ///< Length of data in bytes
+ void* data; ///< Dynamically allocated data
+ size_t len; ///< Length of data in bytes
} PuglBlob;
/// Cross-platform view definition
struct PuglViewImpl {
- PuglWorld* world;
- const PuglBackend* backend;
- PuglInternals* impl;
- PuglHandle handle;
- PuglEventFunc eventFunc;
- char* title;
- PuglBlob clipboard;
- PuglNativeView parent;
- uintptr_t transientParent;
- PuglRect frame;
- PuglEventConfigure lastConfigure;
- PuglHints hints;
- int defaultWidth;
- int defaultHeight;
- int minWidth;
- int minHeight;
- int maxWidth;
- int maxHeight;
- int minAspectX;
- int minAspectY;
- int maxAspectX;
- int maxAspectY;
- bool visible;
+ PuglWorld* world;
+ const PuglBackend* backend;
+ PuglInternals* impl;
+ PuglHandle handle;
+ PuglEventFunc eventFunc;
+ char* title;
+ PuglBlob clipboard;
+ PuglNativeView parent;
+ uintptr_t transientParent;
+ PuglRect frame;
+ PuglEventConfigure lastConfigure;
+ PuglHints hints;
+ int defaultWidth;
+ int defaultHeight;
+ int minWidth;
+ int minHeight;
+ int maxWidth;
+ int maxHeight;
+ int minAspectX;
+ int minAspectY;
+ int maxAspectX;
+ int maxAspectY;
+ bool visible;
};
/// Cross-platform world definition
struct PuglWorldImpl {
- PuglWorldInternals* impl;
- PuglWorldHandle handle;
- char* className;
- double startTime;
- size_t numViews;
- PuglView** views;
+ PuglWorldInternals* impl;
+ PuglWorldHandle handle;
+ char* className;
+ double startTime;
+ size_t numViews;
+ PuglView** views;
};
/// Opaque surface used by graphics backend
@@ -89,23 +89,23 @@ typedef void PuglSurface;
/// Graphics backend interface
struct PuglBackendImpl {
- /// Get visual information from display and setup view as necessary
- PuglStatus (*configure)(PuglView*);
+ /// Get visual information from display and setup view as necessary
+ PuglStatus (*configure)(PuglView*);
- /// Create surface and drawing context
- PuglStatus (*create)(PuglView*);
+ /// Create surface and drawing context
+ PuglStatus (*create)(PuglView*);
- /// Destroy surface and drawing context
- PuglStatus (*destroy)(PuglView*);
+ /// Destroy surface and drawing context
+ PuglStatus (*destroy)(PuglView*);
- /// Enter drawing context, for drawing if expose is non-null
- PuglStatus (*enter)(PuglView*, const PuglEventExpose*);
+ /// Enter drawing context, for drawing if expose is non-null
+ PuglStatus (*enter)(PuglView*, const PuglEventExpose*);
- /// Leave drawing context, after drawing if expose is non-null
- PuglStatus (*leave)(PuglView*, const PuglEventExpose*);
+ /// Leave drawing context, after drawing if expose is non-null
+ PuglStatus (*leave)(PuglView*, const PuglEventExpose*);
- /// Return the puglGetContext() handle for the application, if any
- void* (*getContext)(PuglView*);
+ /// Return the puglGetContext() handle for the application, if any
+ void* (*getContext)(PuglView*);
};
#endif // PUGL_DETAIL_TYPES_H
diff --git a/src/win.c b/src/win.c
index 44033fc..664912b 100644
--- a/src/win.c
+++ b/src/win.c
@@ -32,24 +32,24 @@
#include <wctype.h>
#ifndef WM_MOUSEWHEEL
-# define WM_MOUSEWHEEL 0x020A
+# define WM_MOUSEWHEEL 0x020A
#endif
#ifndef WM_MOUSEHWHEEL
-# define WM_MOUSEHWHEEL 0x020E
+# define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef WHEEL_DELTA
-# define WHEEL_DELTA 120
+# define WHEEL_DELTA 120
#endif
#ifndef GWLP_USERDATA
-# define GWLP_USERDATA (-21)
+# define GWLP_USERDATA (-21)
#endif
-#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)
-#define PUGL_LOCAL_MARK_MSG (WM_USER + 51)
+#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50)
+#define PUGL_LOCAL_MARK_MSG (WM_USER + 51)
#define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52)
-#define PUGL_USER_TIMER_MIN 9470
+#define PUGL_USER_TIMER_MIN 9470
-typedef BOOL (WINAPI *PFN_SetProcessDPIAware)(void);
+typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void);
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
@@ -57,268 +57,267 @@ wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static wchar_t*
puglUtf8ToWideChar(const char* const utf8)
{
- const int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
- if (len > 0) {
- wchar_t* result = (wchar_t*)calloc((size_t)len, sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, utf8, -1, result, len);
- return result;
- }
-
- return NULL;
+ const int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
+ if (len > 0) {
+ wchar_t* result = (wchar_t*)calloc((size_t)len, sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, utf8, -1, result, len);
+ return result;
+ }
+
+ return NULL;
}
static char*
puglWideCharToUtf8(const wchar_t* const wstr, size_t* len)
{
- int n = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
- if (n > 0) {
- char* result = (char*)calloc((size_t)n, sizeof(char));
- WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, n, NULL, NULL);
- *len = (size_t)n;
- return result;
- }
-
- return NULL;
+ int n = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
+ if (n > 0) {
+ char* result = (char*)calloc((size_t)n, sizeof(char));
+ WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, n, NULL, NULL);
+ *len = (size_t)n;
+ return result;
+ }
+
+ return NULL;
}
static bool
puglRegisterWindowClass(const char* name)
{
- WNDCLASSEX wc = { 0 };
- if (GetClassInfoEx(GetModuleHandle(NULL), name, &wc)) {
- return true; // Already registered
- }
-
- wc.cbSize = sizeof(wc);
- wc.style = CS_OWNDC;
- wc.lpfnWndProc = wndProc;
- wc.hInstance = GetModuleHandle(NULL);
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.lpszClassName = name;
-
- return RegisterClassEx(&wc);
+ WNDCLASSEX wc = {0};
+ if (GetClassInfoEx(GetModuleHandle(NULL), name, &wc)) {
+ return true; // Already registered
+ }
+
+ wc.cbSize = sizeof(wc);
+ wc.style = CS_OWNDC;
+ wc.lpfnWndProc = wndProc;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszClassName = name;
+
+ return RegisterClassEx(&wc);
}
PuglWorldInternals*
-puglInitWorldInternals(PuglWorldType PUGL_UNUSED(type),
+puglInitWorldInternals(PuglWorldType PUGL_UNUSED(type),
PuglWorldFlags PUGL_UNUSED(flags))
{
- PuglWorldInternals* impl = (PuglWorldInternals*)calloc(
- 1, sizeof(PuglWorldInternals));
- if (!impl) {
- return NULL;
- }
-
- HMODULE user32 = LoadLibrary("user32.dll");
- if (user32) {
- PFN_SetProcessDPIAware SetProcessDPIAware =
- (PFN_SetProcessDPIAware)GetProcAddress(
- user32, "SetProcessDPIAware");
- if (SetProcessDPIAware) {
- SetProcessDPIAware();
- }
-
- FreeLibrary(user32);
- }
-
- LARGE_INTEGER frequency;
- QueryPerformanceFrequency(&frequency);
- impl->timerFrequency = (double)frequency.QuadPart;
-
- return impl;
+ PuglWorldInternals* impl =
+ (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals));
+ if (!impl) {
+ return NULL;
+ }
+
+ HMODULE user32 = LoadLibrary("user32.dll");
+ if (user32) {
+ PFN_SetProcessDPIAware SetProcessDPIAware =
+ (PFN_SetProcessDPIAware)GetProcAddress(user32, "SetProcessDPIAware");
+ if (SetProcessDPIAware) {
+ SetProcessDPIAware();
+ }
+
+ FreeLibrary(user32);
+ }
+
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ impl->timerFrequency = (double)frequency.QuadPart;
+
+ return impl;
}
void*
puglGetNativeWorld(PuglWorld* PUGL_UNUSED(world))
{
- return GetModuleHandle(NULL);
+ return GetModuleHandle(NULL);
}
PuglInternals*
puglInitViewInternals(void)
{
- return (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ return (PuglInternals*)calloc(1, sizeof(PuglInternals));
}
static PuglStatus
puglPollWinEvents(PuglWorld* world, const double timeout)
{
- (void)world;
-
- if (timeout < 0) {
- WaitMessage();
- } else {
- MsgWaitForMultipleObjects(
- 0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS);
- }
- return PUGL_SUCCESS;
+ (void)world;
+
+ if (timeout < 0) {
+ WaitMessage();
+ } else {
+ MsgWaitForMultipleObjects(
+ 0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS);
+ }
+ return PUGL_SUCCESS;
}
PuglStatus
puglRealize(PuglView* view)
{
- PuglInternals* impl = view->impl;
- if (impl->hwnd) {
- return PUGL_FAILURE;
- }
-
- // 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);
- view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency;
-
- // Register window class if necessary
- if (!puglRegisterWindowClass(view->world->className)) {
- return PUGL_REGISTRATION_FAILED;
- }
-
- if (!view->backend || !view->backend->configure) {
- return PUGL_BAD_BACKEND;
- }
-
- PuglStatus st = PUGL_SUCCESS;
- if ((st = view->backend->configure(view)) ||
- (st = view->backend->create(view))) {
- return st;
- }
-
- if (view->title) {
- puglSetWindowTitle(view, view->title);
- }
-
- view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
-
- puglSetFrame(view, view->frame);
- SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
-
- puglDispatchSimpleEvent(view, PUGL_CREATE);
-
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+ if (impl->hwnd) {
+ return PUGL_FAILURE;
+ }
+
+ // 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);
+ view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency;
+
+ // Register window class if necessary
+ if (!puglRegisterWindowClass(view->world->className)) {
+ return PUGL_REGISTRATION_FAILED;
+ }
+
+ if (!view->backend || !view->backend->configure) {
+ return PUGL_BAD_BACKEND;
+ }
+
+ PuglStatus st = PUGL_SUCCESS;
+ if ((st = view->backend->configure(view)) ||
+ (st = view->backend->create(view))) {
+ return st;
+ }
+
+ if (view->title) {
+ puglSetWindowTitle(view, view->title);
+ }
+
+ view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
+
+ puglSetFrame(view, view->frame);
+ SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
+
+ puglDispatchSimpleEvent(view, PUGL_CREATE);
+
+ return PUGL_SUCCESS;
}
PuglStatus
puglShow(PuglView* view)
{
- PuglInternals* impl = view->impl;
-
- if (!impl->hwnd) {
- const PuglStatus st = puglRealize(view);
- if (st) {
- return st;
- }
- }
-
- ShowWindow(impl->hwnd, SW_SHOWNORMAL);
- SetFocus(impl->hwnd);
- return PUGL_SUCCESS;
+ PuglInternals* impl = view->impl;
+
+ if (!impl->hwnd) {
+ const PuglStatus st = puglRealize(view);
+ if (st) {
+ return st;
+ }
+ }
+
+ ShowWindow(impl->hwnd, SW_SHOWNORMAL);
+ SetFocus(impl->hwnd);
+ return PUGL_SUCCESS;
}
PuglStatus
puglHide(PuglView* view)
{
- PuglInternals* impl = view->impl;
+ PuglInternals* impl = view->impl;
- ShowWindow(impl->hwnd, SW_HIDE);
- return PUGL_SUCCESS;
+ ShowWindow(impl->hwnd, SW_HIDE);
+ return PUGL_SUCCESS;
}
void
puglFreeViewInternals(PuglView* view)
{
- if (view) {
- if (view->backend) {
- view->backend->destroy(view);
- }
-
- ReleaseDC(view->impl->hwnd, view->impl->hdc);
- DestroyWindow(view->impl->hwnd);
- free(view->impl);
- }
+ if (view) {
+ if (view->backend) {
+ view->backend->destroy(view);
+ }
+
+ ReleaseDC(view->impl->hwnd, view->impl->hdc);
+ DestroyWindow(view->impl->hwnd);
+ free(view->impl);
+ }
}
void
puglFreeWorldInternals(PuglWorld* world)
{
- UnregisterClass(world->className, NULL);
- free(world->impl);
+ UnregisterClass(world->className, NULL);
+ free(world->impl);
}
static PuglKey
keySymToSpecial(WPARAM sym)
{
- // clang-format off
- switch (sym) {
- case VK_F1: return PUGL_KEY_F1;
- case VK_F2: return PUGL_KEY_F2;
- case VK_F3: return PUGL_KEY_F3;
- case VK_F4: return PUGL_KEY_F4;
- case VK_F5: return PUGL_KEY_F5;
- case VK_F6: return PUGL_KEY_F6;
- case VK_F7: return PUGL_KEY_F7;
- case VK_F8: return PUGL_KEY_F8;
- case VK_F9: return PUGL_KEY_F9;
- case VK_F10: return PUGL_KEY_F10;
- case VK_F11: return PUGL_KEY_F11;
- case VK_F12: return PUGL_KEY_F12;
- case VK_BACK: return PUGL_KEY_BACKSPACE;
- case VK_DELETE: return PUGL_KEY_DELETE;
- case VK_LEFT: return PUGL_KEY_LEFT;
- case VK_UP: return PUGL_KEY_UP;
- case VK_RIGHT: return PUGL_KEY_RIGHT;
- case VK_DOWN: return PUGL_KEY_DOWN;
- case VK_PRIOR: return PUGL_KEY_PAGE_UP;
- case VK_NEXT: return PUGL_KEY_PAGE_DOWN;
- case VK_HOME: return PUGL_KEY_HOME;
- case VK_END: return PUGL_KEY_END;
- case VK_INSERT: return PUGL_KEY_INSERT;
- case VK_SHIFT:
- case VK_LSHIFT: return PUGL_KEY_SHIFT_L;
- case VK_RSHIFT: return PUGL_KEY_SHIFT_R;
- case VK_CONTROL:
- case VK_LCONTROL: return PUGL_KEY_CTRL_L;
- case VK_RCONTROL: return PUGL_KEY_CTRL_R;
- case VK_MENU:
- case VK_LMENU: return PUGL_KEY_ALT_L;
- case VK_RMENU: return PUGL_KEY_ALT_R;
- case VK_LWIN: return PUGL_KEY_SUPER_L;
- case VK_RWIN: return PUGL_KEY_SUPER_R;
- case VK_CAPITAL: return PUGL_KEY_CAPS_LOCK;
- case VK_SCROLL: return PUGL_KEY_SCROLL_LOCK;
- case VK_NUMLOCK: return PUGL_KEY_NUM_LOCK;
- case VK_SNAPSHOT: return PUGL_KEY_PRINT_SCREEN;
- case VK_PAUSE: return PUGL_KEY_PAUSE;
- }
- // clang-format on
-
- return (PuglKey)0;
+ // clang-format off
+ switch (sym) {
+ case VK_F1: return PUGL_KEY_F1;
+ case VK_F2: return PUGL_KEY_F2;
+ case VK_F3: return PUGL_KEY_F3;
+ case VK_F4: return PUGL_KEY_F4;
+ case VK_F5: return PUGL_KEY_F5;
+ case VK_F6: return PUGL_KEY_F6;
+ case VK_F7: return PUGL_KEY_F7;
+ case VK_F8: return PUGL_KEY_F8;
+ case VK_F9: return PUGL_KEY_F9;
+ case VK_F10: return PUGL_KEY_F10;
+ case VK_F11: return PUGL_KEY_F11;
+ case VK_F12: return PUGL_KEY_F12;
+ case VK_BACK: return PUGL_KEY_BACKSPACE;
+ case VK_DELETE: return PUGL_KEY_DELETE;
+ case VK_LEFT: return PUGL_KEY_LEFT;
+ case VK_UP: return PUGL_KEY_UP;
+ case VK_RIGHT: return PUGL_KEY_RIGHT;
+ case VK_DOWN: return PUGL_KEY_DOWN;
+ case VK_PRIOR: return PUGL_KEY_PAGE_UP;
+ case VK_NEXT: return PUGL_KEY_PAGE_DOWN;
+ case VK_HOME: return PUGL_KEY_HOME;
+ case VK_END: return PUGL_KEY_END;
+ case VK_INSERT: return PUGL_KEY_INSERT;
+ case VK_SHIFT:
+ case VK_LSHIFT: return PUGL_KEY_SHIFT_L;
+ case VK_RSHIFT: return PUGL_KEY_SHIFT_R;
+ case VK_CONTROL:
+ case VK_LCONTROL: return PUGL_KEY_CTRL_L;
+ case VK_RCONTROL: return PUGL_KEY_CTRL_R;
+ case VK_MENU:
+ case VK_LMENU: return PUGL_KEY_ALT_L;
+ case VK_RMENU: return PUGL_KEY_ALT_R;
+ case VK_LWIN: return PUGL_KEY_SUPER_L;
+ case VK_RWIN: return PUGL_KEY_SUPER_R;
+ case VK_CAPITAL: return PUGL_KEY_CAPS_LOCK;
+ case VK_SCROLL: return PUGL_KEY_SCROLL_LOCK;
+ case VK_NUMLOCK: return PUGL_KEY_NUM_LOCK;
+ case VK_SNAPSHOT: return PUGL_KEY_PRINT_SCREEN;
+ case VK_PAUSE: return PUGL_KEY_PAUSE;
+ }
+ // clang-format on
+
+ return (PuglKey)0;
}
static uint32_t
getModifiers(void)
{
- // clang-format off
- return (((GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0u) |
- ((GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0u) |
- ((GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0u) |
- ((GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0u) |
- ((GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0u));
- // clang-format on
+ // clang-format off
+ return (((GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0u) |
+ ((GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0u) |
+ ((GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0u) |
+ ((GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0u) |
+ ((GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0u));
+ // clang-format on
}
static void
@@ -328,59 +327,59 @@ initMouseEvent(PuglEvent* event,
bool press,
LPARAM lParam)
{
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- ClientToScreen(view->impl->hwnd, &pt);
-
- if (press) {
- SetCapture(view->impl->hwnd);
- } else {
- ReleaseCapture();
- }
-
- event->button.time = GetMessageTime() / 1e3;
- event->button.type = press ? PUGL_BUTTON_PRESS : PUGL_BUTTON_RELEASE;
- event->button.x = GET_X_LPARAM(lParam);
- event->button.y = GET_Y_LPARAM(lParam);
- event->button.xRoot = pt.x;
- event->button.yRoot = pt.y;
- event->button.state = getModifiers();
- event->button.button = (uint32_t)button;
+ POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ ClientToScreen(view->impl->hwnd, &pt);
+
+ if (press) {
+ SetCapture(view->impl->hwnd);
+ } else {
+ ReleaseCapture();
+ }
+
+ event->button.time = GetMessageTime() / 1e3;
+ event->button.type = press ? PUGL_BUTTON_PRESS : PUGL_BUTTON_RELEASE;
+ event->button.x = GET_X_LPARAM(lParam);
+ event->button.y = GET_Y_LPARAM(lParam);
+ event->button.xRoot = pt.x;
+ event->button.yRoot = pt.y;
+ event->button.state = getModifiers();
+ event->button.button = (uint32_t)button;
}
static void
initScrollEvent(PuglEvent* event, PuglView* view, LPARAM lParam)
{
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- ScreenToClient(view->impl->hwnd, &pt);
-
- event->scroll.time = GetMessageTime() / 1e3;
- event->scroll.type = PUGL_SCROLL;
- event->scroll.x = pt.x;
- event->scroll.y = pt.y;
- event->scroll.xRoot = GET_X_LPARAM(lParam);
- event->scroll.yRoot = GET_Y_LPARAM(lParam);
- event->scroll.state = getModifiers();
- event->scroll.dx = 0;
- event->scroll.dy = 0;
+ POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
+ ScreenToClient(view->impl->hwnd, &pt);
+
+ event->scroll.time = GetMessageTime() / 1e3;
+ event->scroll.type = PUGL_SCROLL;
+ event->scroll.x = pt.x;
+ event->scroll.y = pt.y;
+ event->scroll.xRoot = GET_X_LPARAM(lParam);
+ event->scroll.yRoot = GET_Y_LPARAM(lParam);
+ event->scroll.state = getModifiers();
+ event->scroll.dx = 0;
+ event->scroll.dy = 0;
}
/// Return the code point for buf, or the replacement character on error
static uint32_t
puglDecodeUTF16(const wchar_t* buf, const int len)
{
- const uint32_t c0 = buf[0];
- const uint32_t c1 = buf[0];
- if (c0 >= 0xD800 && c0 < 0xDC00) {
- if (len < 2) {
- return 0xFFFD; // Surrogate, but length is only 1
- } else if (c1 >= 0xDC00 && c1 <= 0xDFFF) {
- return ((c0 & 0x03FF) << 10) + (c1 & 0x03FF) + 0x10000;
- }
-
- return 0xFFFD; // Unpaired surrogates
- }
-
- return c0;
+ const uint32_t c0 = buf[0];
+ const uint32_t c1 = buf[0];
+ if (c0 >= 0xD800 && c0 < 0xDC00) {
+ if (len < 2) {
+ return 0xFFFD; // Surrogate, but length is only 1
+ } else if (c1 >= 0xDC00 && c1 <= 0xDFFF) {
+ return ((c0 & 0x03FF) << 10) + (c1 & 0x03FF) + 0x10000;
+ }
+
+ return 0xFFFD; // Unpaired surrogates
+ }
+
+ return c0;
}
static void
@@ -390,120 +389,120 @@ initKeyEvent(PuglEventKey* event,
WPARAM wParam,
LPARAM lParam)
{
- POINT rpos = { 0, 0 };
- GetCursorPos(&rpos);
-
- POINT cpos = { rpos.x, rpos.y };
- ScreenToClient(view->impl->hwnd, &rpos);
-
- const unsigned scode = (uint32_t)((lParam & 0xFF0000) >> 16);
- const unsigned vkey = ((wParam == VK_SHIFT)
- ? MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX)
- : (unsigned)wParam);
-
- const unsigned vcode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
- const unsigned kchar = MapVirtualKey(vkey, MAPVK_VK_TO_CHAR);
- const bool dead = kchar >> (sizeof(UINT) * 8 - 1) & 1;
- const bool ext = lParam & 0x01000000;
-
- event->type = press ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
- event->time = GetMessageTime() / 1e3;
- event->state = getModifiers();
- event->xRoot = rpos.x;
- event->yRoot = rpos.y;
- event->x = cpos.x;
- event->y = cpos.y;
- event->keycode = (uint32_t)((lParam & 0xFF0000) >> 16);
- event->key = 0;
-
- const PuglKey special = keySymToSpecial(vkey);
- if (special) {
- if (ext && (special == PUGL_KEY_CTRL || special == PUGL_KEY_ALT)) {
- event->key = (uint32_t)special + 1u; // Right hand key
- } else {
- event->key = (uint32_t)special;
- }
- } else if (!dead) {
- // Translate unshifted key
- BYTE keyboardState[256] = {0};
- wchar_t buf[5] = {0};
-
- event->key = puglDecodeUTF16(
- buf, ToUnicode(vkey, vcode, keyboardState, buf, 4, 1 << 2));
- }
+ POINT rpos = {0, 0};
+ GetCursorPos(&rpos);
+
+ POINT cpos = {rpos.x, rpos.y};
+ ScreenToClient(view->impl->hwnd, &rpos);
+
+ const unsigned scode = (uint32_t)((lParam & 0xFF0000) >> 16);
+ const unsigned vkey =
+ ((wParam == VK_SHIFT) ? MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX)
+ : (unsigned)wParam);
+
+ const unsigned vcode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
+ const unsigned kchar = MapVirtualKey(vkey, MAPVK_VK_TO_CHAR);
+ const bool dead = kchar >> (sizeof(UINT) * 8 - 1) & 1;
+ const bool ext = lParam & 0x01000000;
+
+ event->type = press ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE;
+ event->time = GetMessageTime() / 1e3;
+ event->state = getModifiers();
+ event->xRoot = rpos.x;
+ event->yRoot = rpos.y;
+ event->x = cpos.x;
+ event->y = cpos.y;
+ event->keycode = (uint32_t)((lParam & 0xFF0000) >> 16);
+ event->key = 0;
+
+ const PuglKey special = keySymToSpecial(vkey);
+ if (special) {
+ if (ext && (special == PUGL_KEY_CTRL || special == PUGL_KEY_ALT)) {
+ event->key = (uint32_t)special + 1u; // Right hand key
+ } else {
+ event->key = (uint32_t)special;
+ }
+ } else if (!dead) {
+ // Translate unshifted key
+ BYTE keyboardState[256] = {0};
+ wchar_t buf[5] = {0};
+
+ event->key = puglDecodeUTF16(
+ buf, ToUnicode(vkey, vcode, keyboardState, buf, 4, 1 << 2));
+ }
}
static void
initCharEvent(PuglEvent* event, PuglView* view, WPARAM wParam, LPARAM lParam)
{
- const wchar_t utf16[2] = {wParam & 0xFFFF,
- (wchar_t)((wParam >> 16) & 0xFFFF)};
+ const wchar_t utf16[2] = {wParam & 0xFFFF,
+ (wchar_t)((wParam >> 16) & 0xFFFF)};
- initKeyEvent(&event->key, view, true, wParam, lParam);
- event->type = PUGL_TEXT;
- event->text.character = puglDecodeUTF16(utf16, 2);
+ initKeyEvent(&event->key, view, true, wParam, lParam);
+ event->type = PUGL_TEXT;
+ event->text.character = puglDecodeUTF16(utf16, 2);
- if (!WideCharToMultiByte(
- CP_UTF8, 0, utf16, 2, event->text.string, 8, NULL, NULL)) {
- memset(event->text.string, 0, 8);
- }
+ if (!WideCharToMultiByte(
+ CP_UTF8, 0, utf16, 2, event->text.string, 8, NULL, NULL)) {
+ memset(event->text.string, 0, 8);
+ }
}
static bool
ignoreKeyEvent(PuglView* view, LPARAM lParam)
{
- return view->hints[PUGL_IGNORE_KEY_REPEAT] && (lParam & (1 << 30));
+ return view->hints[PUGL_IGNORE_KEY_REPEAT] && (lParam & (1 << 30));
}
static RECT
handleConfigure(PuglView* view, PuglEvent* event)
{
- RECT rect;
- GetClientRect(view->impl->hwnd, &rect);
- MapWindowPoints(view->impl->hwnd,
- view->parent ? (HWND)view->parent : HWND_DESKTOP,
- (LPPOINT)&rect,
- 2);
-
- const LONG width = rect.right - rect.left;
- const LONG height = rect.bottom - rect.top;
-
- view->frame.x = rect.left;
- view->frame.y = rect.top;
-
- event->configure.type = PUGL_CONFIGURE;
- event->configure.x = view->frame.x;
- event->configure.y = view->frame.y;
- event->configure.width = width;
- event->configure.height = height;
-
- if (view->frame.width != width || view->frame.height != height) {
- view->frame.width = width;
- view->frame.height = height;
- }
-
- return rect;
+ RECT rect;
+ GetClientRect(view->impl->hwnd, &rect);
+ MapWindowPoints(view->impl->hwnd,
+ view->parent ? (HWND)view->parent : HWND_DESKTOP,
+ (LPPOINT)&rect,
+ 2);
+
+ const LONG width = rect.right - rect.left;
+ const LONG height = rect.bottom - rect.top;
+
+ view->frame.x = rect.left;
+ view->frame.y = rect.top;
+
+ event->configure.type = PUGL_CONFIGURE;
+ event->configure.x = view->frame.x;
+ event->configure.y = view->frame.y;
+ event->configure.width = width;
+ event->configure.height = height;
+
+ if (view->frame.width != width || view->frame.height != height) {
+ view->frame.width = width;
+ view->frame.height = height;
+ }
+
+ return rect;
}
static void
handleCrossing(PuglView* view, const PuglEventType type, POINT pos)
{
- POINT root_pos = pos;
- ClientToScreen(view->impl->hwnd, &root_pos);
-
- const PuglEventCrossing ev = {
- type,
- 0,
- GetMessageTime() / 1e3,
- (double)pos.x,
- (double)pos.y,
- (double)root_pos.x,
- (double)root_pos.y,
- getModifiers(),
- PUGL_CROSSING_NORMAL,
- };
-
- puglDispatchEvent(view, (const PuglEvent*)&ev);
+ POINT root_pos = pos;
+ ClientToScreen(view->impl->hwnd, &root_pos);
+
+ const PuglEventCrossing ev = {
+ type,
+ 0,
+ GetMessageTime() / 1e3,
+ (double)pos.x,
+ (double)pos.y,
+ (double)root_pos.x,
+ (double)root_pos.y,
+ getModifiers(),
+ PUGL_CROSSING_NORMAL,
+ };
+
+ puglDispatchEvent(view, (const PuglEvent*)&ev);
}
static void
@@ -511,501 +510,497 @@ constrainAspect(const PuglView* const view,
RECT* const size,
const WPARAM wParam)
{
- const float minA = (float)view->minAspectX / (float)view->minAspectY;
- const float maxA = (float)view->maxAspectX / (float)view->maxAspectY;
- const float w = (float)(size->right - size->left);
- const float h = (float)(size->bottom - size->top);
- const float a = w / h;
-
- switch (wParam) {
- case WMSZ_TOP:
- size->top = (a < minA ? (LONG)((float)size->bottom - w * minA) :
- a > maxA ? (LONG)((float)size->bottom - w * maxA) :
- size->top);
- break;
- case WMSZ_TOPRIGHT:
- case WMSZ_RIGHT:
- case WMSZ_BOTTOMRIGHT:
- size->right = (a < minA ? (LONG)((float)size->left + h * minA) :
- a > maxA ? (LONG)((float)size->left + h * maxA) :
- size->right);
- break;
- case WMSZ_BOTTOM:
- size->bottom = (a < minA ? (LONG)((float)size->top + w * minA) :
- a > maxA ? (LONG)((float)size->top + w * maxA) :
- size->bottom);
- break;
- case WMSZ_BOTTOMLEFT:
- case WMSZ_LEFT:
- case WMSZ_TOPLEFT:
- size->left = (a < minA ? (LONG)((float)size->right - h * minA) :
- a > maxA ? (LONG)((float)size->right - h * maxA) :
- size->left);
- break;
- }
+ const float minA = (float)view->minAspectX / (float)view->minAspectY;
+ const float maxA = (float)view->maxAspectX / (float)view->maxAspectY;
+ const float w = (float)(size->right - size->left);
+ const float h = (float)(size->bottom - size->top);
+ const float a = w / h;
+
+ switch (wParam) {
+ case WMSZ_TOP:
+ size->top = (a < minA ? (LONG)((float)size->bottom - w * minA)
+ : a > maxA ? (LONG)((float)size->bottom - w * maxA)
+ : size->top);
+ break;
+ case WMSZ_TOPRIGHT:
+ case WMSZ_RIGHT:
+ case WMSZ_BOTTOMRIGHT:
+ size->right = (a < minA ? (LONG)((float)size->left + h * minA)
+ : a > maxA ? (LONG)((float)size->left + h * maxA)
+ : size->right);
+ break;
+ case WMSZ_BOTTOM:
+ size->bottom = (a < minA ? (LONG)((float)size->top + w * minA)
+ : a > maxA ? (LONG)((float)size->top + w * maxA)
+ : size->bottom);
+ break;
+ case WMSZ_BOTTOMLEFT:
+ case WMSZ_LEFT:
+ case WMSZ_TOPLEFT:
+ size->left = (a < minA ? (LONG)((float)size->right - h * minA)
+ : a > maxA ? (LONG)((float)size->right - h * maxA)
+ : size->left);
+ break;
+ }
}
static LRESULT
handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
{
- PuglEvent event = {{PUGL_NOTHING, 0}};
- RECT rect = {0, 0, 0, 0};
- POINT pt = {0, 0};
- MINMAXINFO* mmi = NULL;
- void* dummy_ptr = NULL;
-
- if (InSendMessageEx(dummy_ptr)) {
- event.any.flags |= PUGL_IS_SEND_EVENT;
- }
-
- switch (message) {
- case WM_SETCURSOR:
- if (LOWORD(lParam) == HTCLIENT) {
- SetCursor(view->impl->cursor);
- } else {
- return DefWindowProc(view->impl->hwnd, message, wParam, lParam);
- }
- break;
- case WM_SHOWWINDOW:
- if (wParam) {
- handleConfigure(view, &event);
- puglDispatchEvent(view, &event);
- event.type = PUGL_NOTHING;
-
- RedrawWindow(view->impl->hwnd, NULL, NULL,
- RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_INTERNALPAINT);
- }
-
- if ((bool)wParam != view->visible) {
- view->visible = wParam;
- event.any.type = wParam ? PUGL_MAP : PUGL_UNMAP;
- }
- break;
- case WM_SIZE:
- handleConfigure(view, &event);
- InvalidateRect(view->impl->hwnd, NULL, false);
- break;
- case WM_SIZING:
- if (view->minAspectX) {
- constrainAspect(view, (RECT*)lParam, wParam);
- return TRUE;
- }
- break;
- case WM_ENTERSIZEMOVE:
- case WM_ENTERMENULOOP:
- puglDispatchSimpleEvent(view, PUGL_LOOP_ENTER);
- break;
- case WM_TIMER:
- if (wParam >= PUGL_USER_TIMER_MIN) {
- PuglEvent ev = {{PUGL_TIMER, 0}};
- ev.timer.id = wParam - PUGL_USER_TIMER_MIN;
- puglDispatchEvent(view, &ev);
- }
- break;
- case WM_EXITSIZEMOVE:
- case WM_EXITMENULOOP:
- puglDispatchSimpleEvent(view, PUGL_LOOP_LEAVE);
- break;
- case WM_GETMINMAXINFO:
- mmi = (MINMAXINFO*)lParam;
- mmi->ptMinTrackSize.x = view->minWidth;
- mmi->ptMinTrackSize.y = view->minHeight;
- if (view->maxWidth > 0 && view->maxHeight > 0) {
- mmi->ptMaxTrackSize.x = view->maxWidth;
- mmi->ptMaxTrackSize.y = view->maxHeight;
- }
- break;
- case WM_PAINT:
- GetUpdateRect(view->impl->hwnd, &rect, false);
- event.expose.type = PUGL_EXPOSE;
- event.expose.x = rect.left;
- event.expose.y = rect.top;
- event.expose.width = rect.right - rect.left;
- event.expose.height = rect.bottom - rect.top;
- break;
- case WM_ERASEBKGND:
- return true;
- case WM_MOUSEMOVE:
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
-
- if (!view->impl->mouseTracked) {
- TRACKMOUSEEVENT tme = {0};
-
- tme.cbSize = sizeof(tme);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = view->impl->hwnd;
- TrackMouseEvent(&tme);
-
- handleCrossing(view, PUGL_POINTER_IN, pt);
- view->impl->mouseTracked = true;
- }
-
- ClientToScreen(view->impl->hwnd, &pt);
- event.motion.type = PUGL_MOTION;
- event.motion.time = GetMessageTime() / 1e3;
- event.motion.x = GET_X_LPARAM(lParam);
- event.motion.y = GET_Y_LPARAM(lParam);
- event.motion.xRoot = pt.x;
- event.motion.yRoot = pt.y;
- event.motion.state = getModifiers();
- break;
- case WM_MOUSELEAVE:
- GetCursorPos(&pt);
- ScreenToClient(view->impl->hwnd, &pt);
- handleCrossing(view, PUGL_POINTER_OUT, pt);
- view->impl->mouseTracked = false;
- break;
- case WM_LBUTTONDOWN:
- initMouseEvent(&event, view, 1, true, lParam);
- break;
- case WM_MBUTTONDOWN:
- initMouseEvent(&event, view, 2, true, lParam);
- break;
- case WM_RBUTTONDOWN:
- initMouseEvent(&event, view, 3, true, lParam);
- break;
- case WM_LBUTTONUP:
- initMouseEvent(&event, view, 1, false, lParam);
- break;
- case WM_MBUTTONUP:
- initMouseEvent(&event, view, 2, false, lParam);
- break;
- case WM_RBUTTONUP:
- initMouseEvent(&event, view, 3, false, lParam);
- break;
- case WM_MOUSEWHEEL:
- initScrollEvent(&event, view, lParam);
- event.scroll.dy = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA;
- event.scroll.direction = (event.scroll.dy > 0
- ? PUGL_SCROLL_UP
- : PUGL_SCROLL_DOWN);
- break;
- case WM_MOUSEHWHEEL:
- initScrollEvent(&event, view, lParam);
- event.scroll.dx = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA;
- event.scroll.direction = (event.scroll.dx > 0
- ? PUGL_SCROLL_RIGHT
- : PUGL_SCROLL_LEFT);
- break;
- case WM_KEYDOWN:
- if (!ignoreKeyEvent(view, lParam)) {
- initKeyEvent(&event.key, view, true, wParam, lParam);
- }
- break;
- case WM_KEYUP:
- initKeyEvent(&event.key, view, false, wParam, lParam);
- break;
- case WM_CHAR:
- initCharEvent(&event, view, wParam, lParam);
- break;
- case WM_SETFOCUS:
- event.type = PUGL_FOCUS_IN;
- break;
- case WM_KILLFOCUS:
- event.type = PUGL_FOCUS_OUT;
- break;
- case WM_SYSKEYDOWN:
- initKeyEvent(&event.key, view, true, wParam, lParam);
- break;
- case WM_SYSKEYUP:
- initKeyEvent(&event.key, view, false, wParam, lParam);
- break;
- case WM_SYSCHAR:
- return TRUE;
- case PUGL_LOCAL_CLIENT_MSG:
- event.client.type = PUGL_CLIENT;
- event.client.data1 = (uintptr_t)wParam;
- event.client.data2 = (uintptr_t)lParam;
- break;
- case WM_QUIT:
- case PUGL_LOCAL_CLOSE_MSG:
- event.any.type = PUGL_CLOSE;
- break;
- default:
- return DefWindowProc(view->impl->hwnd, message, wParam, lParam);
- }
-
- puglDispatchEvent(view, &event);
-
- return 0;
+ PuglEvent event = {{PUGL_NOTHING, 0}};
+ RECT rect = {0, 0, 0, 0};
+ POINT pt = {0, 0};
+ MINMAXINFO* mmi = NULL;
+ void* dummy_ptr = NULL;
+
+ if (InSendMessageEx(dummy_ptr)) {
+ event.any.flags |= PUGL_IS_SEND_EVENT;
+ }
+
+ switch (message) {
+ case WM_SETCURSOR:
+ if (LOWORD(lParam) == HTCLIENT) {
+ SetCursor(view->impl->cursor);
+ } else {
+ return DefWindowProc(view->impl->hwnd, message, wParam, lParam);
+ }
+ break;
+ case WM_SHOWWINDOW:
+ if (wParam) {
+ handleConfigure(view, &event);
+ puglDispatchEvent(view, &event);
+ event.type = PUGL_NOTHING;
+
+ RedrawWindow(view->impl->hwnd,
+ NULL,
+ NULL,
+ RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_INTERNALPAINT);
+ }
+
+ if ((bool)wParam != view->visible) {
+ view->visible = wParam;
+ event.any.type = wParam ? PUGL_MAP : PUGL_UNMAP;
+ }
+ break;
+ case WM_SIZE:
+ handleConfigure(view, &event);
+ InvalidateRect(view->impl->hwnd, NULL, false);
+ break;
+ case WM_SIZING:
+ if (view->minAspectX) {
+ constrainAspect(view, (RECT*)lParam, wParam);
+ return TRUE;
+ }
+ break;
+ case WM_ENTERSIZEMOVE:
+ case WM_ENTERMENULOOP:
+ puglDispatchSimpleEvent(view, PUGL_LOOP_ENTER);
+ break;
+ case WM_TIMER:
+ if (wParam >= PUGL_USER_TIMER_MIN) {
+ PuglEvent ev = {{PUGL_TIMER, 0}};
+ ev.timer.id = wParam - PUGL_USER_TIMER_MIN;
+ puglDispatchEvent(view, &ev);
+ }
+ break;
+ case WM_EXITSIZEMOVE:
+ case WM_EXITMENULOOP:
+ puglDispatchSimpleEvent(view, PUGL_LOOP_LEAVE);
+ break;
+ case WM_GETMINMAXINFO:
+ mmi = (MINMAXINFO*)lParam;
+ mmi->ptMinTrackSize.x = view->minWidth;
+ mmi->ptMinTrackSize.y = view->minHeight;
+ if (view->maxWidth > 0 && view->maxHeight > 0) {
+ mmi->ptMaxTrackSize.x = view->maxWidth;
+ mmi->ptMaxTrackSize.y = view->maxHeight;
+ }
+ break;
+ case WM_PAINT:
+ GetUpdateRect(view->impl->hwnd, &rect, false);
+ event.expose.type = PUGL_EXPOSE;
+ event.expose.x = rect.left;
+ event.expose.y = rect.top;
+ event.expose.width = rect.right - rect.left;
+ event.expose.height = rect.bottom - rect.top;
+ break;
+ case WM_ERASEBKGND:
+ return true;
+ case WM_MOUSEMOVE:
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (!view->impl->mouseTracked) {
+ TRACKMOUSEEVENT tme = {0};
+
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = view->impl->hwnd;
+ TrackMouseEvent(&tme);
+
+ handleCrossing(view, PUGL_POINTER_IN, pt);
+ view->impl->mouseTracked = true;
+ }
+
+ ClientToScreen(view->impl->hwnd, &pt);
+ event.motion.type = PUGL_MOTION;
+ event.motion.time = GetMessageTime() / 1e3;
+ event.motion.x = GET_X_LPARAM(lParam);
+ event.motion.y = GET_Y_LPARAM(lParam);
+ event.motion.xRoot = pt.x;
+ event.motion.yRoot = pt.y;
+ event.motion.state = getModifiers();
+ break;
+ case WM_MOUSELEAVE:
+ GetCursorPos(&pt);
+ ScreenToClient(view->impl->hwnd, &pt);
+ handleCrossing(view, PUGL_POINTER_OUT, pt);
+ view->impl->mouseTracked = false;
+ break;
+ case WM_LBUTTONDOWN:
+ initMouseEvent(&event, view, 1, true, lParam);
+ break;
+ case WM_MBUTTONDOWN:
+ initMouseEvent(&event, view, 2, true, lParam);
+ break;
+ case WM_RBUTTONDOWN:
+ initMouseEvent(&event, view, 3, true, lParam);
+ break;
+ case WM_LBUTTONUP:
+ initMouseEvent(&event, view, 1, false, lParam);
+ break;
+ case WM_MBUTTONUP:
+ initMouseEvent(&event, view, 2, false, lParam);
+ break;
+ case WM_RBUTTONUP:
+ initMouseEvent(&event, view, 3, false, lParam);
+ break;
+ case WM_MOUSEWHEEL:
+ initScrollEvent(&event, view, lParam);
+ event.scroll.dy = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA;
+ event.scroll.direction =
+ (event.scroll.dy > 0 ? PUGL_SCROLL_UP : PUGL_SCROLL_DOWN);
+ break;
+ case WM_MOUSEHWHEEL:
+ initScrollEvent(&event, view, lParam);
+ event.scroll.dx = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA;
+ event.scroll.direction =
+ (event.scroll.dx > 0 ? PUGL_SCROLL_RIGHT : PUGL_SCROLL_LEFT);
+ break;
+ case WM_KEYDOWN:
+ if (!ignoreKeyEvent(view, lParam)) {
+ initKeyEvent(&event.key, view, true, wParam, lParam);
+ }
+ break;
+ case WM_KEYUP:
+ initKeyEvent(&event.key, view, false, wParam, lParam);
+ break;
+ case WM_CHAR:
+ initCharEvent(&event, view, wParam, lParam);
+ break;
+ case WM_SETFOCUS:
+ event.type = PUGL_FOCUS_IN;
+ break;
+ case WM_KILLFOCUS:
+ event.type = PUGL_FOCUS_OUT;
+ break;
+ case WM_SYSKEYDOWN:
+ initKeyEvent(&event.key, view, true, wParam, lParam);
+ break;
+ case WM_SYSKEYUP:
+ initKeyEvent(&event.key, view, false, wParam, lParam);
+ break;
+ case WM_SYSCHAR:
+ return TRUE;
+ case PUGL_LOCAL_CLIENT_MSG:
+ event.client.type = PUGL_CLIENT;
+ event.client.data1 = (uintptr_t)wParam;
+ event.client.data2 = (uintptr_t)lParam;
+ break;
+ case WM_QUIT:
+ case PUGL_LOCAL_CLOSE_MSG:
+ event.any.type = PUGL_CLOSE;
+ break;
+ default:
+ return DefWindowProc(view->impl->hwnd, message, wParam, lParam);
+ }
+
+ puglDispatchEvent(view, &event);
+
+ return 0;
}
PuglStatus
puglGrabFocus(PuglView* view)
{
- SetFocus(view->impl->hwnd);
- return PUGL_SUCCESS;
+ SetFocus(view->impl->hwnd);
+ return PUGL_SUCCESS;
}
bool
puglHasFocus(const PuglView* view)
{
- return GetFocus() == view->impl->hwnd;
+ return GetFocus() == view->impl->hwnd;
}
PuglStatus
puglRequestAttention(PuglView* view)
{
- FLASHWINFO info = {sizeof(FLASHWINFO),
- view->impl->hwnd,
- FLASHW_ALL|FLASHW_TIMERNOFG,
- 1,
- 0};
+ FLASHWINFO info = {
+ sizeof(FLASHWINFO), view->impl->hwnd, FLASHW_ALL | FLASHW_TIMERNOFG, 1, 0};
- FlashWindowEx(&info);
+ FlashWindowEx(&info);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglStartTimer(PuglView* view, uintptr_t id, double timeout)
{
- const UINT msec = (UINT)floor(timeout * 1000.0);
+ const UINT msec = (UINT)floor(timeout * 1000.0);
- return (SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL)
- ? PUGL_SUCCESS
- : PUGL_UNKNOWN_ERROR);
+ return (SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR);
}
PuglStatus
puglStopTimer(PuglView* view, uintptr_t id)
{
- return (KillTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id)
- ? PUGL_SUCCESS
- : PUGL_UNKNOWN_ERROR);
+ return (KillTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR);
}
PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event)
{
- if (event->type == PUGL_CLIENT) {
- PostMessage(view->impl->hwnd,
- PUGL_LOCAL_CLIENT_MSG,
- (WPARAM)event->client.data1,
- (LPARAM)event->client.data2);
+ if (event->type == PUGL_CLIENT) {
+ PostMessage(view->impl->hwnd,
+ PUGL_LOCAL_CLIENT_MSG,
+ (WPARAM)event->client.data1,
+ (LPARAM)event->client.data2);
- return PUGL_SUCCESS;
- }
+ return PUGL_SUCCESS;
+ }
- return PUGL_UNSUPPORTED_TYPE;
+ return PUGL_UNSUPPORTED_TYPE;
}
#ifndef PUGL_DISABLE_DEPRECATED
PuglStatus
puglWaitForEvent(PuglView* PUGL_UNUSED(view))
{
- WaitMessage();
- return PUGL_SUCCESS;
+ WaitMessage();
+ return PUGL_SUCCESS;
}
#endif
static PuglStatus
puglDispatchViewEvents(PuglView* view)
{
- /* Windows has no facility to process only currently queued messages, which
- causes the event loop to run forever in cases like mouse movement where
- the queue is constantly being filled with new messages. To work around
- this, we post a message to ourselves before starting, record its time
- when it is received, then break the loop on the first message that was
- created afterwards. */
-
- long markTime = 0;
- MSG msg;
- while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) {
- if (msg.message == PUGL_LOCAL_MARK_MSG) {
- markTime = GetMessageTime();
- } else {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- if (markTime != 0 && GetMessageTime() > markTime) {
- break;
- }
- }
- }
-
- return PUGL_SUCCESS;
+ /* Windows has no facility to process only currently queued messages, which
+ causes the event loop to run forever in cases like mouse movement where
+ the queue is constantly being filled with new messages. To work around
+ this, we post a message to ourselves before starting, record its time
+ when it is received, then break the loop on the first message that was
+ created afterwards. */
+
+ long markTime = 0;
+ MSG msg;
+ while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) {
+ if (msg.message == PUGL_LOCAL_MARK_MSG) {
+ markTime = GetMessageTime();
+ } else {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ if (markTime != 0 && GetMessageTime() > markTime) {
+ break;
+ }
+ }
+ }
+
+ return PUGL_SUCCESS;
}
static PuglStatus
puglDispatchWinEvents(PuglWorld* world)
{
- for (size_t i = 0; i < world->numViews; ++i) {
- PostMessage(world->views[i]->impl->hwnd, PUGL_LOCAL_MARK_MSG, 0, 0);
- }
+ for (size_t i = 0; i < world->numViews; ++i) {
+ PostMessage(world->views[i]->impl->hwnd, PUGL_LOCAL_MARK_MSG, 0, 0);
+ }
- for (size_t i = 0; i < world->numViews; ++i) {
- puglDispatchViewEvents(world->views[i]);
- }
+ for (size_t i = 0; i < world->numViews; ++i) {
+ puglDispatchViewEvents(world->views[i]);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglUpdate(PuglWorld* world, double timeout)
{
- const double startTime = puglGetTime(world);
- PuglStatus st = PUGL_SUCCESS;
-
- if (timeout < 0.0) {
- st = puglPollWinEvents(world, timeout);
- st = st ? st : puglDispatchWinEvents(world);
- } else if (timeout == 0.0) {
- st = puglDispatchWinEvents(world);
- } else {
- const double endTime = startTime + timeout - 0.001;
- for (double t = startTime; t < endTime; t = puglGetTime(world)) {
- if ((st = puglPollWinEvents(world, endTime - t)) ||
- (st = puglDispatchWinEvents(world))) {
- break;
- }
- }
- }
-
- for (size_t i = 0; i < world->numViews; ++i) {
- if (world->views[i]->visible) {
- puglDispatchSimpleEvent(world->views[i], PUGL_UPDATE);
- }
-
- UpdateWindow(world->views[i]->impl->hwnd);
- }
-
- return st;
+ const double startTime = puglGetTime(world);
+ PuglStatus st = PUGL_SUCCESS;
+
+ if (timeout < 0.0) {
+ st = puglPollWinEvents(world, timeout);
+ st = st ? st : puglDispatchWinEvents(world);
+ } else if (timeout == 0.0) {
+ st = puglDispatchWinEvents(world);
+ } else {
+ const double endTime = startTime + timeout - 0.001;
+ for (double t = startTime; t < endTime; t = puglGetTime(world)) {
+ if ((st = puglPollWinEvents(world, endTime - t)) ||
+ (st = puglDispatchWinEvents(world))) {
+ break;
+ }
+ }
+ }
+
+ for (size_t i = 0; i < world->numViews; ++i) {
+ if (world->views[i]->visible) {
+ puglDispatchSimpleEvent(world->views[i], PUGL_UPDATE);
+ }
+
+ UpdateWindow(world->views[i]->impl->hwnd);
+ }
+
+ return st;
}
#ifndef PUGL_DISABLE_DEPRECATED
PuglStatus
puglProcessEvents(PuglView* view)
{
- return puglUpdate(view->world, 0.0);
+ return puglUpdate(view->world, 0.0);
}
#endif
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
-
- switch (message) {
- case WM_CREATE:
- PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0);
- return 0;
- case WM_CLOSE:
- PostMessage(hwnd, PUGL_LOCAL_CLOSE_MSG, wParam, lParam);
- return 0;
- case WM_DESTROY:
- return 0;
- default:
- if (view && hwnd == view->impl->hwnd) {
- return handleMessage(view, message, wParam, lParam);
- } else {
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
- }
+ PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (message) {
+ case WM_CREATE:
+ PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0);
+ return 0;
+ case WM_CLOSE:
+ PostMessage(hwnd, PUGL_LOCAL_CLOSE_MSG, wParam, lParam);
+ return 0;
+ case WM_DESTROY:
+ return 0;
+ default:
+ if (view && hwnd == view->impl->hwnd) {
+ return handleMessage(view, message, wParam, lParam);
+ } else {
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ }
}
double
puglGetTime(const PuglWorld* world)
{
- LARGE_INTEGER count;
- QueryPerformanceCounter(&count);
- return ((double)count.QuadPart / world->impl->timerFrequency -
- world->startTime);
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+ return ((double)count.QuadPart / world->impl->timerFrequency -
+ world->startTime);
}
PuglStatus
puglPostRedisplay(PuglView* view)
{
- InvalidateRect(view->impl->hwnd, NULL, false);
- return PUGL_SUCCESS;
+ InvalidateRect(view->impl->hwnd, NULL, false);
+ return PUGL_SUCCESS;
}
PuglStatus
puglPostRedisplayRect(PuglView* view, const PuglRect rect)
{
- const RECT r = {(long)floor(rect.x),
- (long)floor(rect.y),
- (long)ceil(rect.x + rect.width),
- (long)ceil(rect.y + rect.height)};
+ const RECT r = {(long)floor(rect.x),
+ (long)floor(rect.y),
+ (long)ceil(rect.x + rect.width),
+ (long)ceil(rect.y + rect.height)};
- InvalidateRect(view->impl->hwnd, &r, false);
+ InvalidateRect(view->impl->hwnd, &r, false);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglNativeView
puglGetNativeWindow(PuglView* view)
{
- return (PuglNativeView)view->impl->hwnd;
+ return (PuglNativeView)view->impl->hwnd;
}
PuglStatus
puglSetWindowTitle(PuglView* view, const char* title)
{
- puglSetString(&view->title, title);
+ puglSetString(&view->title, title);
- if (view->impl->hwnd) {
- wchar_t* wtitle = puglUtf8ToWideChar(title);
- if (wtitle) {
- SetWindowTextW(view->impl->hwnd, wtitle);
- free(wtitle);
- }
- }
+ if (view->impl->hwnd) {
+ wchar_t* wtitle = puglUtf8ToWideChar(title);
+ if (wtitle) {
+ SetWindowTextW(view->impl->hwnd, wtitle);
+ free(wtitle);
+ }
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
- view->frame = frame;
-
- if (view->impl->hwnd) {
- RECT rect = { (long)frame.x,
- (long)frame.y,
- (long)frame.x + (long)frame.width,
- (long)frame.y + (long)frame.height };
-
- AdjustWindowRectEx(&rect, puglWinGetWindowFlags(view),
- FALSE,
- puglWinGetWindowExFlags(view));
-
- if (!SetWindowPos(view->impl->hwnd,
- HWND_TOP,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER)) {
- return PUGL_UNKNOWN_ERROR;
- }
- }
-
- return PUGL_SUCCESS;
+ view->frame = frame;
+
+ if (view->impl->hwnd) {
+ RECT rect = {(long)frame.x,
+ (long)frame.y,
+ (long)frame.x + (long)frame.width,
+ (long)frame.y + (long)frame.height};
+
+ AdjustWindowRectEx(
+ &rect, puglWinGetWindowFlags(view), FALSE, puglWinGetWindowExFlags(view));
+
+ if (!SetWindowPos(view->impl->hwnd,
+ HWND_TOP,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER)) {
+ return PUGL_UNKNOWN_ERROR;
+ }
+ }
+
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetDefaultSize(PuglView* const view, const int width, const int height)
{
- view->defaultWidth = width;
- view->defaultHeight = height;
- return PUGL_SUCCESS;
+ view->defaultWidth = width;
+ view->defaultHeight = height;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetMinSize(PuglView* const view, const int width, const int height)
{
- view->minWidth = width;
- view->minHeight = height;
- return PUGL_SUCCESS;
+ view->minWidth = width;
+ view->minHeight = height;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetMaxSize(PuglView* const view, const int width, const int height)
{
- view->maxWidth = width;
- view->maxHeight = height;
- return PUGL_SUCCESS;
+ view->maxWidth = width;
+ view->maxHeight = height;
+ return PUGL_SUCCESS;
}
PuglStatus
@@ -1015,28 +1010,28 @@ puglSetAspectRatio(PuglView* const view,
const int maxX,
const int maxY)
{
- view->minAspectX = minX;
- view->minAspectY = minY;
- view->maxAspectX = maxX;
- view->maxAspectY = maxY;
- return PUGL_SUCCESS;
+ view->minAspectX = minX;
+ view->minAspectY = minY;
+ view->maxAspectX = maxX;
+ view->maxAspectY = maxY;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetTransientFor(PuglView* view, PuglNativeView parent)
{
- if (view->parent) {
- return PUGL_FAILURE;
- }
+ if (view->parent) {
+ return PUGL_FAILURE;
+ }
- view->transientParent = parent;
+ view->transientParent = parent;
- if (view->impl->hwnd) {
- SetWindowLongPtr(view->impl->hwnd, GWLP_HWNDPARENT, (LONG_PTR)parent);
- return GetLastError() == NO_ERROR ? PUGL_SUCCESS : PUGL_FAILURE;
- }
+ if (view->impl->hwnd) {
+ SetWindowLongPtr(view->impl->hwnd, GWLP_HWNDPARENT, (LONG_PTR)parent);
+ return GetLastError() == NO_ERROR ? PUGL_SUCCESS : PUGL_FAILURE;
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
const void*
@@ -1044,26 +1039,26 @@ puglGetClipboard(PuglView* const view,
const char** const type,
size_t* const len)
{
- PuglInternals* const impl = view->impl;
-
- if (!IsClipboardFormatAvailable(CF_UNICODETEXT) ||
- !OpenClipboard(impl->hwnd)) {
- return NULL;
- }
-
- HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
- wchar_t* wstr = mem ? (wchar_t*)GlobalLock(mem) : NULL;
- if (!wstr) {
- CloseClipboard();
- return NULL;
- }
-
- free(view->clipboard.data);
- view->clipboard.data = puglWideCharToUtf8(wstr, &view->clipboard.len);
- GlobalUnlock(mem);
- CloseClipboard();
-
- return puglGetInternalClipboard(view, type, len);
+ PuglInternals* const impl = view->impl;
+
+ if (!IsClipboardFormatAvailable(CF_UNICODETEXT) ||
+ !OpenClipboard(impl->hwnd)) {
+ return NULL;
+ }
+
+ HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
+ wchar_t* wstr = mem ? (wchar_t*)GlobalLock(mem) : NULL;
+ if (!wstr) {
+ CloseClipboard();
+ return NULL;
+ }
+
+ free(view->clipboard.data);
+ view->clipboard.data = puglWideCharToUtf8(wstr, &view->clipboard.len);
+ GlobalUnlock(mem);
+ CloseClipboard();
+
+ return puglGetInternalClipboard(view, type, len);
}
PuglStatus
@@ -1072,72 +1067,72 @@ puglSetClipboard(PuglView* const view,
const void* const data,
const size_t len)
{
- PuglInternals* const impl = view->impl;
-
- PuglStatus st = puglSetInternalClipboard(view, type, data, len);
- if (st) {
- return st;
- } else if (!OpenClipboard(impl->hwnd)) {
- return PUGL_UNKNOWN_ERROR;
- }
-
- // Measure string and allocate global memory for clipboard
- const char* str = (const char*)data;
- const int wlen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
- HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE,
- (size_t)(wlen + 1) * sizeof(wchar_t));
- if (!mem) {
- CloseClipboard();
- return PUGL_UNKNOWN_ERROR;
- }
-
- // Lock global memory
- wchar_t* wstr = (wchar_t*)GlobalLock(mem);
- if (!wstr) {
- GlobalFree(mem);
- CloseClipboard();
- return PUGL_UNKNOWN_ERROR;
- }
-
- // Convert string into global memory and set it as clipboard data
- MultiByteToWideChar(CP_UTF8, 0, str, (int)len, wstr, wlen);
- wstr[wlen] = 0;
- GlobalUnlock(mem);
- SetClipboardData(CF_UNICODETEXT, mem);
- CloseClipboard();
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+
+ PuglStatus st = puglSetInternalClipboard(view, type, data, len);
+ if (st) {
+ return st;
+ } else if (!OpenClipboard(impl->hwnd)) {
+ return PUGL_UNKNOWN_ERROR;
+ }
+
+ // Measure string and allocate global memory for clipboard
+ const char* str = (const char*)data;
+ const int wlen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ HGLOBAL mem =
+ GlobalAlloc(GMEM_MOVEABLE, (size_t)(wlen + 1) * sizeof(wchar_t));
+ if (!mem) {
+ CloseClipboard();
+ return PUGL_UNKNOWN_ERROR;
+ }
+
+ // Lock global memory
+ wchar_t* wstr = (wchar_t*)GlobalLock(mem);
+ if (!wstr) {
+ GlobalFree(mem);
+ CloseClipboard();
+ return PUGL_UNKNOWN_ERROR;
+ }
+
+ // Convert string into global memory and set it as clipboard data
+ MultiByteToWideChar(CP_UTF8, 0, str, (int)len, wstr, wlen);
+ wstr[wlen] = 0;
+ GlobalUnlock(mem);
+ SetClipboardData(CF_UNICODETEXT, mem);
+ CloseClipboard();
+ return PUGL_SUCCESS;
}
static const char* const cursor_ids[] = {
- IDC_ARROW, // ARROW
- IDC_IBEAM, // CARET
- IDC_CROSS, // CROSSHAIR
- IDC_HAND, // HAND
- IDC_NO, // NO
- IDC_SIZEWE, // LEFT_RIGHT
- IDC_SIZENS, // UP_DOWN
+ IDC_ARROW, // ARROW
+ IDC_IBEAM, // CARET
+ IDC_CROSS, // CROSSHAIR
+ IDC_HAND, // HAND
+ IDC_NO, // NO
+ IDC_SIZEWE, // LEFT_RIGHT
+ IDC_SIZENS, // UP_DOWN
};
PuglStatus
puglSetCursor(PuglView* view, PuglCursor cursor)
{
- PuglInternals* const impl = view->impl;
- const unsigned index = (unsigned)cursor;
- const unsigned count = sizeof(cursor_ids) / sizeof(cursor_ids[0]);
+ PuglInternals* const impl = view->impl;
+ const unsigned index = (unsigned)cursor;
+ const unsigned count = sizeof(cursor_ids) / sizeof(cursor_ids[0]);
- if (index >= count) {
- return PUGL_BAD_PARAMETER;
- }
+ if (index >= count) {
+ return PUGL_BAD_PARAMETER;
+ }
- const HCURSOR cur = LoadCursor(NULL, cursor_ids[index]);
- if (!cur) {
- return PUGL_FAILURE;
- }
+ const HCURSOR cur = LoadCursor(NULL, cursor_ids[index]);
+ if (!cur) {
+ return PUGL_FAILURE;
+ }
- impl->cursor = cur;
- if (impl->mouseTracked) {
- SetCursor(cur);
- }
+ impl->cursor = cur;
+ if (impl->mouseTracked) {
+ SetCursor(cur);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
diff --git a/src/win.h b/src/win.h
index bc1f763..ccab36a 100644
--- a/src/win.h
+++ b/src/win.h
@@ -26,62 +26,62 @@
typedef PIXELFORMATDESCRIPTOR PuglWinPFD;
struct PuglWorldInternalsImpl {
- double timerFrequency;
+ double timerFrequency;
};
struct PuglInternalsImpl {
- PuglWinPFD pfd;
- int pfId;
- HWND hwnd;
- HCURSOR cursor;
- HDC hdc;
- PuglSurface* surface;
- bool flashing;
- bool mouseTracked;
+ PuglWinPFD pfd;
+ int pfId;
+ HWND hwnd;
+ HCURSOR cursor;
+ HDC hdc;
+ PuglSurface* surface;
+ bool flashing;
+ bool mouseTracked;
};
static inline PuglWinPFD
puglWinGetPixelFormatDescriptor(const PuglHints hints)
{
- const int rgbBits = (hints[PUGL_RED_BITS] + //
- hints[PUGL_GREEN_BITS] + //
- hints[PUGL_BLUE_BITS]);
-
- const DWORD dwFlags = hints[PUGL_DOUBLE_BUFFER] ? PFD_DOUBLEBUFFER : 0u;
-
- PuglWinPFD pfd;
- ZeroMemory(&pfd, sizeof(pfd));
- pfd.nSize = sizeof(pfd);
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | dwFlags;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = (BYTE)rgbBits;
- pfd.cRedBits = (BYTE)hints[PUGL_RED_BITS];
- pfd.cGreenBits = (BYTE)hints[PUGL_GREEN_BITS];
- pfd.cBlueBits = (BYTE)hints[PUGL_BLUE_BITS];
- pfd.cAlphaBits = (BYTE)hints[PUGL_ALPHA_BITS];
- pfd.cDepthBits = (BYTE)hints[PUGL_DEPTH_BITS];
- pfd.cStencilBits = (BYTE)hints[PUGL_STENCIL_BITS];
- pfd.iLayerType = PFD_MAIN_PLANE;
- return pfd;
+ const int rgbBits = (hints[PUGL_RED_BITS] + //
+ hints[PUGL_GREEN_BITS] + //
+ hints[PUGL_BLUE_BITS]);
+
+ const DWORD dwFlags = hints[PUGL_DOUBLE_BUFFER] ? PFD_DOUBLEBUFFER : 0u;
+
+ PuglWinPFD pfd;
+ ZeroMemory(&pfd, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | dwFlags;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = (BYTE)rgbBits;
+ pfd.cRedBits = (BYTE)hints[PUGL_RED_BITS];
+ pfd.cGreenBits = (BYTE)hints[PUGL_GREEN_BITS];
+ pfd.cBlueBits = (BYTE)hints[PUGL_BLUE_BITS];
+ pfd.cAlphaBits = (BYTE)hints[PUGL_ALPHA_BITS];
+ pfd.cDepthBits = (BYTE)hints[PUGL_DEPTH_BITS];
+ pfd.cStencilBits = (BYTE)hints[PUGL_STENCIL_BITS];
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ return pfd;
}
static inline unsigned
puglWinGetWindowFlags(const PuglView* const view)
{
- const bool resizable = view->hints[PUGL_RESIZABLE];
- const unsigned sizeFlags = resizable ? (WS_SIZEBOX | WS_MAXIMIZEBOX) : 0u;
+ const bool resizable = view->hints[PUGL_RESIZABLE];
+ const unsigned sizeFlags = resizable ? (WS_SIZEBOX | WS_MAXIMIZEBOX) : 0u;
- return (WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
- (view->parent
- ? WS_CHILD
- : (WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | sizeFlags)));
+ return (WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
+ (view->parent
+ ? WS_CHILD
+ : (WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | sizeFlags)));
}
static inline unsigned
puglWinGetWindowExFlags(const PuglView* const view)
{
- return WS_EX_NOINHERITLAYOUT | (view->parent ? 0u : WS_EX_APPWINDOW);
+ return WS_EX_NOINHERITLAYOUT | (view->parent ? 0u : WS_EX_APPWINDOW);
}
static inline PuglStatus
@@ -90,48 +90,58 @@ puglWinCreateWindow(PuglView* const view,
HWND* const hwnd,
HDC* const hdc)
{
- const char* className = (const char*)view->world->className;
- const unsigned winFlags = puglWinGetWindowFlags(view);
- const unsigned winExFlags = puglWinGetWindowExFlags(view);
-
- if (view->frame.width == 0.0 && view->frame.height == 0.0) {
- if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) {
- return PUGL_BAD_CONFIGURATION;
- }
-
- RECT desktopRect;
- GetClientRect(GetDesktopWindow(), &desktopRect);
-
- const int screenWidth = desktopRect.right - desktopRect.left;
- const int screenHeight = desktopRect.bottom - desktopRect.top;
-
- view->frame.width = view->defaultWidth;
- view->frame.height = view->defaultHeight;
- view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0;
- view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0;
- }
-
- // The meaning of "parent" depends on the window type (WS_CHILD)
- PuglNativeView parent = view->parent ? view->parent : view->transientParent;
-
- // Calculate total window size to accommodate requested view size
- RECT wr = { (long)view->frame.x, (long)view->frame.y,
- (long)view->frame.width, (long)view->frame.height };
- AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
-
- // Create window and get drawing context
- if (!(*hwnd = CreateWindowEx(winExFlags, className, title, winFlags,
- CW_USEDEFAULT, CW_USEDEFAULT,
- wr.right-wr.left, wr.bottom-wr.top,
- (HWND)parent, NULL, NULL, NULL))) {
- return PUGL_REALIZE_FAILED;
- } else if (!(*hdc = GetDC(*hwnd))) {
- DestroyWindow(*hwnd);
- *hwnd = NULL;
- return PUGL_REALIZE_FAILED;
- }
-
- return PUGL_SUCCESS;
+ const char* className = (const char*)view->world->className;
+ const unsigned winFlags = puglWinGetWindowFlags(view);
+ const unsigned winExFlags = puglWinGetWindowExFlags(view);
+
+ if (view->frame.width == 0.0 && view->frame.height == 0.0) {
+ if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) {
+ return PUGL_BAD_CONFIGURATION;
+ }
+
+ RECT desktopRect;
+ GetClientRect(GetDesktopWindow(), &desktopRect);
+
+ const int screenWidth = desktopRect.right - desktopRect.left;
+ const int screenHeight = desktopRect.bottom - desktopRect.top;
+
+ view->frame.width = view->defaultWidth;
+ view->frame.height = view->defaultHeight;
+ view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0;
+ view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0;
+ }
+
+ // The meaning of "parent" depends on the window type (WS_CHILD)
+ PuglNativeView parent = view->parent ? view->parent : view->transientParent;
+
+ // Calculate total window size to accommodate requested view size
+ RECT wr = {(long)view->frame.x,
+ (long)view->frame.y,
+ (long)view->frame.width,
+ (long)view->frame.height};
+ AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
+
+ // Create window and get drawing context
+ if (!(*hwnd = CreateWindowEx(winExFlags,
+ className,
+ title,
+ winFlags,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ wr.right - wr.left,
+ wr.bottom - wr.top,
+ (HWND)parent,
+ NULL,
+ NULL,
+ NULL))) {
+ return PUGL_REALIZE_FAILED;
+ } else if (!(*hdc = GetDC(*hwnd))) {
+ DestroyWindow(*hwnd);
+ *hwnd = NULL;
+ return PUGL_REALIZE_FAILED;
+ }
+
+ return PUGL_SUCCESS;
}
PuglStatus
diff --git a/src/win_cairo.c b/src/win_cairo.c
index bab8ea0..9dc5ce0 100644
--- a/src/win_cairo.c
+++ b/src/win_cairo.c
@@ -25,149 +25,154 @@
#include <stdlib.h>
-typedef struct {
- cairo_surface_t* surface;
- cairo_t* cr;
- HDC drawDc;
- HBITMAP drawBitmap;
+typedef struct {
+ cairo_surface_t* surface;
+ cairo_t* cr;
+ HDC drawDc;
+ HBITMAP drawBitmap;
} PuglWinCairoSurface;
static PuglStatus
puglWinCairoCreateDrawContext(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
- surface->drawDc = CreateCompatibleDC(impl->hdc);
- surface->drawBitmap = CreateCompatibleBitmap(
- impl->hdc, (int)view->frame.width, (int)view->frame.height);
+ surface->drawDc = CreateCompatibleDC(impl->hdc);
+ surface->drawBitmap = CreateCompatibleBitmap(
+ impl->hdc, (int)view->frame.width, (int)view->frame.height);
- DeleteObject(SelectObject(surface->drawDc, surface->drawBitmap));
+ DeleteObject(SelectObject(surface->drawDc, surface->drawBitmap));
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinCairoDestroyDrawContext(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
- DeleteDC(surface->drawDc);
- DeleteObject(surface->drawBitmap);
+ DeleteDC(surface->drawDc);
+ DeleteObject(surface->drawBitmap);
- surface->drawDc = NULL;
- surface->drawBitmap = NULL;
+ surface->drawDc = NULL;
+ surface->drawBitmap = NULL;
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinCairoConfigure(PuglView* view)
{
- const PuglStatus st = puglWinStubConfigure(view);
+ const PuglStatus st = puglWinStubConfigure(view);
- if (!st) {
- view->impl->surface = (PuglWinCairoSurface*)calloc(
- 1, sizeof(PuglWinCairoSurface));
- }
+ if (!st) {
+ view->impl->surface =
+ (PuglWinCairoSurface*)calloc(1, sizeof(PuglWinCairoSurface));
+ }
- return st;
+ return st;
}
static void
puglWinCairoClose(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
- cairo_surface_destroy(surface->surface);
+ cairo_surface_destroy(surface->surface);
- surface->surface = NULL;
+ surface->surface = NULL;
}
static PuglStatus
puglWinCairoOpen(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
- if (!(surface->surface = cairo_win32_surface_create(surface->drawDc)) ||
- cairo_surface_status(surface->surface) ||
- !(surface->cr = cairo_create(surface->surface)) ||
- cairo_status(surface->cr)) {
- return PUGL_CREATE_CONTEXT_FAILED;
- }
+ if (!(surface->surface = cairo_win32_surface_create(surface->drawDc)) ||
+ cairo_surface_status(surface->surface) ||
+ !(surface->cr = cairo_create(surface->surface)) ||
+ cairo_status(surface->cr)) {
+ return PUGL_CREATE_CONTEXT_FAILED;
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinCairoDestroy(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
- puglWinCairoClose(view);
- puglWinCairoDestroyDrawContext(view);
- free(surface);
- impl->surface = NULL;
+ puglWinCairoClose(view);
+ puglWinCairoDestroyDrawContext(view);
+ free(surface);
+ impl->surface = NULL;
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinCairoEnter(PuglView* view, const PuglEventExpose* expose)
{
- PuglStatus st = PUGL_SUCCESS;
+ PuglStatus st = PUGL_SUCCESS;
- if (expose &&
- !(st = puglWinCairoCreateDrawContext(view)) &&
- !(st = puglWinCairoOpen(view))) {
- PAINTSTRUCT ps;
- BeginPaint(view->impl->hwnd, &ps);
- }
+ if (expose && !(st = puglWinCairoCreateDrawContext(view)) &&
+ !(st = puglWinCairoOpen(view))) {
+ PAINTSTRUCT ps;
+ BeginPaint(view->impl->hwnd, &ps);
+ }
- return st;
+ return st;
}
static PuglStatus
puglWinCairoLeave(PuglView* view, const PuglEventExpose* expose)
{
- PuglInternals* const impl = view->impl;
- PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
-
- if (expose) {
- cairo_surface_flush(surface->surface);
- BitBlt(impl->hdc,
- 0, 0, (int)view->frame.width, (int)view->frame.height,
- surface->drawDc, 0, 0, SRCCOPY);
-
- puglWinCairoClose(view);
- puglWinCairoDestroyDrawContext(view);
-
- PAINTSTRUCT ps;
- EndPaint(view->impl->hwnd, &ps);
- }
-
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface;
+
+ if (expose) {
+ cairo_surface_flush(surface->surface);
+ BitBlt(impl->hdc,
+ 0,
+ 0,
+ (int)view->frame.width,
+ (int)view->frame.height,
+ surface->drawDc,
+ 0,
+ 0,
+ SRCCOPY);
+
+ puglWinCairoClose(view);
+ puglWinCairoDestroyDrawContext(view);
+
+ PAINTSTRUCT ps;
+ EndPaint(view->impl->hwnd, &ps);
+ }
+
+ return PUGL_SUCCESS;
}
static void*
puglWinCairoGetContext(PuglView* view)
{
- return ((PuglWinCairoSurface*)view->impl->surface)->cr;
+ return ((PuglWinCairoSurface*)view->impl->surface)->cr;
}
const PuglBackend*
puglCairoBackend()
{
- static const PuglBackend backend = {puglWinCairoConfigure,
- puglStubCreate,
- puglWinCairoDestroy,
- puglWinCairoEnter,
- puglWinCairoLeave,
- puglWinCairoGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglWinCairoConfigure,
+ puglStubCreate,
+ puglWinCairoDestroy,
+ puglWinCairoEnter,
+ puglWinCairoLeave,
+ puglWinCairoGetContext};
+
+ return &backend;
}
diff --git a/src/win_gl.c b/src/win_gl.c
index fcf511b..4abd5ab 100644
--- a/src/win_gl.c
+++ b/src/win_gl.c
@@ -27,305 +27,301 @@
#include <stdbool.h>
#include <stdlib.h>
-#define WGL_DRAW_TO_WINDOW_ARB 0x2001
-#define WGL_ACCELERATION_ARB 0x2003
-#define WGL_SUPPORT_OPENGL_ARB 0x2010
-#define WGL_DOUBLE_BUFFER_ARB 0x2011
-#define WGL_PIXEL_TYPE_ARB 0x2013
-#define WGL_RED_BITS_ARB 0x2015
-#define WGL_GREEN_BITS_ARB 0x2017
-#define WGL_BLUE_BITS_ARB 0x2019
-#define WGL_ALPHA_BITS_ARB 0x201b
-#define WGL_DEPTH_BITS_ARB 0x2022
-#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_ALPHA_BITS_ARB 0x201b
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_FULL_ACCELERATION_ARB 0x2027
-#define WGL_TYPE_RGBA_ARB 0x202b
-#define WGL_SAMPLE_BUFFERS_ARB 0x2041
-#define WGL_SAMPLES_ARB 0x2042
+#define WGL_TYPE_RGBA_ARB 0x202b
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
typedef HGLRC (*WglCreateContextAttribs)(HDC, HGLRC, const int*);
typedef BOOL (*WglSwapInterval)(int);
-typedef BOOL (*WglChoosePixelFormat)(
- HDC, const int*, const FLOAT*, UINT, int*, UINT*);
+typedef BOOL (
+ *WglChoosePixelFormat)(HDC, const int*, const FLOAT*, UINT, int*, UINT*);
typedef struct {
- WglChoosePixelFormat wglChoosePixelFormat;
- WglCreateContextAttribs wglCreateContextAttribs;
- WglSwapInterval wglSwapInterval;
+ WglChoosePixelFormat wglChoosePixelFormat;
+ WglCreateContextAttribs wglCreateContextAttribs;
+ WglSwapInterval wglSwapInterval;
} PuglWinGlProcs;
typedef struct {
- PuglWinGlProcs procs;
- HGLRC hglrc;
+ PuglWinGlProcs procs;
+ HGLRC hglrc;
} PuglWinGlSurface;
// Struct to manage the fake window used during configuration
typedef struct {
- HWND hwnd;
- HDC hdc;
+ HWND hwnd;
+ HDC hdc;
} PuglFakeWindow;
static PuglStatus
puglWinError(PuglFakeWindow* fakeWin, const PuglStatus status)
{
- if (fakeWin->hwnd) {
- ReleaseDC(fakeWin->hwnd, fakeWin->hdc);
- DestroyWindow(fakeWin->hwnd);
- }
+ if (fakeWin->hwnd) {
+ ReleaseDC(fakeWin->hwnd, fakeWin->hdc);
+ DestroyWindow(fakeWin->hwnd);
+ }
- return status;
+ return status;
}
-static PuglWinGlProcs puglWinGlGetProcs(void)
+static PuglWinGlProcs
+puglWinGlGetProcs(void)
{
- const PuglWinGlProcs procs = {
- (WglChoosePixelFormat)(
- wglGetProcAddress("wglChoosePixelFormatARB")),
- (WglCreateContextAttribs)(
- wglGetProcAddress("wglCreateContextAttribsARB")),
- (WglSwapInterval)(
- wglGetProcAddress("wglSwapIntervalEXT"))
- };
-
- return procs;
+ const PuglWinGlProcs procs = {
+ (WglChoosePixelFormat)(wglGetProcAddress("wglChoosePixelFormatARB")),
+ (WglCreateContextAttribs)(wglGetProcAddress("wglCreateContextAttribsARB")),
+ (WglSwapInterval)(wglGetProcAddress("wglSwapIntervalEXT"))};
+
+ return procs;
}
static PuglStatus
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,
- WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
- WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
- WGL_DOUBLE_BUFFER_ARB, view->hints[PUGL_DOUBLE_BUFFER],
- WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
- WGL_SAMPLE_BUFFERS_ARB, view->hints[PUGL_SAMPLES] ? 1 : 0,
- WGL_SAMPLES_ARB, view->hints[PUGL_SAMPLES],
- WGL_RED_BITS_ARB, view->hints[PUGL_RED_BITS],
- WGL_GREEN_BITS_ARB, view->hints[PUGL_GREEN_BITS],
- WGL_BLUE_BITS_ARB, view->hints[PUGL_BLUE_BITS],
- WGL_ALPHA_BITS_ARB, view->hints[PUGL_ALPHA_BITS],
- WGL_DEPTH_BITS_ARB, view->hints[PUGL_DEPTH_BITS],
- WGL_STENCIL_BITS_ARB, view->hints[PUGL_STENCIL_BITS],
- 0,
- };
- // clang-format on
-
- PuglWinGlSurface* const surface =
- (PuglWinGlSurface*)calloc(1, sizeof(PuglWinGlSurface));
- impl->surface = surface;
-
- // Create fake window for getting at GL context
- PuglStatus st = PUGL_SUCCESS;
- PuglFakeWindow fakeWin = {0, 0};
- static const char* title = "Pugl Configuration";
- if ((st = puglWinCreateWindow(view, title, &fakeWin.hwnd, &fakeWin.hdc))) {
- return puglWinError(&fakeWin, st);
- }
-
- // Set pixel format for fake window
- const PuglWinPFD fakePfd = puglWinGetPixelFormatDescriptor(view->hints);
- const int fakePfId = ChoosePixelFormat(fakeWin.hdc, &fakePfd);
- if (!fakePfId || !SetPixelFormat(fakeWin.hdc, fakePfId, &fakePfd)) {
- return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
- }
-
- // Create fake GL context to get at the functions we need
- HGLRC fakeRc = wglCreateContext(fakeWin.hdc);
- if (!fakeRc) {
- return puglWinError(&fakeWin, PUGL_CREATE_CONTEXT_FAILED);
- }
-
- // Enter fake context and get extension functions
- wglMakeCurrent(fakeWin.hdc, fakeRc);
- surface->procs = puglWinGlGetProcs();
-
- if (surface->procs.wglChoosePixelFormat) {
- // Choose pixel format based on attributes
- UINT numFormats = 0;
- if (!surface->procs.wglChoosePixelFormat(
- fakeWin.hdc, pixelAttrs, NULL, 1u, &impl->pfId, &numFormats)) {
- return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
- }
-
- DescribePixelFormat(
- impl->hdc, impl->pfId, sizeof(impl->pfd), &impl->pfd);
- } else {
- // Modern extensions not available, use basic pixel format
- impl->pfd = fakePfd;
- impl->pfId = fakePfId;
- }
-
- // Dispose of fake window and context
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(fakeRc);
- ReleaseDC(fakeWin.hwnd, fakeWin.hdc);
- DestroyWindow(fakeWin.hwnd);
-
- return PUGL_SUCCESS;
+ 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,
+ WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+ WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
+ WGL_DOUBLE_BUFFER_ARB, view->hints[PUGL_DOUBLE_BUFFER],
+ WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
+ WGL_SAMPLE_BUFFERS_ARB, view->hints[PUGL_SAMPLES] ? 1 : 0,
+ WGL_SAMPLES_ARB, view->hints[PUGL_SAMPLES],
+ WGL_RED_BITS_ARB, view->hints[PUGL_RED_BITS],
+ WGL_GREEN_BITS_ARB, view->hints[PUGL_GREEN_BITS],
+ WGL_BLUE_BITS_ARB, view->hints[PUGL_BLUE_BITS],
+ WGL_ALPHA_BITS_ARB, view->hints[PUGL_ALPHA_BITS],
+ WGL_DEPTH_BITS_ARB, view->hints[PUGL_DEPTH_BITS],
+ WGL_STENCIL_BITS_ARB, view->hints[PUGL_STENCIL_BITS],
+ 0,
+ };
+ // clang-format on
+
+ PuglWinGlSurface* const surface =
+ (PuglWinGlSurface*)calloc(1, sizeof(PuglWinGlSurface));
+ impl->surface = surface;
+
+ // Create fake window for getting at GL context
+ PuglStatus st = PUGL_SUCCESS;
+ PuglFakeWindow fakeWin = {0, 0};
+ static const char* title = "Pugl Configuration";
+ if ((st = puglWinCreateWindow(view, title, &fakeWin.hwnd, &fakeWin.hdc))) {
+ return puglWinError(&fakeWin, st);
+ }
+
+ // Set pixel format for fake window
+ const PuglWinPFD fakePfd = puglWinGetPixelFormatDescriptor(view->hints);
+ const int fakePfId = ChoosePixelFormat(fakeWin.hdc, &fakePfd);
+ if (!fakePfId || !SetPixelFormat(fakeWin.hdc, fakePfId, &fakePfd)) {
+ return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
+ }
+
+ // Create fake GL context to get at the functions we need
+ HGLRC fakeRc = wglCreateContext(fakeWin.hdc);
+ if (!fakeRc) {
+ return puglWinError(&fakeWin, PUGL_CREATE_CONTEXT_FAILED);
+ }
+
+ // Enter fake context and get extension functions
+ wglMakeCurrent(fakeWin.hdc, fakeRc);
+ surface->procs = puglWinGlGetProcs();
+
+ if (surface->procs.wglChoosePixelFormat) {
+ // Choose pixel format based on attributes
+ UINT numFormats = 0;
+ if (!surface->procs.wglChoosePixelFormat(
+ fakeWin.hdc, pixelAttrs, NULL, 1u, &impl->pfId, &numFormats)) {
+ return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED);
+ }
+
+ DescribePixelFormat(impl->hdc, impl->pfId, sizeof(impl->pfd), &impl->pfd);
+ } else {
+ // Modern extensions not available, use basic pixel format
+ impl->pfd = fakePfd;
+ impl->pfId = fakePfId;
+ }
+
+ // Dispose of fake window and context
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(fakeRc);
+ ReleaseDC(fakeWin.hwnd, fakeWin.hdc);
+ DestroyWindow(fakeWin.hwnd);
+
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinGlCreate(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWinGlSurface* const surface = (PuglWinGlSurface*)impl->surface;
- PuglStatus st = PUGL_SUCCESS;
-
- const int contextAttribs[] = {
- WGL_CONTEXT_MAJOR_VERSION_ARB,
- view->hints[PUGL_CONTEXT_VERSION_MAJOR],
-
- WGL_CONTEXT_MINOR_VERSION_ARB,
- view->hints[PUGL_CONTEXT_VERSION_MINOR],
-
- WGL_CONTEXT_FLAGS_ARB,
- (view->hints[PUGL_USE_DEBUG_CONTEXT] ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
-
- WGL_CONTEXT_PROFILE_MASK_ARB,
- (view->hints[PUGL_USE_COMPAT_PROFILE]
- ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB
- : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB),
-
- 0};
-
- // Create real window with desired pixel format
- if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) {
- return st;
- } else if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) {
- ReleaseDC(impl->hwnd, impl->hdc);
- DestroyWindow(impl->hwnd);
- impl->hwnd = NULL;
- impl->hdc = NULL;
- return PUGL_SET_FORMAT_FAILED;
- }
-
- // Create GL context
- if (surface->procs.wglCreateContextAttribs &&
- !(surface->hglrc = surface->procs.wglCreateContextAttribs(
- impl->hdc, 0, contextAttribs))) {
- return PUGL_CREATE_CONTEXT_FAILED;
- } else if (!(surface->hglrc = wglCreateContext(impl->hdc))) {
- return PUGL_CREATE_CONTEXT_FAILED;
- }
-
- // Enter context and set swap interval
- wglMakeCurrent(impl->hdc, surface->hglrc);
- const int swapInterval = view->hints[PUGL_SWAP_INTERVAL];
- if (surface->procs.wglSwapInterval && swapInterval != PUGL_DONT_CARE) {
- surface->procs.wglSwapInterval(swapInterval);
- }
-
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ PuglWinGlSurface* const surface = (PuglWinGlSurface*)impl->surface;
+ PuglStatus st = PUGL_SUCCESS;
+
+ const int contextAttribs[] = {
+ WGL_CONTEXT_MAJOR_VERSION_ARB,
+ view->hints[PUGL_CONTEXT_VERSION_MAJOR],
+
+ WGL_CONTEXT_MINOR_VERSION_ARB,
+ view->hints[PUGL_CONTEXT_VERSION_MINOR],
+
+ WGL_CONTEXT_FLAGS_ARB,
+ (view->hints[PUGL_USE_DEBUG_CONTEXT] ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
+
+ WGL_CONTEXT_PROFILE_MASK_ARB,
+ (view->hints[PUGL_USE_COMPAT_PROFILE]
+ ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB
+ : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB),
+
+ 0};
+
+ // Create real window with desired pixel format
+ if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) {
+ return st;
+ } else if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) {
+ ReleaseDC(impl->hwnd, impl->hdc);
+ DestroyWindow(impl->hwnd);
+ impl->hwnd = NULL;
+ impl->hdc = NULL;
+ return PUGL_SET_FORMAT_FAILED;
+ }
+
+ // Create GL context
+ if (surface->procs.wglCreateContextAttribs &&
+ !(surface->hglrc = surface->procs.wglCreateContextAttribs(
+ impl->hdc, 0, contextAttribs))) {
+ return PUGL_CREATE_CONTEXT_FAILED;
+ } else if (!(surface->hglrc = wglCreateContext(impl->hdc))) {
+ return PUGL_CREATE_CONTEXT_FAILED;
+ }
+
+ // Enter context and set swap interval
+ wglMakeCurrent(impl->hdc, surface->hglrc);
+ const int swapInterval = view->hints[PUGL_SWAP_INTERVAL];
+ if (surface->procs.wglSwapInterval && swapInterval != PUGL_DONT_CARE) {
+ surface->procs.wglSwapInterval(swapInterval);
+ }
+
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinGlDestroy(PuglView* view)
{
- PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface;
- if (surface) {
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(surface->hglrc);
- free(surface);
- view->impl->surface = NULL;
- }
-
- return PUGL_SUCCESS;
+ PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface;
+ if (surface) {
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(surface->hglrc);
+ free(surface);
+ view->impl->surface = NULL;
+ }
+
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinGlEnter(PuglView* view, const PuglEventExpose* expose)
{
- PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface;
+ PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface;
- wglMakeCurrent(view->impl->hdc, surface->hglrc);
+ wglMakeCurrent(view->impl->hdc, surface->hglrc);
- if (expose) {
- PAINTSTRUCT ps;
- BeginPaint(view->impl->hwnd, &ps);
- }
+ if (expose) {
+ PAINTSTRUCT ps;
+ BeginPaint(view->impl->hwnd, &ps);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglWinGlLeave(PuglView* view, const PuglEventExpose* expose)
{
- if (expose) {
- PAINTSTRUCT ps;
- EndPaint(view->impl->hwnd, &ps);
- SwapBuffers(view->impl->hdc);
- }
-
- wglMakeCurrent(NULL, NULL);
- return PUGL_SUCCESS;
+ if (expose) {
+ PAINTSTRUCT ps;
+ EndPaint(view->impl->hwnd, &ps);
+ SwapBuffers(view->impl->hdc);
+ }
+
+ wglMakeCurrent(NULL, NULL);
+ return PUGL_SUCCESS;
}
PuglGlFunc
puglGetProcAddress(const char* name)
{
- const PuglGlFunc func = (PuglGlFunc)wglGetProcAddress(name);
+ const PuglGlFunc func = (PuglGlFunc)wglGetProcAddress(name);
- /* Windows has the annoying property that wglGetProcAddress returns NULL
- for functions from OpenGL 1.1, so we fall back to pulling them directly
- from opengl32.dll */
+ /* Windows has the annoying property that wglGetProcAddress returns NULL
+ for functions from OpenGL 1.1, so we fall back to pulling them directly
+ from opengl32.dll */
- return func
- ? func
- : (PuglGlFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), name);
+ return func
+ ? func
+ : (PuglGlFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), name);
}
PuglStatus
puglEnterContext(PuglView* view)
{
- return view->backend->enter(view, NULL);
+ return view->backend->enter(view, NULL);
}
PuglStatus
puglLeaveContext(PuglView* view)
{
- return view->backend->leave(view, NULL);
+ return view->backend->leave(view, NULL);
}
const PuglBackend*
puglGlBackend(void)
{
- static const PuglBackend backend = {puglWinGlConfigure,
- puglWinGlCreate,
- puglWinGlDestroy,
- puglWinGlEnter,
- puglWinGlLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglWinGlConfigure,
+ puglWinGlCreate,
+ puglWinGlDestroy,
+ puglWinGlEnter,
+ puglWinGlLeave,
+ puglStubGetContext};
+
+ return &backend;
}
diff --git a/src/win_stub.c b/src/win_stub.c
index 2027836..cf86390 100644
--- a/src/win_stub.c
+++ b/src/win_stub.c
@@ -23,58 +23,58 @@
PuglStatus
puglWinStubConfigure(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglStatus st = PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ PuglStatus st = PUGL_SUCCESS;
- if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) {
- return st;
- }
+ if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) {
+ return st;
+ }
- impl->pfd = puglWinGetPixelFormatDescriptor(view->hints);
- impl->pfId = ChoosePixelFormat(impl->hdc, &impl->pfd);
+ impl->pfd = puglWinGetPixelFormatDescriptor(view->hints);
+ impl->pfId = ChoosePixelFormat(impl->hdc, &impl->pfd);
- if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) {
- ReleaseDC(impl->hwnd, impl->hdc);
- DestroyWindow(impl->hwnd);
- impl->hwnd = NULL;
- impl->hdc = NULL;
- return PUGL_SET_FORMAT_FAILED;
- }
+ if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) {
+ ReleaseDC(impl->hwnd, impl->hdc);
+ DestroyWindow(impl->hwnd);
+ impl->hwnd = NULL;
+ impl->hdc = NULL;
+ return PUGL_SET_FORMAT_FAILED;
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglWinStubEnter(PuglView* view, const PuglEventExpose* expose)
{
- if (expose) {
- PAINTSTRUCT ps;
- BeginPaint(view->impl->hwnd, &ps);
- }
+ if (expose) {
+ PAINTSTRUCT ps;
+ BeginPaint(view->impl->hwnd, &ps);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglWinStubLeave(PuglView* view, const PuglEventExpose* expose)
{
- if (expose) {
- PAINTSTRUCT ps;
- EndPaint(view->impl->hwnd, &ps);
- }
+ if (expose) {
+ PAINTSTRUCT ps;
+ EndPaint(view->impl->hwnd, &ps);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
const PuglBackend*
puglStubBackend(void)
{
- static const PuglBackend backend = {puglWinStubConfigure,
- puglStubCreate,
- puglStubDestroy,
- puglWinStubEnter,
- puglWinStubLeave,
- puglStubGetContext};
+ static const PuglBackend backend = {puglWinStubConfigure,
+ puglStubCreate,
+ puglStubDestroy,
+ puglWinStubEnter,
+ puglWinStubLeave,
+ puglStubGetContext};
- return &backend;
+ return &backend;
}
diff --git a/src/win_vulkan.c b/src/win_vulkan.c
index f862716..d35d204 100644
--- a/src/win_vulkan.c
+++ b/src/win_vulkan.c
@@ -28,78 +28,77 @@
#include <stdlib.h>
-struct PuglVulkanLoaderImpl
-{
- HMODULE libvulkan;
- PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
- PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+struct PuglVulkanLoaderImpl {
+ HMODULE libvulkan;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
};
PuglVulkanLoader*
puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world))
{
- PuglVulkanLoader* loader =
- (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
- if (!loader) {
- return NULL;
- }
+ PuglVulkanLoader* loader =
+ (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
+ if (!loader) {
+ return NULL;
+ }
- if (!(loader->libvulkan = LoadLibrary("vulkan-1.dll"))) {
- free(loader);
- return NULL;
- }
+ if (!(loader->libvulkan = LoadLibrary("vulkan-1.dll"))) {
+ free(loader);
+ return NULL;
+ }
- loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(
- loader->libvulkan, "vkGetInstanceProcAddr");
+ loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(
+ loader->libvulkan, "vkGetInstanceProcAddr");
- loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)GetProcAddress(
- loader->libvulkan, "vkGetDeviceProcAddr");
+ loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)GetProcAddress(
+ loader->libvulkan, "vkGetDeviceProcAddr");
- return loader;
+ return loader;
}
void
puglFreeVulkanLoader(PuglVulkanLoader* loader)
{
- if (loader) {
- FreeLibrary(loader->libvulkan);
- free(loader);
- }
+ if (loader) {
+ FreeLibrary(loader->libvulkan);
+ free(loader);
+ }
}
PFN_vkGetInstanceProcAddr
puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader)
{
- return loader->vkGetInstanceProcAddr;
+ return loader->vkGetInstanceProcAddr;
}
PFN_vkGetDeviceProcAddr
puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader)
{
- return loader->vkGetDeviceProcAddr;
+ return loader->vkGetDeviceProcAddr;
}
const PuglBackend*
puglVulkanBackend()
{
- static const PuglBackend backend = {puglWinStubConfigure,
- puglStubCreate,
- puglStubDestroy,
- puglWinStubEnter,
- puglWinStubLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglWinStubConfigure,
+ puglStubCreate,
+ puglStubDestroy,
+ puglWinStubEnter,
+ puglWinStubLeave,
+ puglStubGetContext};
+
+ return &backend;
}
const char* const*
puglGetInstanceExtensions(uint32_t* const count)
{
- static const char* const extensions[] = {"VK_KHR_surface",
- "VK_KHR_win32_surface"};
+ static const char* const extensions[] = {"VK_KHR_surface",
+ "VK_KHR_win32_surface"};
- *count = 2;
- return extensions;
+ *count = 2;
+ return extensions;
}
VkResult
@@ -109,19 +108,19 @@ puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
const VkAllocationCallbacks* const pAllocator,
VkSurfaceKHR* const pSurface)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* const impl = view->impl;
- PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR =
- (PFN_vkCreateWin32SurfaceKHR)
- vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR =
+ (PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr(
+ instance, "vkCreateWin32SurfaceKHR");
- const VkWin32SurfaceCreateInfoKHR createInfo = {
- VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
- NULL,
- 0,
- GetModuleHandle(NULL),
- impl->hwnd,
- };
+ const VkWin32SurfaceCreateInfoKHR createInfo = {
+ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
+ NULL,
+ 0,
+ GetModuleHandle(NULL),
+ impl->hwnd,
+ };
- return vkCreateWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface);
+ return vkCreateWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface);
}
diff --git a/src/x11.c b/src/x11.c
index 686e35c..2b594b7 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -32,17 +32,17 @@
#include <X11/keysym.h>
#ifdef HAVE_XRANDR
-# include <X11/extensions/Xrandr.h>
+# include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_XSYNC
-# include <X11/extensions/sync.h>
-# include <X11/extensions/syncconst.h>
+# include <X11/extensions/sync.h>
+# include <X11/extensions/syncconst.h>
#endif
#ifdef HAVE_XCURSOR
-# include <X11/Xcursor/Xcursor.h>
-# include <X11/cursorfont.h>
+# include <X11/Xcursor/Xcursor.h>
+# include <X11/cursorfont.h>
#endif
#include <sys/select.h>
@@ -56,881 +56,913 @@
#include <time.h>
#ifndef MIN
-# define MIN(a, b) (((a) < (b)) ? (a) : (b))
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
-# define MAX(a, b) (((a) > (b)) ? (a) : (b))
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
enum WmClientStateMessageAction {
- WM_STATE_REMOVE,
- WM_STATE_ADD,
- WM_STATE_TOGGLE
+ WM_STATE_REMOVE,
+ WM_STATE_ADD,
+ WM_STATE_TOGGLE
};
static bool
puglInitXSync(PuglWorldInternals* impl)
{
#ifdef HAVE_XSYNC
- int syncMajor = 0;
- int syncMinor = 0;
- int errorBase = 0;
- XSyncSystemCounter* counters = NULL;
- int numCounters = 0;
-
- if (XSyncQueryExtension(impl->display, &impl->syncEventBase, &errorBase) &&
- XSyncInitialize(impl->display, &syncMajor, &syncMinor) &&
- (counters = XSyncListSystemCounters(impl->display, &numCounters))) {
-
- for (int n = 0; n < numCounters; ++n) {
- if (!strcmp(counters[n].name, "SERVERTIME")) {
- impl->serverTimeCounter = counters[n].counter;
- impl->syncSupported = true;
- break;
- }
- }
-
- XSyncFreeSystemCounterList(counters);
- }
+ int syncMajor = 0;
+ int syncMinor = 0;
+ int errorBase = 0;
+ XSyncSystemCounter* counters = NULL;
+ int numCounters = 0;
+
+ if (XSyncQueryExtension(impl->display, &impl->syncEventBase, &errorBase) &&
+ XSyncInitialize(impl->display, &syncMajor, &syncMinor) &&
+ (counters = XSyncListSystemCounters(impl->display, &numCounters))) {
+ for (int n = 0; n < numCounters; ++n) {
+ if (!strcmp(counters[n].name, "SERVERTIME")) {
+ impl->serverTimeCounter = counters[n].counter;
+ impl->syncSupported = true;
+ break;
+ }
+ }
+
+ XSyncFreeSystemCounterList(counters);
+ }
#else
- (void)impl;
+ (void)impl;
#endif
- return false;
+ return false;
}
PuglWorldInternals*
puglInitWorldInternals(PuglWorldType type, PuglWorldFlags flags)
{
- if (type == PUGL_PROGRAM && (flags & PUGL_WORLD_THREADS)) {
- XInitThreads();
- }
-
- Display* display = XOpenDisplay(NULL);
- if (!display) {
- return NULL;
- }
-
- PuglWorldInternals* impl = (PuglWorldInternals*)calloc(
- 1, sizeof(PuglWorldInternals));
-
- impl->display = display;
-
- // Intern the various atoms we will need
- impl->atoms.CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0);
- impl->atoms.UTF8_STRING = XInternAtom(display, "UTF8_STRING", 0);
- impl->atoms.WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", 0);
- impl->atoms.WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", 0);
- impl->atoms.PUGL_CLIENT_MSG = XInternAtom(display, "_PUGL_CLIENT_MSG", 0);
- impl->atoms.NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", 0);
- impl->atoms.NET_WM_STATE = XInternAtom(display, "_NET_WM_STATE", 0);
- impl->atoms.NET_WM_STATE_DEMANDS_ATTENTION =
- XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", 0);
-
- // Open input method
- XSetLocaleModifiers("");
- if (!(impl->xim = XOpenIM(display, NULL, NULL, NULL))) {
- XSetLocaleModifiers("@im=");
- impl->xim = XOpenIM(display, NULL, NULL, NULL);
- }
-
- puglInitXSync(impl);
- XFlush(display);
-
- return impl;
+ if (type == PUGL_PROGRAM && (flags & PUGL_WORLD_THREADS)) {
+ XInitThreads();
+ }
+
+ Display* display = XOpenDisplay(NULL);
+ if (!display) {
+ return NULL;
+ }
+
+ PuglWorldInternals* impl =
+ (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals));
+
+ impl->display = display;
+
+ // Intern the various atoms we will need
+ impl->atoms.CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0);
+ impl->atoms.UTF8_STRING = XInternAtom(display, "UTF8_STRING", 0);
+ impl->atoms.WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", 0);
+ impl->atoms.WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", 0);
+ impl->atoms.PUGL_CLIENT_MSG = XInternAtom(display, "_PUGL_CLIENT_MSG", 0);
+ impl->atoms.NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", 0);
+ impl->atoms.NET_WM_STATE = XInternAtom(display, "_NET_WM_STATE", 0);
+ impl->atoms.NET_WM_STATE_DEMANDS_ATTENTION =
+ XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", 0);
+
+ // Open input method
+ XSetLocaleModifiers("");
+ if (!(impl->xim = XOpenIM(display, NULL, NULL, NULL))) {
+ XSetLocaleModifiers("@im=");
+ impl->xim = XOpenIM(display, NULL, NULL, NULL);
+ }
+
+ puglInitXSync(impl);
+ XFlush(display);
+
+ return impl;
}
void*
puglGetNativeWorld(PuglWorld* world)
{
- return world->impl->display;
+ return world->impl->display;
}
PuglInternals*
puglInitViewInternals(void)
{
- PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
#ifdef HAVE_XCURSOR
- impl->cursorShape = XC_arrow;
+ impl->cursorShape = XC_arrow;
#endif
- return impl;
+ return impl;
}
static PuglStatus
puglPollX11Socket(PuglWorld* world, const double timeout)
{
- if (XPending(world->impl->display) > 0) {
- return PUGL_SUCCESS;
- }
-
- const int fd = ConnectionNumber(world->impl->display);
- const int nfds = fd + 1;
- int ret = 0;
- fd_set fds;
- FD_ZERO(&fds); // NOLINT
- FD_SET(fd, &fds);
-
- if (timeout < 0.0) {
- ret = select(nfds, &fds, NULL, NULL, NULL);
- } else {
- const long sec = (long)timeout;
- const long usec = (long)((timeout - (double)sec) * 1e6);
- struct timeval tv = {sec, usec};
- ret = select(nfds, &fds, NULL, NULL, &tv);
- }
-
- return ret < 0 ? PUGL_UNKNOWN_ERROR : PUGL_SUCCESS;
+ if (XPending(world->impl->display) > 0) {
+ return PUGL_SUCCESS;
+ }
+
+ const int fd = ConnectionNumber(world->impl->display);
+ const int nfds = fd + 1;
+ int ret = 0;
+ fd_set fds;
+ FD_ZERO(&fds); // NOLINT
+ FD_SET(fd, &fds);
+
+ if (timeout < 0.0) {
+ ret = select(nfds, &fds, NULL, NULL, NULL);
+ } else {
+ const long sec = (long)timeout;
+ const long usec = (long)((timeout - (double)sec) * 1e6);
+ struct timeval tv = {sec, usec};
+ ret = select(nfds, &fds, NULL, NULL, &tv);
+ }
+
+ return ret < 0 ? PUGL_UNKNOWN_ERROR : PUGL_SUCCESS;
}
static PuglView*
puglFindView(PuglWorld* world, const Window window)
{
- for (size_t i = 0; i < world->numViews; ++i) {
- if (world->views[i]->impl->win == window) {
- return world->views[i];
- }
- }
+ for (size_t i = 0; i < world->numViews; ++i) {
+ if (world->views[i]->impl->win == window) {
+ return world->views[i];
+ }
+ }
- return NULL;
+ return NULL;
}
static PuglStatus
updateSizeHints(const PuglView* view)
{
- if (!view->impl->win) {
- return PUGL_SUCCESS;
- }
-
- Display* display = view->world->impl->display;
- XSizeHints sizeHints = {0};
-
- if (!view->hints[PUGL_RESIZABLE]) {
- sizeHints.flags = PBaseSize | PMinSize | PMaxSize;
- sizeHints.base_width = (int)view->frame.width;
- sizeHints.base_height = (int)view->frame.height;
- sizeHints.min_width = (int)view->frame.width;
- sizeHints.min_height = (int)view->frame.height;
- sizeHints.max_width = (int)view->frame.width;
- sizeHints.max_height = (int)view->frame.height;
- } else {
- if (view->defaultWidth || view->defaultHeight) {
- sizeHints.flags = PBaseSize;
- sizeHints.base_width = view->defaultWidth;
- sizeHints.base_height = view->defaultHeight;
- }
- if (view->minWidth || view->minHeight) {
- sizeHints.flags = PMinSize;
- sizeHints.min_width = view->minWidth;
- sizeHints.min_height = view->minHeight;
- }
- if (view->maxWidth || view->maxHeight) {
- sizeHints.flags = PMaxSize;
- sizeHints.max_width = view->maxWidth;
- sizeHints.max_height = view->maxHeight;
- }
- if (view->minAspectX) {
- sizeHints.flags |= PAspect;
- sizeHints.min_aspect.x = view->minAspectX;
- sizeHints.min_aspect.y = view->minAspectY;
- sizeHints.max_aspect.x = view->maxAspectX;
- sizeHints.max_aspect.y = view->maxAspectY;
- }
- }
-
- XSetNormalHints(display, view->impl->win, &sizeHints);
- return PUGL_SUCCESS;
+ if (!view->impl->win) {
+ return PUGL_SUCCESS;
+ }
+
+ Display* display = view->world->impl->display;
+ XSizeHints sizeHints = {0};
+
+ if (!view->hints[PUGL_RESIZABLE]) {
+ sizeHints.flags = PBaseSize | PMinSize | PMaxSize;
+ sizeHints.base_width = (int)view->frame.width;
+ sizeHints.base_height = (int)view->frame.height;
+ sizeHints.min_width = (int)view->frame.width;
+ sizeHints.min_height = (int)view->frame.height;
+ sizeHints.max_width = (int)view->frame.width;
+ sizeHints.max_height = (int)view->frame.height;
+ } else {
+ if (view->defaultWidth || view->defaultHeight) {
+ sizeHints.flags = PBaseSize;
+ sizeHints.base_width = view->defaultWidth;
+ sizeHints.base_height = view->defaultHeight;
+ }
+ if (view->minWidth || view->minHeight) {
+ sizeHints.flags = PMinSize;
+ sizeHints.min_width = view->minWidth;
+ sizeHints.min_height = view->minHeight;
+ }
+ if (view->maxWidth || view->maxHeight) {
+ sizeHints.flags = PMaxSize;
+ sizeHints.max_width = view->maxWidth;
+ sizeHints.max_height = view->maxHeight;
+ }
+ if (view->minAspectX) {
+ sizeHints.flags |= PAspect;
+ sizeHints.min_aspect.x = view->minAspectX;
+ sizeHints.min_aspect.y = view->minAspectY;
+ sizeHints.max_aspect.x = view->maxAspectX;
+ sizeHints.max_aspect.y = view->maxAspectY;
+ }
+ }
+
+ XSetNormalHints(display, view->impl->win, &sizeHints);
+ return PUGL_SUCCESS;
}
#ifdef HAVE_XCURSOR
static PuglStatus
puglDefineCursorShape(PuglView* view, unsigned shape)
{
- PuglInternals* const impl = view->impl;
- PuglWorld* const world = view->world;
- Display* const display = world->impl->display;
- const Cursor cur = XcursorShapeLoadCursor(display, shape);
-
- if (cur) {
- XDefineCursor(display, impl->win, cur);
- XFreeCursor(display, cur);
- return PUGL_SUCCESS;
- }
-
- return PUGL_FAILURE;
+ PuglInternals* const impl = view->impl;
+ PuglWorld* const world = view->world;
+ Display* const display = world->impl->display;
+ const Cursor cur = XcursorShapeLoadCursor(display, shape);
+
+ if (cur) {
+ XDefineCursor(display, impl->win, cur);
+ XFreeCursor(display, cur);
+ return PUGL_SUCCESS;
+ }
+
+ return PUGL_FAILURE;
}
#endif
PuglStatus
puglRealize(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglWorld* const world = view->world;
- PuglX11Atoms* const atoms = &view->world->impl->atoms;
- Display* const display = world->impl->display;
- const int screen = DefaultScreen(display);
- const Window root = RootWindow(display, screen);
- const Window parent = view->parent ? (Window)view->parent : root;
- XSetWindowAttributes attr = {0};
- PuglStatus st = PUGL_SUCCESS;
-
- // Ensure that we're unrealized and that a reasonable backend has been set
- if (impl->win) {
- return PUGL_FAILURE;
- } else if (!view->backend || !view->backend->configure) {
- return PUGL_BAD_BACKEND;
- }
-
- // Set the size to the default if it has not already been set
- if (view->frame.width == 0.0 && view->frame.height == 0.0) {
- if (view->defaultWidth == 0.0 || view->defaultHeight == 0.0) {
- return PUGL_BAD_CONFIGURATION;
- }
-
- view->frame.width = view->defaultWidth;
- view->frame.height = view->defaultHeight;
- }
-
- // Center top-level windows if a position has not been set
- if (!view->parent && view->frame.x == 0.0 && view->frame.y == 0.0) {
- const int screenWidth = DisplayWidth(display, screen);
- const int screenHeight = DisplayHeight(display, screen);
-
- view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0;
- view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0;
- }
-
- // Configure the backend to get the visual info
- impl->display = display;
- impl->screen = screen;
- if ((st = view->backend->configure(view)) || !impl->vi) {
- view->backend->destroy(view);
- return st ? st : PUGL_BACKEND_FAILED;
- }
-
- // Create a colormap based on the visual info from the backend
- attr.colormap =
- XCreateColormap(display, parent, impl->vi->visual, AllocNone);
-
- // Set the event mask to request all of the event types we react to
- attr.event_mask |= ButtonPressMask;
- attr.event_mask |= ButtonReleaseMask;
- attr.event_mask |= EnterWindowMask;
- attr.event_mask |= ExposureMask;
- attr.event_mask |= FocusChangeMask;
- attr.event_mask |= KeyPressMask;
- attr.event_mask |= KeyReleaseMask;
- attr.event_mask |= LeaveWindowMask;
- attr.event_mask |= PointerMotionMask;
- attr.event_mask |= StructureNotifyMask;
- attr.event_mask |= VisibilityChangeMask;
-
- // Create the window
- impl->win = XCreateWindow(display,
- parent,
- (int)view->frame.x,
- (int)view->frame.y,
- (unsigned)view->frame.width,
- (unsigned)view->frame.height,
- 0,
- impl->vi->depth,
- InputOutput,
- impl->vi->visual,
- CWColormap | CWEventMask,
- &attr);
-
- // Create the backend drawing context/surface
- if ((st = view->backend->create(view))) {
- return st;
- }
+ PuglInternals* const impl = view->impl;
+ PuglWorld* const world = view->world;
+ PuglX11Atoms* const atoms = &view->world->impl->atoms;
+ Display* const display = world->impl->display;
+ const int screen = DefaultScreen(display);
+ const Window root = RootWindow(display, screen);
+ const Window parent = view->parent ? (Window)view->parent : root;
+ XSetWindowAttributes attr = {0};
+ PuglStatus st = PUGL_SUCCESS;
+
+ // Ensure that we're unrealized and that a reasonable backend has been set
+ if (impl->win) {
+ return PUGL_FAILURE;
+ } else if (!view->backend || !view->backend->configure) {
+ return PUGL_BAD_BACKEND;
+ }
+
+ // Set the size to the default if it has not already been set
+ if (view->frame.width == 0.0 && view->frame.height == 0.0) {
+ if (view->defaultWidth == 0.0 || view->defaultHeight == 0.0) {
+ return PUGL_BAD_CONFIGURATION;
+ }
+
+ view->frame.width = view->defaultWidth;
+ view->frame.height = view->defaultHeight;
+ }
+
+ // Center top-level windows if a position has not been set
+ if (!view->parent && view->frame.x == 0.0 && view->frame.y == 0.0) {
+ const int screenWidth = DisplayWidth(display, screen);
+ const int screenHeight = DisplayHeight(display, screen);
+
+ view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0;
+ view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0;
+ }
+
+ // Configure the backend to get the visual info
+ impl->display = display;
+ impl->screen = screen;
+ if ((st = view->backend->configure(view)) || !impl->vi) {
+ view->backend->destroy(view);
+ return st ? st : PUGL_BACKEND_FAILED;
+ }
+
+ // Create a colormap based on the visual info from the backend
+ attr.colormap = XCreateColormap(display, parent, impl->vi->visual, AllocNone);
+
+ // Set the event mask to request all of the event types we react to
+ attr.event_mask |= ButtonPressMask;
+ attr.event_mask |= ButtonReleaseMask;
+ attr.event_mask |= EnterWindowMask;
+ attr.event_mask |= ExposureMask;
+ attr.event_mask |= FocusChangeMask;
+ attr.event_mask |= KeyPressMask;
+ attr.event_mask |= KeyReleaseMask;
+ attr.event_mask |= LeaveWindowMask;
+ attr.event_mask |= PointerMotionMask;
+ attr.event_mask |= StructureNotifyMask;
+ attr.event_mask |= VisibilityChangeMask;
+
+ // Create the window
+ impl->win = XCreateWindow(display,
+ parent,
+ (int)view->frame.x,
+ (int)view->frame.y,
+ (unsigned)view->frame.width,
+ (unsigned)view->frame.height,
+ 0,
+ impl->vi->depth,
+ InputOutput,
+ impl->vi->visual,
+ CWColormap | CWEventMask,
+ &attr);
+
+ // Create the backend drawing context/surface
+ if ((st = view->backend->create(view))) {
+ return st;
+ }
#ifdef HAVE_XRANDR
- // Set refresh rate hint to the real refresh rate
- XRRScreenConfiguration* conf = XRRGetScreenInfo(display, parent);
- short current_rate = XRRConfigCurrentRate(conf);
+ // Set refresh rate hint to the real refresh rate
+ XRRScreenConfiguration* conf = XRRGetScreenInfo(display, parent);
+ short current_rate = XRRConfigCurrentRate(conf);
- view->hints[PUGL_REFRESH_RATE] = current_rate;
- XRRFreeScreenConfigInfo(conf);
+ view->hints[PUGL_REFRESH_RATE] = current_rate;
+ XRRFreeScreenConfigInfo(conf);
#endif
- updateSizeHints(view);
+ updateSizeHints(view);
- XClassHint classHint = { world->className, world->className };
- XSetClassHint(display, impl->win, &classHint);
+ XClassHint classHint = {world->className, world->className};
+ XSetClassHint(display, impl->win, &classHint);
- if (view->title) {
- puglSetWindowTitle(view, view->title);
- }
+ if (view->title) {
+ puglSetWindowTitle(view, view->title);
+ }
- if (parent == root) {
- XSetWMProtocols(display, impl->win, &atoms->WM_DELETE_WINDOW, 1);
- }
+ if (parent == root) {
+ XSetWMProtocols(display, impl->win, &atoms->WM_DELETE_WINDOW, 1);
+ }
- if (view->transientParent) {
- XSetTransientForHint(display, impl->win, (Window)view->transientParent);
- }
+ if (view->transientParent) {
+ XSetTransientForHint(display, impl->win, (Window)view->transientParent);
+ }
- // Create input context
- impl->xic = XCreateIC(world->impl->xim,
- XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, impl->win,
- XNFocusWindow, impl->win,
- NULL);
+ // Create input context
+ impl->xic = XCreateIC(world->impl->xim,
+ XNInputStyle,
+ XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow,
+ impl->win,
+ XNFocusWindow,
+ impl->win,
+ NULL);
#ifdef HAVE_XCURSOR
- puglDefineCursorShape(view, impl->cursorShape);
+ puglDefineCursorShape(view, impl->cursorShape);
#endif
- puglDispatchSimpleEvent(view, PUGL_CREATE);
+ puglDispatchSimpleEvent(view, PUGL_CREATE);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
PuglStatus
puglShow(PuglView* view)
{
- PuglStatus st = PUGL_SUCCESS;
+ PuglStatus st = PUGL_SUCCESS;
- if (!view->impl->win) {
- if ((st = puglRealize(view))) {
- return st;
- }
- }
+ if (!view->impl->win) {
+ if ((st = puglRealize(view))) {
+ return st;
+ }
+ }
- XMapRaised(view->impl->display, view->impl->win);
- puglPostRedisplay(view);
+ XMapRaised(view->impl->display, view->impl->win);
+ puglPostRedisplay(view);
- return st;
+ return st;
}
PuglStatus
puglHide(PuglView* view)
{
- XUnmapWindow(view->impl->display, view->impl->win);
- return PUGL_SUCCESS;
+ XUnmapWindow(view->impl->display, view->impl->win);
+ return PUGL_SUCCESS;
}
void
puglFreeViewInternals(PuglView* view)
{
- if (view && view->impl) {
- if (view->impl->xic) {
- XDestroyIC(view->impl->xic);
- }
- if (view->backend) {
- view->backend->destroy(view);
- }
- if (view->impl->display) {
- XDestroyWindow(view->impl->display, view->impl->win);
- }
- XFree(view->impl->vi);
- free(view->impl);
- }
+ if (view && view->impl) {
+ if (view->impl->xic) {
+ XDestroyIC(view->impl->xic);
+ }
+ if (view->backend) {
+ view->backend->destroy(view);
+ }
+ if (view->impl->display) {
+ XDestroyWindow(view->impl->display, view->impl->win);
+ }
+ XFree(view->impl->vi);
+ free(view->impl);
+ }
}
void
puglFreeWorldInternals(PuglWorld* world)
{
- if (world->impl->xim) {
- XCloseIM(world->impl->xim);
- }
- XCloseDisplay(world->impl->display);
- free(world->impl->timers);
- free(world->impl);
+ if (world->impl->xim) {
+ XCloseIM(world->impl->xim);
+ }
+ XCloseDisplay(world->impl->display);
+ free(world->impl->timers);
+ free(world->impl);
}
static PuglKey
keySymToSpecial(KeySym sym)
{
- switch (sym) {
- case XK_F1: return PUGL_KEY_F1;
- case XK_F2: return PUGL_KEY_F2;
- case XK_F3: return PUGL_KEY_F3;
- case XK_F4: return PUGL_KEY_F4;
- case XK_F5: return PUGL_KEY_F5;
- case XK_F6: return PUGL_KEY_F6;
- case XK_F7: return PUGL_KEY_F7;
- case XK_F8: return PUGL_KEY_F8;
- case XK_F9: return PUGL_KEY_F9;
- case XK_F10: return PUGL_KEY_F10;
- case XK_F11: return PUGL_KEY_F11;
- case XK_F12: return PUGL_KEY_F12;
- case XK_Left: return PUGL_KEY_LEFT;
- case XK_Up: return PUGL_KEY_UP;
- case XK_Right: return PUGL_KEY_RIGHT;
- case XK_Down: return PUGL_KEY_DOWN;
- case XK_Page_Up: return PUGL_KEY_PAGE_UP;
- case XK_Page_Down: return PUGL_KEY_PAGE_DOWN;
- case XK_Home: return PUGL_KEY_HOME;
- case XK_End: return PUGL_KEY_END;
- case XK_Insert: return PUGL_KEY_INSERT;
- case XK_Shift_L: return PUGL_KEY_SHIFT_L;
- case XK_Shift_R: return PUGL_KEY_SHIFT_R;
- case XK_Control_L: return PUGL_KEY_CTRL_L;
- case XK_Control_R: return PUGL_KEY_CTRL_R;
- case XK_Alt_L: return PUGL_KEY_ALT_L;
- case XK_ISO_Level3_Shift:
- case XK_Alt_R: return PUGL_KEY_ALT_R;
- case XK_Super_L: return PUGL_KEY_SUPER_L;
- case XK_Super_R: return PUGL_KEY_SUPER_R;
- case XK_Menu: return PUGL_KEY_MENU;
- case XK_Caps_Lock: return PUGL_KEY_CAPS_LOCK;
- case XK_Scroll_Lock: return PUGL_KEY_SCROLL_LOCK;
- case XK_Num_Lock: return PUGL_KEY_NUM_LOCK;
- case XK_Print: return PUGL_KEY_PRINT_SCREEN;
- case XK_Pause: return PUGL_KEY_PAUSE;
- default: break;
- }
- return (PuglKey)0;
+ switch (sym) {
+ case XK_F1:
+ return PUGL_KEY_F1;
+ case XK_F2:
+ return PUGL_KEY_F2;
+ case XK_F3:
+ return PUGL_KEY_F3;
+ case XK_F4:
+ return PUGL_KEY_F4;
+ case XK_F5:
+ return PUGL_KEY_F5;
+ case XK_F6:
+ return PUGL_KEY_F6;
+ case XK_F7:
+ return PUGL_KEY_F7;
+ case XK_F8:
+ return PUGL_KEY_F8;
+ case XK_F9:
+ return PUGL_KEY_F9;
+ case XK_F10:
+ return PUGL_KEY_F10;
+ case XK_F11:
+ return PUGL_KEY_F11;
+ case XK_F12:
+ return PUGL_KEY_F12;
+ case XK_Left:
+ return PUGL_KEY_LEFT;
+ case XK_Up:
+ return PUGL_KEY_UP;
+ case XK_Right:
+ return PUGL_KEY_RIGHT;
+ case XK_Down:
+ return PUGL_KEY_DOWN;
+ case XK_Page_Up:
+ return PUGL_KEY_PAGE_UP;
+ case XK_Page_Down:
+ return PUGL_KEY_PAGE_DOWN;
+ case XK_Home:
+ return PUGL_KEY_HOME;
+ case XK_End:
+ return PUGL_KEY_END;
+ case XK_Insert:
+ return PUGL_KEY_INSERT;
+ case XK_Shift_L:
+ return PUGL_KEY_SHIFT_L;
+ case XK_Shift_R:
+ return PUGL_KEY_SHIFT_R;
+ case XK_Control_L:
+ return PUGL_KEY_CTRL_L;
+ case XK_Control_R:
+ return PUGL_KEY_CTRL_R;
+ case XK_Alt_L:
+ return PUGL_KEY_ALT_L;
+ case XK_ISO_Level3_Shift:
+ case XK_Alt_R:
+ return PUGL_KEY_ALT_R;
+ case XK_Super_L:
+ return PUGL_KEY_SUPER_L;
+ case XK_Super_R:
+ return PUGL_KEY_SUPER_R;
+ case XK_Menu:
+ return PUGL_KEY_MENU;
+ case XK_Caps_Lock:
+ return PUGL_KEY_CAPS_LOCK;
+ case XK_Scroll_Lock:
+ return PUGL_KEY_SCROLL_LOCK;
+ case XK_Num_Lock:
+ return PUGL_KEY_NUM_LOCK;
+ case XK_Print:
+ return PUGL_KEY_PRINT_SCREEN;
+ case XK_Pause:
+ return PUGL_KEY_PAUSE;
+ default:
+ break;
+ }
+ return (PuglKey)0;
}
static int
lookupString(XIC xic, XEvent* xevent, char* str, KeySym* sym)
{
- Status status = 0;
+ Status status = 0;
#ifdef X_HAVE_UTF8_STRING
- const int n = Xutf8LookupString(xic, &xevent->xkey, str, 7, sym, &status);
+ const int n = Xutf8LookupString(xic, &xevent->xkey, str, 7, sym, &status);
#else
- const int n = XmbLookupString(xic, &xevent->xkey, str, 7, sym, &status);
+ const int n = XmbLookupString(xic, &xevent->xkey, str, 7, sym, &status);
#endif
- return status == XBufferOverflow ? 0 : n;
+ return status == XBufferOverflow ? 0 : n;
}
static void
translateKey(PuglView* view, XEvent* xevent, PuglEvent* event)
{
- const unsigned state = xevent->xkey.state;
- const bool filter = XFilterEvent(xevent, None);
-
- event->key.keycode = xevent->xkey.keycode;
- xevent->xkey.state = 0;
-
- // Lookup unshifted key
- char ustr[8] = {0};
- KeySym sym = 0;
- const int ufound = XLookupString(&xevent->xkey, ustr, 8, &sym, NULL);
- const PuglKey special = keySymToSpecial(sym);
-
- event->key.key = ((special || ufound <= 0)
- ? special
- : puglDecodeUTF8((const uint8_t*)ustr));
-
- if (xevent->type == KeyPress && !filter && !special) {
- // Lookup shifted key for possible text event
- xevent->xkey.state = state;
-
- char sstr[8] = {0};
- const int sfound = lookupString(view->impl->xic, xevent, sstr, &sym);
- if (sfound > 0) {
- // Dispatch key event now
- puglDispatchEvent(view, event);
-
- // "Return" a text event in its place
- event->text.type = PUGL_TEXT;
- event->text.character = puglDecodeUTF8((const uint8_t*)sstr);
- memcpy(event->text.string, sstr, sizeof(sstr));
- }
- }
+ const unsigned state = xevent->xkey.state;
+ const bool filter = XFilterEvent(xevent, None);
+
+ event->key.keycode = xevent->xkey.keycode;
+ xevent->xkey.state = 0;
+
+ // Lookup unshifted key
+ char ustr[8] = {0};
+ KeySym sym = 0;
+ const int ufound = XLookupString(&xevent->xkey, ustr, 8, &sym, NULL);
+ const PuglKey special = keySymToSpecial(sym);
+
+ event->key.key =
+ ((special || ufound <= 0) ? special : puglDecodeUTF8((const uint8_t*)ustr));
+
+ if (xevent->type == KeyPress && !filter && !special) {
+ // Lookup shifted key for possible text event
+ xevent->xkey.state = state;
+
+ char sstr[8] = {0};
+ const int sfound = lookupString(view->impl->xic, xevent, sstr, &sym);
+ if (sfound > 0) {
+ // Dispatch key event now
+ puglDispatchEvent(view, event);
+
+ // "Return" a text event in its place
+ event->text.type = PUGL_TEXT;
+ event->text.character = puglDecodeUTF8((const uint8_t*)sstr);
+ memcpy(event->text.string, sstr, sizeof(sstr));
+ }
+ }
}
static uint32_t
translateModifiers(const unsigned xstate)
{
- return (((xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0u) |
- ((xstate & ControlMask) ? PUGL_MOD_CTRL : 0u) |
- ((xstate & Mod1Mask) ? PUGL_MOD_ALT : 0u) |
- ((xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0u));
+ return (((xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0u) |
+ ((xstate & ControlMask) ? PUGL_MOD_CTRL : 0u) |
+ ((xstate & Mod1Mask) ? PUGL_MOD_ALT : 0u) |
+ ((xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0u));
}
static PuglEvent
translateEvent(PuglView* view, XEvent xevent)
{
- const PuglX11Atoms* atoms = &view->world->impl->atoms;
-
- PuglEvent event = {{PUGL_NOTHING, 0}};
- event.any.flags = xevent.xany.send_event ? PUGL_IS_SEND_EVENT : 0;
-
- switch (xevent.type) {
- case ClientMessage:
- if (xevent.xclient.message_type == atoms->WM_PROTOCOLS) {
- const Atom protocol = (Atom)xevent.xclient.data.l[0];
- if (protocol == atoms->WM_DELETE_WINDOW) {
- event.type = PUGL_CLOSE;
- }
- } else if (xevent.xclient.message_type == atoms->PUGL_CLIENT_MSG) {
- event.type = PUGL_CLIENT;
- event.client.data1 = (uintptr_t)xevent.xclient.data.l[0];
- event.client.data2 = (uintptr_t)xevent.xclient.data.l[1];
- }
- break;
- case VisibilityNotify:
- view->visible = xevent.xvisibility.state != VisibilityFullyObscured;
- break;
- case MapNotify:
- event.type = PUGL_MAP;
- break;
- case UnmapNotify:
- event.type = PUGL_UNMAP;
- view->visible = false;
- break;
- case ConfigureNotify:
- event.type = PUGL_CONFIGURE;
- event.configure.x = xevent.xconfigure.x;
- event.configure.y = xevent.xconfigure.y;
- event.configure.width = xevent.xconfigure.width;
- event.configure.height = xevent.xconfigure.height;
- break;
- case Expose:
- event.type = PUGL_EXPOSE;
- event.expose.x = xevent.xexpose.x;
- event.expose.y = xevent.xexpose.y;
- event.expose.width = xevent.xexpose.width;
- event.expose.height = xevent.xexpose.height;
- break;
- case MotionNotify:
- event.type = PUGL_MOTION;
- event.motion.time = (double)xevent.xmotion.time / 1e3;
- event.motion.x = xevent.xmotion.x;
- event.motion.y = xevent.xmotion.y;
- event.motion.xRoot = xevent.xmotion.x_root;
- event.motion.yRoot = xevent.xmotion.y_root;
- event.motion.state = translateModifiers(xevent.xmotion.state);
- if (xevent.xmotion.is_hint == NotifyHint) {
- event.motion.flags |= PUGL_IS_HINT;
- }
- break;
- case ButtonPress:
- if (xevent.xbutton.button >= 4 && xevent.xbutton.button <= 7) {
- event.type = PUGL_SCROLL;
- event.scroll.time = (double)xevent.xbutton.time / 1e3;
- event.scroll.x = xevent.xbutton.x;
- event.scroll.y = xevent.xbutton.y;
- event.scroll.xRoot = xevent.xbutton.x_root;
- event.scroll.yRoot = xevent.xbutton.y_root;
- event.scroll.state = translateModifiers(xevent.xbutton.state);
- event.scroll.dx = 0.0;
- event.scroll.dy = 0.0;
- switch (xevent.xbutton.button) {
- case 4:
- event.scroll.dy = 1.0;
- event.scroll.direction = PUGL_SCROLL_UP;
- break;
- case 5:
- event.scroll.dy = -1.0;
- event.scroll.direction = PUGL_SCROLL_DOWN;
- break;
- case 6:
- event.scroll.dx = -1.0;
- event.scroll.direction = PUGL_SCROLL_LEFT;
- break;
- case 7:
- event.scroll.dx = 1.0;
- event.scroll.direction = PUGL_SCROLL_RIGHT;
- break;
- }
- // fallthru
- }
- // fallthru
- case ButtonRelease:
- if (xevent.xbutton.button < 4 || xevent.xbutton.button > 7) {
- event.button.type = ((xevent.type == ButtonPress)
- ? PUGL_BUTTON_PRESS
- : PUGL_BUTTON_RELEASE);
- event.button.time = (double)xevent.xbutton.time / 1e3;
- event.button.x = xevent.xbutton.x;
- event.button.y = xevent.xbutton.y;
- event.button.xRoot = xevent.xbutton.x_root;
- event.button.yRoot = xevent.xbutton.y_root;
- event.button.state = translateModifiers(xevent.xbutton.state);
- event.button.button = xevent.xbutton.button;
- }
- break;
- case KeyPress:
- case KeyRelease:
- event.type = ((xevent.type == KeyPress)
- ? PUGL_KEY_PRESS
- : PUGL_KEY_RELEASE);
- event.key.time = (double)xevent.xkey.time / 1e3;
- event.key.x = xevent.xkey.x;
- event.key.y = xevent.xkey.y;
- event.key.xRoot = xevent.xkey.x_root;
- event.key.yRoot = xevent.xkey.y_root;
- event.key.state = translateModifiers(xevent.xkey.state);
- translateKey(view, &xevent, &event);
- break;
- case EnterNotify:
- case LeaveNotify:
- event.type = ((xevent.type == EnterNotify)
- ? PUGL_POINTER_IN
- : PUGL_POINTER_OUT);
- event.crossing.time = (double)xevent.xcrossing.time / 1e3;
- event.crossing.x = xevent.xcrossing.x;
- event.crossing.y = xevent.xcrossing.y;
- event.crossing.xRoot = xevent.xcrossing.x_root;
- event.crossing.yRoot = xevent.xcrossing.y_root;
- event.crossing.state = translateModifiers(xevent.xcrossing.state);
- event.crossing.mode = PUGL_CROSSING_NORMAL;
- if (xevent.xcrossing.mode == NotifyGrab) {
- event.crossing.mode = PUGL_CROSSING_GRAB;
- } else if (xevent.xcrossing.mode == NotifyUngrab) {
- event.crossing.mode = PUGL_CROSSING_UNGRAB;
- }
- break;
-
- case FocusIn:
- case FocusOut:
- event.type = (xevent.type == FocusIn) ? PUGL_FOCUS_IN : PUGL_FOCUS_OUT;
- event.focus.mode = PUGL_CROSSING_NORMAL;
- if (xevent.xfocus.mode == NotifyGrab) {
- event.focus.mode = PUGL_CROSSING_GRAB;
- } else if (xevent.xfocus.mode == NotifyUngrab) {
- event.focus.mode = PUGL_CROSSING_UNGRAB;
- }
- break;
-
- default:
- break;
- }
-
- return event;
+ const PuglX11Atoms* atoms = &view->world->impl->atoms;
+
+ PuglEvent event = {{PUGL_NOTHING, 0}};
+ event.any.flags = xevent.xany.send_event ? PUGL_IS_SEND_EVENT : 0;
+
+ switch (xevent.type) {
+ case ClientMessage:
+ if (xevent.xclient.message_type == atoms->WM_PROTOCOLS) {
+ const Atom protocol = (Atom)xevent.xclient.data.l[0];
+ if (protocol == atoms->WM_DELETE_WINDOW) {
+ event.type = PUGL_CLOSE;
+ }
+ } else if (xevent.xclient.message_type == atoms->PUGL_CLIENT_MSG) {
+ event.type = PUGL_CLIENT;
+ event.client.data1 = (uintptr_t)xevent.xclient.data.l[0];
+ event.client.data2 = (uintptr_t)xevent.xclient.data.l[1];
+ }
+ break;
+ case VisibilityNotify:
+ view->visible = xevent.xvisibility.state != VisibilityFullyObscured;
+ break;
+ case MapNotify:
+ event.type = PUGL_MAP;
+ break;
+ case UnmapNotify:
+ event.type = PUGL_UNMAP;
+ view->visible = false;
+ break;
+ case ConfigureNotify:
+ event.type = PUGL_CONFIGURE;
+ event.configure.x = xevent.xconfigure.x;
+ event.configure.y = xevent.xconfigure.y;
+ event.configure.width = xevent.xconfigure.width;
+ event.configure.height = xevent.xconfigure.height;
+ break;
+ case Expose:
+ event.type = PUGL_EXPOSE;
+ event.expose.x = xevent.xexpose.x;
+ event.expose.y = xevent.xexpose.y;
+ event.expose.width = xevent.xexpose.width;
+ event.expose.height = xevent.xexpose.height;
+ break;
+ case MotionNotify:
+ event.type = PUGL_MOTION;
+ event.motion.time = (double)xevent.xmotion.time / 1e3;
+ event.motion.x = xevent.xmotion.x;
+ event.motion.y = xevent.xmotion.y;
+ event.motion.xRoot = xevent.xmotion.x_root;
+ event.motion.yRoot = xevent.xmotion.y_root;
+ event.motion.state = translateModifiers(xevent.xmotion.state);
+ if (xevent.xmotion.is_hint == NotifyHint) {
+ event.motion.flags |= PUGL_IS_HINT;
+ }
+ break;
+ case ButtonPress:
+ if (xevent.xbutton.button >= 4 && xevent.xbutton.button <= 7) {
+ event.type = PUGL_SCROLL;
+ event.scroll.time = (double)xevent.xbutton.time / 1e3;
+ event.scroll.x = xevent.xbutton.x;
+ event.scroll.y = xevent.xbutton.y;
+ event.scroll.xRoot = xevent.xbutton.x_root;
+ event.scroll.yRoot = xevent.xbutton.y_root;
+ event.scroll.state = translateModifiers(xevent.xbutton.state);
+ event.scroll.dx = 0.0;
+ event.scroll.dy = 0.0;
+ switch (xevent.xbutton.button) {
+ case 4:
+ event.scroll.dy = 1.0;
+ event.scroll.direction = PUGL_SCROLL_UP;
+ break;
+ case 5:
+ event.scroll.dy = -1.0;
+ event.scroll.direction = PUGL_SCROLL_DOWN;
+ break;
+ case 6:
+ event.scroll.dx = -1.0;
+ event.scroll.direction = PUGL_SCROLL_LEFT;
+ break;
+ case 7:
+ event.scroll.dx = 1.0;
+ event.scroll.direction = PUGL_SCROLL_RIGHT;
+ break;
+ }
+ // fallthru
+ }
+ // fallthru
+ case ButtonRelease:
+ if (xevent.xbutton.button < 4 || xevent.xbutton.button > 7) {
+ event.button.type = ((xevent.type == ButtonPress) ? PUGL_BUTTON_PRESS
+ : PUGL_BUTTON_RELEASE);
+ event.button.time = (double)xevent.xbutton.time / 1e3;
+ event.button.x = xevent.xbutton.x;
+ event.button.y = xevent.xbutton.y;
+ event.button.xRoot = xevent.xbutton.x_root;
+ event.button.yRoot = xevent.xbutton.y_root;
+ event.button.state = translateModifiers(xevent.xbutton.state);
+ event.button.button = xevent.xbutton.button;
+ }
+ break;
+ case KeyPress:
+ case KeyRelease:
+ event.type =
+ ((xevent.type == KeyPress) ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE);
+ event.key.time = (double)xevent.xkey.time / 1e3;
+ event.key.x = xevent.xkey.x;
+ event.key.y = xevent.xkey.y;
+ event.key.xRoot = xevent.xkey.x_root;
+ event.key.yRoot = xevent.xkey.y_root;
+ event.key.state = translateModifiers(xevent.xkey.state);
+ translateKey(view, &xevent, &event);
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ event.type =
+ ((xevent.type == EnterNotify) ? PUGL_POINTER_IN : PUGL_POINTER_OUT);
+ event.crossing.time = (double)xevent.xcrossing.time / 1e3;
+ event.crossing.x = xevent.xcrossing.x;
+ event.crossing.y = xevent.xcrossing.y;
+ event.crossing.xRoot = xevent.xcrossing.x_root;
+ event.crossing.yRoot = xevent.xcrossing.y_root;
+ event.crossing.state = translateModifiers(xevent.xcrossing.state);
+ event.crossing.mode = PUGL_CROSSING_NORMAL;
+ if (xevent.xcrossing.mode == NotifyGrab) {
+ event.crossing.mode = PUGL_CROSSING_GRAB;
+ } else if (xevent.xcrossing.mode == NotifyUngrab) {
+ event.crossing.mode = PUGL_CROSSING_UNGRAB;
+ }
+ break;
+
+ case FocusIn:
+ case FocusOut:
+ event.type = (xevent.type == FocusIn) ? PUGL_FOCUS_IN : PUGL_FOCUS_OUT;
+ event.focus.mode = PUGL_CROSSING_NORMAL;
+ if (xevent.xfocus.mode == NotifyGrab) {
+ event.focus.mode = PUGL_CROSSING_GRAB;
+ } else if (xevent.xfocus.mode == NotifyUngrab) {
+ event.focus.mode = PUGL_CROSSING_UNGRAB;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return event;
}
PuglStatus
puglGrabFocus(PuglView* view)
{
- XSetInputFocus(
- view->impl->display, view->impl->win, RevertToNone, CurrentTime);
- return PUGL_SUCCESS;
+ XSetInputFocus(
+ view->impl->display, view->impl->win, RevertToNone, CurrentTime);
+ return PUGL_SUCCESS;
}
bool
puglHasFocus(const PuglView* view)
{
- int revertTo = 0;
- Window focusedWindow = 0;
- XGetInputFocus(view->impl->display, &focusedWindow, &revertTo);
- return focusedWindow == view->impl->win;
+ int revertTo = 0;
+ Window focusedWindow = 0;
+ XGetInputFocus(view->impl->display, &focusedWindow, &revertTo);
+ return focusedWindow == view->impl->win;
}
PuglStatus
puglRequestAttention(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- const PuglX11Atoms* const atoms = &view->world->impl->atoms;
- XEvent event = {0};
-
- event.type = ClientMessage;
- event.xclient.window = impl->win;
- event.xclient.format = 32;
- event.xclient.message_type = atoms->NET_WM_STATE;
- event.xclient.data.l[0] = WM_STATE_ADD;
- event.xclient.data.l[1] = (long)atoms->NET_WM_STATE_DEMANDS_ATTENTION;
- event.xclient.data.l[2] = 0;
- event.xclient.data.l[3] = 1;
- event.xclient.data.l[4] = 0;
-
- const Window root = RootWindow(impl->display, impl->screen);
- XSendEvent(impl->display,
- root,
- False,
- SubstructureNotifyMask | SubstructureRedirectMask,
- &event);
-
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ const PuglX11Atoms* const atoms = &view->world->impl->atoms;
+ XEvent event = {0};
+
+ event.type = ClientMessage;
+ event.xclient.window = impl->win;
+ event.xclient.format = 32;
+ event.xclient.message_type = atoms->NET_WM_STATE;
+ event.xclient.data.l[0] = WM_STATE_ADD;
+ event.xclient.data.l[1] = (long)atoms->NET_WM_STATE_DEMANDS_ATTENTION;
+ event.xclient.data.l[2] = 0;
+ event.xclient.data.l[3] = 1;
+ event.xclient.data.l[4] = 0;
+
+ const Window root = RootWindow(impl->display, impl->screen);
+ XSendEvent(impl->display,
+ root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event);
+
+ return PUGL_SUCCESS;
}
PuglStatus
puglStartTimer(PuglView* view, uintptr_t id, double timeout)
{
#ifdef HAVE_XSYNC
- if (view->world->impl->syncSupported) {
- XSyncValue value;
- XSyncIntToValue(&value, (int)floor(timeout * 1000.0));
-
- PuglWorldInternals* w = view->world->impl;
- Display* const display = w->display;
- const XSyncCounter counter = w->serverTimeCounter;
- const XSyncTestType type = XSyncPositiveTransition;
- const XSyncTrigger trigger = {counter, XSyncRelative, value, type};
- XSyncAlarmAttributes attr = {trigger, value, True, XSyncAlarmActive};
- const XSyncAlarm alarm = XSyncCreateAlarm(display, 0x17, &attr);
- const PuglTimer timer = {alarm, view, id};
-
- if (alarm != None) {
- for (size_t i = 0; i < w->numTimers; ++i) {
- if (w->timers[i].view == view && w->timers[i].id == id) {
- // Replace existing timer
- XSyncDestroyAlarm(w->display, w->timers[i].alarm);
- w->timers[i] = timer;
- return PUGL_SUCCESS;
- }
- }
-
- // Add new timer
- const size_t size = ++w->numTimers * sizeof(timer);
- w->timers = (PuglTimer*)realloc(w->timers, size);
- w->timers[w->numTimers - 1] = timer;
- return PUGL_SUCCESS;
- }
- }
+ if (view->world->impl->syncSupported) {
+ XSyncValue value;
+ XSyncIntToValue(&value, (int)floor(timeout * 1000.0));
+
+ PuglWorldInternals* w = view->world->impl;
+ Display* const display = w->display;
+ const XSyncCounter counter = w->serverTimeCounter;
+ const XSyncTestType type = XSyncPositiveTransition;
+ const XSyncTrigger trigger = {counter, XSyncRelative, value, type};
+ XSyncAlarmAttributes attr = {trigger, value, True, XSyncAlarmActive};
+ const XSyncAlarm alarm = XSyncCreateAlarm(display, 0x17, &attr);
+ const PuglTimer timer = {alarm, view, id};
+
+ if (alarm != None) {
+ for (size_t i = 0; i < w->numTimers; ++i) {
+ if (w->timers[i].view == view && w->timers[i].id == id) {
+ // Replace existing timer
+ XSyncDestroyAlarm(w->display, w->timers[i].alarm);
+ w->timers[i] = timer;
+ return PUGL_SUCCESS;
+ }
+ }
+
+ // Add new timer
+ const size_t size = ++w->numTimers * sizeof(timer);
+ w->timers = (PuglTimer*)realloc(w->timers, size);
+ w->timers[w->numTimers - 1] = timer;
+ return PUGL_SUCCESS;
+ }
+ }
#else
- (void)view;
- (void)id;
- (void)timeout;
+ (void)view;
+ (void)id;
+ (void)timeout;
#endif
- return PUGL_FAILURE;
+ return PUGL_FAILURE;
}
PuglStatus
puglStopTimer(PuglView* view, uintptr_t id)
{
#ifdef HAVE_XSYNC
- PuglWorldInternals* w = view->world->impl;
-
- for (size_t i = 0; i < w->numTimers; ++i) {
- if (w->timers[i].view == view && w->timers[i].id == id) {
- XSyncDestroyAlarm(w->display, w->timers[i].alarm);
-
- if (i == w->numTimers - 1) {
- memset(&w->timers[i], 0, sizeof(PuglTimer));
- } else {
- memmove(w->timers + i,
- w->timers + i + 1,
- sizeof(PuglTimer) * (w->numTimers - i - 1));
-
- memset(&w->timers[i], 0, sizeof(PuglTimer));
- }
-
- --w->numTimers;
- return PUGL_SUCCESS;
- }
- }
+ PuglWorldInternals* w = view->world->impl;
+
+ for (size_t i = 0; i < w->numTimers; ++i) {
+ if (w->timers[i].view == view && w->timers[i].id == id) {
+ XSyncDestroyAlarm(w->display, w->timers[i].alarm);
+
+ if (i == w->numTimers - 1) {
+ memset(&w->timers[i], 0, sizeof(PuglTimer));
+ } else {
+ memmove(w->timers + i,
+ w->timers + i + 1,
+ sizeof(PuglTimer) * (w->numTimers - i - 1));
+
+ memset(&w->timers[i], 0, sizeof(PuglTimer));
+ }
+
+ --w->numTimers;
+ return PUGL_SUCCESS;
+ }
+ }
#else
- (void)view;
- (void)id;
+ (void)view;
+ (void)id;
#endif
- return PUGL_FAILURE;
+ return PUGL_FAILURE;
}
static XEvent
puglEventToX(PuglView* view, const PuglEvent* event)
{
- XEvent xev = {0};
- xev.xany.send_event = True;
-
- switch (event->type) {
- case PUGL_EXPOSE: {
- const double x = floor(event->expose.x);
- const double y = floor(event->expose.y);
- const double w = ceil(event->expose.x + event->expose.width) - x;
- const double h = ceil(event->expose.y + event->expose.height) - y;
-
- xev.xexpose.type = Expose;
- xev.xexpose.serial = 0;
- xev.xexpose.display = view->impl->display;
- xev.xexpose.window = view->impl->win;
- xev.xexpose.x = (int)x;
- xev.xexpose.y = (int)y;
- xev.xexpose.width = (int)w;
- xev.xexpose.height = (int)h;
- break;
- }
-
- case PUGL_CLIENT:
- xev.xclient.type = ClientMessage;
- xev.xclient.serial = 0;
- xev.xclient.send_event = True;
- xev.xclient.display = view->impl->display;
- xev.xclient.window = view->impl->win;
- xev.xclient.message_type = view->world->impl->atoms.PUGL_CLIENT_MSG;
- xev.xclient.format = 32;
- xev.xclient.data.l[0] = (long)event->client.data1;
- xev.xclient.data.l[1] = (long)event->client.data2;
- break;
-
- default:
- break;
- }
-
- return xev;
+ XEvent xev = {0};
+ xev.xany.send_event = True;
+
+ switch (event->type) {
+ case PUGL_EXPOSE: {
+ const double x = floor(event->expose.x);
+ const double y = floor(event->expose.y);
+ const double w = ceil(event->expose.x + event->expose.width) - x;
+ const double h = ceil(event->expose.y + event->expose.height) - y;
+
+ xev.xexpose.type = Expose;
+ xev.xexpose.serial = 0;
+ xev.xexpose.display = view->impl->display;
+ xev.xexpose.window = view->impl->win;
+ xev.xexpose.x = (int)x;
+ xev.xexpose.y = (int)y;
+ xev.xexpose.width = (int)w;
+ xev.xexpose.height = (int)h;
+ break;
+ }
+
+ case PUGL_CLIENT:
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.display = view->impl->display;
+ xev.xclient.window = view->impl->win;
+ xev.xclient.message_type = view->world->impl->atoms.PUGL_CLIENT_MSG;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = (long)event->client.data1;
+ xev.xclient.data.l[1] = (long)event->client.data2;
+ break;
+
+ default:
+ break;
+ }
+
+ return xev;
}
PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event)
{
- XEvent xev = puglEventToX(view, event);
+ XEvent xev = puglEventToX(view, event);
- if (xev.type) {
- if (XSendEvent(view->impl->display, view->impl->win, False, 0, &xev)) {
- return PUGL_SUCCESS;
- } else {
- return PUGL_UNKNOWN_ERROR;
- }
- }
+ if (xev.type) {
+ if (XSendEvent(view->impl->display, view->impl->win, False, 0, &xev)) {
+ return PUGL_SUCCESS;
+ } else {
+ return PUGL_UNKNOWN_ERROR;
+ }
+ }
- return PUGL_UNSUPPORTED_TYPE;
+ return PUGL_UNSUPPORTED_TYPE;
}
#ifndef PUGL_DISABLE_DEPRECATED
PuglStatus
puglWaitForEvent(PuglView* view)
{
- XEvent xevent;
- XPeekEvent(view->impl->display, &xevent);
- return PUGL_SUCCESS;
+ XEvent xevent;
+ XPeekEvent(view->impl->display, &xevent);
+ return PUGL_SUCCESS;
}
#endif
static void
mergeExposeEvents(PuglEventExpose* dst, const PuglEventExpose* src)
{
- if (!dst->type) {
- *dst = *src;
- } else {
- const double max_x = MAX(dst->x + dst->width, src->x + src->width);
- const double max_y = MAX(dst->y + dst->height, src->y + src->height);
-
- dst->x = MIN(dst->x, src->x);
- dst->y = MIN(dst->y, src->y);
- dst->width = max_x - dst->x;
- dst->height = max_y - dst->y;
- }
+ if (!dst->type) {
+ *dst = *src;
+ } else {
+ const double max_x = MAX(dst->x + dst->width, src->x + src->width);
+ const double max_y = MAX(dst->y + dst->height, src->y + src->height);
+
+ dst->x = MIN(dst->x, src->x);
+ dst->y = MIN(dst->y, src->y);
+ dst->width = max_x - dst->x;
+ dst->height = max_y - dst->y;
+ }
}
static void
handleSelectionNotify(const PuglWorld* world, PuglView* view)
{
- uint8_t* str = NULL;
- Atom type = 0;
- int fmt = 0;
- unsigned long len = 0;
- unsigned long left = 0;
-
- XGetWindowProperty(world->impl->display,
- view->impl->win,
- XA_PRIMARY,
- 0,
- 0x1FFFFFFF,
- False,
- AnyPropertyType,
- &type,
- &fmt,
- &len,
- &left,
- &str);
-
- if (str && fmt == 8 && type == world->impl->atoms.UTF8_STRING &&
- left == 0) {
- puglSetBlob(&view->clipboard, str, len);
- }
-
- XFree(str);
+ uint8_t* str = NULL;
+ Atom type = 0;
+ int fmt = 0;
+ unsigned long len = 0;
+ unsigned long left = 0;
+
+ XGetWindowProperty(world->impl->display,
+ view->impl->win,
+ XA_PRIMARY,
+ 0,
+ 0x1FFFFFFF,
+ False,
+ AnyPropertyType,
+ &type,
+ &fmt,
+ &len,
+ &left,
+ &str);
+
+ if (str && fmt == 8 && type == world->impl->atoms.UTF8_STRING && left == 0) {
+ puglSetBlob(&view->clipboard, str, len);
+ }
+
+ XFree(str);
}
static void
@@ -938,305 +970,308 @@ handleSelectionRequest(const PuglWorld* world,
PuglView* view,
const XSelectionRequestEvent* request)
{
- XSelectionEvent note = {SelectionNotify,
- request->serial,
- False,
- world->impl->display,
- request->requestor,
- request->selection,
- request->target,
- None,
- request->time};
-
- const char* type = NULL;
- size_t len = 0;
- const void* data = puglGetInternalClipboard(view, &type, &len);
- if (data && request->selection == world->impl->atoms.CLIPBOARD &&
- request->target == world->impl->atoms.UTF8_STRING) {
- note.property = request->property;
- XChangeProperty(world->impl->display,
- note.requestor,
- note.property,
- note.target,
- 8,
- PropModeReplace,
- (const uint8_t*)data,
- (int)len);
- } else {
- note.property = None;
- }
-
- XSendEvent(world->impl->display, note.requestor, True, 0, (XEvent*)&note);
+ XSelectionEvent note = {SelectionNotify,
+ request->serial,
+ False,
+ world->impl->display,
+ request->requestor,
+ request->selection,
+ request->target,
+ None,
+ request->time};
+
+ const char* type = NULL;
+ size_t len = 0;
+ const void* data = puglGetInternalClipboard(view, &type, &len);
+ if (data && request->selection == world->impl->atoms.CLIPBOARD &&
+ request->target == world->impl->atoms.UTF8_STRING) {
+ note.property = request->property;
+ XChangeProperty(world->impl->display,
+ note.requestor,
+ note.property,
+ note.target,
+ 8,
+ PropModeReplace,
+ (const uint8_t*)data,
+ (int)len);
+ } else {
+ note.property = None;
+ }
+
+ XSendEvent(world->impl->display, note.requestor, True, 0, (XEvent*)&note);
}
/// Flush pending configure and expose events for all views
static void
flushExposures(PuglWorld* world)
{
- for (size_t i = 0; i < world->numViews; ++i) {
- PuglView* const view = world->views[i];
-
- if (view->visible) {
- puglDispatchSimpleEvent(view, PUGL_UPDATE);
- }
-
- const PuglEvent configure = view->impl->pendingConfigure;
- const PuglEvent expose = view->impl->pendingExpose;
-
- view->impl->pendingConfigure.type = PUGL_NOTHING;
- view->impl->pendingExpose.type = PUGL_NOTHING;
-
- if (configure.type || expose.type) {
- view->backend->enter(view, expose.type ? &expose.expose : NULL);
- puglDispatchEventInContext(view, &configure);
- puglDispatchEventInContext(view, &expose);
- view->backend->leave(view, expose.type ? &expose.expose : NULL);
- }
- }
+ for (size_t i = 0; i < world->numViews; ++i) {
+ PuglView* const view = world->views[i];
+
+ if (view->visible) {
+ puglDispatchSimpleEvent(view, PUGL_UPDATE);
+ }
+
+ const PuglEvent configure = view->impl->pendingConfigure;
+ const PuglEvent expose = view->impl->pendingExpose;
+
+ view->impl->pendingConfigure.type = PUGL_NOTHING;
+ view->impl->pendingExpose.type = PUGL_NOTHING;
+
+ if (configure.type || expose.type) {
+ view->backend->enter(view, expose.type ? &expose.expose : NULL);
+ puglDispatchEventInContext(view, &configure);
+ puglDispatchEventInContext(view, &expose);
+ view->backend->leave(view, expose.type ? &expose.expose : NULL);
+ }
+ }
}
static bool
handleTimerEvent(PuglWorld* world, XEvent xevent)
{
#ifdef HAVE_XSYNC
- if (xevent.type == world->impl->syncEventBase + XSyncAlarmNotify) {
- XSyncAlarmNotifyEvent* notify = ((XSyncAlarmNotifyEvent*)&xevent);
-
- for (size_t i = 0; i < world->impl->numTimers; ++i) {
- if (world->impl->timers[i].alarm == notify->alarm) {
- PuglEvent event = {{PUGL_TIMER, 0}};
- event.timer.id = world->impl->timers[i].id;
- puglDispatchEvent(world->impl->timers[i].view,
- (const PuglEvent*)&event);
- }
- }
-
- return true;
- }
+ if (xevent.type == world->impl->syncEventBase + XSyncAlarmNotify) {
+ XSyncAlarmNotifyEvent* notify = ((XSyncAlarmNotifyEvent*)&xevent);
+
+ for (size_t i = 0; i < world->impl->numTimers; ++i) {
+ if (world->impl->timers[i].alarm == notify->alarm) {
+ PuglEvent event = {{PUGL_TIMER, 0}};
+ event.timer.id = world->impl->timers[i].id;
+ puglDispatchEvent(world->impl->timers[i].view,
+ (const PuglEvent*)&event);
+ }
+ }
+
+ return true;
+ }
#else
- (void)world;
- (void)xevent;
+ (void)world;
+ (void)xevent;
#endif
- return false;
+ return false;
}
static PuglStatus
puglDispatchX11Events(PuglWorld* world)
{
- const PuglX11Atoms* const atoms = &world->impl->atoms;
-
- // Flush output to the server once at the start
- Display* display = world->impl->display;
- XFlush(display);
-
- // Process all queued events (without further flushing)
- while (XEventsQueued(display, QueuedAfterReading) > 0) {
- XEvent xevent;
- XNextEvent(display, &xevent);
-
- if (handleTimerEvent(world, xevent)) {
- continue;
- }
-
- PuglView* view = puglFindView(world, xevent.xany.window);
- if (!view) {
- continue;
- }
-
- // Handle special events
- PuglInternals* const impl = view->impl;
- if (xevent.type == KeyRelease && view->hints[PUGL_IGNORE_KEY_REPEAT]) {
- XEvent next;
- if (XCheckTypedWindowEvent(display, impl->win, KeyPress, &next) &&
- next.type == KeyPress &&
- next.xkey.time == xevent.xkey.time &&
- next.xkey.keycode == xevent.xkey.keycode) {
- continue;
- }
- } else if (xevent.type == FocusIn) {
- XSetICFocus(impl->xic);
- } else if (xevent.type == FocusOut) {
- XUnsetICFocus(impl->xic);
- } else if (xevent.type == SelectionClear) {
- puglSetBlob(&view->clipboard, NULL, 0);
- } else if (xevent.type == SelectionNotify &&
- xevent.xselection.selection == atoms->CLIPBOARD &&
- xevent.xselection.target == atoms->UTF8_STRING &&
- xevent.xselection.property == XA_PRIMARY) {
- handleSelectionNotify(world, view);
- } else if (xevent.type == SelectionRequest) {
- handleSelectionRequest(world, view, &xevent.xselectionrequest);
- }
-
- // Translate X11 event to Pugl event
- const PuglEvent event = translateEvent(view, xevent);
-
- if (event.type == PUGL_EXPOSE) {
- // Expand expose event to be dispatched after loop
- mergeExposeEvents(&view->impl->pendingExpose.expose, &event.expose);
- } else if (event.type == PUGL_CONFIGURE) {
- // Expand configure event to be dispatched after loop
- view->impl->pendingConfigure = event;
- view->frame.x = event.configure.x;
- view->frame.y = event.configure.y;
- view->frame.width = event.configure.width;
- view->frame.height = event.configure.height;
- } else if (event.type == PUGL_MAP && view->parent) {
- XWindowAttributes attrs;
- XGetWindowAttributes(view->impl->display, view->impl->win, &attrs);
-
- const PuglEventConfigure configure = {
- PUGL_CONFIGURE, 0, attrs.x, attrs.y, attrs.width, attrs.height};
-
- puglDispatchEvent(view, (const PuglEvent*)&configure);
- puglDispatchEvent(view, &event);
- } else {
- // Dispatch event to application immediately
- puglDispatchEvent(view, &event);
- }
- }
-
- return PUGL_SUCCESS;
+ const PuglX11Atoms* const atoms = &world->impl->atoms;
+
+ // Flush output to the server once at the start
+ Display* display = world->impl->display;
+ XFlush(display);
+
+ // Process all queued events (without further flushing)
+ while (XEventsQueued(display, QueuedAfterReading) > 0) {
+ XEvent xevent;
+ XNextEvent(display, &xevent);
+
+ if (handleTimerEvent(world, xevent)) {
+ continue;
+ }
+
+ PuglView* view = puglFindView(world, xevent.xany.window);
+ if (!view) {
+ continue;
+ }
+
+ // Handle special events
+ PuglInternals* const impl = view->impl;
+ if (xevent.type == KeyRelease && view->hints[PUGL_IGNORE_KEY_REPEAT]) {
+ XEvent next;
+ if (XCheckTypedWindowEvent(display, impl->win, KeyPress, &next) &&
+ next.type == KeyPress && next.xkey.time == xevent.xkey.time &&
+ next.xkey.keycode == xevent.xkey.keycode) {
+ continue;
+ }
+ } else if (xevent.type == FocusIn) {
+ XSetICFocus(impl->xic);
+ } else if (xevent.type == FocusOut) {
+ XUnsetICFocus(impl->xic);
+ } else if (xevent.type == SelectionClear) {
+ puglSetBlob(&view->clipboard, NULL, 0);
+ } else if (xevent.type == SelectionNotify &&
+ xevent.xselection.selection == atoms->CLIPBOARD &&
+ xevent.xselection.target == atoms->UTF8_STRING &&
+ xevent.xselection.property == XA_PRIMARY) {
+ handleSelectionNotify(world, view);
+ } else if (xevent.type == SelectionRequest) {
+ handleSelectionRequest(world, view, &xevent.xselectionrequest);
+ }
+
+ // Translate X11 event to Pugl event
+ const PuglEvent event = translateEvent(view, xevent);
+
+ if (event.type == PUGL_EXPOSE) {
+ // Expand expose event to be dispatched after loop
+ mergeExposeEvents(&view->impl->pendingExpose.expose, &event.expose);
+ } else if (event.type == PUGL_CONFIGURE) {
+ // Expand configure event to be dispatched after loop
+ view->impl->pendingConfigure = event;
+ view->frame.x = event.configure.x;
+ view->frame.y = event.configure.y;
+ view->frame.width = event.configure.width;
+ view->frame.height = event.configure.height;
+ } else if (event.type == PUGL_MAP && view->parent) {
+ XWindowAttributes attrs;
+ XGetWindowAttributes(view->impl->display, view->impl->win, &attrs);
+
+ const PuglEventConfigure configure = {
+ PUGL_CONFIGURE, 0, attrs.x, attrs.y, attrs.width, attrs.height};
+
+ puglDispatchEvent(view, (const PuglEvent*)&configure);
+ puglDispatchEvent(view, &event);
+ } else {
+ // Dispatch event to application immediately
+ puglDispatchEvent(view, &event);
+ }
+ }
+
+ return PUGL_SUCCESS;
}
#ifndef PUGL_DISABLE_DEPRECATED
PuglStatus
puglProcessEvents(PuglView* view)
{
- return puglUpdate(view->world, 0.0);
+ return puglUpdate(view->world, 0.0);
}
#endif
PuglStatus
puglUpdate(PuglWorld* world, double timeout)
{
- const double startTime = puglGetTime(world);
- PuglStatus st = PUGL_SUCCESS;
-
- world->impl->dispatchingEvents = true;
-
- if (timeout < 0.0) {
- st = puglPollX11Socket(world, timeout);
- st = st ? st : puglDispatchX11Events(world);
- } else if (timeout <= 0.001) {
- st = puglDispatchX11Events(world);
- } else {
- const double endTime = startTime + timeout - 0.001;
- for (double t = startTime; t < endTime; t = puglGetTime(world)) {
- if ((st = puglPollX11Socket(world, endTime - t)) ||
- (st = puglDispatchX11Events(world))) {
- break;
- }
- }
- }
-
- flushExposures(world);
-
- world->impl->dispatchingEvents = false;
-
- return st;
+ const double startTime = puglGetTime(world);
+ PuglStatus st = PUGL_SUCCESS;
+
+ world->impl->dispatchingEvents = true;
+
+ if (timeout < 0.0) {
+ st = puglPollX11Socket(world, timeout);
+ st = st ? st : puglDispatchX11Events(world);
+ } else if (timeout <= 0.001) {
+ st = puglDispatchX11Events(world);
+ } else {
+ const double endTime = startTime + timeout - 0.001;
+ for (double t = startTime; t < endTime; t = puglGetTime(world)) {
+ if ((st = puglPollX11Socket(world, endTime - t)) ||
+ (st = puglDispatchX11Events(world))) {
+ break;
+ }
+ }
+ }
+
+ flushExposures(world);
+
+ world->impl->dispatchingEvents = false;
+
+ return st;
}
double
puglGetTime(const PuglWorld* world)
{
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) -
- world->startTime;
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) -
+ world->startTime;
}
PuglStatus
puglPostRedisplay(PuglView* view)
{
- const PuglRect rect = { 0, 0, view->frame.width, view->frame.height };
+ const PuglRect rect = {0, 0, view->frame.width, view->frame.height};
- return puglPostRedisplayRect(view, rect);
+ return puglPostRedisplayRect(view, rect);
}
PuglStatus
puglPostRedisplayRect(PuglView* view, PuglRect rect)
{
- const PuglEventExpose event = {
- PUGL_EXPOSE, 0, rect.x, rect.y, rect.width, rect.height
- };
-
- if (view->world->impl->dispatchingEvents) {
- // Currently dispatching events, add/expand expose for the loop end
- mergeExposeEvents(&view->impl->pendingExpose.expose, &event);
- } else if (view->visible) {
- // Not dispatching events, send an X expose so we wake up next time
- return puglSendEvent(view, (const PuglEvent*)&event);
- }
-
- return PUGL_SUCCESS;
+ const PuglEventExpose event = {
+ PUGL_EXPOSE, 0, rect.x, rect.y, rect.width, rect.height};
+
+ if (view->world->impl->dispatchingEvents) {
+ // Currently dispatching events, add/expand expose for the loop end
+ mergeExposeEvents(&view->impl->pendingExpose.expose, &event);
+ } else if (view->visible) {
+ // Not dispatching events, send an X expose so we wake up next time
+ return puglSendEvent(view, (const PuglEvent*)&event);
+ }
+
+ return PUGL_SUCCESS;
}
PuglNativeView
puglGetNativeWindow(PuglView* view)
{
- return (PuglNativeView)view->impl->win;
+ return (PuglNativeView)view->impl->win;
}
PuglStatus
puglSetWindowTitle(PuglView* view, const char* title)
{
- Display* display = view->world->impl->display;
- const PuglX11Atoms* const atoms = &view->world->impl->atoms;
-
- puglSetString(&view->title, title);
-
- if (view->impl->win) {
- XStoreName(display, view->impl->win, title);
- XChangeProperty(display, view->impl->win, atoms->NET_WM_NAME,
- atoms->UTF8_STRING, 8, PropModeReplace,
- (const uint8_t*)title, (int)strlen(title));
- }
-
- return PUGL_SUCCESS;
+ Display* display = view->world->impl->display;
+ const PuglX11Atoms* const atoms = &view->world->impl->atoms;
+
+ puglSetString(&view->title, title);
+
+ if (view->impl->win) {
+ XStoreName(display, view->impl->win, title);
+ XChangeProperty(display,
+ view->impl->win,
+ atoms->NET_WM_NAME,
+ atoms->UTF8_STRING,
+ 8,
+ PropModeReplace,
+ (const uint8_t*)title,
+ (int)strlen(title));
+ }
+
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
- if (view->impl->win) {
- if (!XMoveResizeWindow(view->world->impl->display,
- view->impl->win,
- (int)frame.x,
- (int)frame.y,
- (unsigned)frame.width,
- (unsigned)frame.height)) {
- return PUGL_UNKNOWN_ERROR;
- }
- }
-
- view->frame = frame;
- return PUGL_SUCCESS;
+ if (view->impl->win) {
+ if (!XMoveResizeWindow(view->world->impl->display,
+ view->impl->win,
+ (int)frame.x,
+ (int)frame.y,
+ (unsigned)frame.width,
+ (unsigned)frame.height)) {
+ return PUGL_UNKNOWN_ERROR;
+ }
+ }
+
+ view->frame = frame;
+ return PUGL_SUCCESS;
}
PuglStatus
puglSetDefaultSize(PuglView* const view, const int width, const int height)
{
- view->defaultWidth = width;
- view->defaultHeight = height;
- return updateSizeHints(view);
+ view->defaultWidth = width;
+ view->defaultHeight = height;
+ return updateSizeHints(view);
}
PuglStatus
puglSetMinSize(PuglView* const view, const int width, const int height)
{
- view->minWidth = width;
- view->minHeight = height;
- return updateSizeHints(view);
+ view->minWidth = width;
+ view->minHeight = height;
+ return updateSizeHints(view);
}
PuglStatus
puglSetMaxSize(PuglView* const view, const int width, const int height)
{
- view->minWidth = width;
- view->minHeight = height;
- return updateSizeHints(view);
+ view->minWidth = width;
+ view->minHeight = height;
+ return updateSizeHints(view);
}
PuglStatus
@@ -1246,27 +1281,27 @@ puglSetAspectRatio(PuglView* const view,
const int maxX,
const int maxY)
{
- view->minAspectX = minX;
- view->minAspectY = minY;
- view->maxAspectX = maxX;
- view->maxAspectY = maxY;
+ view->minAspectX = minX;
+ view->minAspectY = minY;
+ view->maxAspectX = maxX;
+ view->maxAspectY = maxY;
- return updateSizeHints(view);
+ return updateSizeHints(view);
}
PuglStatus
puglSetTransientFor(PuglView* view, PuglNativeView parent)
{
- Display* display = view->world->impl->display;
+ Display* display = view->world->impl->display;
- view->transientParent = parent;
+ view->transientParent = parent;
- if (view->impl->win) {
- XSetTransientForHint(display, view->impl->win,
- (Window)view->transientParent);
- }
+ if (view->impl->win) {
+ XSetTransientForHint(
+ display, view->impl->win, (Window)view->transientParent);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
const void*
@@ -1274,29 +1309,29 @@ puglGetClipboard(PuglView* const view,
const char** const type,
size_t* const len)
{
- PuglInternals* const impl = view->impl;
- const PuglX11Atoms* const atoms = &view->world->impl->atoms;
-
- const Window owner = XGetSelectionOwner(impl->display, atoms->CLIPBOARD);
- if (owner != None && owner != impl->win) {
- // Clear internal selection
- puglSetBlob(&view->clipboard, NULL, 0);
-
- // Request selection from the owner
- XConvertSelection(impl->display,
- atoms->CLIPBOARD,
- atoms->UTF8_STRING,
- XA_PRIMARY,
- impl->win,
- CurrentTime);
-
- // Run event loop until data is received
- while (!view->clipboard.data) {
- puglUpdate(view->world, -1.0);
- }
- }
-
- return puglGetInternalClipboard(view, type, len);
+ PuglInternals* const impl = view->impl;
+ const PuglX11Atoms* const atoms = &view->world->impl->atoms;
+
+ const Window owner = XGetSelectionOwner(impl->display, atoms->CLIPBOARD);
+ if (owner != None && owner != impl->win) {
+ // Clear internal selection
+ puglSetBlob(&view->clipboard, NULL, 0);
+
+ // Request selection from the owner
+ XConvertSelection(impl->display,
+ atoms->CLIPBOARD,
+ atoms->UTF8_STRING,
+ XA_PRIMARY,
+ impl->win,
+ CurrentTime);
+
+ // Run event loop until data is received
+ while (!view->clipboard.data) {
+ puglUpdate(view->world, -1.0);
+ }
+ }
+
+ return puglGetInternalClipboard(view, type, len);
}
PuglStatus
@@ -1305,27 +1340,27 @@ puglSetClipboard(PuglView* const view,
const void* const data,
const size_t len)
{
- PuglInternals* const impl = view->impl;
- const PuglX11Atoms* const atoms = &view->world->impl->atoms;
+ PuglInternals* const impl = view->impl;
+ const PuglX11Atoms* const atoms = &view->world->impl->atoms;
- PuglStatus st = puglSetInternalClipboard(view, type, data, len);
- if (st) {
- return st;
- }
+ PuglStatus st = puglSetInternalClipboard(view, type, data, len);
+ if (st) {
+ return st;
+ }
- XSetSelectionOwner(impl->display, atoms->CLIPBOARD, impl->win, CurrentTime);
- return PUGL_SUCCESS;
+ XSetSelectionOwner(impl->display, atoms->CLIPBOARD, impl->win, CurrentTime);
+ return PUGL_SUCCESS;
}
#ifdef HAVE_XCURSOR
static const unsigned cursor_nums[] = {
- XC_arrow, // ARROW
- XC_xterm, // CARET
- XC_crosshair, // CROSSHAIR
- XC_hand2, // HAND
- XC_pirate, // NO
- XC_sb_h_double_arrow, // LEFT_RIGHT
- XC_sb_v_double_arrow, // UP_DOWN
+ XC_arrow, // ARROW
+ XC_xterm, // CARET
+ XC_crosshair, // CROSSHAIR
+ XC_hand2, // HAND
+ XC_pirate, // NO
+ XC_sb_h_double_arrow, // LEFT_RIGHT
+ XC_sb_v_double_arrow, // UP_DOWN
};
#endif
@@ -1333,24 +1368,24 @@ PuglStatus
puglSetCursor(PuglView* view, PuglCursor cursor)
{
#ifdef HAVE_XCURSOR
- PuglInternals* const impl = view->impl;
- const unsigned index = (unsigned)cursor;
- const unsigned count = sizeof(cursor_nums) / sizeof(cursor_nums[0]);
- if (index >= count) {
- return PUGL_BAD_PARAMETER;
- }
+ PuglInternals* const impl = view->impl;
+ const unsigned index = (unsigned)cursor;
+ const unsigned count = sizeof(cursor_nums) / sizeof(cursor_nums[0]);
+ if (index >= count) {
+ return PUGL_BAD_PARAMETER;
+ }
- const unsigned shape = cursor_nums[index];
- if (!impl->win || impl->cursorShape == shape) {
- return PUGL_SUCCESS;
- }
+ const unsigned shape = cursor_nums[index];
+ if (!impl->win || impl->cursorShape == shape) {
+ return PUGL_SUCCESS;
+ }
- impl->cursorShape = cursor_nums[index];
+ impl->cursorShape = cursor_nums[index];
- return puglDefineCursorShape(view, impl->cursorShape);
+ return puglDefineCursorShape(view, impl->cursorShape);
#else
- (void)view;
- (void)cursor;
- return PUGL_FAILURE;
+ (void)view;
+ (void)cursor;
+ return PUGL_FAILURE;
#endif
}
diff --git a/src/x11.h b/src/x11.h
index 5749a19..313b4f5 100644
--- a/src/x11.h
+++ b/src/x11.h
@@ -30,48 +30,49 @@
#include <stdint.h>
typedef struct {
- Atom CLIPBOARD;
- Atom UTF8_STRING;
- Atom WM_PROTOCOLS;
- Atom WM_DELETE_WINDOW;
- Atom PUGL_CLIENT_MSG;
- Atom NET_WM_NAME;
- Atom NET_WM_STATE;
- Atom NET_WM_STATE_DEMANDS_ATTENTION;
+ Atom CLIPBOARD;
+ Atom UTF8_STRING;
+ Atom WM_PROTOCOLS;
+ Atom WM_DELETE_WINDOW;
+ Atom PUGL_CLIENT_MSG;
+ Atom NET_WM_NAME;
+ Atom NET_WM_STATE;
+ Atom NET_WM_STATE_DEMANDS_ATTENTION;
} PuglX11Atoms;
typedef struct {
- XID alarm;
- PuglView* view;
- uintptr_t id;
+ XID alarm;
+ PuglView* view;
+ uintptr_t id;
} PuglTimer;
struct PuglWorldInternalsImpl {
- Display* display;
- PuglX11Atoms atoms;
- XIM xim;
- PuglTimer* timers;
- size_t numTimers;
- XID serverTimeCounter;
- int syncEventBase;
- bool syncSupported;
- bool dispatchingEvents;
+ Display* display;
+ PuglX11Atoms atoms;
+ XIM xim;
+ PuglTimer* timers;
+ size_t numTimers;
+ XID serverTimeCounter;
+ int syncEventBase;
+ bool syncSupported;
+ bool dispatchingEvents;
};
struct PuglInternalsImpl {
- Display* display;
- XVisualInfo* vi;
- Window win;
- XIC xic;
- PuglSurface* surface;
- PuglEvent pendingConfigure;
- PuglEvent pendingExpose;
- int screen;
+ Display* display;
+ XVisualInfo* vi;
+ Window win;
+ XIC xic;
+ PuglSurface* surface;
+ PuglEvent pendingConfigure;
+ PuglEvent pendingExpose;
+ int screen;
#ifdef HAVE_XCURSOR
- unsigned cursorShape;
+ unsigned cursorShape;
#endif
};
-PuglStatus puglX11StubConfigure(PuglView* view);
+PuglStatus
+puglX11StubConfigure(PuglView* view);
#endif // PUGL_DETAIL_X11_H
diff --git a/src/x11_cairo.c b/src/x11_cairo.c
index 3147266..a0e7d08 100644
--- a/src/x11_cairo.c
+++ b/src/x11_cairo.c
@@ -27,140 +27,137 @@
#include <stdlib.h>
typedef struct {
- cairo_surface_t* back;
- cairo_surface_t* front;
- cairo_t* cr;
+ cairo_surface_t* back;
+ cairo_surface_t* front;
+ cairo_t* cr;
} PuglX11CairoSurface;
static void
puglX11CairoClose(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
- cairo_surface_destroy(surface->front);
- cairo_surface_destroy(surface->back);
- surface->front = surface->back = NULL;
+ cairo_surface_destroy(surface->front);
+ cairo_surface_destroy(surface->back);
+ surface->front = surface->back = NULL;
}
static PuglStatus
puglX11CairoOpen(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
-
- surface->back = cairo_xlib_surface_create(impl->display,
- impl->win,
- impl->vi->visual,
- (int)view->frame.width,
- (int)view->frame.height);
-
- surface->front = cairo_surface_create_similar(
- surface->back,
- cairo_surface_get_content(surface->back),
- (int)view->frame.width,
- (int)view->frame.height);
-
- if (cairo_surface_status(surface->back) ||
- cairo_surface_status(surface->front)) {
- puglX11CairoClose(view);
- return PUGL_CREATE_CONTEXT_FAILED;
- }
-
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
+
+ surface->back = cairo_xlib_surface_create(impl->display,
+ impl->win,
+ impl->vi->visual,
+ (int)view->frame.width,
+ (int)view->frame.height);
+
+ surface->front =
+ cairo_surface_create_similar(surface->back,
+ cairo_surface_get_content(surface->back),
+ (int)view->frame.width,
+ (int)view->frame.height);
+
+ if (cairo_surface_status(surface->back) ||
+ cairo_surface_status(surface->front)) {
+ puglX11CairoClose(view);
+ return PUGL_CREATE_CONTEXT_FAILED;
+ }
+
+ return PUGL_SUCCESS;
}
static PuglStatus
puglX11CairoCreate(PuglView* view)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* const impl = view->impl;
- impl->surface = (cairo_surface_t*)calloc(1, sizeof(PuglX11CairoSurface));
+ impl->surface = (cairo_surface_t*)calloc(1, sizeof(PuglX11CairoSurface));
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglX11CairoDestroy(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
- puglX11CairoClose(view);
- free(surface);
+ puglX11CairoClose(view);
+ free(surface);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglX11CairoEnter(PuglView* view, const PuglEventExpose* expose)
{
- PuglInternals* const impl = view->impl;
- PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
- PuglStatus st = PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
+ PuglStatus st = PUGL_SUCCESS;
- if (expose && !(st = puglX11CairoOpen(view))) {
- surface->cr = cairo_create(surface->front);
+ if (expose && !(st = puglX11CairoOpen(view))) {
+ surface->cr = cairo_create(surface->front);
- if (cairo_status(surface->cr)) {
- st = PUGL_CREATE_CONTEXT_FAILED;
- }
- }
+ if (cairo_status(surface->cr)) {
+ st = PUGL_CREATE_CONTEXT_FAILED;
+ }
+ }
- return st;
+ return st;
}
static PuglStatus
puglX11CairoLeave(PuglView* view, const PuglEventExpose* expose)
{
- PuglInternals* const impl = view->impl;
- PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
-
- if (expose) {
- // Destroy front context and create a new one for drawing to the back
- cairo_destroy(surface->cr);
- surface->cr = cairo_create(surface->back);
-
- // Clip to expose region
- cairo_rectangle(surface->cr,
- expose->x,
- expose->y,
- expose->width,
- expose->height);
- cairo_clip(surface->cr);
-
- // Paint front onto back
- cairo_set_source_surface(surface->cr, surface->front, 0, 0);
- cairo_paint(surface->cr);
-
- // Flush to X and close everything
- cairo_destroy(surface->cr);
- cairo_surface_flush(surface->back);
- puglX11CairoClose(view);
- surface->cr = NULL;
- }
-
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
+
+ if (expose) {
+ // Destroy front context and create a new one for drawing to the back
+ cairo_destroy(surface->cr);
+ surface->cr = cairo_create(surface->back);
+
+ // Clip to expose region
+ cairo_rectangle(
+ surface->cr, expose->x, expose->y, expose->width, expose->height);
+ cairo_clip(surface->cr);
+
+ // Paint front onto back
+ cairo_set_source_surface(surface->cr, surface->front, 0, 0);
+ cairo_paint(surface->cr);
+
+ // Flush to X and close everything
+ cairo_destroy(surface->cr);
+ cairo_surface_flush(surface->back);
+ puglX11CairoClose(view);
+ surface->cr = NULL;
+ }
+
+ return PUGL_SUCCESS;
}
static void*
puglX11CairoGetContext(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
+ PuglInternals* const impl = view->impl;
+ PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface;
- return surface->cr;
+ return surface->cr;
}
const PuglBackend*
puglCairoBackend(void)
{
- static const PuglBackend backend = {puglX11StubConfigure,
- puglX11CairoCreate,
- puglX11CairoDestroy,
- puglX11CairoEnter,
- puglX11CairoLeave,
- puglX11CairoGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglX11StubConfigure,
+ puglX11CairoCreate,
+ puglX11CairoDestroy,
+ puglX11CairoEnter,
+ puglX11CairoLeave,
+ puglX11CairoGetContext};
+
+ return &backend;
}
diff --git a/src/x11_gl.c b/src/x11_gl.c
index 50b37b8..d0330b0 100644
--- a/src/x11_gl.c
+++ b/src/x11_gl.c
@@ -31,14 +31,14 @@
#include <stdlib.h>
typedef struct {
- GLXFBConfig fb_config;
- GLXContext ctx;
+ GLXFBConfig fb_config;
+ GLXContext ctx;
} PuglX11GlSurface;
static int
puglX11GlHintValue(const int value)
{
- return value == PUGL_DONT_CARE ? (int)GLX_DONT_CARE : value;
+ return value == PUGL_DONT_CARE ? (int)GLX_DONT_CARE : value;
}
static int
@@ -46,185 +46,191 @@ puglX11GlGetAttrib(Display* const display,
GLXFBConfig fb_config,
const int attrib)
{
- int value = 0;
- glXGetFBConfigAttrib(display, fb_config, attrib, &value);
- return value;
+ int value = 0;
+ glXGetFBConfigAttrib(display, fb_config, attrib, &value);
+ return value;
}
static PuglStatus
puglX11GlConfigure(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- const int screen = impl->screen;
- Display* const display = impl->display;
-
- PuglX11GlSurface* const surface =
- (PuglX11GlSurface*)calloc(1, sizeof(PuglX11GlSurface));
- impl->surface = surface;
-
- const int attrs[] = {
- GLX_X_RENDERABLE, True,
- GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
- 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]),
- GLX_ALPHA_SIZE, puglX11GlHintValue(view->hints[PUGL_ALPHA_BITS]),
- GLX_DEPTH_SIZE, puglX11GlHintValue(view->hints[PUGL_DEPTH_BITS]),
- GLX_STENCIL_SIZE, puglX11GlHintValue(view->hints[PUGL_STENCIL_BITS]),
- GLX_DOUBLEBUFFER, puglX11GlHintValue(view->hints[PUGL_DOUBLE_BUFFER]),
- None
- };
-
- int n_fbc = 0;
- GLXFBConfig* fbc = glXChooseFBConfig(display, screen, attrs, &n_fbc);
- if (n_fbc <= 0) {
- return PUGL_CREATE_CONTEXT_FAILED;
- }
-
- 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);
-
- XFree(fbc);
-
- return PUGL_SUCCESS;
+ PuglInternals* const impl = view->impl;
+ const int screen = impl->screen;
+ Display* const display = impl->display;
+
+ PuglX11GlSurface* const surface =
+ (PuglX11GlSurface*)calloc(1, sizeof(PuglX11GlSurface));
+ impl->surface = surface;
+
+ // clang-format off
+ const int attrs[] = {
+ GLX_X_RENDERABLE, True,
+ GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ 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]),
+ GLX_ALPHA_SIZE, puglX11GlHintValue(view->hints[PUGL_ALPHA_BITS]),
+ GLX_DEPTH_SIZE, puglX11GlHintValue(view->hints[PUGL_DEPTH_BITS]),
+ GLX_STENCIL_SIZE, puglX11GlHintValue(view->hints[PUGL_STENCIL_BITS]),
+ GLX_DOUBLEBUFFER, puglX11GlHintValue(view->hints[PUGL_DOUBLE_BUFFER]),
+ None
+ };
+ // clang-format on
+
+ int n_fbc = 0;
+ GLXFBConfig* fbc = glXChooseFBConfig(display, screen, attrs, &n_fbc);
+ if (n_fbc <= 0) {
+ return PUGL_CREATE_CONTEXT_FAILED;
+ }
+
+ 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);
+
+ XFree(fbc);
+
+ return PUGL_SUCCESS;
}
static PuglStatus
puglX11GlEnter(PuglView* view, const PuglEventExpose* PUGL_UNUSED(expose))
{
- PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface;
- glXMakeCurrent(view->impl->display, view->impl->win, surface->ctx);
- return PUGL_SUCCESS;
+ PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface;
+ glXMakeCurrent(view->impl->display, view->impl->win, surface->ctx);
+ return PUGL_SUCCESS;
}
static PuglStatus
puglX11GlLeave(PuglView* view, const PuglEventExpose* expose)
{
- if (expose && view->hints[PUGL_DOUBLE_BUFFER]) {
- glXSwapBuffers(view->impl->display, view->impl->win);
- }
+ if (expose && view->hints[PUGL_DOUBLE_BUFFER]) {
+ glXSwapBuffers(view->impl->display, view->impl->win);
+ }
- glXMakeCurrent(view->impl->display, None, NULL);
+ glXMakeCurrent(view->impl->display, None, NULL);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static PuglStatus
puglX11GlCreate(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- PuglX11GlSurface* const surface = (PuglX11GlSurface*)impl->surface;
- Display* const display = impl->display;
- GLXFBConfig fb_config = surface->fb_config;
-
- const int ctx_attrs[] = {
- GLX_CONTEXT_MAJOR_VERSION_ARB, view->hints[PUGL_CONTEXT_VERSION_MAJOR],
- GLX_CONTEXT_MINOR_VERSION_ARB, view->hints[PUGL_CONTEXT_VERSION_MINOR],
- GLX_CONTEXT_FLAGS_ARB, (view->hints[PUGL_USE_DEBUG_CONTEXT]
- ? GLX_CONTEXT_DEBUG_BIT_ARB
- : 0),
- GLX_CONTEXT_PROFILE_MASK_ARB, (view->hints[PUGL_USE_COMPAT_PROFILE]
- ? GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
- : GLX_CONTEXT_CORE_PROFILE_BIT_ARB),
- 0};
-
- PFNGLXCREATECONTEXTATTRIBSARBPROC create_context =
- (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(
- (const uint8_t*)"glXCreateContextAttribsARB");
-
- PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT =
- (PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress(
- (const uint8_t*)"glXSwapIntervalEXT");
-
- surface->ctx = create_context(display, fb_config, 0, True, ctx_attrs);
- if (!surface->ctx) {
- surface->ctx =
- glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True);
- }
-
- if (!surface->ctx) {
- return PUGL_CREATE_CONTEXT_FAILED;
- }
-
- const int swapInterval = view->hints[PUGL_SWAP_INTERVAL];
- if (glXSwapIntervalEXT && swapInterval != PUGL_DONT_CARE) {
- puglX11GlEnter(view, NULL);
- glXSwapIntervalEXT(display, impl->win, swapInterval);
- puglX11GlLeave(view, NULL);
- }
-
- glXGetConfig(impl->display,
- impl->vi,
- 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;
+ PuglInternals* const impl = view->impl;
+ PuglX11GlSurface* const surface = (PuglX11GlSurface*)impl->surface;
+ Display* const display = impl->display;
+ GLXFBConfig fb_config = surface->fb_config;
+
+ const int ctx_attrs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB,
+ view->hints[PUGL_CONTEXT_VERSION_MAJOR],
+
+ GLX_CONTEXT_MINOR_VERSION_ARB,
+ view->hints[PUGL_CONTEXT_VERSION_MINOR],
+
+ GLX_CONTEXT_FLAGS_ARB,
+ (view->hints[PUGL_USE_DEBUG_CONTEXT] ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+
+ GLX_CONTEXT_PROFILE_MASK_ARB,
+ (view->hints[PUGL_USE_COMPAT_PROFILE]
+ ? GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
+ : GLX_CONTEXT_CORE_PROFILE_BIT_ARB),
+ 0};
+
+ PFNGLXCREATECONTEXTATTRIBSARBPROC create_context =
+ (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress(
+ (const uint8_t*)"glXCreateContextAttribsARB");
+
+ PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT =
+ (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress(
+ (const uint8_t*)"glXSwapIntervalEXT");
+
+ surface->ctx = create_context(display, fb_config, 0, True, ctx_attrs);
+ if (!surface->ctx) {
+ surface->ctx =
+ glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True);
+ }
+
+ if (!surface->ctx) {
+ return PUGL_CREATE_CONTEXT_FAILED;
+ }
+
+ const int swapInterval = view->hints[PUGL_SWAP_INTERVAL];
+ if (glXSwapIntervalEXT && swapInterval != PUGL_DONT_CARE) {
+ puglX11GlEnter(view, NULL);
+ glXSwapIntervalEXT(display, impl->win, swapInterval);
+ puglX11GlLeave(view, NULL);
+ }
+
+ glXGetConfig(impl->display,
+ impl->vi,
+ 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;
}
static PuglStatus
puglX11GlDestroy(PuglView* view)
{
- PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface;
- if (surface) {
- glXDestroyContext(view->impl->display, surface->ctx);
- free(surface);
- view->impl->surface = NULL;
- }
- return PUGL_SUCCESS;
+ PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface;
+ if (surface) {
+ glXDestroyContext(view->impl->display, surface->ctx);
+ free(surface);
+ view->impl->surface = NULL;
+ }
+ return PUGL_SUCCESS;
}
PuglGlFunc
puglGetProcAddress(const char* name)
{
- return glXGetProcAddress((const uint8_t*)name);
+ return glXGetProcAddress((const uint8_t*)name);
}
PuglStatus
puglEnterContext(PuglView* view)
{
- return view->backend->enter(view, NULL);
+ return view->backend->enter(view, NULL);
}
PuglStatus
puglLeaveContext(PuglView* view)
{
- return view->backend->leave(view, NULL);
+ return view->backend->leave(view, NULL);
}
const PuglBackend*
puglGlBackend(void)
{
- static const PuglBackend backend = {puglX11GlConfigure,
- puglX11GlCreate,
- puglX11GlDestroy,
- puglX11GlEnter,
- puglX11GlLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglX11GlConfigure,
+ puglX11GlCreate,
+ puglX11GlDestroy,
+ puglX11GlEnter,
+ puglX11GlLeave,
+ puglStubGetContext};
+
+ return &backend;
}
diff --git a/src/x11_stub.c b/src/x11_stub.c
index be66a88..de89a86 100644
--- a/src/x11_stub.c
+++ b/src/x11_stub.c
@@ -27,32 +27,32 @@
PuglStatus
puglX11StubConfigure(PuglView* view)
{
- PuglInternals* const impl = view->impl;
- XVisualInfo pat = {0};
- int n = 0;
+ PuglInternals* const impl = view->impl;
+ XVisualInfo pat = {0};
+ int n = 0;
- pat.screen = impl->screen;
- impl->vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n);
+ 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;
+ 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;
+ return PUGL_SUCCESS;
}
const PuglBackend*
puglStubBackend(void)
{
- static const PuglBackend backend = {
- puglX11StubConfigure,
- puglStubCreate,
- puglStubDestroy,
- puglStubEnter,
- puglStubLeave,
- puglStubGetContext,
- };
-
- return &backend;
+ static const PuglBackend backend = {
+ puglX11StubConfigure,
+ puglStubCreate,
+ puglStubDestroy,
+ puglStubEnter,
+ puglStubLeave,
+ puglStubGetContext,
+ };
+
+ return &backend;
}
diff --git a/src/x11_vulkan.c b/src/x11_vulkan.c
index b32111c..77bdd59 100644
--- a/src/x11_vulkan.c
+++ b/src/x11_vulkan.c
@@ -31,78 +31,77 @@
#include <stdint.h>
#include <stdlib.h>
-struct PuglVulkanLoaderImpl
-{
- void* libvulkan;
- PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
- PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+struct PuglVulkanLoaderImpl {
+ void* libvulkan;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
};
PuglVulkanLoader*
puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world))
{
- PuglVulkanLoader* loader =
- (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
- if (!loader) {
- return NULL;
- }
+ PuglVulkanLoader* loader =
+ (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
+ if (!loader) {
+ return NULL;
+ }
- if (!(loader->libvulkan = dlopen("libvulkan.so", RTLD_LAZY))) {
- free(loader);
- return NULL;
- }
+ if (!(loader->libvulkan = dlopen("libvulkan.so", RTLD_LAZY))) {
+ free(loader);
+ return NULL;
+ }
- loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(
- loader->libvulkan, "vkGetInstanceProcAddr");
+ loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(
+ loader->libvulkan, "vkGetInstanceProcAddr");
- loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)dlsym(
- loader->libvulkan, "vkGetDeviceProcAddr");
+ loader->vkGetDeviceProcAddr =
+ (PFN_vkGetDeviceProcAddr)dlsym(loader->libvulkan, "vkGetDeviceProcAddr");
- return loader;
+ return loader;
}
void
puglFreeVulkanLoader(PuglVulkanLoader* loader)
{
- if (loader) {
- dlclose(loader->libvulkan);
- free(loader);
- }
+ if (loader) {
+ dlclose(loader->libvulkan);
+ free(loader);
+ }
}
PFN_vkGetInstanceProcAddr
puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader)
{
- return loader->vkGetInstanceProcAddr;
+ return loader->vkGetInstanceProcAddr;
}
PFN_vkGetDeviceProcAddr
puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader)
{
- return loader->vkGetDeviceProcAddr;
+ return loader->vkGetDeviceProcAddr;
}
const PuglBackend*
puglVulkanBackend(void)
{
- static const PuglBackend backend = {puglX11StubConfigure,
- puglStubCreate,
- puglStubDestroy,
- puglStubEnter,
- puglStubLeave,
- puglStubGetContext};
-
- return &backend;
+ static const PuglBackend backend = {puglX11StubConfigure,
+ puglStubCreate,
+ puglStubDestroy,
+ puglStubEnter,
+ puglStubLeave,
+ puglStubGetContext};
+
+ return &backend;
}
const char* const*
puglGetInstanceExtensions(uint32_t* const count)
{
- static const char* const extensions[] = {"VK_KHR_surface",
- "VK_KHR_xlib_surface"};
+ static const char* const extensions[] = {"VK_KHR_surface",
+ "VK_KHR_xlib_surface"};
- *count = 2;
- return extensions;
+ *count = 2;
+ return extensions;
}
VkResult
@@ -112,20 +111,20 @@ puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr,
const VkAllocationCallbacks* const allocator,
VkSurfaceKHR* const surface)
{
- PuglInternals* const impl = view->impl;
- PuglWorldInternals* world_impl = view->world->impl;
-
- PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR =
- (PFN_vkCreateXlibSurfaceKHR)
- vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR");
-
- const VkXlibSurfaceCreateInfoKHR info = {
- VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
- NULL,
- 0,
- world_impl->display,
- impl->win,
- };
-
- return vkCreateXlibSurfaceKHR(instance, &info, allocator, surface);
+ PuglInternals* const impl = view->impl;
+ PuglWorldInternals* world_impl = view->world->impl;
+
+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR =
+ (PFN_vkCreateXlibSurfaceKHR)vkGetInstanceProcAddr(instance,
+ "vkCreateXlibSurfaceKHR");
+
+ const VkXlibSurfaceCreateInfoKHR info = {
+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+ NULL,
+ 0,
+ world_impl->display,
+ impl->win,
+ };
+
+ return vkCreateXlibSurfaceKHR(instance, &info, allocator, surface);
}
diff --git a/test/test_build.c b/test/test_build.c
index 5259c7c..957e0bd 100644
--- a/test/test_build.c
+++ b/test/test_build.c
@@ -28,5 +28,5 @@
int
main(void)
{
- return 0;
+ return 0;
}
diff --git a/test/test_build.cpp b/test/test_build.cpp
index 5beb4c3..20235e8 100644
--- a/test/test_build.cpp
+++ b/test/test_build.cpp
@@ -29,5 +29,5 @@
int
main()
{
- return 0;
+ return 0;
}
diff --git a/test/test_clipboard.c b/test/test_clipboard.c
index c1180b0..5749b65 100644
--- a/test/test_clipboard.c
+++ b/test/test_clipboard.c
@@ -30,75 +30,75 @@
#include <stddef.h>
typedef struct {
- PuglWorld* world;
- PuglView* views[2];
- PuglTestOptions opts;
- bool exposed;
+ PuglWorld* world;
+ PuglView* views[2];
+ PuglTestOptions opts;
+ bool exposed;
} PuglTest;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTest* test = (PuglTest*)puglGetHandle(view);
+ PuglTest* test = (PuglTest*)puglGetHandle(view);
- if (event->type == PUGL_EXPOSE) {
- test->exposed = true;
- }
+ if (event->type == PUGL_EXPOSE) {
+ test->exposed = true;
+ }
- if (test->opts.verbose) {
- printEvent(event, "Event: ", true);
- }
+ if (test->opts.verbose) {
+ printEvent(event, "Event: ", true);
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0),
- {NULL, NULL},
- puglParseTestOptions(&argc, &argv),
- false};
-
- puglSetClassName(test.world, "Pugl Test");
-
- // Set up views
- for (unsigned i = 0u; i < 2; ++i) {
- test.views[i] = puglNewView(test.world);
- puglSetBackend(test.views[i], puglStubBackend());
- puglSetHandle(test.views[i], &test);
- puglSetEventFunc(test.views[i], onEvent);
- puglSetDefaultSize(test.views[i], 512, 512);
-
- assert(!puglShow(test.views[i]));
- }
-
- // Update until view is exposed
- while (!test.exposed) {
- assert(!puglUpdate(test.world, 0.0));
- }
-
- // Set clipboard text via the first view
- puglSetClipboard(test.views[0], NULL, "Text", 5);
-
- // Get clipboard contents via the second view
- const char* type = NULL;
- size_t len = 0;
- const void* const contents = puglGetClipboard(test.views[1], &type, &len);
-
- // Check that the data made it over
- assert(!strcmp(type, "text/plain"));
- assert(len == 5);
- assert(contents);
- assert(!strcmp((const char*)contents, "Text"));
-
- // Try setting the clipboard to an unsupported type
- assert(puglSetClipboard(test.views[0], "text/csv", "a,b,c", 6));
-
- // Tear down
- puglFreeView(test.views[0]);
- puglFreeView(test.views[1]);
- puglFreeWorld(test.world);
-
- return 0;
+ PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0),
+ {NULL, NULL},
+ puglParseTestOptions(&argc, &argv),
+ false};
+
+ puglSetClassName(test.world, "Pugl Test");
+
+ // Set up views
+ for (unsigned i = 0u; i < 2; ++i) {
+ test.views[i] = puglNewView(test.world);
+ puglSetBackend(test.views[i], puglStubBackend());
+ puglSetHandle(test.views[i], &test);
+ puglSetEventFunc(test.views[i], onEvent);
+ puglSetDefaultSize(test.views[i], 512, 512);
+
+ assert(!puglShow(test.views[i]));
+ }
+
+ // Update until view is exposed
+ while (!test.exposed) {
+ assert(!puglUpdate(test.world, 0.0));
+ }
+
+ // Set clipboard text via the first view
+ puglSetClipboard(test.views[0], NULL, "Text", 5);
+
+ // Get clipboard contents via the second view
+ const char* type = NULL;
+ size_t len = 0;
+ const void* const contents = puglGetClipboard(test.views[1], &type, &len);
+
+ // Check that the data made it over
+ assert(!strcmp(type, "text/plain"));
+ assert(len == 5);
+ assert(contents);
+ assert(!strcmp((const char*)contents, "Text"));
+
+ // Try setting the clipboard to an unsupported type
+ assert(puglSetClipboard(test.views[0], "text/csv", "a,b,c", 6));
+
+ // Tear down
+ puglFreeView(test.views[0]);
+ puglFreeView(test.views[1]);
+ puglFreeWorld(test.world);
+
+ return 0;
}
diff --git a/test/test_gl_hints.c b/test/test_gl_hints.c
index c30d0ed..3be3651 100644
--- a/test/test_gl_hints.c
+++ b/test/test_gl_hints.c
@@ -30,60 +30,60 @@
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- (void)view;
- (void)event;
+ (void)view;
+ (void)event;
- return PUGL_SUCCESS;
+ 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));
- assert(!puglSetViewHint(view, PUGL_REFRESH_RATE, PUGL_DONT_CARE));
-
- // Realize view and print all hints for debugging convenience
- assert(!puglRealize(view));
- printViewHints(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);
- assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE);
-
- // Tear down
- puglFreeView(view);
- puglFreeWorld(world);
-
- return 0;
+ 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));
+ assert(!puglSetViewHint(view, PUGL_REFRESH_RATE, PUGL_DONT_CARE));
+
+ // Realize view and print all hints for debugging convenience
+ assert(!puglRealize(view));
+ printViewHints(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);
+ assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE);
+
+ // Tear down
+ puglFreeView(view);
+ puglFreeWorld(world);
+
+ return 0;
}
diff --git a/test/test_realize.c b/test/test_realize.c
index bb0b327..3c4e09a 100644
--- a/test/test_realize.c
+++ b/test/test_realize.c
@@ -34,67 +34,67 @@
#include <stddef.h>
typedef enum {
- START,
- CREATED,
+ START,
+ CREATED,
} State;
typedef struct {
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
- State state;
+ PuglWorld* world;
+ PuglView* view;
+ PuglTestOptions opts;
+ State state;
} PuglTest;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTest* test = (PuglTest*)puglGetHandle(view);
-
- if (test->opts.verbose) {
- printEvent(event, "Event: ", true);
- }
-
- switch (event->type) {
- case PUGL_CREATE:
- assert(test->state == START);
- test->state = CREATED;
- break;
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglTest* test = (PuglTest*)puglGetHandle(view);
+
+ if (test->opts.verbose) {
+ printEvent(event, "Event: ", true);
+ }
+
+ switch (event->type) {
+ case PUGL_CREATE:
+ assert(test->state == START);
+ test->state = CREATED;
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0),
- NULL,
- puglParseTestOptions(&argc, &argv),
- START};
-
- // Set up view
- test.view = puglNewView(test.world);
- puglSetClassName(test.world, "Pugl Test");
- puglSetBackend(test.view, puglStubBackend());
- puglSetHandle(test.view, &test);
- puglSetEventFunc(test.view, onEvent);
- puglSetDefaultSize(test.view, 512, 512);
-
- // Create initially invisible window
- assert(!puglRealize(test.view));
- assert(!puglGetVisible(test.view));
- while (test.state < CREATED) {
- assert(!puglUpdate(test.world, -1.0));
- }
-
- // Check that calling realize() again is okay
- assert(puglRealize(test.view) == PUGL_FAILURE);
-
- // Tear down
- puglFreeView(test.view);
- puglFreeWorld(test.world);
-
- return 0;
+ PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0),
+ NULL,
+ puglParseTestOptions(&argc, &argv),
+ START};
+
+ // Set up view
+ test.view = puglNewView(test.world);
+ puglSetClassName(test.world, "Pugl Test");
+ puglSetBackend(test.view, puglStubBackend());
+ puglSetHandle(test.view, &test);
+ puglSetEventFunc(test.view, onEvent);
+ puglSetDefaultSize(test.view, 512, 512);
+
+ // Create initially invisible window
+ assert(!puglRealize(test.view));
+ assert(!puglGetVisible(test.view));
+ while (test.state < CREATED) {
+ assert(!puglUpdate(test.world, -1.0));
+ }
+
+ // Check that calling realize() again is okay
+ assert(puglRealize(test.view) == PUGL_FAILURE);
+
+ // Tear down
+ puglFreeView(test.view);
+ puglFreeWorld(test.world);
+
+ return 0;
}
diff --git a/test/test_redisplay.c b/test/test_redisplay.c
index 1d5b084..c5b9887 100644
--- a/test/test_redisplay.c
+++ b/test/test_redisplay.c
@@ -38,19 +38,18 @@ static const double timeout = -1.0;
#endif
typedef enum {
- START,
- EXPOSED,
- SHOULD_REDISPLAY,
- POSTED_REDISPLAY,
- REDISPLAYED,
+ START,
+ EXPOSED,
+ SHOULD_REDISPLAY,
+ POSTED_REDISPLAY,
+ REDISPLAYED,
} State;
-typedef struct
-{
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
- State state;
+typedef struct {
+ PuglWorld* world;
+ PuglView* view;
+ PuglTestOptions opts;
+ State state;
} PuglTest;
static const PuglRect redisplayRect = {2, 4, 8, 16};
@@ -59,83 +58,84 @@ static const uintptr_t postRedisplayId = 42;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTest* test = (PuglTest*)puglGetHandle(view);
-
- if (test->opts.verbose) {
- printEvent(event, "Event: ", true);
- }
-
- switch (event->type) {
- case PUGL_UPDATE:
- if (test->state == SHOULD_REDISPLAY) {
- puglPostRedisplayRect(view, redisplayRect);
- test->state = POSTED_REDISPLAY;
- }
- break;
-
- case PUGL_EXPOSE:
- if (test->state == START) {
- test->state = EXPOSED;
- } else if (test->state == POSTED_REDISPLAY &&
- event->expose.x == redisplayRect.x &&
- event->expose.y == redisplayRect.y &&
- event->expose.width == redisplayRect.width &&
- event->expose.height == redisplayRect.height) {
- test->state = REDISPLAYED;
- }
- break;
-
- case PUGL_CLIENT:
- if (event->client.data1 == postRedisplayId) {
- test->state = SHOULD_REDISPLAY;
- }
- break;
-
- default: break;
- }
-
- return PUGL_SUCCESS;
+ PuglTest* test = (PuglTest*)puglGetHandle(view);
+
+ if (test->opts.verbose) {
+ printEvent(event, "Event: ", true);
+ }
+
+ switch (event->type) {
+ case PUGL_UPDATE:
+ if (test->state == SHOULD_REDISPLAY) {
+ puglPostRedisplayRect(view, redisplayRect);
+ test->state = POSTED_REDISPLAY;
+ }
+ break;
+
+ case PUGL_EXPOSE:
+ if (test->state == START) {
+ test->state = EXPOSED;
+ } else if (test->state == POSTED_REDISPLAY &&
+ event->expose.x == redisplayRect.x &&
+ event->expose.y == redisplayRect.y &&
+ event->expose.width == redisplayRect.width &&
+ event->expose.height == redisplayRect.height) {
+ test->state = REDISPLAYED;
+ }
+ break;
+
+ case PUGL_CLIENT:
+ if (event->client.data1 == postRedisplayId) {
+ test->state = SHOULD_REDISPLAY;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTest app = {puglNewWorld(PUGL_PROGRAM, 0),
- NULL,
- puglParseTestOptions(&argc, &argv),
- START};
-
- // Set up view
- app.view = puglNewView(app.world);
- puglSetClassName(app.world, "Pugl Test");
- puglSetBackend(app.view, puglStubBackend());
- puglSetHandle(app.view, &app);
- puglSetEventFunc(app.view, onEvent);
- puglSetDefaultSize(app.view, 512, 512);
-
- // Create and show window
- assert(!puglRealize(app.view));
- assert(!puglShow(app.view));
- while (app.state != EXPOSED) {
- assert(!puglUpdate(app.world, timeout));
- }
-
- // Send a custom event to trigger a redisplay in the event loop
- PuglEvent client_event = {{PUGL_CLIENT, 0}};
- client_event.client.data1 = postRedisplayId;
- client_event.client.data2 = 0;
- assert(!puglSendEvent(app.view, &client_event));
-
- // Loop until an expose happens in the same iteration as the redisplay
- app.state = SHOULD_REDISPLAY;
- while (app.state != REDISPLAYED) {
- assert(!puglUpdate(app.world, timeout));
- assert(app.state != POSTED_REDISPLAY);
- }
-
- // Tear down
- puglFreeView(app.view);
- puglFreeWorld(app.world);
-
- return 0;
+ PuglTest app = {puglNewWorld(PUGL_PROGRAM, 0),
+ NULL,
+ puglParseTestOptions(&argc, &argv),
+ START};
+
+ // Set up view
+ app.view = puglNewView(app.world);
+ puglSetClassName(app.world, "Pugl Test");
+ puglSetBackend(app.view, puglStubBackend());
+ puglSetHandle(app.view, &app);
+ puglSetEventFunc(app.view, onEvent);
+ puglSetDefaultSize(app.view, 512, 512);
+
+ // Create and show window
+ assert(!puglRealize(app.view));
+ assert(!puglShow(app.view));
+ while (app.state != EXPOSED) {
+ assert(!puglUpdate(app.world, timeout));
+ }
+
+ // Send a custom event to trigger a redisplay in the event loop
+ PuglEvent client_event = {{PUGL_CLIENT, 0}};
+ client_event.client.data1 = postRedisplayId;
+ client_event.client.data2 = 0;
+ assert(!puglSendEvent(app.view, &client_event));
+
+ // Loop until an expose happens in the same iteration as the redisplay
+ app.state = SHOULD_REDISPLAY;
+ while (app.state != REDISPLAYED) {
+ assert(!puglUpdate(app.world, timeout));
+ assert(app.state != POSTED_REDISPLAY);
+ }
+
+ // Tear down
+ puglFreeView(app.view);
+ puglFreeWorld(app.world);
+
+ return 0;
}
diff --git a/test/test_show_hide.c b/test/test_show_hide.c
index 4280408..584448c 100644
--- a/test/test_show_hide.c
+++ b/test/test_show_hide.c
@@ -31,118 +31,118 @@
#include <stddef.h>
typedef enum {
- START,
- CREATED,
- CONFIGURED,
- MAPPED,
- EXPOSED,
- UNMAPPED,
- DESTROYED,
+ START,
+ CREATED,
+ CONFIGURED,
+ MAPPED,
+ EXPOSED,
+ UNMAPPED,
+ DESTROYED,
} State;
typedef struct {
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
- State state;
+ PuglWorld* world;
+ PuglView* view;
+ PuglTestOptions opts;
+ State state;
} PuglTest;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTest* test = (PuglTest*)puglGetHandle(view);
-
- if (test->opts.verbose) {
- printEvent(event, "Event: ", true);
- }
-
- switch (event->type) {
- case PUGL_CREATE:
- assert(test->state == START);
- test->state = CREATED;
- break;
- case PUGL_CONFIGURE:
- if (test->state == CREATED) {
- test->state = CONFIGURED;
- }
- break;
- case PUGL_MAP:
- assert(test->state == CONFIGURED || test->state == UNMAPPED);
- test->state = MAPPED;
- break;
- case PUGL_EXPOSE:
- assert(test->state == MAPPED || test->state == EXPOSED);
- test->state = EXPOSED;
- break;
- case PUGL_UNMAP:
- assert(test->state == EXPOSED);
- test->state = UNMAPPED;
- break;
- case PUGL_DESTROY:
- assert(test->state == UNMAPPED);
- test->state = DESTROYED;
- break;
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglTest* test = (PuglTest*)puglGetHandle(view);
+
+ if (test->opts.verbose) {
+ printEvent(event, "Event: ", true);
+ }
+
+ switch (event->type) {
+ case PUGL_CREATE:
+ assert(test->state == START);
+ test->state = CREATED;
+ break;
+ case PUGL_CONFIGURE:
+ if (test->state == CREATED) {
+ test->state = CONFIGURED;
+ }
+ break;
+ case PUGL_MAP:
+ assert(test->state == CONFIGURED || test->state == UNMAPPED);
+ test->state = MAPPED;
+ break;
+ case PUGL_EXPOSE:
+ assert(test->state == MAPPED || test->state == EXPOSED);
+ test->state = EXPOSED;
+ break;
+ case PUGL_UNMAP:
+ assert(test->state == EXPOSED);
+ test->state = UNMAPPED;
+ break;
+ case PUGL_DESTROY:
+ assert(test->state == UNMAPPED);
+ test->state = DESTROYED;
+ break;
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
static void
tick(PuglWorld* world)
{
#ifdef __APPLE__
- // FIXME: Expose events are not events on MacOS, so we can't block
- // indefinitely here since it will block forever
- assert(!puglUpdate(world, 1 / 30.0));
+ // FIXME: Expose events are not events on MacOS, so we can't block
+ // indefinitely here since it will block forever
+ assert(!puglUpdate(world, 1 / 30.0));
#else
- assert(!puglUpdate(world, -1));
+ assert(!puglUpdate(world, -1));
#endif
}
int
main(int argc, char** argv)
{
- PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0),
- NULL,
- puglParseTestOptions(&argc, &argv),
- START};
-
- // Set up view
- test.view = puglNewView(test.world);
- puglSetClassName(test.world, "Pugl Test");
- puglSetBackend(test.view, puglStubBackend());
- puglSetHandle(test.view, &test);
- puglSetEventFunc(test.view, onEvent);
- puglSetDefaultSize(test.view, 512, 512);
-
- // Create initially invisible window
- assert(!puglRealize(test.view));
- assert(!puglGetVisible(test.view));
- while (test.state < CREATED) {
- tick(test.world);
- }
-
- // Show and hide window a couple of times
- for (unsigned i = 0u; i < 2u; ++i) {
- assert(!puglShow(test.view));
- while (test.state != EXPOSED) {
- tick(test.world);
- }
-
- assert(puglGetVisible(test.view));
- assert(!puglHide(test.view));
- while (test.state != UNMAPPED) {
- tick(test.world);
- }
- }
-
- // Tear down
- assert(!puglGetVisible(test.view));
- puglFreeView(test.view);
- assert(test.state == DESTROYED);
- puglFreeWorld(test.world);
-
- return 0;
+ PuglTest test = {puglNewWorld(PUGL_PROGRAM, 0),
+ NULL,
+ puglParseTestOptions(&argc, &argv),
+ START};
+
+ // Set up view
+ test.view = puglNewView(test.world);
+ puglSetClassName(test.world, "Pugl Test");
+ puglSetBackend(test.view, puglStubBackend());
+ puglSetHandle(test.view, &test);
+ puglSetEventFunc(test.view, onEvent);
+ puglSetDefaultSize(test.view, 512, 512);
+
+ // Create initially invisible window
+ assert(!puglRealize(test.view));
+ assert(!puglGetVisible(test.view));
+ while (test.state < CREATED) {
+ tick(test.world);
+ }
+
+ // Show and hide window a couple of times
+ for (unsigned i = 0u; i < 2u; ++i) {
+ assert(!puglShow(test.view));
+ while (test.state != EXPOSED) {
+ tick(test.world);
+ }
+
+ assert(puglGetVisible(test.view));
+ assert(!puglHide(test.view));
+ while (test.state != UNMAPPED) {
+ tick(test.world);
+ }
+ }
+
+ // Tear down
+ assert(!puglGetVisible(test.view));
+ puglFreeView(test.view);
+ assert(test.state == DESTROYED);
+ puglFreeWorld(test.world);
+
+ return 0;
}
diff --git a/test/test_stub_hints.c b/test/test_stub_hints.c
index 2bfc86c..1cc1180 100644
--- a/test/test_stub_hints.c
+++ b/test/test_stub_hints.c
@@ -30,51 +30,51 @@
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- (void)view;
- (void)event;
+ (void)view;
+ (void)event;
- return PUGL_SUCCESS;
+ 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));
- assert(!puglSetViewHint(view, PUGL_REFRESH_RATE, PUGL_DONT_CARE));
-
- // Realize view and print all hints for debugging convenience
- assert(!puglRealize(view));
- printViewHints(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);
- assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE);
-
- // Tear down
- puglFreeView(view);
- puglFreeWorld(world);
-
- return 0;
+ 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));
+ assert(!puglSetViewHint(view, PUGL_REFRESH_RATE, PUGL_DONT_CARE));
+
+ // Realize view and print all hints for debugging convenience
+ assert(!puglRealize(view));
+ printViewHints(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);
+ assert(puglGetViewHint(view, PUGL_REFRESH_RATE) != PUGL_DONT_CARE);
+
+ // Tear down
+ puglFreeView(view);
+ puglFreeWorld(world);
+
+ return 0;
}
diff --git a/test/test_timer.c b/test/test_timer.c
index 0b77396..18518ec 100644
--- a/test/test_timer.c
+++ b/test/test_timer.c
@@ -50,112 +50,110 @@ static const uintptr_t timerId = 1u;
static const double timerPeriod = 1 / 60.0;
typedef enum {
- START,
- EXPOSED,
+ START,
+ EXPOSED,
} State;
typedef struct {
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
- size_t numAlarms;
- State state;
+ PuglWorld* world;
+ PuglView* view;
+ PuglTestOptions opts;
+ size_t numAlarms;
+ State state;
} PuglTest;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTest* test = (PuglTest*)puglGetHandle(view);
+ PuglTest* test = (PuglTest*)puglGetHandle(view);
- if (test->opts.verbose) {
- printEvent(event, "Event: ", true);
- }
+ if (test->opts.verbose) {
+ printEvent(event, "Event: ", true);
+ }
- switch (event->type) {
- case PUGL_EXPOSE:
- test->state = EXPOSED;
- break;
+ switch (event->type) {
+ case PUGL_EXPOSE:
+ test->state = EXPOSED;
+ break;
- case PUGL_TIMER:
- assert(event->timer.id == timerId);
- ++test->numAlarms;
- break;
+ case PUGL_TIMER:
+ assert(event->timer.id == timerId);
+ ++test->numAlarms;
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
}
static double
roundPeriod(const double period)
{
- return floor(period * 1000.0) / 1000.0; // Round down to milliseconds
+ return floor(period * 1000.0) / 1000.0; // Round down to milliseconds
}
int
main(int argc, char** argv)
{
- PuglTest app = {puglNewWorld(PUGL_PROGRAM, 0),
- NULL,
- puglParseTestOptions(&argc, &argv),
- 0,
- START};
-
- // Set up view
- app.view = puglNewView(app.world);
- puglSetClassName(app.world, "Pugl Test");
- puglSetBackend(app.view, puglStubBackend());
- puglSetHandle(app.view, &app);
- puglSetEventFunc(app.view, onEvent);
- puglSetDefaultSize(app.view, 512, 512);
-
- // Create and show window
- assert(!puglRealize(app.view));
- assert(!puglShow(app.view));
- while (app.state != EXPOSED) {
- assert(!puglUpdate(app.world, timeout));
- }
-
- // Register a timer with a longer period first
- assert(!puglStartTimer(app.view, timerId, timerPeriod * 2.0));
-
- // Replace it with the one we want (to ensure timers are replaced)
- assert(!puglStartTimer(app.view, timerId, timerPeriod));
-
- const double startTime = puglGetTime(app.world);
-
- puglUpdate(app.world, 1.0);
-
- // Calculate the actual period of the timer
- const double endTime = puglGetTime(app.world);
- const double duration = endTime - startTime;
- const double expectedPeriod = roundPeriod(timerPeriod);
- const double actualPeriod = roundPeriod(duration / (double)app.numAlarms);
- const double difference = fabs(actualPeriod - expectedPeriod);
-
- if (difference > tolerance) {
- fprintf(stderr,
- "error: Period not within %f of %f\n",
- tolerance,
- expectedPeriod);
- fprintf(stderr, "note: Actual period %f\n", actualPeriod);
- }
-
- assert(difference <= tolerance);
-
- // Deregister timer and tick once to synchronize
- assert(!puglStopTimer(app.view, timerId));
- puglUpdate(app.world, 0.0);
-
- // Update for a half second and check that we receive no more alarms
- app.numAlarms = 0;
- puglUpdate(app.world, 0.5);
- assert(app.numAlarms == 0);
-
- puglFreeView(app.view);
- puglFreeWorld(app.world);
-
- return 0;
+ PuglTest app = {puglNewWorld(PUGL_PROGRAM, 0),
+ NULL,
+ puglParseTestOptions(&argc, &argv),
+ 0,
+ START};
+
+ // Set up view
+ app.view = puglNewView(app.world);
+ puglSetClassName(app.world, "Pugl Test");
+ puglSetBackend(app.view, puglStubBackend());
+ puglSetHandle(app.view, &app);
+ puglSetEventFunc(app.view, onEvent);
+ puglSetDefaultSize(app.view, 512, 512);
+
+ // Create and show window
+ assert(!puglRealize(app.view));
+ assert(!puglShow(app.view));
+ while (app.state != EXPOSED) {
+ assert(!puglUpdate(app.world, timeout));
+ }
+
+ // Register a timer with a longer period first
+ assert(!puglStartTimer(app.view, timerId, timerPeriod * 2.0));
+
+ // Replace it with the one we want (to ensure timers are replaced)
+ assert(!puglStartTimer(app.view, timerId, timerPeriod));
+
+ const double startTime = puglGetTime(app.world);
+
+ puglUpdate(app.world, 1.0);
+
+ // Calculate the actual period of the timer
+ const double endTime = puglGetTime(app.world);
+ const double duration = endTime - startTime;
+ const double expectedPeriod = roundPeriod(timerPeriod);
+ const double actualPeriod = roundPeriod(duration / (double)app.numAlarms);
+ const double difference = fabs(actualPeriod - expectedPeriod);
+
+ if (difference > tolerance) {
+ fprintf(
+ stderr, "error: Period not within %f of %f\n", tolerance, expectedPeriod);
+ fprintf(stderr, "note: Actual period %f\n", actualPeriod);
+ }
+
+ assert(difference <= tolerance);
+
+ // Deregister timer and tick once to synchronize
+ assert(!puglStopTimer(app.view, timerId));
+ puglUpdate(app.world, 0.0);
+
+ // Update for a half second and check that we receive no more alarms
+ app.numAlarms = 0;
+ puglUpdate(app.world, 0.5);
+ assert(app.numAlarms == 0);
+
+ puglFreeView(app.view);
+ puglFreeWorld(app.world);
+
+ return 0;
}
diff --git a/test/test_update.c b/test/test_update.c
index b35e96e..89de0b6 100644
--- a/test/test_update.c
+++ b/test/test_update.c
@@ -37,89 +37,89 @@ static const double timeout = -1.0;
#endif
typedef enum {
- START,
- EXPOSED1,
- UPDATED,
- EXPOSED2,
+ START,
+ EXPOSED1,
+ UPDATED,
+ EXPOSED2,
} State;
typedef struct {
- PuglWorld* world;
- PuglView* view;
- PuglTestOptions opts;
- State state;
+ PuglWorld* world;
+ PuglView* view;
+ PuglTestOptions opts;
+ State state;
} PuglTest;
static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
{
- PuglTest* test = (PuglTest*)puglGetHandle(view);
-
- if (test->opts.verbose) {
- printEvent(event, "Event: ", true);
- }
-
- switch (event->type) {
- case PUGL_EXPOSE:
- switch (test->state) {
- case START:
- test->state = EXPOSED1;
- break;
- case UPDATED:
- test->state = EXPOSED2;
- break;
- default:
- break;
- }
- break;
-
- case PUGL_UPDATE:
- if (test->state == EXPOSED1) {
- puglPostRedisplay(view);
- test->state = UPDATED;
- }
- break;
-
- default:
- break;
- }
-
- return PUGL_SUCCESS;
+ PuglTest* test = (PuglTest*)puglGetHandle(view);
+
+ if (test->opts.verbose) {
+ printEvent(event, "Event: ", true);
+ }
+
+ switch (event->type) {
+ case PUGL_EXPOSE:
+ switch (test->state) {
+ case START:
+ test->state = EXPOSED1;
+ break;
+ case UPDATED:
+ test->state = EXPOSED2;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case PUGL_UPDATE:
+ if (test->state == EXPOSED1) {
+ puglPostRedisplay(view);
+ test->state = UPDATED;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return PUGL_SUCCESS;
}
int
main(int argc, char** argv)
{
- PuglTest app = {puglNewWorld(PUGL_PROGRAM, 0),
- NULL,
- puglParseTestOptions(&argc, &argv),
- START};
-
- // Set up view
- app.view = puglNewView(app.world);
- puglSetClassName(app.world, "Pugl Test");
- puglSetBackend(app.view, puglStubBackend());
- puglSetHandle(app.view, &app);
- puglSetEventFunc(app.view, onEvent);
- puglSetDefaultSize(app.view, 512, 512);
-
- // Create and show window
- assert(!puglRealize(app.view));
- assert(!puglShow(app.view));
-
- // Tick until an expose happens
- while (app.state < EXPOSED1) {
- assert(!puglUpdate(app.world, timeout));
- assert(app.state != UPDATED);
- }
-
- // Tick once and ensure the update and the expose it posted both happened
- assert(!puglUpdate(app.world, 0.0));
- assert(app.state == EXPOSED2);
-
- // Tear down
- puglFreeView(app.view);
- puglFreeWorld(app.world);
-
- return 0;
+ PuglTest app = {puglNewWorld(PUGL_PROGRAM, 0),
+ NULL,
+ puglParseTestOptions(&argc, &argv),
+ START};
+
+ // Set up view
+ app.view = puglNewView(app.world);
+ puglSetClassName(app.world, "Pugl Test");
+ puglSetBackend(app.view, puglStubBackend());
+ puglSetHandle(app.view, &app);
+ puglSetEventFunc(app.view, onEvent);
+ puglSetDefaultSize(app.view, 512, 512);
+
+ // Create and show window
+ assert(!puglRealize(app.view));
+ assert(!puglShow(app.view));
+
+ // Tick until an expose happens
+ while (app.state < EXPOSED1) {
+ assert(!puglUpdate(app.world, timeout));
+ assert(app.state != UPDATED);
+ }
+
+ // Tick once and ensure the update and the expose it posted both happened
+ assert(!puglUpdate(app.world, 0.0));
+ assert(app.state == EXPOSED2);
+
+ // Tear down
+ puglFreeView(app.view);
+ puglFreeWorld(app.world);
+
+ return 0;
}
diff --git a/test/test_utils.h b/test/test_utils.h
index 7a91535..2464737 100644
--- a/test/test_utils.h
+++ b/test/test_utils.h
@@ -29,328 +29,328 @@
#include <string.h>
#ifdef __GNUC__
-# define PUGL_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
+# define PUGL_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
#else
-# define PUGL_LOG_FUNC(fmt, arg1)
+# define PUGL_LOG_FUNC(fmt, arg1)
#endif
typedef struct {
- int samples;
- int doubleBuffer;
- int sync;
- bool continuous;
- bool help;
- bool ignoreKeyRepeat;
- bool resizable;
- bool verbose;
- bool errorChecking;
+ int samples;
+ int doubleBuffer;
+ int sync;
+ bool continuous;
+ bool help;
+ bool ignoreKeyRepeat;
+ bool resizable;
+ bool verbose;
+ bool errorChecking;
} PuglTestOptions;
PUGL_LOG_FUNC(1, 2)
static int
logError(const char* fmt, ...)
{
- fprintf(stderr, "error: ");
+ fprintf(stderr, "error: ");
- va_list args; // NOLINT
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
+ va_list args; // NOLINT
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
- return 1;
+ return 1;
}
static inline int
printModifiers(const uint32_t mods)
{
- return fprintf(stderr, "Modifiers:%s%s%s%s\n",
- (mods & PUGL_MOD_SHIFT) ? " Shift" : "",
- (mods & PUGL_MOD_CTRL) ? " Ctrl" : "",
- (mods & PUGL_MOD_ALT) ? " Alt" : "",
- (mods & PUGL_MOD_SUPER) ? " Super" : "");
+ return fprintf(stderr,
+ "Modifiers:%s%s%s%s\n",
+ (mods & PUGL_MOD_SHIFT) ? " Shift" : "",
+ (mods & PUGL_MOD_CTRL) ? " Ctrl" : "",
+ (mods & PUGL_MOD_ALT) ? " Alt" : "",
+ (mods & PUGL_MOD_SUPER) ? " Super" : "");
}
static inline const char*
crossingModeString(const PuglCrossingMode mode)
{
- switch (mode) {
- case PUGL_CROSSING_NORMAL:
- return "normal";
- case PUGL_CROSSING_GRAB:
- return "grab";
- case PUGL_CROSSING_UNGRAB:
- return "ungrab";
- }
+ switch (mode) {
+ case PUGL_CROSSING_NORMAL:
+ return "normal";
+ case PUGL_CROSSING_GRAB:
+ return "grab";
+ case PUGL_CROSSING_UNGRAB:
+ return "ungrab";
+ }
- return "unknown";
+ return "unknown";
}
static inline const char*
scrollDirectionString(const PuglScrollDirection direction)
{
- switch (direction) {
- case PUGL_SCROLL_UP:
- return "up";
- case PUGL_SCROLL_DOWN:
- return "down";
- case PUGL_SCROLL_LEFT:
- return "left";
- case PUGL_SCROLL_RIGHT:
- return "right";
- case PUGL_SCROLL_SMOOTH:
- return "smooth";
- }
+ switch (direction) {
+ case PUGL_SCROLL_UP:
+ return "up";
+ case PUGL_SCROLL_DOWN:
+ return "down";
+ case PUGL_SCROLL_LEFT:
+ return "left";
+ case PUGL_SCROLL_RIGHT:
+ return "right";
+ case PUGL_SCROLL_SMOOTH:
+ return "smooth";
+ }
- return "unknown";
+ return "unknown";
}
static inline int
printEvent(const PuglEvent* event, const char* prefix, const bool verbose)
{
-#define FFMT "%6.1f"
-#define PFMT FFMT " " FFMT
+#define FFMT "%6.1f"
+#define PFMT FFMT " " FFMT
#define PRINT(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
- switch (event->type) {
- case PUGL_NOTHING:
- return 0;
- case PUGL_KEY_PRESS:
- return PRINT("%sKey press code %3u key U+%04X\n",
- prefix,
- event->key.keycode,
- event->key.key);
- case PUGL_KEY_RELEASE:
- return PRINT("%sKey release code %3u key U+%04X\n",
- prefix,
- event->key.keycode,
- event->key.key);
- case PUGL_TEXT:
- return PRINT("%sText entry code %3u char U+%04X (%s)\n",
- prefix,
- event->text.keycode,
- event->text.character,
- event->text.string);
- case PUGL_BUTTON_PRESS:
- case PUGL_BUTTON_RELEASE:
- return (PRINT("%sMouse %u %s at " PFMT " ",
- prefix,
- event->button.button,
- (event->type == PUGL_BUTTON_PRESS) ? "down" : "up ",
- event->button.x,
- event->button.y) +
- printModifiers(event->scroll.state));
- case PUGL_SCROLL:
- return (PRINT("%sScroll %5.1f %5.1f (%s) at " PFMT " ",
- prefix,
- event->scroll.dx,
- event->scroll.dy,
- scrollDirectionString(event->scroll.direction),
- event->scroll.x,
- event->scroll.y) +
- printModifiers(event->scroll.state));
- case PUGL_POINTER_IN:
- return PRINT("%sMouse enter at " PFMT " (%s)\n",
- prefix,
- event->crossing.x,
- event->crossing.y,
- crossingModeString(event->crossing.mode));
- case PUGL_POINTER_OUT:
- return PRINT("%sMouse leave at " PFMT " (%s)\n",
- prefix,
- event->crossing.x,
- event->crossing.y,
- crossingModeString(event->crossing.mode));
- case PUGL_FOCUS_IN:
- return PRINT("%sFocus in (%s)\n",
- prefix,
- crossingModeString(event->crossing.mode));
- case PUGL_FOCUS_OUT:
- return PRINT("%sFocus out (%s)\n",
- prefix,
- crossingModeString(event->crossing.mode));
- case PUGL_CLIENT:
- return PRINT("%sClient %" PRIXPTR " %" PRIXPTR "\n",
- prefix,
- event->client.data1,
- event->client.data2);
- case PUGL_LOOP_ENTER:
- return PRINT("%sLoop enter\n", prefix);
- case PUGL_LOOP_LEAVE:
- return PRINT("%sLoop leave\n", prefix);
- default:
- break;
- }
+ switch (event->type) {
+ case PUGL_NOTHING:
+ return 0;
+ case PUGL_KEY_PRESS:
+ return PRINT("%sKey press code %3u key U+%04X\n",
+ prefix,
+ event->key.keycode,
+ event->key.key);
+ case PUGL_KEY_RELEASE:
+ return PRINT("%sKey release code %3u key U+%04X\n",
+ prefix,
+ event->key.keycode,
+ event->key.key);
+ case PUGL_TEXT:
+ return PRINT("%sText entry code %3u char U+%04X (%s)\n",
+ prefix,
+ event->text.keycode,
+ event->text.character,
+ event->text.string);
+ case PUGL_BUTTON_PRESS:
+ case PUGL_BUTTON_RELEASE:
+ return (PRINT("%sMouse %u %s at " PFMT " ",
+ prefix,
+ event->button.button,
+ (event->type == PUGL_BUTTON_PRESS) ? "down" : "up ",
+ event->button.x,
+ event->button.y) +
+ printModifiers(event->scroll.state));
+ case PUGL_SCROLL:
+ return (PRINT("%sScroll %5.1f %5.1f (%s) at " PFMT " ",
+ prefix,
+ event->scroll.dx,
+ event->scroll.dy,
+ scrollDirectionString(event->scroll.direction),
+ event->scroll.x,
+ event->scroll.y) +
+ printModifiers(event->scroll.state));
+ case PUGL_POINTER_IN:
+ return PRINT("%sMouse enter at " PFMT " (%s)\n",
+ prefix,
+ event->crossing.x,
+ event->crossing.y,
+ crossingModeString(event->crossing.mode));
+ case PUGL_POINTER_OUT:
+ return PRINT("%sMouse leave at " PFMT " (%s)\n",
+ prefix,
+ event->crossing.x,
+ event->crossing.y,
+ crossingModeString(event->crossing.mode));
+ case PUGL_FOCUS_IN:
+ return PRINT(
+ "%sFocus in (%s)\n", prefix, crossingModeString(event->crossing.mode));
+ case PUGL_FOCUS_OUT:
+ return PRINT(
+ "%sFocus out (%s)\n", prefix, crossingModeString(event->crossing.mode));
+ case PUGL_CLIENT:
+ return PRINT("%sClient %" PRIXPTR " %" PRIXPTR "\n",
+ prefix,
+ event->client.data1,
+ event->client.data2);
+ case PUGL_LOOP_ENTER:
+ return PRINT("%sLoop enter\n", prefix);
+ case PUGL_LOOP_LEAVE:
+ return PRINT("%sLoop leave\n", prefix);
+ default:
+ break;
+ }
- if (verbose) {
- switch (event->type) {
- case PUGL_CREATE:
- return fprintf(stderr, "%sCreate\n", prefix);
- case PUGL_DESTROY:
- return fprintf(stderr, "%sDestroy\n", prefix);
- case PUGL_MAP:
- return fprintf(stderr, "%sMap\n", prefix);
- case PUGL_UNMAP:
- return fprintf(stderr, "%sUnmap\n", prefix);
- case PUGL_UPDATE:
- return fprintf(stderr, "%sUpdate\n", prefix);
- case PUGL_CONFIGURE:
- return PRINT("%sConfigure " PFMT " " PFMT "\n",
- prefix,
- event->configure.x,
- event->configure.y,
- event->configure.width,
- event->configure.height);
- case PUGL_EXPOSE:
- return PRINT("%sExpose " PFMT " " PFMT "\n",
- prefix,
- event->expose.x,
- event->expose.y,
- event->expose.width,
- event->expose.height);
- case PUGL_CLOSE:
- return PRINT("%sClose\n", prefix);
- case PUGL_MOTION:
- return PRINT("%sMouse motion at " PFMT "\n",
- prefix,
- event->motion.x,
- event->motion.y);
- case PUGL_TIMER:
- return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id);
- default:
- return PRINT("%sUnknown event type %d\n", prefix, (int)event->type);
- }
- }
+ if (verbose) {
+ switch (event->type) {
+ case PUGL_CREATE:
+ return fprintf(stderr, "%sCreate\n", prefix);
+ case PUGL_DESTROY:
+ return fprintf(stderr, "%sDestroy\n", prefix);
+ case PUGL_MAP:
+ return fprintf(stderr, "%sMap\n", prefix);
+ case PUGL_UNMAP:
+ return fprintf(stderr, "%sUnmap\n", prefix);
+ case PUGL_UPDATE:
+ return fprintf(stderr, "%sUpdate\n", prefix);
+ case PUGL_CONFIGURE:
+ return PRINT("%sConfigure " PFMT " " PFMT "\n",
+ prefix,
+ event->configure.x,
+ event->configure.y,
+ event->configure.width,
+ event->configure.height);
+ case PUGL_EXPOSE:
+ return PRINT("%sExpose " PFMT " " PFMT "\n",
+ prefix,
+ event->expose.x,
+ event->expose.y,
+ event->expose.width,
+ event->expose.height);
+ case PUGL_CLOSE:
+ return PRINT("%sClose\n", prefix);
+ case PUGL_MOTION:
+ return PRINT("%sMouse motion at " PFMT "\n",
+ prefix,
+ event->motion.x,
+ event->motion.y);
+ case PUGL_TIMER:
+ return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id);
+ default:
+ return PRINT("%sUnknown event type %d\n", prefix, (int)event->type);
+ }
+ }
#undef PRINT
#undef PFMT
#undef FFMT
- return 0;
+ return 0;
}
static inline const char*
puglViewHintString(const PuglViewHint hint)
{
- switch (hint) {
- case PUGL_USE_COMPAT_PROFILE:
- return "Use compatible profile";
- case PUGL_USE_DEBUG_CONTEXT:
- return "Use debug context";
- case PUGL_CONTEXT_VERSION_MAJOR:
- return "Context major version";
- case PUGL_CONTEXT_VERSION_MINOR:
- return "Context minor version";
- case PUGL_RED_BITS:
- return "Red bits";
- case PUGL_GREEN_BITS:
- return "Green bits";
- case PUGL_BLUE_BITS:
- return "Blue bits";
- case PUGL_ALPHA_BITS:
- return "Alpha bits";
- case PUGL_DEPTH_BITS:
- return "Depth bits";
- case PUGL_STENCIL_BITS:
- return "Stencil bits";
- case PUGL_SAMPLES:
- return "Samples";
- case PUGL_DOUBLE_BUFFER:
- return "Double buffer";
- case PUGL_SWAP_INTERVAL:
- return "Swap interval";
- case PUGL_RESIZABLE:
- return "Resizable";
- case PUGL_IGNORE_KEY_REPEAT:
- return "Ignore key repeat";
- case PUGL_REFRESH_RATE:
- return "Refresh rate";
- case PUGL_NUM_VIEW_HINTS:
- return "Unknown";
- }
+ switch (hint) {
+ case PUGL_USE_COMPAT_PROFILE:
+ return "Use compatible profile";
+ case PUGL_USE_DEBUG_CONTEXT:
+ return "Use debug context";
+ case PUGL_CONTEXT_VERSION_MAJOR:
+ return "Context major version";
+ case PUGL_CONTEXT_VERSION_MINOR:
+ return "Context minor version";
+ case PUGL_RED_BITS:
+ return "Red bits";
+ case PUGL_GREEN_BITS:
+ return "Green bits";
+ case PUGL_BLUE_BITS:
+ return "Blue bits";
+ case PUGL_ALPHA_BITS:
+ return "Alpha bits";
+ case PUGL_DEPTH_BITS:
+ return "Depth bits";
+ case PUGL_STENCIL_BITS:
+ return "Stencil bits";
+ case PUGL_SAMPLES:
+ return "Samples";
+ case PUGL_DOUBLE_BUFFER:
+ return "Double buffer";
+ case PUGL_SWAP_INTERVAL:
+ return "Swap interval";
+ case PUGL_RESIZABLE:
+ return "Resizable";
+ case PUGL_IGNORE_KEY_REPEAT:
+ return "Ignore key repeat";
+ case PUGL_REFRESH_RATE:
+ return "Refresh rate";
+ case PUGL_NUM_VIEW_HINTS:
+ return "Unknown";
+ }
- return "Unknown";
+ return "Unknown";
}
static inline void
printViewHints(const PuglView* view)
{
- for (int i = 0; i < PUGL_NUM_VIEW_HINTS; ++i) {
- const PuglViewHint hint = (PuglViewHint)i;
- fprintf(stderr,
- "%s: %d\n",
- puglViewHintString(hint),
- puglGetViewHint(view, hint));
- }
+ for (int i = 0; i < PUGL_NUM_VIEW_HINTS; ++i) {
+ const PuglViewHint hint = (PuglViewHint)i;
+ fprintf(stderr,
+ "%s: %d\n",
+ puglViewHintString(hint),
+ puglGetViewHint(view, hint));
+ }
}
static inline void
puglPrintTestUsage(const char* prog, const char* posHelp)
{
- printf("Usage: %s [OPTION]... %s\n\n"
- " -a Enable anti-aliasing\n"
- " -c Continuously animate and draw\n"
- " -d Directly draw to window (no double-buffering)\n"
- " -e Enable platform error-checking\n"
- " -f Fast drawing, explicitly disable vertical sync\n"
- " -h Display this help\n"
- " -i Ignore key repeat\n"
- " -v Print verbose output\n"
- " -r Resizable window\n"
- " -s Explicitly enable vertical sync\n",
- prog, posHelp);
+ printf("Usage: %s [OPTION]... %s\n\n"
+ " -a Enable anti-aliasing\n"
+ " -c Continuously animate and draw\n"
+ " -d Directly draw to window (no double-buffering)\n"
+ " -e Enable platform error-checking\n"
+ " -f Fast drawing, explicitly disable vertical sync\n"
+ " -h Display this help\n"
+ " -i Ignore key repeat\n"
+ " -v Print verbose output\n"
+ " -r Resizable window\n"
+ " -s Explicitly enable vertical sync\n",
+ prog,
+ posHelp);
}
static inline PuglTestOptions
puglParseTestOptions(int* pargc, char*** pargv)
{
- PuglTestOptions opts = {
- 0,
- PUGL_TRUE,
- PUGL_DONT_CARE,
- false,
- false,
- false,
- false,
- false,
- false,
- };
+ PuglTestOptions opts = {
+ 0,
+ PUGL_TRUE,
+ PUGL_DONT_CARE,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ };
- char** const argv = *pargv;
- int i = 1;
- for (; i < *pargc; ++i) {
- if (!strcmp(argv[i], "-a")) {
- opts.samples = 4;
- } else if (!strcmp(argv[i], "-c")) {
- opts.continuous = true;
- } else if (!strcmp(argv[i], "-d")) {
- opts.doubleBuffer = PUGL_FALSE;
- } else if (!strcmp(argv[i], "-e")) {
- opts.errorChecking = PUGL_TRUE;
- } else if (!strcmp(argv[i], "-f")) {
- opts.sync = PUGL_FALSE;
- } else if (!strcmp(argv[i], "-h")) {
- opts.help = true;
- return opts;
- } else if (!strcmp(argv[i], "-i")) {
- opts.ignoreKeyRepeat = true;
- } else if (!strcmp(argv[i], "-r")) {
- opts.resizable = true;
- } else if (!strcmp(argv[i], "-s")) {
- opts.sync = PUGL_TRUE;
- } else if (!strcmp(argv[i], "-v")) {
- opts.verbose = true;
- } else if (argv[i][0] != '-') {
- break;
- } else {
- opts.help = true;
- logError("Unknown option: %s\n", argv[i]);
- }
- }
+ char** const argv = *pargv;
+ int i = 1;
+ for (; i < *pargc; ++i) {
+ if (!strcmp(argv[i], "-a")) {
+ opts.samples = 4;
+ } else if (!strcmp(argv[i], "-c")) {
+ opts.continuous = true;
+ } else if (!strcmp(argv[i], "-d")) {
+ opts.doubleBuffer = PUGL_FALSE;
+ } else if (!strcmp(argv[i], "-e")) {
+ opts.errorChecking = PUGL_TRUE;
+ } else if (!strcmp(argv[i], "-f")) {
+ opts.sync = PUGL_FALSE;
+ } else if (!strcmp(argv[i], "-h")) {
+ opts.help = true;
+ return opts;
+ } else if (!strcmp(argv[i], "-i")) {
+ opts.ignoreKeyRepeat = true;
+ } else if (!strcmp(argv[i], "-r")) {
+ opts.resizable = true;
+ } else if (!strcmp(argv[i], "-s")) {
+ opts.sync = PUGL_TRUE;
+ } else if (!strcmp(argv[i], "-v")) {
+ opts.verbose = true;
+ } else if (argv[i][0] != '-') {
+ break;
+ } else {
+ opts.help = true;
+ logError("Unknown option: %s\n", argv[i]);
+ }
+ }
- *pargc -= i;
- *pargv += i;
+ *pargc -= i;
+ *pargv += i;
- return opts;
+ return opts;
}
#endif // TEST_TEST_UTILS_H