diff --git a/cmake/yup.cmake b/cmake/yup.cmake index 5f386a26a..8518adfc3 100644 --- a/cmake/yup.cmake +++ b/cmake/yup.cmake @@ -444,6 +444,7 @@ function (_yup_module_setup_plugin_client_clap target_name plugin_client_target _yup_glob_recurse ("${module_path}/clap/*" all_module_files_clap) target_sources (${custom_target_name} PRIVATE ${all_module_files_clap}) + source_group (TREE ${module_path}/clap/ FILES ${all_module_files_clap}) set_source_files_properties (${all_module_files_clap} PROPERTIES HEADER_FILE_ONLY TRUE) endfunction() @@ -622,6 +623,7 @@ function (yup_add_module module_path) _yup_glob_recurse ("${module_path}/*" all_module_files) target_sources (${module_name} PRIVATE ${all_module_files}) + source_group (TREE ${module_path}/ FILES ${all_module_files}) set_source_files_properties (${all_module_files} PROPERTIES HEADER_FILE_ONLY TRUE) # ==== Setup parent scope variables diff --git a/examples/graphics/source/main.cpp b/examples/graphics/source/main.cpp index 6a56acf74..501744c78 100644 --- a/examples/graphics/source/main.cpp +++ b/examples/graphics/source/main.cpp @@ -36,7 +36,7 @@ class CustomWindow { public: CustomWindow() - : yup::DocumentWindow (yup::ComponentNative::defaultFlags, yup::Color (0xff404040)) + : yup::DocumentWindow ({}, yup::Color (0xff404040)) { rive::Factory* factory = getNativeComponent()->getFactory(); if (factory == nullptr) diff --git a/examples/render/source/main.cpp b/examples/render/source/main.cpp index 1c09e6db5..92b25d61e 100644 --- a/examples/render/source/main.cpp +++ b/examples/render/source/main.cpp @@ -35,7 +35,8 @@ class CustomWindow public: CustomWindow() // Fluid and continuous animations needs continuous repainting - : yup::DocumentWindow (yup::ComponentNative::defaultFlags | yup::ComponentNative::renderContinuous, {}, 60.0f) + : yup::DocumentWindow (yup::ComponentNative::Options() + .withFlags(yup::ComponentNative::defaultFlags | yup::ComponentNative::renderContinuous), {}) { // Set title setTitle ("main"); diff --git a/modules/yup_audio_plugin_client/clap/yup_audio_plugin_client_CLAP.cpp b/modules/yup_audio_plugin_client/clap/yup_audio_plugin_client_CLAP.cpp index 4c4463d98..3bd5d651f 100644 --- a/modules/yup_audio_plugin_client/clap/yup_audio_plugin_client_CLAP.cpp +++ b/modules/yup_audio_plugin_client/clap/yup_audio_plugin_client_CLAP.cpp @@ -706,7 +706,9 @@ bool AudioPluginWrapperCLAP::initialise() if (wrapper->audioProcessorEditor->shouldRenderContinuous()) flags.set (yup::ComponentNative::renderContinuous); - wrapper->audioProcessorEditor->addToDesktop (flags, window->cocoa); + yup::ComponentNative::Options options; + options.flags = flags; + wrapper->audioProcessorEditor->addToDesktop (options, window->cocoa); wrapper->audioProcessorEditor->attachedToNative(); return true; diff --git a/modules/yup_graphics/context/yup_GraphicsContext.h b/modules/yup_graphics/context/yup_GraphicsContext.h index ed7d2585c..431c69124 100644 --- a/modules/yup_graphics/context/yup_GraphicsContext.h +++ b/modules/yup_graphics/context/yup_GraphicsContext.h @@ -35,6 +35,15 @@ class JUCE_API GraphicsContext { public: //============================================================================== + /** Enumerates supported graphics APIs. */ + enum Api + { + OpenGL, ///< Specifies the use of OpenGL for rendering. + Direct3D, ///< Specifies the use of Direct3D for rendering. + Metal, ///< Specifies the use of Metal for rendering. + Dawn ///< Specifies the use of Dawn, a Vulkan-like API. + }; + /** Configuration options for creating a graphics context. */ struct Options { @@ -48,15 +57,6 @@ class JUCE_API GraphicsContext bool disableRasterOrdering = false; ///< Disables specific raster ordering features for performance. }; - /** Enumerates supported graphics APIs. */ - enum Api - { - OpenGL, ///< Specifies the use of OpenGL for rendering. - Direct3D, ///< Specifies the use of Direct3D for rendering. - Metal, ///< Specifies the use of Metal for rendering. - Dawn ///< Specifies the use of Dawn, a Vulkan-like API. - }; - //============================================================================== /** Default constructor. */ GraphicsContext() noexcept = default; diff --git a/modules/yup_graphics/native/yup_GraphicsContext_d3d.cpp b/modules/yup_graphics/native/yup_GraphicsContext_d3d.cpp index 7db02f2fd..831eb06e3 100644 --- a/modules/yup_graphics/native/yup_GraphicsContext_d3d.cpp +++ b/modules/yup_graphics/native/yup_GraphicsContext_d3d.cpp @@ -19,6 +19,7 @@ ============================================================================== */ +#if YUP_RIVE_USE_D3D #include "rive/renderer/rive_renderer.hpp" #include "rive/renderer/d3d/render_context_d3d_impl.hpp" #include "rive/renderer/d3d/d3d11.hpp" @@ -171,3 +172,4 @@ std::unique_ptr juce_constructDirect3DGraphicsContext (Graphics } } // namespace yup +#endif diff --git a/modules/yup_graphics/native/yup_GraphicsContext_dawn.cpp b/modules/yup_graphics/native/yup_GraphicsContext_dawn.cpp index 5c3d7d200..1abdd3846 100644 --- a/modules/yup_graphics/native/yup_GraphicsContext_dawn.cpp +++ b/modules/yup_graphics/native/yup_GraphicsContext_dawn.cpp @@ -280,17 +280,4 @@ std::unique_ptr juce_constructDawnGraphicsContext (GraphicsCont } } // namespace yup - -#else - -namespace yup -{ - -std::unique_ptr juce_constructDawnGraphicsContext (GraphicsContext::Options options) -{ - return nullptr; -} - -} // namespace yup - #endif diff --git a/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp b/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp index 57fa22ebe..7e9a78f4f 100644 --- a/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp +++ b/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp @@ -19,6 +19,7 @@ ============================================================================== */ +#if YUP_RIVE_USE_OPENGL || JUCE_LINUX || JUCE_WASM || JUCE_ANDROID #include "rive/renderer/rive_renderer.hpp" #include "rive/renderer/gl/gles3.hpp" #include "rive/renderer/gl/render_buffer_gl_impl.hpp" @@ -75,12 +76,6 @@ class LowLevelRenderContextGL : public GraphicsContext public: LowLevelRenderContextGL() { - if (! m_plsContext) - { - fprintf (stderr, "Failed to create a renderer.\n"); - exit (-1); - } - #if RIVE_DESKTOP_GL // Load the OpenGL API using glad. if (! gladLoadCustomLoader ((GLADloadproc) glfwGetProcAddress)) @@ -90,6 +85,13 @@ class LowLevelRenderContextGL : public GraphicsContext } #endif + m_plsContext = rive::gpu::RenderContextGLImpl::MakeContext (rive::gpu::RenderContextGLImpl::ContextOptions()); + if (! m_plsContext) + { + fprintf (stderr, "Failed to create a renderer.\n"); + exit (-1); + } + printf ("GL_VENDOR: %s\n", glGetString (GL_VENDOR)); printf ("GL_RENDERER: %s\n", glGetString (GL_RENDERER)); printf ("GL_VERSION: %s\n", glGetString (GL_VERSION)); @@ -148,15 +150,13 @@ class LowLevelRenderContextGL : public GraphicsContext void end (void*) override { - m_plsContext->flush ({ .renderTarget = m_renderTarget.get() }); + m_plsContext->flush ({ m_renderTarget.get() }); m_plsContext->static_impl_cast()->unbindGLInternalResources(); } private: - std::unique_ptr m_plsContext = - rive::gpu::RenderContextGLImpl::MakeContext (rive::gpu::RenderContextGLImpl::ContextOptions()); - + std::unique_ptr m_plsContext; rive::rcp m_renderTarget; }; @@ -166,3 +166,4 @@ std::unique_ptr juce_constructOpenGLGraphicsContext (GraphicsCo } } // namespace yup +#endif diff --git a/modules/yup_graphics/native/yup_GraphicsContext_impl.cpp b/modules/yup_graphics/native/yup_GraphicsContext_impl.cpp index a5b6cf775..0b5bb02ef 100644 --- a/modules/yup_graphics/native/yup_GraphicsContext_impl.cpp +++ b/modules/yup_graphics/native/yup_GraphicsContext_impl.cpp @@ -24,14 +24,26 @@ namespace yup std::unique_ptr GraphicsContext::createContext (Options options) { -#if JUCE_MAC || JUCE_IOS +#if (JUCE_MAC || JUCE_IOS) +#if YUP_RIVE_USE_METAL return createContext (Api::Metal, options); +#else + return createContext (Api::OpenGL, options); +#endif + #elif JUCE_WINDOWS +#if YUP_RIVE_USE_D3D return createContext (Api::Direct3D, options); +#else + return createContext (Api::OpenGL, options); +#endif + #elif JUCE_LINUX || JUCE_WASM || JUCE_ANDROID return createContext (Api::OpenGL, options); + #else return nullptr; + #endif } @@ -39,22 +51,29 @@ std::unique_ptr GraphicsContext::createContext (Api graphicsApi { switch (graphicsApi) { -#if JUCE_MAC || JUCE_IOS - case Api::Metal: - return juce_constructMetalGraphicsContext (options); -#elif JUCE_WINDOWS - case Api::Direct3D: - return juce_constructDirect3DGraphicsContext (options); -#elif JUCE_LINUX || JUCE_WASM || JUCE_ANDROID - case Api::OpenGL: - return juce_constructOpenGLGraphicsContext (options); +#if YUP_RIVE_USE_METAL && (JUCE_MAC || JUCE_IOS) + case Api::Metal: + return juce_constructMetalGraphicsContext (options); +#endif + +#if YUP_RIVE_USE_D3D && JUCE_WINDOWS + case Api::Direct3D: + return juce_constructDirect3DGraphicsContext (options); +#endif + +#if YUP_RIVE_USE_OPENGL || JUCE_LINUX || JUCE_WASM || JUCE_ANDROID + case Api::OpenGL: + return juce_constructOpenGLGraphicsContext (options); +#endif + +#if YUP_RIVE_USE_DAWN + case Api::Dawn: + return juce_constructDawnGraphicsContext (options); #endif - case Api::Dawn: - return juce_constructDawnGraphicsContext (options); - default: - Logger::outputDebugString ("Invalid API requested for current platform"); - return nullptr; + default: + Logger::outputDebugString ("Invalid API requested for current platform"); + return nullptr; } Logger::outputDebugString ("Failed to create the graphics context"); diff --git a/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp b/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp index 355b8020d..75afaf3b1 100644 --- a/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp +++ b/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp @@ -19,6 +19,7 @@ ============================================================================== */ +#if YUP_RIVE_USE_METAL #include "rive/renderer/rive_renderer.hpp" #include "rive/renderer/metal/render_context_metal_impl.h" @@ -122,3 +123,4 @@ std::unique_ptr juce_constructMetalGraphicsContext (GraphicsCon } } // namespace yup +#endif diff --git a/modules/yup_graphics/yup_graphics.cpp b/modules/yup_graphics/yup_graphics.cpp index cf27921ba..801c53f5a 100644 --- a/modules/yup_graphics/yup_graphics.cpp +++ b/modules/yup_graphics/yup_graphics.cpp @@ -33,19 +33,38 @@ //============================================================================== #if JUCE_WINDOWS + +#if YUP_RIVE_USE_D3D #include #include #include "native/yup_GraphicsContext_d3d.cpp" +#endif + +#if YUP_RIVE_USE_OPENGL +#include "native/yup_GraphicsContext_gl.cpp" +#endif + +//============================================================================== #elif JUCE_MAC || JUCE_IOS + +#if YUP_RIVE_USE_METAL #import #import #import #include "native/yup_GraphicsContext_metal.cpp" +#endif + +#if YUP_RIVE_USE_OPENGL +#include "native/yup_GraphicsContext_gl.cpp" +#endif + +//============================================================================== #elif JUCE_LINUX || JUCE_WASM || JUCE_ANDROID + #if JUCE_EMSCRIPTEN && RIVE_WEBGL #include #include @@ -55,8 +74,15 @@ #endif +//============================================================================== + +#if YUP_RIVE_USE_DAWN #include "native/yup_GraphicsContext_dawn.cpp" #include "native/yup_GraphicsContext_dawn_helper.cpp" +#endif + +//============================================================================== + #include "native/yup_GraphicsContext_impl.cpp" //============================================================================== diff --git a/modules/yup_graphics/yup_graphics.h b/modules/yup_graphics/yup_graphics.h index e6b70e4fe..d86131a62 100644 --- a/modules/yup_graphics/yup_graphics.h +++ b/modules/yup_graphics/yup_graphics.h @@ -49,12 +49,13 @@ #include +#include + //============================================================================== +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wattributes") #include #include - -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wattributes") #include #include JUCE_END_IGNORE_WARNINGS_GCC_LIKE diff --git a/modules/yup_gui/component/yup_Component.cpp b/modules/yup_gui/component/yup_Component.cpp index cdbbd66d8..5837238ee 100644 --- a/modules/yup_gui/component/yup_Component.cpp +++ b/modules/yup_gui/component/yup_Component.cpp @@ -329,7 +329,7 @@ bool Component::isOnDesktop() const return options.onDesktop; } -void Component::addToDesktop (ComponentNative::Flags flags, void* parent, std::optional framerateRedraw) +void Component::addToDesktop (const ComponentNative::Options& nativeOptions, void* parent) { if (options.onDesktop) removeFromDesktop(); @@ -342,7 +342,7 @@ void Component::addToDesktop (ComponentNative::Flags flags, void* parent, std::o options.onDesktop = true; - native = ComponentNative::createFor (*this, flags, parent, framerateRedraw); + native = ComponentNative::createFor (*this, nativeOptions, parent); setBounds (getBounds()); // This is needed to update based on scaleDpi } diff --git a/modules/yup_gui/component/yup_Component.h b/modules/yup_gui/component/yup_Component.h index 67ab9f5cb..d5a84b3f8 100644 --- a/modules/yup_gui/component/yup_Component.h +++ b/modules/yup_gui/component/yup_Component.h @@ -95,9 +95,7 @@ class JUCE_API Component //============================================================================== bool isOnDesktop() const; - void addToDesktop (ComponentNative::Flags flags, - void* parent = nullptr, - std::optional framerateRedraw = std::nullopt); + void addToDesktop (const ComponentNative::Options& nativeOptions, void* parent); void removeFromDesktop(); virtual void userTriedToCloseWindow(); diff --git a/modules/yup_gui/component/yup_ComponentNative.h b/modules/yup_gui/component/yup_ComponentNative.h index 61ae186db..18b0962aa 100644 --- a/modules/yup_gui/component/yup_ComponentNative.h +++ b/modules/yup_gui/component/yup_ComponentNative.h @@ -39,6 +39,36 @@ class JUCE_API ComponentNative static inline constexpr Flags renderContinuous = Flags::declareValue(); static inline constexpr Flags defaultFlags = decoratedWindow; + //============================================================================== + /** Configuration options for creating a native component. */ + struct Options + { + /** Default constructor, initializes the options with default values. */ + constexpr Options() noexcept = default; + + Options& withFlags(Flags newFlags) noexcept + { + flags = newFlags; + return *this; + } + + Options& withGraphicsApi(std::optional newGraphicsApi) noexcept + { + graphicsApi = newGraphicsApi; + return *this; + } + + Options& withFramerateRedraw(std::optional newFramerateRedraw) noexcept + { + framerateRedraw = newFramerateRedraw; + return *this; + } + + Flags flags = defaultFlags; ///< + std::optional graphicsApi; ///< + std::optional framerateRedraw; ///< + }; + //============================================================================== ComponentNative (Component& newComponent, const Flags& newFlags); virtual ~ComponentNative(); @@ -104,9 +134,8 @@ class JUCE_API ComponentNative //============================================================================== static std::unique_ptr createFor (Component& component, - const Flags& flags, - void* parent, - std::optional framerateRedraw); + const Options& options, + void* parent); protected: Component& component; diff --git a/modules/yup_gui/native/yup_Windowing_glfw.cpp b/modules/yup_gui/native/yup_Windowing_glfw.cpp index 47a251eaf..c17ad3b39 100644 --- a/modules/yup_gui/native/yup_Windowing_glfw.cpp +++ b/modules/yup_gui/native/yup_Windowing_glfw.cpp @@ -268,6 +268,60 @@ void setNativeParent (void* nativeDisplay, void* nativeWindow, GLFWwindow* windo //============================================================================== +GraphicsContext::Api getGraphicsContextApi (const std::optional& forceContextApi) +{ + GraphicsContext::Api desiredApi; + +#if JUCE_MAC +#if YUP_RIVE_USE_METAL + desiredApi = forceContextApi.value_or(GraphicsContext::Metal); +#elif YUP_RIVE_USE_OPENGL + desiredApi = forceContextApi.value_or(GraphicsContext::OpenGL); +#endif +#endif + +#if JUCE_WINDOWS +#if YUP_RIVE_USE_D3D + desiredApi = forceContextApi.value_or(GraphicsContext::Direct3D); +#elif YUP_RIVE_USE_OPENGL + desiredApi = forceContextApi.value_or(GraphicsContext::OpenGL); +#endif +#endif + + return desiredApi; +} + +void setContextWindowHints (GraphicsContext::Api desiredApi) +{ + if (desiredApi == GraphicsContext::Metal) + { + glfwWindowHint (GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint (GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE); + } + + if (desiredApi == GraphicsContext::Direct3D) + { + glfwWindowHint (GLFW_CLIENT_API, GLFW_NO_API); + } + + if (desiredApi == GraphicsContext::OpenGL) + { +#if defined(ANGLE) + glfwWindowHint (GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); + glfwWindowHint (GLFW_CLIENT_API, GLFW_OPENGL_ES_API); + glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 0); + glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#else + glfwWindowHint (GLFW_CLIENT_API, GLFW_OPENGL_API); + glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, YUP_RIVE_OPENGL_MAJOR); + glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, YUP_RIVE_OPENGL_MINOR); +#endif + } +} + +//============================================================================== + class GLFWComponentNative final : public ComponentNative , public Timer @@ -279,7 +333,10 @@ class GLFWComponentNative final //============================================================================== - GLFWComponentNative (Component& component, const Flags& flags, void* parent, std::optional framerateRedraw); + GLFWComponentNative (Component& component, + const Options& options, + void* parent); + ~GLFWComponentNative() override; //============================================================================== @@ -365,12 +422,14 @@ class GLFWComponentNative final void handleMoved (int xpos, int ypos); void handleResized (int width, int height); void handleFocusChanged (bool gotFocus); + void handleContentScaleChanged (float xscale, float yscale); void handleUserTriedToCloseWindow(); //============================================================================== Point getScaledCursorPosition() const; //============================================================================== + static void glfwWindowContentScale (GLFWwindow* window, float xscale, float yscale); static void glfwWindowClose (GLFWwindow* window); static void glfwWindowPos (GLFWwindow* window, int xpos, int ypos); static void glfwWindowSize (GLFWwindow* window, int width, int height); @@ -385,10 +444,15 @@ class GLFWComponentNative final void triggerRenderingUpdate(); void renderContext(); + void startRendering(); + void stopRendering(); + GLFWwindow* window = nullptr; void* parentWindow = nullptr; String windowTitle; + GraphicsContext::Api currentGraphicsApi; + std::unique_ptr context; std::unique_ptr renderer; @@ -416,6 +480,7 @@ class GLFWComponentNative final std::atomic shouldRenderContinuous = false; bool renderAtomicMode = false; bool renderWireframe = false; + bool forceSizeChange = false; int forcedRedraws = 0; static constexpr int defaultForcedRedraws = 3; @@ -434,27 +499,36 @@ std::atomic_flag GLFWComponentNative::isInitialised = ATOMIC_FLAG_INIT; //============================================================================== -GLFWComponentNative::GLFWComponentNative (Component& component, const Flags& flags, void* parent, std::optional framerateRedraw) - : ComponentNative (component, flags) +GLFWComponentNative::GLFWComponentNative (Component& component, + const Options& options, + void* parent) + : ComponentNative (component, options.flags) , Thread ("YUP Render Thread") , parentWindow (parent) + , currentGraphicsApi (getGraphicsContextApi (options.graphicsApi)) , screenBounds (component.getBounds().to()) - , desiredFrameRate (framerateRedraw.value_or (60.0f)) - , shouldRenderContinuous (flags.test (renderContinuous)) + , desiredFrameRate (options.framerateRedraw.value_or (60.0f)) + , shouldRenderContinuous (options.flags.test (renderContinuous)) { #if JUCE_MAC - gpu = MTLCreateSystemDefaultDevice(); - queue = [gpu newCommandQueue]; - swapchain = [CAMetalLayer layer]; - swapchain.device = gpu; - swapchain.opaque = YES; + if (currentGraphicsApi == GraphicsContext::Metal) + { + gpu = MTLCreateSystemDefaultDevice(); + queue = [gpu newCommandQueue]; + swapchain = [CAMetalLayer layer]; + swapchain.device = gpu; + swapchain.opaque = YES; + } #endif + // Setup window hints + setContextWindowHints (currentGraphicsApi); + glfwWindowHint (GLFW_VISIBLE, component.isVisible() ? GLFW_TRUE : GLFW_FALSE); - glfwWindowHint (GLFW_DECORATED, flags.test (decoratedWindow) ? GLFW_TRUE : GLFW_FALSE); + glfwWindowHint (GLFW_DECORATED, options.flags.test (decoratedWindow) ? GLFW_TRUE : GLFW_FALSE); + // Create the window and parent it auto monitor = component.isFullScreen() ? glfwGetPrimaryMonitor() : nullptr; - window = glfwCreateWindow (1, 1, component.getTitle().toRawUTF8(), monitor, nullptr); if (window == nullptr) return; @@ -463,22 +537,28 @@ GLFWComponentNative::GLFWComponentNative (Component& component, const Flags& fla setNativeParent (nullptr, parent, window); #if JUCE_MAC - NSWindow* nswindow = glfwGetCocoaWindow (window); - nswindow.contentView.layer = swapchain; - nswindow.contentView.wantsLayer = YES; + if (currentGraphicsApi == GraphicsContext::Metal) + { + NSWindow* nswindow = glfwGetCocoaWindow (window); + nswindow.contentView.layer = swapchain; + nswindow.contentView.wantsLayer = YES; + } #endif - context = GraphicsContext::createContext (GraphicsContext::Options {}); + // Create the rendering context + if (currentGraphicsApi == GraphicsContext::OpenGL) + { + glfwMakeContextCurrent (window); + glfwSwapInterval (0); + } + + context = GraphicsContext::createContext (currentGraphicsApi, GraphicsContext::Options {}); if (context == nullptr) return; -#if JUCE_EMSCRIPTEN && RIVE_WEBGL - glfwMakeContextCurrent (window); - //glfwSwapInterval (0); -#endif - + // Setup callbacks glfwSetWindowUserPointer (window, this); - + glfwSetWindowContentScaleCallback (window, glfwWindowContentScale); glfwSetWindowCloseCallback (window, glfwWindowClose); glfwSetWindowSizeCallback (window, glfwWindowSize); glfwSetWindowPosCallback (window, glfwWindowPos); @@ -488,35 +568,29 @@ GLFWComponentNative::GLFWComponentNative (Component& component, const Flags& fla glfwSetScrollCallback (window, glfwMouseScroll); glfwSetKeyCallback (window, glfwKeyPress); + // Resize after callbacks are in place setBounds ( { screenBounds.getX(), screenBounds.getY(), jmax (1, screenBounds.getWidth()), jmax (1, screenBounds.getHeight()) }); -#if JUCE_EMSCRIPTEN && RIVE_WEBGL - startTimerHz (desiredFrameRate); -#else - startThread (Priority::high); -#endif + // Start the rendering + startRendering(); } GLFWComponentNative::~GLFWComponentNative() { - jassert (window != nullptr); + // Stop the rendering + stopRendering(); -#if JUCE_EMSCRIPTEN && RIVE_WEBGL - stopTimer(); -#else - signalThreadShouldExit(); - renderEvent.signal(); - commandEvent.signal(); - stopThread (-1); -#endif - - glfwSetWindowUserPointer (window, nullptr); - glfwDestroyWindow (window); - window = nullptr; + // Destroy the window + if (window != nullptr) + { + glfwSetWindowUserPointer (window, nullptr); + glfwDestroyWindow (window); + window = nullptr; + } } //============================================================================== @@ -908,10 +982,12 @@ void GLFWComponentNative::timerCallback() void GLFWComponentNative::renderContext() { + jassert (context != nullptr); + auto [contentWidth, contentHeight] = getContentSize(); auto renderContinuous = shouldRenderContinuous.load (std::memory_order_relaxed); - if (currentContentWidth != contentWidth || currentContentHeight != contentHeight) + if (forceSizeChange || currentContentWidth != contentWidth || currentContentHeight != contentHeight) { currentContentWidth = contentWidth; currentContentHeight = contentHeight; @@ -929,9 +1005,6 @@ void GLFWComponentNative::renderContext() setPosition (nativeWindowPos.getTopLeft()); } - jassert (context != nullptr); - jassert (renderer != nullptr); - if (! renderContinuous && currentRepaintArea.isEmpty()) return; @@ -953,6 +1026,8 @@ void GLFWComponentNative::renderContext() context->begin (frameDescriptor); // Repaint components hierarchy + jassert (renderer != nullptr); + Graphics g (*context, *renderer); component.internalPaint (g, desiredFrameRate); @@ -960,6 +1035,10 @@ void GLFWComponentNative::renderContext() context->end (getNativeHandle()); context->tick(); + // Swap buffers + if (window != nullptr && currentGraphicsApi == GraphicsContext::OpenGL) + glfwSwapBuffers (window); + if (! renderContinuous) { if (forcedRedraws > 0) @@ -982,6 +1061,29 @@ void GLFWComponentNative::triggerRenderingUpdate() //============================================================================== +void GLFWComponentNative::startRendering() +{ +#if JUCE_EMSCRIPTEN && RIVE_WEBGL + startTimerHz (desiredFrameRate); +#else + startThread (Priority::high); +#endif +} + +void GLFWComponentNative::stopRendering() +{ +#if JUCE_EMSCRIPTEN && RIVE_WEBGL + stopTimer(); +#else + signalThreadShouldExit(); + renderEvent.signal(); + commandEvent.signal(); + stopThread (-1); +#endif +} + +//============================================================================== + void GLFWComponentNative::handleMouseMoveOrDrag (const Point& localPosition) { const auto event = MouseEvent() @@ -1130,6 +1232,16 @@ void GLFWComponentNative::handleFocusChanged (bool gotFocus) //DBG ("handleFocusChanged: " << (gotFocus ? 1 : 0)); } +void GLFWComponentNative::handleContentScaleChanged (float xscale, float yscale) +{ + int width, height; + glfwGetWindowSize (window, &width, &height); + + forceSizeChange = true; + + handleResized(width, height); +} + void GLFWComponentNative::handleUserTriedToCloseWindow() { component.internalUserTriedToCloseWindow(); @@ -1166,15 +1278,21 @@ void GLFWComponentNative::updateComponentUnderMouse (const MouseEvent& event) //============================================================================== std::unique_ptr ComponentNative::createFor (Component& component, - const Flags& flags, - void* parent, - std::optional framerateRedraw) + const Options& options, + void* parent) { - return std::make_unique (component, flags, parent, framerateRedraw); + return std::make_unique (component, options, parent); } //============================================================================== +void GLFWComponentNative::glfwWindowContentScale (GLFWwindow* window, float xscale, float yscale) +{ + auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window)); + + nativeComponent->handleContentScaleChanged (xscale, yscale); +} + void GLFWComponentNative::glfwWindowClose (GLFWwindow* window) { auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window)); @@ -1309,43 +1427,39 @@ void Desktop::updateDisplays() void initialiseYup_Windowing() { - glfwSetErrorCallback (+[] (int code, const char* message) - { - DBG ("GLFW Error: " << code << " - " << message); - }); + // Setup error callback + { + auto errorCallback = +[](int code, const char* message) + { + DBG ("GLFW Error: " << code << " - " << message); + }; + glfwSetErrorCallback (errorCallback); + } + + // Initialise glfw glfwInit(); -#if JUCE_MAC || JUCE_WINDOWS - glfwWindowHint (GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint (GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE); -#elif defined(ANGLE) - glfwWindowHint (GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); - glfwWindowHint (GLFW_CLIENT_API, GLFW_OPENGL_ES_API); - glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 0); - glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#else - glfwWindowHint (GLFW_CLIENT_API, GLFW_OPENGL_API); - glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 6); -#endif + // Setup monitor callback + { + Desktop::getInstance()->updateDisplays(); - Desktop::getInstance()->updateDisplays(); + auto monitorCallback = +[] (GLFWmonitor* monitor, int event) + { + auto desktop = Desktop::getInstance(); - glfwSetMonitorCallback (+[] (GLFWmonitor* monitor, int event) - { - auto desktop = Desktop::getInstance(); + if (event == GLFW_CONNECTED) + { + } + else if (event == GLFW_DISCONNECTED) + { + } - if (event == GLFW_CONNECTED) - { - } - else if (event == GLFW_DISCONNECTED) - { - } + desktop->updateDisplays(); + }; - desktop->updateDisplays(); - }); + glfwSetMonitorCallback (monitorCallback); + } GLFWComponentNative::isInitialised.test_and_set(); } diff --git a/modules/yup_gui/windowing/yup_DocumentWindow.cpp b/modules/yup_gui/windowing/yup_DocumentWindow.cpp index 0b1073227..caa940c1d 100644 --- a/modules/yup_gui/windowing/yup_DocumentWindow.cpp +++ b/modules/yup_gui/windowing/yup_DocumentWindow.cpp @@ -24,10 +24,10 @@ namespace yup //============================================================================== -DocumentWindow::DocumentWindow (ComponentNative::Flags flags, const Color& backgroundColor, std::optional framerateRedraw) +DocumentWindow::DocumentWindow (const ComponentNative::Options& options, const Color& backgroundColor) : backgroundColor (backgroundColor) { - addToDesktop (flags, nullptr, framerateRedraw); + addToDesktop (options, nullptr); } DocumentWindow::~DocumentWindow() diff --git a/modules/yup_gui/windowing/yup_DocumentWindow.h b/modules/yup_gui/windowing/yup_DocumentWindow.h index 1969b129f..b57f78a88 100644 --- a/modules/yup_gui/windowing/yup_DocumentWindow.h +++ b/modules/yup_gui/windowing/yup_DocumentWindow.h @@ -29,9 +29,8 @@ class JUCE_API DocumentWindow : public Component public: //============================================================================== DocumentWindow ( - ComponentNative::Flags flags = ComponentNative::defaultFlags, - const Color& backgroundColor = {}, - std::optional framerateRedraw = std::nullopt); + const ComponentNative::Options& options = {}, + const Color& backgroundColor = {}); ~DocumentWindow() override; //============================================================================== diff --git a/thirdparty/rive_renderer/rive_renderer.h b/thirdparty/rive_renderer/rive_renderer.h index 54f1329b6..e54bd559b 100644 --- a/thirdparty/rive_renderer/rive_renderer.h +++ b/thirdparty/rive_renderer/rive_renderer.h @@ -47,4 +47,70 @@ #pragma once -// TODO - Other deps: rive-decoders rive-dependencies +//============================================================================== +/** Config: YUP_RIVE_USE_METAL + Enables the use of the Metal renderer on macOS (the default is enabled). +*/ +#ifndef YUP_RIVE_USE_METAL +#define YUP_RIVE_USE_METAL 1 +#endif + +/** Config: YUP_RIVE_USE_D3D + Enables the use of the Direct3D renderer on Windows (the default is enabled). +*/ +#ifndef YUP_RIVE_USE_D3D +#define YUP_RIVE_USE_D3D 1 +#endif + +/** Config: YUP_RIVE_USE_OPENGL + Enables the use of the OpenGL renderer on platform that support it but where it is not used by default (in + the specific case macOS and Windows). + + You will need to link to the specific OpenGL framework on macOS when building your application with this + flag set: add "-framework OpenGL" to link flags. +*/ +#ifndef YUP_RIVE_USE_OPENGL +#define YUP_RIVE_USE_OPENGL 0 +#endif + +/** Config: YUP_RIVE_USE_DAWN + Enables the use of the Dawn renderer on platform that support it. +*/ +#ifndef YUP_RIVE_USE_DAWN +#define YUP_RIVE_USE_DAWN 0 +#endif + +//============================================================================== +/** Config: YUP_RIVE_OPENGL_MAJOR + Enables a speficic OpenGL major version. Must be at least 4. +*/ +#ifndef YUP_RIVE_OPENGL_MAJOR +#define YUP_RIVE_OPENGL_MAJOR 4 +#endif + +/** Config: YUP_RIVE_OPENGL_MINOR + Enables a speficic OpenGL minor version. Must be at least 2. +*/ +#ifndef YUP_RIVE_OPENGL_MINOR +#define YUP_RIVE_OPENGL_MINOR 2 +#endif + +//============================================================================== + +#if YUP_RIVE_USE_OPENGL +#if __APPLE__ && !YUP_RIVE_USE_METAL && !YUP_RIVE_USE_DAWN +#error Must select at least one between YUP_RIVE_USE_METAL, YUP_RIVE_USE_OPENGL or YUP_RIVE_USE_DAWN +#elif _WIN32 && !YUP_RIVE_USE_D3D && !YUP_RIVE_USE_DAWN +#error Must select at least one between YUP_RIVE_USE_D3D, YUP_RIVE_USE_OPENGL or YUP_RIVE_USE_DAWN +#endif + +#if !defined(RIVE_DESKTOP_GL) && !defined(RIVE_WEBGL) +#define RIVE_DESKTOP_GL 1 +#endif +#endif + +#if YUP_RIVE_USE_DAWN +#if !defined(RIVE_DAWN) +#define RIVE_DAWN 1 +#endif +#endif diff --git a/thirdparty/rive_renderer/rive_renderer_apple.mm b/thirdparty/rive_renderer/rive_renderer_apple.mm index 76a98a524..6cfe4f229 100644 --- a/thirdparty/rive_renderer/rive_renderer_apple.mm +++ b/thirdparty/rive_renderer/rive_renderer_apple.mm @@ -21,5 +21,20 @@ #include "rive_renderer.h" +#if YUP_RIVE_USE_METAL #include "source/metal/render_context_metal_impl.mm" #include "source/metal/background_shader_compiler.mm" +#endif + +#if YUP_RIVE_USE_OPENGL +#include "source/gl/gl_state.cpp" +#include "source/gl/gl_utils.cpp" +#include "source/gl/load_gles_extensions.cpp" +#include "source/gl/load_store_actions_ext.cpp" +#include "source/gl/pls_impl_ext_native.cpp" +#include "source/gl/pls_impl_framebuffer_fetch.cpp" +#include "source/gl/pls_impl_rw_texture.cpp" +#include "source/gl/render_buffer_gl_impl.cpp" +#include "source/gl/render_context_gl_impl.cpp" +#include "source/gl/render_target_gl.cpp" +#endif diff --git a/thirdparty/rive_renderer/rive_renderer_emscripten.cpp b/thirdparty/rive_renderer/rive_renderer_emscripten.cpp index c87b7aa7b..db25ae00a 100644 --- a/thirdparty/rive_renderer/rive_renderer_emscripten.cpp +++ b/thirdparty/rive_renderer/rive_renderer_emscripten.cpp @@ -21,6 +21,12 @@ #include "rive_renderer.h" +#if __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wshorten-64-to-32" + #pragma clang diagnostic ignored "-Wattributes" +#endif + #if RIVE_WEBGPU #include "source/webgpu/em_js_handle.cpp" #include "source/webgpu/render_context_webgpu_impl.cpp" @@ -40,3 +46,7 @@ #error "No renderer backend defined" #endif + +#if __clang__ + #pragma clang diagnostic pop +#endif diff --git a/thirdparty/rive_renderer/rive_renderer_linux.cpp b/thirdparty/rive_renderer/rive_renderer_linux.cpp index b2876968e..2ae90a57b 100644 --- a/thirdparty/rive_renderer/rive_renderer_linux.cpp +++ b/thirdparty/rive_renderer/rive_renderer_linux.cpp @@ -21,6 +21,12 @@ #include "rive_renderer.h" +#if __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wshorten-64-to-32" + #pragma clang diagnostic ignored "-Wattributes" +#endif + #include "source/gl/gl_state.cpp" #include "source/gl/gl_utils.cpp" #include "source/gl/load_gles_extensions.cpp" @@ -31,3 +37,7 @@ #include "source/gl/render_buffer_gl_impl.cpp" #include "source/gl/render_context_gl_impl.cpp" #include "source/gl/render_target_gl.cpp" + +#if __clang__ + #pragma clang diagnostic pop +#endif diff --git a/thirdparty/rive_renderer/rive_renderer_osx.c b/thirdparty/rive_renderer/rive_renderer_osx.c index f62197ddb..bd56709eb 100644 --- a/thirdparty/rive_renderer/rive_renderer_osx.c +++ b/thirdparty/rive_renderer/rive_renderer_osx.c @@ -19,4 +19,8 @@ ============================================================================== */ +#include "rive_renderer.h" + +#if YUP_RIVE_USE_METAL #include "source/generated/shaders/rive_pls_macosx.metallib.c" +#endif diff --git a/thirdparty/rive_renderer/rive_renderer_windows.cpp b/thirdparty/rive_renderer/rive_renderer_windows.cpp index bf9ad0041..38748a3d8 100644 --- a/thirdparty/rive_renderer/rive_renderer_windows.cpp +++ b/thirdparty/rive_renderer/rive_renderer_windows.cpp @@ -21,8 +21,25 @@ #include "rive_renderer.h" +#if YUP_RIVE_USE_D3D #pragma comment (lib, "d3d11.lib") #pragma comment (lib, "d3dcompiler.lib") #pragma comment (lib, "dxgi.lib") #include "source/d3d/render_context_d3d_impl.cpp" +#endif + +#if YUP_RIVE_USE_OPENGL +#pragma comment (lib, "opengl32.lib") + +#include "source/gl/gl_state.cpp" +#include "source/gl/gl_utils.cpp" +#include "source/gl/load_gles_extensions.cpp" +#include "source/gl/load_store_actions_ext.cpp" +#include "source/gl/pls_impl_ext_native.cpp" +#include "source/gl/pls_impl_framebuffer_fetch.cpp" +#include "source/gl/pls_impl_rw_texture.cpp" +#include "source/gl/render_buffer_gl_impl.cpp" +#include "source/gl/render_context_gl_impl.cpp" +#include "source/gl/render_target_gl.cpp" +#endif