diff --git a/Makefile b/Makefile index 17c6f4f..1152361 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/deps/Makefile b/deps/Makefile index 8cbe099..5b42a3a 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -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 diff --git a/include/GL/gl.h b/include/GL/gl.h new file mode 100644 index 0000000..4450158 --- /dev/null +++ b/include/GL/gl.h @@ -0,0 +1,41 @@ +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021 Filipe Coelho + * + * 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 +#endif diff --git a/include/GL/glew.h b/include/GL/glew.h index 2ec0dd6..3332e71 100644 --- a/include/GL/glew.h +++ b/include/GL/glew.h @@ -78,20 +78,22 @@ // ----------------------------------------------------------------------- // OpenGL includes -#ifdef DISTRHO_OS_MAC -# ifdef DGL_USE_OPENGL3 -# include -# include +#ifndef HEADLESS +# ifdef DISTRHO_OS_MAC +# ifdef DGL_USE_OPENGL3 +# include +# include +# else +# include +# endif # else -# include -# endif -#else -# ifdef DISTRHO_OS_WINDOWS -# define GL_GLEXT_PROTOTYPES -# endif -# ifndef __GLEW_H__ -# include -# include +# ifdef DISTRHO_OS_WINDOWS +# define GL_GLEXT_PROTOTYPES +# endif +# ifndef __GLEW_H__ +# include +# include +# endif # endif #endif diff --git a/include/neon-compat/pmmintrin.h b/include/neon-compat/pmmintrin.h index 7d1091c..b21efb9 100644 --- a/include/neon-compat/pmmintrin.h +++ b/include/neon-compat/pmmintrin.h @@ -25,7 +25,7 @@ static inline void __builtin_ia32_pause() { - __asm__ __volatile__("isb\n"); + // __asm__ __volatile__("isb\n"); } static inline diff --git a/plugins/Makefile b/plugins/Makefile index e5e7c25..ae07729 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -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 diff --git a/src/CardinalPlugin.cpp b/src/CardinalPlugin.cpp index 664efa9..0ae3550 100644 --- a/src/CardinalPlugin.cpp +++ b/src/CardinalPlugin.cpp @@ -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; diff --git a/src/DistrhoPluginInfo.h b/src/DistrhoPluginInfo.h index d1ed90f..cb8a88e 100644 --- a/src/DistrhoPluginInfo.h +++ b/src/DistrhoPluginInfo.h @@ -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 diff --git a/src/Makefile b/src/Makefile index 2f1ba6b..64a3590 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/override/RemoteNanoVG.cpp b/src/override/RemoteNanoVG.cpp index 3a8027b..15f639d 100644 --- a/src/override/RemoteNanoVG.cpp +++ b/src/override/RemoteNanoVG.cpp @@ -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 diff --git a/src/override/RemoteWindow.cpp b/src/override/RemoteWindow.cpp index 65ca0b6..5c95a0c 100644 --- a/src/override/RemoteWindow.cpp +++ b/src/override/RemoteWindow.cpp @@ -25,15 +25,10 @@ * the License, or (at your option) any later version. */ -#define NANOVG_GL2 1 - #include #include #include -#include "../src/Rack/dep/glfw/deps/stb_image_write.h" -#include - #include #include #include @@ -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 +#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; } diff --git a/src/override/common.cpp b/src/override/common.cpp index fe80771..1161457 100644 --- a/src/override/common.cpp +++ b/src/override/common.cpp @@ -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 #include diff --git a/src/override/context.cpp b/src/override/context.cpp index 3efdb25..f3c6cd6 100644 --- a/src/override/context.cpp +++ b/src/override/context.cpp @@ -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 { diff --git a/src/override/dep.cpp b/src/override/dep.cpp index 1e389ae..8fd9e03 100644 --- a/src/override/dep.cpp +++ b/src/override/dep.cpp @@ -15,7 +15,7 @@ * For a full copy of the GNU General Public License see the LICENSE file. */ -#include "OpenGL.hpp" +#include // fix blendish build, missing symbol in debug mode #ifdef DEBUG