| #include "fiddle_context.hpp" |
| |
| #include "rive/pls/pls_factory.hpp" |
| #include "rive/pls/pls_renderer.hpp" |
| #include "rive/pls/gl/pls_render_context_gl.hpp" |
| #include "rive/pls/gl/pls_render_target_gl.hpp" |
| #include "rive/pls/metal/pls_render_context_metal.h" |
| #include "rive/pls/metal/pls_render_target_metal.h" |
| #import <Metal/Metal.h> |
| #import <QuartzCore/CAMetalLayer.h> |
| |
| #define GLFW_INCLUDE_NONE |
| #define GLFW_EXPOSE_NATIVE_COCOA |
| #include "GLFW/glfw3.h" |
| #include <GLFW/glfw3native.h> |
| |
| using namespace rive; |
| using namespace rive::pls; |
| |
| class FiddleContextMetalPLS : public FiddleContext |
| { |
| public: |
| FiddleContextMetalPLS() { printf("==== MTLDevice: %s ====\n", m_gpu.name.UTF8String); } |
| |
| float dpiScale() const override |
| { |
| NSWindow* nsWindow = glfwGetCocoaWindow(g_window); |
| return nsWindow.screen.backingScaleFactor; |
| } |
| |
| std::unique_ptr<Factory> makeFactory() override { return std::make_unique<PLSFactory>(); } |
| |
| void onSizeChanged(int width, int height) override |
| { |
| NSWindow* nsWindow = glfwGetCocoaWindow(g_window); |
| nsWindow.contentView.wantsLayer = YES; |
| float backingScaleFactor = [[nsWindow screen] backingScaleFactor]; |
| |
| m_swapchain = [CAMetalLayer layer]; |
| m_swapchain.device = m_gpu; |
| m_swapchain.opaque = YES; |
| m_swapchain.framebufferOnly = YES; |
| m_swapchain.pixelFormat = MTLPixelFormatBGRA8Unorm; |
| m_swapchain.contentsScale = backingScaleFactor; |
| m_swapchain.displaySyncEnabled = NO; |
| nsWindow.contentView.layer = m_swapchain; |
| |
| m_renderTarget = m_plsContext->makeRenderTarget(MTLPixelFormatBGRA8Unorm, width, height); |
| } |
| |
| void toggleZoomWindow() override {} |
| |
| std::unique_ptr<Renderer> makeRenderer(int width, int height) override |
| { |
| return std::make_unique<PLSRenderer>(m_plsContext.get()); |
| } |
| |
| void begin() override |
| { |
| m_surface = [m_swapchain nextDrawable]; |
| m_renderTarget->setTargetTexture(m_surface.texture); |
| |
| PLSRenderContext::FrameDescriptor frameDescriptor; |
| frameDescriptor.renderTarget = m_renderTarget; |
| frameDescriptor.clearColor = 0xff404040; |
| frameDescriptor.wireframe = g_wireframe; |
| frameDescriptor.fillsDisabled = g_disableFill; |
| frameDescriptor.strokesDisabled = g_disableStroke; |
| m_plsContext->beginFrame(std::move(frameDescriptor)); |
| } |
| |
| void end() override |
| { |
| m_plsContext->flush(); |
| |
| id<MTLCommandBuffer> commandBuffer = [m_queue commandBuffer]; |
| [commandBuffer presentDrawable:m_surface]; |
| [commandBuffer commit]; |
| } |
| |
| void shrinkGPUResourcesToFit() final { m_plsContext->shrinkGPUResourcesToFit(); } |
| |
| private: |
| id<MTLDevice> m_gpu = MTLCreateSystemDefaultDevice(); |
| id<MTLCommandQueue> m_queue = [m_gpu newCommandQueue]; |
| id<CAMetalDrawable> m_surface = nil; |
| std::unique_ptr<PLSRenderContextMetal> m_plsContext = |
| PLSRenderContextMetal::Make(m_gpu, m_queue); |
| CAMetalLayer* m_swapchain; |
| rcp<PLSRenderTargetMetal> m_renderTarget; |
| }; |
| |
| std::unique_ptr<FiddleContext> FiddleContext::MakeMetalPLS() |
| { |
| return std::make_unique<FiddleContextMetalPLS>(); |
| } |