| @@ -35,7 +35,11 @@ endif | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Check for X11+OpenGL dependencies (unless headless build) | |||
| ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) | |||
| ifneq ($(HEADLESS),true) | |||
| ifneq ($(HAVE_OPENGL),true) | |||
| $(error X11 dependency not installed/available) | |||
| @@ -50,6 +54,7 @@ ifneq ($(HAVE_XRANDR),true) | |||
| $(warning Xrandr dependency not installed/available) | |||
| endif | |||
| endif | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| @@ -63,7 +68,9 @@ ifneq ($(SYSDEPS),true) | |||
| endif | |||
| dgl: | |||
| ifneq ($(HEADLESS),true) | |||
| $(MAKE) -C dpf/dgl opengl USE_NANOVG_FBO=true | |||
| endif | |||
| plugins: deps | |||
| $(MAKE) all -C plugins | |||
| @@ -136,15 +136,24 @@ $(DEP_PATH)/libarchive-3.4.3/.stamp-patched: | |||
| sed -i -e "s/TARGETS archive archive_static/TARGETS archive_static/" $(DEP_PATH)/libarchive-3.4.3/libarchive/CMakeLists.txt | |||
| touch $@ | |||
| ifeq ($(MACOS),true) | |||
| # skip libsamplerate tests | |||
| $(DEP_PATH)/lib/libsamplerate.a: $(DEP_PATH)/libsamplerate-0.1.9/.stamp-patched | |||
| $(DEP_PATH)/libsamplerate-0.1.9/.stamp-patched: | |||
| $(DEP_MAKE) -C $(DEP_PATH) libsamplerate-0.1.9 | |||
| sed -i -e "s/src doc examples tests/src/" $(DEP_PATH)/libsamplerate-0.1.9/Makefile.in | |||
| touch $@ | |||
| # zstd cmake is borked, see https://github.com/facebook/zstd/issues/1401 | |||
| # zstd also fails to build on old systems, patch that too | |||
| $(DEP_PATH)/lib/libzstd.a: $(DEP_PATH)/zstd-1.4.5/.stamp-patched | |||
| $(DEP_PATH)/zstd-1.4.5/.stamp-patched: | |||
| $(DEP_MAKE) -C $(DEP_PATH) zstd-1.4.5 | |||
| sed -i -e "56,66d" $(DEP_PATH)/zstd-1.4.5/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake | |||
| sed -i -e "146,175d" $(DEP_PATH)/zstd-1.4.5/programs/util.c | |||
| sed -i -e "142,144d" $(DEP_PATH)/zstd-1.4.5/programs/util.c | |||
| touch $@ | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Build targets | |||
| @@ -0,0 +1,41 @@ | |||
| /* | |||
| * DISTRHO Cardinal Plugin | |||
| * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 3 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| // this file matches the top of `OpenGL.hpp` provided by DPF | |||
| #pragma once | |||
| #ifdef HEADLESS | |||
| # define GL_COLOR_BUFFER_BIT 0 | |||
| # define GL_DEPTH_BUFFER_BIT 0 | |||
| # define GL_STENCIL_BUFFER_BIT 0 | |||
| # define GL_PROJECTION 0 | |||
| # define GL_TRIANGLES 0 | |||
| static inline void glBegin(int) {} | |||
| static inline void glEnd() {} | |||
| static inline void glColor3f(float, float, float) {} | |||
| static inline void glVertex3f(float, float, float) {} | |||
| static inline void glClear(int) {} | |||
| static inline void glClearColor(double, double, double, double) {} | |||
| static inline void glLoadIdentity() {} | |||
| static inline void glMatrixMode(int) {} | |||
| static inline void glOrtho(double, double, double, double, double, double) {} | |||
| static inline void glViewport(double, double, double, double) {} | |||
| typedef unsigned int GLuint; | |||
| #else | |||
| # include_next <GL/gl.h> | |||
| #endif | |||
| @@ -78,20 +78,22 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // OpenGL includes | |||
| #ifdef DISTRHO_OS_MAC | |||
| # ifdef DGL_USE_OPENGL3 | |||
| # include <OpenGL/gl3.h> | |||
| # include <OpenGL/gl3ext.h> | |||
| #ifndef HEADLESS | |||
| # ifdef DISTRHO_OS_MAC | |||
| # ifdef DGL_USE_OPENGL3 | |||
| # include <OpenGL/gl3.h> | |||
| # include <OpenGL/gl3ext.h> | |||
| # else | |||
| # include <OpenGL/gl.h> | |||
| # endif | |||
| # else | |||
| # include <OpenGL/gl.h> | |||
| # endif | |||
| #else | |||
| # ifdef DISTRHO_OS_WINDOWS | |||
| # define GL_GLEXT_PROTOTYPES | |||
| # endif | |||
| # ifndef __GLEW_H__ | |||
| # include <GL/gl.h> | |||
| # include <GL/glext.h> | |||
| # ifdef DISTRHO_OS_WINDOWS | |||
| # define GL_GLEXT_PROTOTYPES | |||
| # endif | |||
| # ifndef __GLEW_H__ | |||
| # include <GL/gl.h> | |||
| # include <GL/glext.h> | |||
| # endif | |||
| # endif | |||
| #endif | |||
| @@ -25,7 +25,7 @@ | |||
| static inline | |||
| void __builtin_ia32_pause() | |||
| { | |||
| __asm__ __volatile__("isb\n"); | |||
| // __asm__ __volatile__("isb\n"); | |||
| } | |||
| static inline | |||
| @@ -286,6 +286,10 @@ BASE_FLAGS += -I../include/mingw-compat | |||
| BASE_FLAGS += -I../include/mingw-std-threads | |||
| endif | |||
| ifeq ($(HEADLESS),true) | |||
| BASE_FLAGS += -DHEADLESS | |||
| endif | |||
| ifeq ($(WITH_LTO),true) | |||
| BASE_FLAGS += -fno-strict-aliasing -flto | |||
| endif | |||
| @@ -46,7 +46,7 @@ namespace plugin { | |||
| void initStaticPlugins(); | |||
| void destroyStaticPlugins(); | |||
| } | |||
| #ifdef __MOD_DEVICES__ | |||
| #if defined(__MOD_DEVICES__) && !defined(HEADLESS) | |||
| namespace window { | |||
| void WindowInit(Window* window, DISTRHO_NAMESPACE::Plugin* plugin); | |||
| } | |||
| @@ -70,6 +70,9 @@ struct Initializer { | |||
| settings::isPlugin = true; | |||
| settings::skipLoadOnLaunch = true; | |||
| settings::showTipsOnLaunch = false; | |||
| #ifdef HEADLESS | |||
| settings::headless = true; | |||
| #endif | |||
| #ifdef __MOD_DEVICES__ | |||
| settings::threadCount = 3; | |||
| #else | |||
| @@ -244,7 +247,7 @@ public: | |||
| context->patch->loadTemplate(); | |||
| context->engine->startFallbackThread(); | |||
| #ifdef __MOD_DEVICES__ | |||
| #if defined(__MOD_DEVICES__) && !defined(HEADLESS) | |||
| context->window = new rack::window::Window; | |||
| rack::window::WindowInit(context->window, this); | |||
| /* | |||
| @@ -260,17 +263,10 @@ public: | |||
| { | |||
| const MutexLocker cml(context->mutex); | |||
| rack::contextSet(context); | |||
| #ifdef __MOD_DEVICES__ | |||
| #if defined(__MOD_DEVICES__) && !defined(HEADLESS) | |||
| delete context->window; | |||
| context->window = nullptr; | |||
| #endif | |||
| /* | |||
| delete context->scene; | |||
| context->scene = nullptr; | |||
| delete context->event; | |||
| context->event = nullptr; | |||
| */ | |||
| } | |||
| delete context; | |||
| @@ -22,7 +22,14 @@ | |||
| #define DISTRHO_PLUGIN_NAME "Cardinal" | |||
| #define DISTRHO_PLUGIN_URI "https://distrho.kx.studio/plugins/cardinal" | |||
| #ifdef HEADLESS | |||
| #define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #else | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
| #define DISTRHO_UI_USE_NANOVG 1 | |||
| #define DISTRHO_UI_USER_RESIZABLE 1 | |||
| #endif | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 | |||
| @@ -30,11 +37,8 @@ | |||
| #define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 1 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
| // #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | |||
| // #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Analyzer" | |||
| #define DISTRHO_UI_USE_NANOVG 1 | |||
| #define DISTRHO_UI_USER_RESIZABLE 1 | |||
| enum Parameters { | |||
| kParameterCount | |||
| @@ -28,14 +28,17 @@ FILES_DSP = \ | |||
| override/library.cpp \ | |||
| override/network.cpp | |||
| # override/osdialog.cpp | |||
| # override/RemoteNanoVG.cpp | |||
| # override/RemoteWindow.cpp | |||
| ifeq ($(HEADLESS),true) | |||
| FILES_DSP += \ | |||
| override/osdialog.cpp \ | |||
| override/RemoteNanoVG.cpp \ | |||
| override/RemoteWindow.cpp | |||
| else | |||
| FILES_UI = \ | |||
| CardinalUI.cpp \ | |||
| override/MenuBar.cpp \ | |||
| override/Window.cpp | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # Import base definitions | |||
| @@ -143,6 +146,10 @@ BASE_FLAGS += -I../include/mingw-compat | |||
| BASE_FLAGS += -I../include/mingw-std-threads | |||
| endif | |||
| ifeq ($(HEADLESS),true) | |||
| BASE_FLAGS += -DHEADLESS | |||
| endif | |||
| ifeq ($(WITH_LTO),true) | |||
| BASE_FLAGS += -fno-strict-aliasing -flto | |||
| endif | |||
| @@ -15,16 +15,23 @@ | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #ifndef HEADLESS | |||
| #include "OpenGL.hpp" | |||
| #endif | |||
| #include "src/nanovg/nanovg.h" | |||
| #define NANOVG_GL2_IMPLEMENTATION | |||
| // #define NANOVG_GLES2_IMPLEMENTATION | |||
| #include "src/nanovg/nanovg_gl.h" | |||
| #define NANOVG_FBO_VALID 1 | |||
| #include "src/nanovg/nanovg_gl_utils.h" | |||
| #ifdef HEADLESS | |||
| struct NVGLUframebuffer; | |||
| void nvgluBindFramebuffer(NVGLUframebuffer* fb) {} | |||
| NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) { return nullptr; } | |||
| void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) {} | |||
| #else | |||
| # define NANOVG_GLES2_IMPLEMENTATION | |||
| # define NANOVG_FBO_VALID 1 | |||
| # include "src/nanovg/nanovg_gl.h" | |||
| # include "src/nanovg/nanovg_gl_utils.h" | |||
| #endif | |||
| #if defined(__GNUC__) && (__GNUC__ >= 6) | |||
| # pragma GCC diagnostic push | |||
| @@ -38,18 +45,6 @@ | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| // typedef struct NVGLUframebuffer { | |||
| // NVGcontext* ctx; | |||
| // GLuint fbo; | |||
| // GLuint rbo; | |||
| // GLuint texture; | |||
| // int image; | |||
| // } NVGLUframebuffer; | |||
| // | |||
| // void nvgluBindFramebuffer(NVGLUframebuffer* fb) {} | |||
| // NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) { return nullptr; } | |||
| // void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) {} | |||
| #define GLFWAPI | |||
| extern "C" { | |||
| @@ -63,5 +58,7 @@ GLFWAPI int glfwGetKeyScancode(int key) { return 0; } | |||
| } | |||
| #define STB_IMAGE_WRITE_IMPLEMENTATION | |||
| #include "../src/Rack/dep/glfw/deps/stb_image_write.h" | |||
| #ifndef HEADLESS | |||
| # define STB_IMAGE_WRITE_IMPLEMENTATION | |||
| # include "../src/Rack/dep/glfw/deps/stb_image_write.h" | |||
| #endif | |||
| @@ -25,15 +25,10 @@ | |||
| * the License, or (at your option) any later version. | |||
| */ | |||
| #define NANOVG_GL2 1 | |||
| #include <map> | |||
| #include <queue> | |||
| #include <thread> | |||
| #include "../src/Rack/dep/glfw/deps/stb_image_write.h" | |||
| #include <GL/osmesa.h> | |||
| #include <window/Window.hpp> | |||
| #include <asset.hpp> | |||
| #include <widget/Widget.hpp> | |||
| @@ -49,9 +44,24 @@ | |||
| #endif | |||
| #include "DistrhoPlugin.hpp" | |||
| #include "extra/Thread.hpp" | |||
| #include "../WindowParameters.hpp" | |||
| #ifndef HEADLESS | |||
| # include "../src/Rack/dep/glfw/deps/stb_image_write.h" | |||
| # include "extra/Thread.hpp" | |||
| # include <GL/osmesa.h> | |||
| #endif | |||
| #ifdef HEADLESS | |||
| namespace rack { | |||
| namespace app { | |||
| widget::Widget* createMenuBar() { return new widget::Widget; } | |||
| } | |||
| } | |||
| #endif | |||
| namespace rack { | |||
| namespace window { | |||
| @@ -103,14 +113,20 @@ struct WindowParams { | |||
| float rackBrightness = 1.0f; | |||
| }; | |||
| struct Window::Internal : public Thread { | |||
| struct Window::Internal | |||
| #ifndef HEADLESS | |||
| : public Thread | |||
| #endif | |||
| { | |||
| DISTRHO_NAMESPACE::Plugin* plugin = nullptr; | |||
| DISTRHO_NAMESPACE::WindowParameters params; | |||
| DISTRHO_NAMESPACE::WindowParametersCallback* callback = nullptr; | |||
| Context* context = nullptr; | |||
| Window* self = nullptr; | |||
| #ifndef HEADLESS | |||
| OSMesaContext mesa = nullptr; | |||
| GLubyte* mesaBuffer = nullptr; | |||
| #endif | |||
| math::Vec size = minWindowSize; | |||
| std::string lastWindowTitle; | |||
| @@ -127,6 +143,7 @@ struct Window::Internal : public Thread { | |||
| bool fbDirtyOnSubpixelChange = true; | |||
| #ifndef HEADLESS | |||
| void run() override { | |||
| self->run(); | |||
| int i=0; | |||
| @@ -146,6 +163,7 @@ struct Window::Internal : public Thread { | |||
| } | |||
| d_stdout("thread quit"); | |||
| } | |||
| #endif | |||
| }; | |||
| Window::Window() { | |||
| @@ -154,6 +172,7 @@ Window::Window() { | |||
| internal->self = this; | |||
| } | |||
| #ifndef HEADLESS | |||
| static void flipBitmap(uint8_t* pixels, int width, int height, int depth) { | |||
| for (int y = 0; y < height / 2; y++) { | |||
| int flipY = height - y - 1; | |||
| @@ -163,11 +182,13 @@ static void flipBitmap(uint8_t* pixels, int width, int height, int depth) { | |||
| std::memcpy(&pixels[flipY * width * depth], tmp, width * depth); | |||
| } | |||
| } | |||
| #endif | |||
| void WindowInit(Window* const window, DISTRHO_NAMESPACE::Plugin* const plugin) | |||
| { | |||
| window->internal->plugin = plugin; | |||
| #ifndef HEADLESS | |||
| window->internal->mesa = OSMesaCreateContextExt(OSMESA_RGBA, 24, 8, 0, nullptr); | |||
| DISTRHO_SAFE_ASSERT_RETURN(window->internal->mesa != nullptr,); | |||
| @@ -196,6 +217,7 @@ void WindowInit(Window* const window, DISTRHO_NAMESPACE::Plugin* const plugin) | |||
| // window->vg = nvgCreateGLES2(nvgFlags); | |||
| // window->fbVg = nvgCreateSharedGLES2(window->vg, nvgFlags); | |||
| // #endif | |||
| #endif | |||
| // Load default Blendish font | |||
| window->uiFont = window->loadFont(asset::system("res/fonts/DejaVuSans.ttf")); | |||
| @@ -210,6 +232,7 @@ void WindowInit(Window* const window, DISTRHO_NAMESPACE::Plugin* const plugin) | |||
| APP->scene->onContextCreate(e); | |||
| } | |||
| #ifndef HEADLESS | |||
| d_stdout("all good with mesa and GL? %d | %p %p %p", ok, window->internal->mesa, window->vg, window->fbVg); | |||
| // window->internal->startThread(); | |||
| @@ -277,6 +300,7 @@ void WindowInit(Window* const window, DISTRHO_NAMESPACE::Plugin* const plugin) | |||
| delete[] pixels; | |||
| d_stdout("idle - after png"); | |||
| #endif | |||
| } | |||
| void WindowMods(Window* const window, const int mods) | |||
| @@ -296,6 +320,7 @@ Window::~Window() { | |||
| internal->fontCache.clear(); | |||
| internal->imageCache.clear(); | |||
| #ifndef HEADLESS | |||
| // #if defined NANOVG_GL2 | |||
| nvgDeleteGL2(vg); | |||
| nvgDeleteGL2(fbVg); | |||
| @@ -310,6 +335,8 @@ Window::~Window() { | |||
| OSMesaDestroyContext(internal->mesa); | |||
| delete[] internal->mesaBuffer; | |||
| #endif | |||
| delete internal; | |||
| } | |||
| @@ -15,6 +15,16 @@ | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| /** | |||
| * This file is an edited version of VCVRack's common.cpp | |||
| * Copyright (C) 2016-2021 VCV. | |||
| * | |||
| * This program is free software: you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 3 of | |||
| * the License, or (at your option) any later version. | |||
| */ | |||
| #include <common.hpp> | |||
| #include <string.hpp> | |||
| @@ -8,6 +8,16 @@ | |||
| #include "DistrhoPluginUtils.hpp" | |||
| /** | |||
| * This file is an edited version of VCVRack's context.cpp | |||
| * Copyright (C) 2016-2021 VCV. | |||
| * | |||
| * This program is free software: you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 3 of | |||
| * the License, or (at your option) any later version. | |||
| */ | |||
| namespace rack { | |||
| @@ -15,7 +15,7 @@ | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #include "OpenGL.hpp" | |||
| #include <cstdio> | |||
| // fix blendish build, missing symbol in debug mode | |||
| #ifdef DEBUG | |||