configure.ac add with-cuda/nv, update cakewalk theme, add cuda/plugins=mandel+nbody...
authorGood Guy <[email protected]>
Sun, 16 Jun 2019 18:45:39 +0000 (12:45 -0600)
committerGood Guy <[email protected]>
Sun, 16 Jun 2019 18:45:39 +0000 (12:45 -0600)
50 files changed:
cinelerra-5.1/configure.ac
cinelerra-5.1/ffmpeg/video/h264_nvenc.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/h265_nvenc.mp4 [new file with mode: 0644]
cinelerra-5.1/plugin_cuda [new file with mode: 0644]
cinelerra-5.1/plugin_defs
cinelerra-5.1/plugins/Makefile
cinelerra-5.1/plugins/mandelcuda/.swp [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/mandelbrot.C [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/mandelbrot.h [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/mandelbrotwindow.C [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/mandelbrotwindow.h [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/mandelcuda.cu [new file with mode: 0644]
cinelerra-5.1/plugins/mandelcuda/mandelcuda.h [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/.swp [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/bodysys.cu [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/nbody.C [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/nbody.h [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/nbodycuda.cu [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/nbodycuda.h [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/nbodywindow.C [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/nbodywindow.h [new file with mode: 0644]
cinelerra-5.1/plugins/nbodycuda/renders.C [new file with mode: 0644]
cinelerra-5.1/plugins/theme_cakewalk/data/cin_icon_rec.png
cinelerra-5.1/plugins/theme_cakewalk/data/cin_icon_vwin.png
cinelerra-5.1/plugins/theme_cakewalk/data/heroine_icon.png
cinelerra-5.1/plugins/theme_cakewalk/data/in_checked.png
cinelerra-5.1/plugins/theme_cakewalk/data/in_checkedhi.png
cinelerra-5.1/plugins/theme_cakewalk/data/in_dn.png
cinelerra-5.1/plugins/theme_cakewalk/data/in_hi.png
cinelerra-5.1/plugins/theme_cakewalk/data/in_up.png
cinelerra-5.1/plugins/theme_cakewalk/data/inpoint.png
cinelerra-5.1/plugins/theme_cakewalk/data/label_checked.png
cinelerra-5.1/plugins/theme_cakewalk/data/label_checkedhi.png
cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_dn.png
cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_up.png
cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_uphi.png
cinelerra-5.1/plugins/theme_cakewalk/data/out_checked.png
cinelerra-5.1/plugins/theme_cakewalk/data/out_checkedhi.png
cinelerra-5.1/plugins/theme_cakewalk/data/out_dn.png
cinelerra-5.1/plugins/theme_cakewalk/data/out_hi.png
cinelerra-5.1/plugins/theme_cakewalk/data/out_up.png
cinelerra-5.1/plugins/theme_cakewalk/data/outpoint.png
cinelerra-5.1/plugins/theme_cakewalk/data/pot_dn.png
cinelerra-5.1/plugins/theme_cakewalk/data/pot_hi.png
cinelerra-5.1/plugins/theme_cakewalk/data/pot_up.png
cinelerra-5.1/thirdparty/Makefile
cinelerra-5.1/thirdparty/downloads.txt
cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz [new file with mode: 0644]

index 90048a290fa23a145c91eb07be2dfb6cf1988edf..0f8c6e417cd167c3bb4d1846ffba26f7eca18a58 100644 (file)
@@ -58,6 +58,8 @@ CHECK_WITH([thirdparty],[use thirdparty build],[CIN_3RDPARTY],[yes])
 CHECK_WITH([shuttle],[shuttle device],[SHUTTLE],[yes])
 CHECK_WITH([vaapi],[video acceleration api],[VAAPI],[yes])
 CHECK_WITH([vdpau],[video decode+presentation api for unix],[VDPAU],[yes])
+CHECK_WITH([nv],[video acceleration api],[NV],[yes])
+CHECK_WITH([cuda],[video decode+presentation api for unix],[CUDA],[auto])
 
 if test "x$WANT_LV2" != "xno"; then
   GTK2_LIBS=`pkg-config --libs gtk+-2.0`
@@ -414,6 +416,11 @@ PKG_3RD([libwebp],[auto],
   [ usr/local/lib*/libwebp*.a ],
   [ usr/local/include ])
 
+PKG_3RD([ffnvcodec],[auto],
+  [ffnvcodec],
+  [ ],
+  [ . ])
+
 AC_SUBST(STATIC_PKGS)
 
 AC_DEFUN([CHECK_ENABLE], [
@@ -589,6 +596,7 @@ if test "x$WANT_VAAPI" != "xno" -a "x$HAVE_VAAPI" = "xyes"; then
   CHECK_HEADERS([vaapi_drm], [va drm headers], [va/va_drm.h])
   CHECK_LIB([vaapi_drm], [va-drm], [vaGetDisplayDRM])
 fi
+#CHECK_LIB([NVENC], [nvidia-encode], [NvEncodeAPICreateInstance])
 
 #if test "x$HAVE_mjpegtools" = "xyes"; then
 #CFG_CFLAGS+=" -I/usr/include/mjpegtools -I/usr/local/include/mjpegtools"
@@ -606,7 +614,6 @@ AC_ARG_WITH(m4_tolower([$1]),
   if test "x$WANT_$1" = "xyes" ; then
     AC_MSG_ERROR([required for $1 support.])
   fi
-  echo "=== want $1 Failed."
   WANT_$1=no
  elif test "x$WANT_$1" = "xauto" ; then
   WANT_$1=yes
@@ -683,6 +690,9 @@ CHECK_WANT([LV2], [auto], [use lv2], [
  CHECK_HEADERS([lv2], [suil headers], [suil/suil.h])
  CFLAGS="$saved_CFLAGS"])
 
+CHECK_WANT([CUDA], [auto], [build cuda plugins], [
+  CHECK_HEADERS([CUDA], [cuda sdk], [/usr/local/cuda/include/cuda.h])])
+
 CHECK_WANT([DL], [auto], [system has libdl], [
  CHECK_LIB([DL], [dl], [dlopen])])
 
@@ -832,6 +842,7 @@ PKG_PROVIDE([sratom], [$WANT_LV2])
 PKG_PROVIDE([serd], [$WANT_LV2])
 PKG_PROVIDE([sord], [$WANT_LV2])
 PKG_PROVIDE([suil], [$WANT_LV2])
+PKG_PROVIDE([ffnvcodec], [$WANT_NV])
 
 if test "x$WANT_LV2" = "xyes"; then
   if test "x$HAVE_lv2" = "xyes" -a "x$BUILD_lilv" = "x0"; then
@@ -884,6 +895,8 @@ echo "  using: with-libzmpeg = $WANT_LIBZMPEG"
 echo "  using: with-commerical = $WANT_COMMERCIAL"
 echo "  using: with-vaapi = $WANT_VAAPI"
 echo "  using: with-vdpau = $WANT_VDPAU"
+echo "  using: with-nv = $WANT_NV"
+echo "  using: with-cuda = $WANT_CUDA"
 echo ""
 echo "  using: thirdparty build = $WANT_CIN_3RDPARTY"
 echo "  using: single-user  = $WANT_CINBIN_BUILD"
@@ -920,6 +933,10 @@ if test "x$WANT_VDPAU" != "xno" -a "x$HAVE_VDPAU" = "xyes"; then
   WANT_VDPAU="yes"
   CFG_WANTS+=" VDPAU"
 fi
+if test "x$WANT_NV" != "xno"; then
+  WANT_NV="yes"
+  CFG_WANTS+=" NV"
+fi
 
 if test "x$HAVE_DL" = "xyes"; then
   EXTRA_LIBS+=' -ldl'
diff --git a/cinelerra-5.1/ffmpeg/video/h264_nvenc.mp4 b/cinelerra-5.1/ffmpeg/video/h264_nvenc.mp4
new file mode 100644 (file)
index 0000000..d48bacd
--- /dev/null
@@ -0,0 +1,4 @@
+mp4 h264_nvenc
+# encode for nvidia graphics hw only
+preset medium
+profile main
diff --git a/cinelerra-5.1/ffmpeg/video/h265_nvenc.mp4 b/cinelerra-5.1/ffmpeg/video/h265_nvenc.mp4
new file mode 100644 (file)
index 0000000..784d8a6
--- /dev/null
@@ -0,0 +1,4 @@
+mp4 hevc_nvenc
+# encode for nvidia graphics hw only
+preset medium
+profile main
diff --git a/cinelerra-5.1/plugin_cuda b/cinelerra-5.1/plugin_cuda
new file mode 100644 (file)
index 0000000..10ee7fa
--- /dev/null
@@ -0,0 +1,32 @@
+#cuda compile
+
+CUDA_PATH ?= /usr/local/cuda-10.1
+TARGET_SIZE := 64 # 32
+HOST_COMPILER ?= g++
+NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER)
+NVCCFLAGS := -m${TARGET_SIZE} -Xcompiler -fPIC -Xcompiler -fno-omit-frame-pointer -g
+LDFLAGS = -lcuda -L /usr/local/cuda/targets/x86_64-linux/lib -lcudart
+
+SMS ?= 30 35 37 50 52 60 61 70 75
+$(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm)))
+HIGHEST_SM := $(lastword $(sort $(SMS)))
+GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM)
+
+# samples source access BEWARE!
+# contains includes which conflict: search /usr/include first
+CFLAGS += -I/usr/include -I/usr/local/cuda/samples
+CFLAGS += -I/usr/local/cuda/samples/common/inc
+CFLAGS += -I/usr/local/cuda/targets/x86_64-linux/include
+CFLAGS += -Wno-unused-function
+
+INCLUDES += -I$(TOPDIR)/cinelerra -I$(TOPDIR)/guicast
+INCLUDES += -I/usr/local/cuda/samples
+INCLUDES += -I/usr/local/cuda/samples/common/inc
+INCLUDES += -I/usr/local/cuda/targets/x86_64-linux/include
+
+CUFLAGS := $(INCLUDES) $(NVCCFLAGS) $(GENCODE_FLAGS)
+$(shell mkdir -p $(OBJDIR))
+$(shell echo $(CUFLAGS) > $(OBJDIR)/cu_flags)
+
+$(OBJDIR)/%.o: %.cu
+       $(NVCC) `cat $(OBJDIR)/cu_flags` $(BFLAGS) -DMSGQUAL=$* -c $< -o $@
index 5890e213d3ca335fe12b9695241117e0391eea54..afd04e88c81dbd4fae8e367604fe2671c5bf2381 100644 (file)
@@ -15,6 +15,7 @@ themes := \
        theme_suv \
        theme_neophyte \
        theme_unflat \
+       theme_cakewalk \
 
 plugin_dirs += video
 video := \
@@ -76,6 +77,8 @@ video := \
        motionblur \
        motion-cv \
        motion-hv \
+       mandelcuda \
+       nbodycuda \
        oil \
        overlay \
        perspective \
index 77292863e0147a448d46605d0bc85c171389e014..2bf29432dd7deb59cdeb6ddcfd94f0c80f8e4a1a 100644 (file)
@@ -11,6 +11,9 @@ include $(TOPDIR)/opencv_build
 OPENCV_OBJS := findobj flowobj gaborobj moveobj stylizeobj puzzleobj
 $(OPENCV_OBJS): opencv
 endif
+ifneq ($(WANT_CUDA), no)
+CUDA_OBJS := mandelcuda nbodycuda
+endif
 
 # burn must come before any other effecttv plugin
 # colors must come before any plugin
@@ -18,6 +21,7 @@ endif
 # motion must come before perspective
 
 DIRS = $(OPENCV_OBJS) \
+       $(CUDA_OBJS) \
        1080to480 \
        1080to540 \
        720to480 \
diff --git a/cinelerra-5.1/plugins/mandelcuda/.swp b/cinelerra-5.1/plugins/mandelcuda/.swp
new file mode 100644 (file)
index 0000000..5d9b1b9
Binary files /dev/null and b/cinelerra-5.1/plugins/mandelcuda/.swp differ
diff --git a/cinelerra-5.1/plugins/mandelcuda/Makefile b/cinelerra-5.1/plugins/mandelcuda/Makefile
new file mode 100644 (file)
index 0000000..95d8587
--- /dev/null
@@ -0,0 +1,17 @@
+TOPDIR?=../..
+include $(TOPDIR)/plugin_defs
+include $(TOPDIR)/plugin_cuda
+
+PLUGIN = mandelcuda
+
+OBJS := \
+       $(OBJDIR)/mandelbrot.o \
+       $(OBJDIR)/mandelbrotwindow.o \
+       $(OBJDIR)/mandelcuda.o \
+
+include $(TOPDIR)/plugin_config
+
+$(OBJDIR)/mandelbrot.o: mandelbrot.C  mandelbrot.h 
+$(OBJDIR)/mandelbrotwindow.o: mandelbrotwindow.C  mandelbrotwindow.h
+$(OBJDIR)/mandelcuda.o: mandelcuda.cu  mandelcuda.h 
+
diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelbrot.C b/cinelerra-5.1/plugins/mandelcuda/mandelbrot.C
new file mode 100644 (file)
index 0000000..693b867
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "clip.h"
+#include "filexml.h"
+#include "mandelbrot.h"
+#include "mandelbrotwindow.h"
+#include "language.h"
+#include "mutex.h"
+
+#include "cwindow.h"
+#include "cwindowgui.h"
+#include "mwindow.h"
+#include "pluginserver.h"
+#include "playback3d.h"
+
+REGISTER_PLUGIN(Mandelbrot)
+
+
+MandelbrotConfig::MandelbrotConfig()
+{
+}
+
+int MandelbrotConfig::equivalent(MandelbrotConfig &that)
+{
+       return is_julia == that.is_julia && scale == that.scale &&
+               x_off == that.x_off && y_off == that.y_off &&
+               x_julia == that.x_julia && y_julia == that.y_julia &&
+               color == that.color && crunch == that.crunch &&
+               step == that.step;
+}
+
+void MandelbrotConfig::copy_from(MandelbrotConfig &that)
+{
+       is_julia = that.is_julia;
+       x_off = that.x_off;
+       y_off = that.y_off;
+       scale = that.scale;
+       x_julia = that.x_julia;
+       y_julia = that.y_julia;
+       color = that.color;
+       crunch = that.crunch;
+       step = that.step;
+}
+
+void MandelbrotConfig::interpolate( MandelbrotConfig &prev, MandelbrotConfig &next, 
+       long prev_frame, long next_frame, long current_frame)
+{
+       copy_from(prev);
+       double u = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+       double v = 1. - u;
+       this->x_off = u*prev.x_off + v*next.x_off;
+       this->y_off = u*prev.y_off + v*next.y_off;
+       this->scale = u*prev.scale + v*next.scale;
+       this->x_julia = u*prev.x_julia + v*next.x_julia;
+       this->y_julia = u*prev.y_julia + v*next.y_julia;
+}
+
+void MandelbrotConfig::limits()
+{
+       bclamp(scale, -1.e4, 1.e4);
+       bclamp(crunch, 1, 0x10000);
+}
+
+
+Mandelbrot::Mandelbrot(PluginServer *server)
+ : PluginVClient(server)
+{
+       config.reset();
+       config.startJulia();
+       vfrm = 0;
+       img_w = img_h = 0;
+       pbo_id = -1;
+       animation_frame = 0;
+}
+
+Mandelbrot::~Mandelbrot()
+{
+       delete vfrm;
+}
+
+const char* Mandelbrot::plugin_title() { return N_("Mandelbrot"); }
+int Mandelbrot::is_realtime() { return 1; }
+int Mandelbrot::is_synthesis() { return 1; }
+
+NEW_WINDOW_MACRO(Mandelbrot, MandelbrotWindow);
+LOAD_CONFIGURATION_MACRO(Mandelbrot, MandelbrotConfig)
+
+void Mandelbrot::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+       output.set_shared_output(keyframe->xbuf);
+       output.tag.set_title("MANDELCUDA");
+       output.tag.set_property("IS_JULIA", config.is_julia);
+       output.tag.set_property("SCALE", config.scale);
+       output.tag.set_property("X_OFF", config.x_off);
+       output.tag.set_property("Y_OFF", config.y_off);
+       output.tag.set_property("X_JULIA", config.x_julia);
+       output.tag.set_property("Y_JULIA", config.y_julia);
+       output.tag.set_property("COLOR", config.color);
+       output.tag.set_property("CRUNCH", config.crunch);
+       output.tag.set_property("STEP", config.step);
+       output.append_tag();
+       output.append_newline();
+       output.tag.set_title("/MANDELCUDA");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+}
+
+void Mandelbrot::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+       input.set_shared_input(keyframe->xbuf);
+
+       int result = 0;
+       while( !(result = input.read_tag()) ) {
+               if( input.tag.title_is("MANDELCUDA") ) {
+                       config.is_julia = input.tag.get_property("IS_JULIA", config.is_julia);
+                       config.scale = input.tag.get_property("SCALE", config.scale);
+                       config.x_off = input.tag.get_property("X_OFF", config.x_off);
+                       config.y_off = input.tag.get_property("Y_OFF", config.y_off);
+                       config.x_julia = input.tag.get_property("X_JULIA", config.x_julia);
+                       config.y_julia = input.tag.get_property("Y_JULIA", config.y_julia);
+                       config.color = input.tag.get_property("COLOR", config.color);
+                       config.crunch = input.tag.get_property("CRUNCH", config.crunch);
+                       config.step = input.tag.get_property("STEP", config.step);
+               }
+       }
+       config.limits();
+}
+
+void Mandelbrot::update_gui()
+{
+       if( !thread ) return;
+       if( !load_configuration() ) return;
+       thread->window->lock_window("Mandelbrot::update_gui");
+       MandelbrotWindow *window = (MandelbrotWindow*)thread->window;
+       window->update_gui();
+       window->flush();
+       window->unlock_window();
+}
+
+void MandelbrotConfig::reset()
+{
+       is_julia = 0;
+       x_julia = 0.0;
+       y_julia = 0.0;
+       x_off = -0.5;
+       y_off = 0.0;
+       scale = 3.2;
+       color = 0x00030507;
+       crunch = 512;
+       step = 0;
+}
+
+void MandelbrotConfig::startJulia()
+{
+       is_julia = 1;
+       x_julia = -0.172400;
+       y_julia = -0.652693;
+       x_off = -0.085760;
+       y_off = 0.007040;
+}
+
+// Get a sub-pixel sample location
+void Mandelbrot::GetSample(int sampleIndex, float &x, float &y)
+{
+       static const unsigned char pairData[128][2] = {
+               {64, 64}, {0, 0}, {1, 63}, {63, 1}, {96, 32}, {97, 95}, {36, 96}, {30, 31},
+               {95, 127}, {4, 97}, {33, 62}, {62, 33}, {31, 126}, {67, 99}, {99, 65}, {2, 34},
+               {81, 49}, {19, 80}, {113, 17}, {112, 112}, {80, 16}, {115, 81}, {46, 15}, {82, 79},
+               {48, 78}, {16, 14}, {49, 113}, {114, 48}, {45, 45}, {18, 47}, {20, 109}, {79, 115},
+               {65, 82}, {52, 94}, {15, 124}, {94, 111}, {61, 18}, {47, 30}, {83, 100}, {98, 50},
+               {110, 2}, {117, 98}, {50, 59}, {77, 35}, {3, 114}, {5, 77}, {17, 66}, {32, 13},
+               {127, 20}, {34, 76}, {35, 110}, {100, 12}, {116, 67}, {66, 46}, {14, 28}, {23, 93},
+               {102, 83}, {86, 61}, {44, 125}, {76, 3}, {109, 36}, {6, 51}, {75, 89}, {91, 21},
+               {60, 117}, {29, 43}, {119, 29}, {74, 70}, {126, 87}, {93, 75}, {71, 24}, {106, 102},
+               {108, 58}, {89, 9}, {103, 23}, {72, 56}, {120, 8}, {88, 40}, {11, 88}, {104, 120},
+               {57, 105}, {118, 122}, {53, 6}, {125, 44}, {43, 68}, {58, 73}, {24, 22}, {22, 5},
+               {40, 86}, {122, 108}, {87, 90}, {56, 42}, {70, 121}, {8, 7}, {37, 52}, {25, 55},
+               {69, 11}, {10, 106}, {12, 38}, {26, 69}, {27, 116}, {38, 25}, {59, 54}, {107, 72},
+               {121, 57}, {39, 37}, {73, 107}, {85, 123}, {28, 103}, {123, 74}, {55, 85}, {101, 41},
+               {42, 104}, {84, 27}, {111, 91}, {9, 19}, {21, 39}, {90, 53}, {41, 60}, {54, 26},
+               {92, 119}, {51, 71}, {124, 101}, {68, 92}, {78, 10}, {13, 118}, {7, 84}, {105, 4}
+       };
+
+       x = (1.0f / 128.0f) * (0.5f + (float) pairData[sampleIndex][0]);
+       y = (1.0f / 128.0f) * (0.5f + (float) pairData[sampleIndex][1]);
+} // GetSample
+
+// render Mandelbrot image using CUDA
+void Mandelbrot::renderImage()
+{
+       float xs, ys;
+       // Get the anti-alias sub-pixel sample location
+       GetSample(pass & 127, xs, ys);
+
+       // Get the pixel scale and offset
+       double s = config.scale / (float) img_w;
+       double x  = (xs - (double) img_w * 0.5f) * s + config.x_off;
+       double y  = (ys - (double) img_h * 0.5f) * s + config.y_off;
+
+       uchar4 colors;
+       colors.w = (config.color>>24) & 0xff;
+       colors.x = (config.color>>16) & 0xff;
+       colors.y = (config.color>>8)  & 0xff;
+       colors.z = (config.color>>0)  & 0xff;
+
+       cuda.Run(vfrm->get_data(), img_w*img_h*4, config.is_julia, config.crunch,
+               x, y, config.x_julia, config.y_julia, s, colors, pass, animation_frame);
+       ++pass;
+}
+
+void Mandelbrot::displayFunc()
+{
+       if( config.step ) {
+               animation_frame += config.step;
+               pass = 0;
+       }
+       // render the Mandelbrot image
+       renderImage();
+}
+
+void Mandelbrot::init()
+{
+       animation_frame = 0;
+       pass = 0;
+}
+
+int Mandelbrot::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
+{
+
+       int need_reconfigure = load_configuration();
+       if( need_reconfigure ) pass = 0;
+       output = get_output(0);
+       color_model = output->get_color_model();
+       img_w = output->get_w();
+       img_h = output->get_h();
+       if( !start_position )
+               init();
+       if( vfrm &&
+           (vfrm->get_w() != img_w || vfrm->get_h() != img_h) ) {
+               delete vfrm;  vfrm = 0;
+       }
+       if( !vfrm )
+               vfrm = new VFrame(img_w, img_h, BC_RGBA8888);
+
+       if( get_use_opengl() )
+               return run_opengl();
+// always use_opengl
+       Canvas *canvas = server->mwindow->cwindow->gui->canvas;
+       return server->mwindow->playback_3d->run_plugin(canvas, this);
+}
+
+// opengl from here down
+
+void Mandelbrot::init_cuda()
+{
+       cuda.init_dev();
+       GLuint pbo[1];
+       glGenBuffers(1, pbo);
+       glBindBuffer(GL_ARRAY_BUFFER, pbo_id=*pbo);
+       glBufferData(GL_ARRAY_BUFFER, img_w*img_h*4, 0, GL_STATIC_DRAW);
+       cuda.init(pbo_id, img_w, img_h);
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+void Mandelbrot::finish_cuda()
+{
+       cuda.finish();
+       GLuint pbo[1];  *pbo = pbo_id;
+       glDeleteBuffers(1, pbo);
+       pbo_id = -1;
+}
+
+int Mandelbrot::handle_opengl()
+{
+       vfrm->enable_opengl();
+       vfrm->init_screen();
+       init_cuda();
+       displayFunc();
+       output->transfer_from(vfrm);
+       finish_cuda();
+       return 0;
+}
+
diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelbrot.h b/cinelerra-5.1/plugins/mandelcuda/mandelbrot.h
new file mode 100644 (file)
index 0000000..c2931cf
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef MANDELCUDA_H
+#define MANDELCUDA_H
+
+#include "pluginvclient.h"
+
+typedef struct {
+    unsigned char x, y, z, w;
+} uchar4;
+
+#include "mandelcuda.h"
+
+class MandelbrotConfig;
+class Mandelbrot;
+
+class MandelbrotConfig
+{
+public:
+       MandelbrotConfig();
+
+       int equivalent(MandelbrotConfig &that);
+       void copy_from(MandelbrotConfig &that);
+       void interpolate(MandelbrotConfig &prev, MandelbrotConfig &next, 
+               long prev_frame, long next_frame, long current_frame);
+
+       int is_julia;
+       float x_off, y_off, scale;
+       float x_julia, y_julia;
+       int color, crunch, step;
+
+       void limits();
+       void reset();
+       void startJulia();
+};
+
+class Mandelbrot : public PluginVClient
+{
+public:
+       Mandelbrot(PluginServer *server);
+       ~Mandelbrot();
+       PLUGIN_CLASS_MEMBERS2(MandelbrotConfig)
+       int is_realtime();
+       int is_synthesis();
+       void update_gui();
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+       int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
+       int handle_opengl();
+
+       void GetSample(int sampleIndex, float &x, float &y);
+       void renderImage();
+       void displayFunc();
+       void initData();
+       void init();
+
+       VFrame *output, *vfrm;
+       int color_model, pass;
+       int img_w, img_h;
+       int pbo_id;
+       int animation_frame;
+       MandelCuda cuda;
+
+       void init_cuda();
+       void finish_cuda();
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelbrotwindow.C b/cinelerra-5.1/plugins/mandelcuda/mandelbrotwindow.C
new file mode 100644 (file)
index 0000000..c4b1168
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "cwindow.h"
+#include "cwindowgui.h"
+#include "edl.h"
+#include "edlsession.h"
+#include "language.h"
+#include "mandelbrot.h"
+#include "mandelbrotwindow.h"
+#include "mwindow.h"
+#include "mwindowgui.h"
+#include "pluginserver.h"
+#include "theme.h"
+
+MandelbrotWindow::MandelbrotWindow(Mandelbrot *plugin)
+ : PluginClientWindow(plugin, 180, 130, 180, 130, 0)
+{
+       this->plugin = plugin; 
+       press_x = press_y = 0;
+       button_no = 0;
+       pending_config = 0;
+}
+
+MandelbrotWindow::~MandelbrotWindow()
+{
+}
+
+void MandelbrotWindow::create_objects()
+{
+       int x = 10, y = 10, pad = 5;
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x,y, _("Mandelbrot:"), MEDIUMFONT, YELLOW));
+       y += title->get_h() + pad;
+       add_subwindow(is_julia = new MandelbrotIsJulia(this, x, y));
+       y += is_julia->get_h() + pad;
+       add_subwindow(drag = new MandelbrotDrag(this, x, y));
+       y += drag->get_h() + pad;
+       add_subwindow(reset = new MandelbrotReset(this, x, y));
+       show_window();
+}
+
+void MandelbrotWindow::update_gui()
+{
+}
+
+
+void MandelbrotWindow::send_configure_change()
+{
+       pending_config = 0;
+       plugin->send_configure_change();
+}
+
+int MandelbrotWindow::grab_event(XEvent *event)
+{
+       int ret = do_grab_event(event);
+       if( pending_config && !grab_event_count() )
+               send_configure_change();
+       return ret;
+}
+
+int MandelbrotWindow::do_grab_event(XEvent *event)
+{
+       switch( event->type ) {
+       case ButtonPress: break;
+       case ButtonRelease: break;
+       case MotionNotify: break;
+       default:
+               return 0;
+       }
+
+       MWindow *mwindow = plugin->server->mwindow;
+       CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
+       CWindowCanvas *canvas = cwindow_gui->canvas;
+       int cursor_x, cursor_y;
+       cwindow_gui->get_relative_cursor(cursor_x, cursor_y);
+       cursor_x -= canvas->view_x;
+       cursor_y -= canvas->view_y;
+       float output_x = cursor_x, output_y = cursor_y;
+       canvas->canvas_to_output(mwindow->edl, 0, output_x, output_y);
+
+       if( !button_no ) {
+               if( cursor_x < 0 || cursor_x >= canvas->view_w ||
+                   cursor_y < 0 || cursor_y >= canvas->view_h )
+                       return 0;
+       }
+
+       switch( event->type ) {
+       case ButtonPress:
+               if( button_no ) return 0;
+               press_x = output_x;  press_y = output_y;
+               button_no = event->xbutton.button;
+               break;
+       case ButtonRelease:
+               if( !button_no ) return 0;
+               button_no = 0;
+               return 1;
+       case MotionNotify: {
+               if( !button_no ) return 0;
+               EDL *edl = plugin->get_edl();
+               double dx = 0, dy = 0, jx = 0, jy = 0, ds = 1;
+               double out_w = edl->session->output_w, out_h = edl->session->output_h;
+               double fx = (double)(press_x - output_x) / (2. * out_w);
+               double fy = (double)(press_y - output_y) / (2. * out_h);
+               press_x = output_x;  press_y = output_y;
+               switch( button_no ) {
+               case LEFT_BUTTON: {
+                       dx = fx * plugin->config.scale;
+                       dy = fy * plugin->config.scale;
+                       break; }
+               case MIDDLE_BUTTON: {
+                       ds = fy >= 0.f ? 1-fy : 1/(1+fy);
+                       bclamp(ds, 1-0.05f, 1+0.05f);
+                       break; }
+               case RIGHT_BUTTON: {
+                       jx = fx;
+                       jy = fy;
+                       break; }
+               }
+               plugin->config.x_off += dx;
+               plugin->config.y_off += dy;
+               plugin->config.x_julia += jx;
+               plugin->config.y_julia += jy;
+               plugin->config.scale *= ds;
+               pending_config = 1;
+               break; }
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+void MandelbrotWindow::done_event(int result)
+{
+       ungrab(client->server->mwindow->cwindow->gui);
+}
+MandelbrotDrag::MandelbrotDrag(MandelbrotWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, 0, _("Drag"))
+{
+       this->gui = gui;
+}
+int MandelbrotDrag::handle_event()
+{
+       CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
+       int value = get_value();
+       if( value ) {
+               if( !gui->grab(cwindow_gui) ) {
+                       update(value = 0);
+                       flicker(10,50);
+               }
+       }
+       else
+               gui->ungrab(cwindow_gui);
+       return 1;
+}
+
+MandelbrotIsJulia::MandelbrotIsJulia(MandelbrotWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, gui->plugin->config.is_julia, _("Julia"))
+{
+       this->gui = gui;
+}
+MandelbrotIsJulia::~MandelbrotIsJulia()
+{
+}
+
+int MandelbrotIsJulia::handle_event()
+{
+       Mandelbrot *plugin = gui->plugin;
+       plugin->config.is_julia = get_value();
+       gui->send_configure_change();
+       return 1;
+}
+
+MandelbrotReset::MandelbrotReset(MandelbrotWindow *gui, int x, int y)
+ : BC_GenericButton(x, y, _("Reset"))
+{
+       this->gui = gui;
+}
+MandelbrotReset::~MandelbrotReset()
+{
+}
+
+int MandelbrotReset::handle_event()
+{
+       Mandelbrot *plugin = gui->plugin;
+       int is_julia = plugin->config.is_julia;
+       plugin->config.reset();
+       if( is_julia )
+               plugin->config.startJulia();
+       gui->send_configure_change();
+       return 1;
+}
+
+
+
diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelbrotwindow.h b/cinelerra-5.1/plugins/mandelcuda/mandelbrotwindow.h
new file mode 100644 (file)
index 0000000..98208fc
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef MANDELCUDAWINDOW_H
+#define MANDELCUDAWINDOW_H
+
+
+#include "guicast.h"
+#include "mandelbrot.h"
+
+class Mandelbrot;
+class MandelbrotIsJulia;
+class MandelbrotDrag;
+class MandelbrotWindow;
+
+class MandelbrotIsJulia : public BC_CheckBox
+{
+public:
+       MandelbrotIsJulia(MandelbrotWindow *gui, int x, int y);
+       ~MandelbrotIsJulia();
+       int handle_event();
+
+       MandelbrotWindow *gui;
+};
+
+class MandelbrotReset : public BC_GenericButton
+{
+public:
+       MandelbrotReset(MandelbrotWindow *gui, int x, int y);
+       ~MandelbrotReset();
+       int handle_event();
+
+       MandelbrotWindow *gui;
+};
+
+class MandelbrotDrag : public BC_CheckBox
+{
+public:
+       MandelbrotDrag(MandelbrotWindow *gui, int x, int y);
+
+       int handle_event();
+       MandelbrotWindow *gui;
+};
+
+class MandelbrotWindow : public PluginClientWindow
+{
+public:
+       MandelbrotWindow(Mandelbrot *plugin);
+       ~MandelbrotWindow();
+       void create_objects();
+       void update_gui();
+
+       int grab_event(XEvent *event);
+       int do_grab_event(XEvent *event);
+       void done_event(int result);
+       void send_configure_change();
+
+       Mandelbrot *plugin;
+       MandelbrotIsJulia *is_julia;
+       MandelbrotDrag *drag;
+       MandelbrotReset *reset;
+       int press_x, press_y;
+       int button_no, pending_config;
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelcuda.cu b/cinelerra-5.1/plugins/mandelcuda/mandelcuda.cu
new file mode 100644 (file)
index 0000000..8ba357e
--- /dev/null
@@ -0,0 +1,160 @@
+#include "mandelcuda.h"
+#include <cuda_runtime.h>
+#include <cuda_gl_interop.h>
+#include "helper_cuda.h"
+#include "helper_gl.h"
+
+// The dimensions of the thread block
+#define BLOCKDIM_X 16
+#define BLOCKDIM_Y 16
+#define ABS(n) ((n) < 0 ? -(n) : (n))
+
+void MandelCuda::init_dev()
+{
+       if( numSMs ) return;
+//     int dev_id = findCudaDevice(argc, (const char **)argv);
+       int dev_id = gpuGetMaxGflopsDeviceId();
+       checkCudaErrors(cudaSetDevice(dev_id));
+       cudaDeviceProp deviceProp;
+       checkCudaErrors(cudaGetDeviceProperties(&deviceProp, dev_id));
+printf("GPU Device %d: \"%s\" with compute capability %d.%d\n",
+  dev_id, deviceProp.name, deviceProp.major, deviceProp.minor);
+       version = deviceProp.major * 10 + deviceProp.minor;
+       numSMs = deviceProp.multiProcessorCount;
+       if( !numSMs ) numSMs = -1;
+}
+
+void MandelCuda::init(int pbo, int pw, int ph)
+{
+       if( pbo_id >= 0 ) return;
+       pbo_id = pbo;  pbo_w = pw;  pbo_h = ph;
+       checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cuda_pbo, pbo_id, cudaGraphicsMapFlagsNone));
+       checkCudaErrors(cudaGraphicsMapResources(1, &cuda_pbo, 0));
+       size_t pbo_bytes = 0;
+       checkCudaErrors(cudaGraphicsResourceGetMappedPointer(&pbo_mem, &pbo_bytes, cuda_pbo));
+}
+
+void MandelCuda::finish()
+{
+       pbo_id = -1;
+       pbo_w = pbo_h = 0;
+       checkCudaErrors(cudaGraphicsUnmapResources(1, &cuda_pbo));
+       pbo_mem = 0;
+       cudaGraphicsUnregisterResource(cuda_pbo);  cuda_pbo = 0;
+}
+
+
+MandelCuda::MandelCuda()
+{
+       version = 0;
+       numSMs = 0;
+       pbo_id = -1;
+       pbo_w = pbo_h = 0;
+       cuda_pbo = 0;
+       pbo_mem = 0;
+}
+MandelCuda::~MandelCuda()
+{
+}
+
+static inline int iDivUp(int a, int b)
+{
+    int v = a / b;
+    return a % b ? v+1 : v;
+}
+
+// Determine if two pixel colors are within tolerance
+__device__ inline int CheckColors(const uchar4 &color0, const uchar4 &color1)
+{
+       int x = color1.x - color0.x;
+       if( ABS(x) > 10 ) return 1;
+       int y = color1.y - color0.y;
+        if( ABS(y) > 10 ) return 1;
+       int z = color1.z - color0.z;
+        if( ABS(z) > 10 ) return 1;
+       return 0;
+}
+
+
+// The core MandelCuda calculation function template
+template<class T> __device__
+inline int CalcCore(const int n, T ix, T iy, T xC, T yC)
+{
+    T x = ix, y = iy;
+    T xx = x * x, yy = y * y;
+    int i = n;
+    while( --i && (xx + yy < 4.0f) ) {
+       y = x * y +  x * y + yC ;  // 2*x*y + yC
+        x = xx - yy + xC ;
+        yy = y * y;
+        xx = x * x;
+    }
+
+    return i;
+}
+
+template<class T> __global__
+void Calc(uchar4 *dst, const int img_w, const int img_h, const int is_julia,
+               const int crunch, const int gridWidth, const int numBlocks,
+               const T x_off, const T y_off, const T x_julia, const T y_julia, const T scale,
+               const uchar4 colors, const int frame, const int animationFrame)
+{
+       // loop until all blocks completed
+       for( unsigned int bidx=blockIdx.x; bidx<numBlocks; bidx+=gridDim.x ) {
+               unsigned int blockX = bidx % gridWidth;
+               unsigned int blockY = bidx / gridWidth;
+               const int x = blockDim.x * blockX + threadIdx.x;
+               const int y = blockDim.y * blockY + threadIdx.y;
+               if( x >= img_w || y >= img_h ) continue;
+               int pi = img_w*y + x, n = !frame ? 1 : 0;
+               uchar4 pixel = dst[pi];
+               if( !n && x > 0 )
+                       n += CheckColors(pixel, dst[pi-1]);
+               if( !n && x+1 < img_w )
+                       n += CheckColors(pixel, dst[pi+1]);
+               if( !n && y > 0 )
+                       n += CheckColors(pixel, dst[pi-img_w]);
+               if( !n && y+1 < img_h )
+                       n += CheckColors(pixel, dst[pi+img_w]);
+               if( !n ) continue;
+
+               const T tx = T(x) * scale + x_off;
+               const T ty = T(y) * scale + y_off;
+               const T ix = is_julia ? tx : 0;
+               const T iy = is_julia ? ty : 0;
+               const T xC = is_julia ? x_julia : tx;
+               const T yC = is_julia ? y_julia : ty;
+               int m = CalcCore(crunch, ix,iy, xC,yC);
+               m = m > 0 ? crunch - m : 0;
+               if( m ) m += animationFrame;
+
+               uchar4 color;
+               color.x = m * colors.x;
+               color.y = m * colors.y;
+               color.z = m * colors.z;
+               color.w = 0;
+
+               int frame1 = frame+1, frame2 = frame1/2;
+               color.x = (pixel.x * frame + color.x + frame2) / frame1;
+               color.y = (pixel.y * frame + color.y + frame2) / frame1;
+               color.z = (pixel.z * frame + color.z + frame2) / frame1;
+               dst[pi] = color; // Output the pixel
+       }
+}
+
+
+void MandelCuda::Run(unsigned char *data, unsigned int size, int is_julia, int crunch,
+               double x_off, double y_off, double x_julia, double y_julia, double scale,
+               uchar4 colors, int pass, int animationFrame)
+{
+       if( numSMs < 0 ) return;
+       checkCudaErrors(cudaMemcpy(pbo_mem, data, size, cudaMemcpyHostToDevice));
+       dim3 threads(BLOCKDIM_X, BLOCKDIM_Y);
+       dim3 grid(iDivUp(pbo_w, BLOCKDIM_X), iDivUp(pbo_h, BLOCKDIM_Y));
+       Calc<float><<<numSMs, threads>>>((uchar4 *)pbo_mem, pbo_w, pbo_h,
+                       is_julia, crunch, grid.x, grid.x*grid.y,
+                       float(x_off), float(y_off), float(x_julia), float(y_julia), float(scale),
+                       colors, pass, animationFrame);
+       checkCudaErrors(cudaMemcpy(data, pbo_mem, size, cudaMemcpyDeviceToHost));
+}
+
diff --git a/cinelerra-5.1/plugins/mandelcuda/mandelcuda.h b/cinelerra-5.1/plugins/mandelcuda/mandelcuda.h
new file mode 100644 (file)
index 0000000..3fc9c48
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __MANDELCUDA_CUH__
+#define __MANDELCUDA_CUH__
+
+class MandelCuda
+{
+public:
+       MandelCuda();
+       ~MandelCuda();
+
+       void init_dev();
+       void Run(unsigned char *data, unsigned int size, int is_julia, int crunch,
+               double x, double y, double jx, double jy, double scale,
+               uchar4 color, int pass, int animationFrame);
+       void init(int pbo, int pw, int ph);
+       void finish();
+
+       int version, numSMs;
+       int pbo_id, pbo_w, pbo_h;
+       struct cudaGraphicsResource *cuda_pbo;
+       void *pbo_mem;
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/nbodycuda/.swp b/cinelerra-5.1/plugins/nbodycuda/.swp
new file mode 100644 (file)
index 0000000..5d9b1b9
Binary files /dev/null and b/cinelerra-5.1/plugins/nbodycuda/.swp differ
diff --git a/cinelerra-5.1/plugins/nbodycuda/Makefile b/cinelerra-5.1/plugins/nbodycuda/Makefile
new file mode 100644 (file)
index 0000000..a99f748
--- /dev/null
@@ -0,0 +1,20 @@
+TOPDIR?=../..
+include $(TOPDIR)/plugin_defs
+include $(TOPDIR)/plugin_cuda
+
+PLUGIN = nbodycuda
+
+OBJS := \
+       $(OBJDIR)/nbody.o \
+       $(OBJDIR)/nbodywindow.o \
+       $(OBJDIR)/nbodycuda.o \
+       $(OBJDIR)/bodysys.o \
+       $(OBJDIR)/renders.o \
+
+include $(TOPDIR)/plugin_config
+
+$(OBJDIR)/nbody.o: nbody.C  nbody.h 
+$(OBJDIR)/nbodywindow.o: nbodywindow.C  nbodywindow.h
+$(OBJDIR)/nbodycuda.o: nbodycuda.cu  nbodycuda.h 
+$(OBJDIR)/bodysys.o: bodysys.cu
+$(OBJDIR)/renders.o: renders.C
diff --git a/cinelerra-5.1/plugins/nbodycuda/bodysys.cu b/cinelerra-5.1/plugins/nbodycuda/bodysys.cu
new file mode 100644 (file)
index 0000000..76c997b
--- /dev/null
@@ -0,0 +1 @@
+#include "5_Simulations/nbody/bodysystemcuda.cu"
diff --git a/cinelerra-5.1/plugins/nbodycuda/nbody.C b/cinelerra-5.1/plugins/nbodycuda/nbody.C
new file mode 100644 (file)
index 0000000..ae15e64
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glext.h>
+
+#include "clip.h"
+#include "filexml.h"
+#include "language.h"
+#include "mutex.h"
+
+#include "cwindow.h"
+#include "cwindowgui.h"
+#include "mwindow.h"
+#include "pluginserver.h"
+#include "playback3d.h"
+
+#include "nbody.h"
+#include "nbodycuda.h"
+#include "nbodywindow.h"
+
+
+static struct N_BodyParams demoParams[] = {
+       { 0.016f, 1.54f, 8.0f,      0.1f, 1.0f, 1.0f,     0, -2, -100},
+       { 0.016f, 0.68f, 20.0f,     0.1f, 1.0f, 0.8f,     0, -2, -30},
+       { 0.0006f, 0.16f, 1000.0f,  1.0f, 1.0f, 0.07f,    0, 0, -1.5f},
+       { 0.0006f, 0.16f, 1000.0f,  1.0f, 1.0f, 0.07f,    0, 0, -1.5f},
+       { 0.0019f, 0.32f, 276.0f,   1.0f, 1.0f, 0.07f,    0, 0, -5},
+       { 0.0016f, 0.32f, 272.0f,   0.145f, 1.0f, 0.08f,  0, 0, -5},
+       { 0.0160f, 6.04f, 0.0f,     1.0f, 1.0f, 0.76f,    0, 0, -50},
+};
+const int N_BodyParams::num_demos = sizeof(demoParams)/sizeof(*demoParams);
+
+
+REGISTER_PLUGIN(N_BodyMain)
+
+void N_BodyConfig::reset(int i)
+{
+       *(N_BodyParams*)this = demoParams[i];
+       trans[0] = trans_lag[0] = m_x;
+       trans[1] = trans_lag[1] = m_y;
+       trans[2] = trans_lag[2] = m_z;
+       rot[0] = rot_lag[0] = 0;
+       rot[1] = rot_lag[1] = 0;
+       rot[2] = rot_lag[2] = 0;
+       mode = ParticleRenderer::PARTICLE_SPRITES_COLOR;
+       numBodies = 4096;
+       inertia = 0.1;
+}
+
+N_BodyConfig::N_BodyConfig()
+{
+       reset();
+}
+
+int N_BodyConfig::equivalent(N_BodyConfig &that)
+{
+       return m_timestep == that.m_timestep &&
+               m_clusterScale == that.m_clusterScale &&
+               m_velocityScale == that.m_velocityScale &&
+               m_softening == that. m_softening &&
+               m_damping == that.m_damping &&
+               m_pointSize == that.m_pointSize &&
+               m_x == that.m_x &&
+               m_y == that.m_y &&
+               m_z == that.m_z &&
+               trans[0] == that.trans[0] &&
+               trans[1] == that.trans[1] &&
+               trans[2] == that.trans[2] &&
+               trans_lag[0] == that.trans_lag[0] &&
+               trans_lag[1] == that.trans_lag[1] &&
+               trans_lag[2] == that.trans_lag[2] &&
+               rot[0] == that.rot[0] &&
+               rot[1] == that.rot[1] &&
+               rot[2] == that.rot[2] &&
+               rot_lag[0] == that.rot_lag[0] &&
+               rot_lag[1] == that.rot_lag[1] &&
+               rot_lag[2] == that.rot_lag[2] &&
+               inertia == that.inertia &&
+               numBodies == that.numBodies;
+       return 1;
+}
+
+void N_BodyConfig::copy_from(N_BodyConfig &that)
+{
+       m_timestep = that.m_timestep;
+       m_clusterScale = that.m_clusterScale;
+       m_velocityScale = that.m_velocityScale;
+       m_softening = that. m_softening;
+       m_damping = that.m_damping;
+       m_pointSize = that.m_pointSize;
+       m_x = that.m_x;
+       m_y = that.m_y;
+       m_z = that.m_z;
+       trans[0] = that.trans[0];
+       trans[1] = that.trans[1];
+       trans[2] = that.trans[2];
+       trans_lag[0] = that.trans_lag[0];
+       trans_lag[1] = that.trans_lag[1];
+       trans_lag[2] = that.trans_lag[2];
+       rot[0] = that.rot[0];
+       rot[1] = that.rot[1];
+       rot[2] = that.rot[2];
+       rot_lag[0] = that.rot_lag[0];
+       rot_lag[1] = that.rot_lag[1];
+       rot_lag[2] = that.rot_lag[2];
+       inertia = that.inertia;
+       numBodies = that.numBodies;
+}
+
+void N_BodyConfig::interpolate( N_BodyConfig &prev, N_BodyConfig &next, 
+       long prev_frame, long next_frame, long current_frame)
+{
+       copy_from(next);
+}
+
+void N_BodyConfig::limits()
+{
+       if( m_damping < 0.001 ) m_damping = 0.001;
+       if( trans[2] < 0.005 ) trans[2] = 0.005;
+       int n = 1;
+       while( n < numBodies ) n <<= 1;
+       bclamp(n, 0x0010, 0x4000);
+       numBodies = n;
+       bclamp(inertia, 0.f,1.f);
+       bclamp(mode, 0, (int)ParticleRenderer::PARTICLE_NUM_MODES-1);
+}
+
+
+N_BodyMain::N_BodyMain(PluginServer *server)
+ : PluginVClient(server)
+{
+       cuda = 0;
+       blockSize = 256;
+
+       m_nbody = 0;
+       m_renderer = 0;
+       m_hPos = 0;
+       m_hVel = 0;
+       m_hColor = 0;
+
+       curr_position = -1;
+       new_position = -1;
+}
+
+N_BodyMain::~N_BodyMain()
+{
+       delete cuda;
+}
+
+void N_BodyMain::init(int numBodies)
+{
+       selectDemo(0);
+       delete m_nbody;      m_nbody = new N_BodySystem(numBodies, 1, blockSize);
+       int sz = numBodies*4;
+       delete [] m_hPos;    m_hPos = new float[sz];
+       delete [] m_hVel;    m_hVel = new float[sz];
+       delete [] m_hColor;  m_hColor = new float[sz];
+       delete m_renderer;   m_renderer = new ParticleRenderer;
+// config here
+       m_nbody->setSoftening(config.m_softening);
+       m_nbody->setDamping(config.m_damping);
+       reset(numBodies, NBODY_CONFIG_RANDOM);
+       resetRenderer();
+}
+
+void N_BodyMain::reset(int numBodies, NBodyConfig cfg)
+{
+       randomizeBodies(cfg, m_hPos, m_hVel, m_hColor,
+               config.m_clusterScale, config.m_velocityScale,
+               numBodies, true);
+       setArrays(m_hPos, m_hVel);
+}
+
+void N_BodyMain::resetRenderer()
+{
+       float color[4] = { 1.0f, 0.6f, 0.3f, 1.0f};
+       m_renderer->setBaseColor(color);
+       m_renderer->setColors(m_hColor, m_nbody->getNumBodies());
+       m_renderer->setSpriteSize(config.m_pointSize);
+}
+
+void N_BodyMain::selectDemo(int index)
+{
+       config.reset(index);
+}
+
+void N_BodyMain::finalize()
+{
+       delete [] m_hPos;    m_hPos = 0;
+       delete [] m_hVel;    m_hVel = 0;
+       delete [] m_hColor;  m_hColor = 0;
+       delete m_nbody;      m_nbody = 0;
+       delete m_renderer;   m_renderer = 0;
+}
+
+void N_BodyMain::draw()
+{
+       cuda->draw_event();
+       glClearColor(0.,0.,0.,1.);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       glColor4f(1.,1.,1.,1.);
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       float inertia = config.inertia;
+       for( int c=0; c<3; ++c ) {
+               config.trans_lag[c] += (config.trans[c] - config.trans_lag[c]) * inertia;
+               config.rot_lag[c] += (config.rot[c] - config.rot_lag[c]) * inertia;
+       }
+
+       glTranslatef(config.trans_lag[0], config.trans_lag[1], config.trans_lag[2]);
+       glRotatef(config.rot_lag[0], 1.0, 0.0, 0.0);
+       glRotatef(config.rot_lag[1], 0.0, 1.0, 0.0);
+       glDisable(GL_TEXTURE_2D);
+       display();
+}
+
+
+const char* N_BodyMain::plugin_title() { return N_("N_Body"); }
+int N_BodyMain::is_realtime() { return 1; }
+int N_BodyMain::is_synthesis() { return 1; }
+
+NEW_WINDOW_MACRO(N_BodyMain, N_BodyWindow);
+LOAD_CONFIGURATION_MACRO(N_BodyMain, N_BodyConfig)
+
+void N_BodyMain::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+
+// cause data to be stored directly in text
+       output.set_shared_output(keyframe->xbuf);
+       output.tag.set_title("NBODYCUDA");
+       output.tag.set_property("TIMESTEP", config.m_timestep);
+       output.tag.set_property("CLUSTER_SCALE", config.m_clusterScale);
+       output.tag.set_property("VELOCITY_SCALE", config.m_velocityScale);
+       output.tag.set_property("SOFTENING", config.m_softening);
+       output.tag.set_property("DAMPING", config.m_damping);
+       output.tag.set_property("POINT_SIZE", config.m_pointSize);
+       output.tag.set_property("X", config.m_x);
+       output.tag.set_property("Y", config.m_y);
+       output.tag.set_property("Z", config.m_z);
+       output.tag.set_property("TRANS_X",config.trans[0]);
+       output.tag.set_property("TRANS_Y",config.trans[1]);
+       output.tag.set_property("TRANS_Z",config.trans[2]);
+       output.tag.set_property("TRANS_LAG_X",config.trans_lag[0]);
+       output.tag.set_property("TRANS_LAG_Y",config.trans_lag[1]);
+       output.tag.set_property("TRANS_LAG_Z",config.trans_lag[2]);
+       output.tag.set_property("ROT_X",config.rot[0]);
+       output.tag.set_property("ROT_Y",config.rot[1]);
+       output.tag.set_property("ROT_Z",config.rot[2]);
+       output.tag.set_property("ROT_LAG_X",config.rot_lag[0]);
+       output.tag.set_property("ROT_LAG_Y",config.rot_lag[1]);
+       output.tag.set_property("ROT_LAG_Z",config.rot_lag[2]);
+       output.tag.set_property("INERTIA", config.inertia);
+       output.tag.set_property("MODE", config.mode);
+       output.tag.set_property("NUM_BODIES", config.numBodies);
+       output.append_tag();
+       output.append_newline();
+       output.tag.set_title("/NBODYCUDA");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+}
+
+void N_BodyMain::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+       input.set_shared_input(keyframe->xbuf);
+
+       int result = 0;
+       while( !(result = input.read_tag()) ) {
+               if( input.tag.title_is("NBODYCUDA") ) {
+                       config.m_timestep = input.tag.get_property("TIMESTEP", config.m_timestep);
+                       config.m_clusterScale = input.tag.get_property("CLUSTER_SCALE", config.m_clusterScale);
+                       config.m_velocityScale = input.tag.get_property("VELOCITY_SCALE", config.m_velocityScale);
+                       config.m_softening = input.tag.get_property("SOFTENING", config.m_softening);
+                       config.m_damping = input.tag.get_property("DAMPING", config.m_damping);
+                       config.m_pointSize = input.tag.get_property("POINT_SIZE", config.m_pointSize);
+                       config.m_x = input.tag.get_property("X", config.m_x);
+                       config.m_y = input.tag.get_property("Y", config.m_y);
+                       config.m_z = input.tag.get_property("Z", config.m_z);
+                       config.trans[0] = input.tag.get_property("TRANS_X", config.trans[0]);
+                       config.trans[1] = input.tag.get_property("TRANS_Y", config.trans[1]);
+                       config.trans[2] = input.tag.get_property("TRANS_Z", config.trans[2]);
+                       config.trans_lag[0] = input.tag.get_property("TRANS_LAG_X", config.trans_lag[0]);
+                       config.trans_lag[1] = input.tag.get_property("TRANS_LAG_Y", config.trans_lag[1]);
+                       config.trans_lag[2] = input.tag.get_property("TRANS_LAG_Z", config.trans_lag[2]);
+                       config.rot[0] = input.tag.get_property("ROT_X", config.rot[0]);
+                       config.rot[1] = input.tag.get_property("ROT_Y", config.rot[1]);
+                       config.rot[2] = input.tag.get_property("ROT_Z", config.rot[2]);
+                       config.rot_lag[0] = input.tag.get_property("ROT_LAG_X", config.rot_lag[0]);
+                       config.rot_lag[1] = input.tag.get_property("ROT_LAG_Y", config.rot_lag[1]);
+                       config.rot_lag[2] = input.tag.get_property("ROT_LAG_Z", config.rot_lag[2]);
+                       config.inertia = input.tag.get_property("INERTIA", config.inertia);
+                       config.mode = input.tag.get_property("MODE", config.mode);
+                       config.numBodies = input.tag.get_property("NUM_BODIES", config.numBodies);
+               }
+       }
+       config.limits();
+}
+
+void N_BodyMain::update_gui()
+{
+       if( !thread ) return;
+       if( !load_configuration() ) return;
+       thread->window->lock_window("N_BodyMain::update_gui");
+       N_BodyWindow *window = (N_BodyWindow*)thread->window;
+       window->update_gui();
+       window->flush();
+       window->unlock_window();
+}
+
+int N_BodyMain::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
+{
+
+       //int need_reconfigure =
+       load_configuration();
+       new_position = start_position;
+       output = get_output(0);
+       color_model = output->get_color_model();
+       if( get_use_opengl() )
+               return run_opengl();
+// always use_opengl
+       Canvas *canvas = server->mwindow->cwindow->gui->canvas;
+       return server->mwindow->playback_3d->run_plugin(canvas, this);
+}
+
+// cuda
+
+N_BodyCuda::N_BodyCuda()
+{
+       version = 0;
+       numSMs = 0;
+}
+N_BodyCuda::~N_BodyCuda()
+{
+}
+
+// opengl from here down
+
+void N_BodyMain::init_cuda()
+{
+       if( !cuda ) {
+               cuda = new N_BodyCuda();
+               cuda->init_dev();
+       }
+       cuda->init();
+}
+void N_BodyMain::finish_cuda()
+{
+       cuda->finish();
+}
+
+int N_BodyMain::handle_opengl()
+{
+       output->enable_opengl();
+       output->init_screen();
+       if( !m_nbody || get_source_position() == 0 ||
+           (int)m_nbody->getNumBodies() != config.numBodies )
+               init(config.numBodies);
+       init_cuda();
+       if( curr_position != new_position ) {
+               updateSimulation();
+               curr_position = new_position;
+       }
+       draw();
+       finish_cuda();
+       output->set_opengl_state(VFrame::SCREEN);
+       if( !get_use_opengl() ) // rendering
+               output->screen_to_ram();
+       return 0;
+}
+
diff --git a/cinelerra-5.1/plugins/nbodycuda/nbody.h b/cinelerra-5.1/plugins/nbodycuda/nbody.h
new file mode 100644 (file)
index 0000000..3d97e6a
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef NBODYCUDA_H
+#define NBODYCUDA_H
+
+#include "pluginvclient.h"
+
+#include <cuda_runtime.h>
+#include <cuda_gl_interop.h>
+#include <helper_cuda.h>
+#include <helper_functions.h>
+
+#include <5_Simulations/nbody/bodysystemcuda.h>
+#include <5_Simulations/nbody/render_particles.h>
+#include "nbodycuda.h"
+
+class N_BodyConfig;
+class N_BodyMain;
+class N_BodyCuda;
+
+
+class N_BodyParams
+{
+public: 
+       float m_timestep, m_clusterScale, m_velocityScale;
+       float m_softening, m_damping, m_pointSize;
+       float m_x, m_y, m_z;
+       static const int num_demos;
+};
+class N_BodyCamera
+{
+public:
+       float trans[3];
+       float rot[3];
+       float trans_lag[3];
+       float rot_lag[3];
+};
+
+class N_BodyConfig : public N_BodyParams, public N_BodyCamera
+{
+public:
+       N_BodyConfig();
+       void reset(int i=0);
+       int mode;
+       float inertia;
+       int numBodies;
+
+       int equivalent(N_BodyConfig &that);
+       void copy_from(N_BodyConfig &that);
+       void interpolate(N_BodyConfig &prev, N_BodyConfig &next, 
+               long prev_frame, long next_frame, long current_frame);
+       void limits();
+};
+
+class N_BodyMain : public PluginVClient
+{
+public:
+       N_BodyMain(PluginServer *server);
+       ~N_BodyMain();
+       PLUGIN_CLASS_MEMBERS2(N_BodyConfig)
+       int is_realtime();
+       int is_synthesis();
+       void update_gui();
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+       int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
+       void initData();
+       void reset();
+       int handle_opengl();
+
+       int color_model, pass;
+       VFrame *output;
+       N_BodyCuda *cuda;
+
+       void init_cuda();
+       void finish_cuda();
+
+       BodySystem<float> *m_nbody;
+       ParticleRenderer *m_renderer;
+
+       float *m_hPos, *m_hVel;
+       float *m_hColor;
+
+       char deviceName[100];
+       enum { M_VIEW = 0, M_MOVE };
+       int blockSize;
+
+       int activeDemo;
+       int64_t curr_position, new_position;
+
+       void init(int numBodies);
+       void reset(int numBodies, NBodyConfig cfg);
+       void resetRenderer();
+       void selectDemo(int index);
+       void updateParams() {
+               m_nbody->setSoftening(config.m_softening);
+               m_nbody->setDamping(config.m_damping);
+       }
+
+       void updateSimulation() {
+               m_nbody->update(config.m_timestep);
+       }
+
+       void display() { // display particles
+               m_renderer->setSpriteSize(config.m_pointSize);
+               m_renderer->setPBO(m_nbody->getCurrentReadBuffer(),
+                       m_nbody->getNumBodies(), (sizeof(float) > 4));
+               m_renderer->display((ParticleRenderer::DisplayMode)config.mode);
+       }
+       void draw();
+
+       void getArrays(float *pos, float *vel) {
+               float *_pos = m_nbody->getArray(BODYSYSTEM_POSITION);
+               float *_vel = m_nbody->getArray(BODYSYSTEM_VELOCITY);
+               memcpy(pos, _pos, m_nbody->getNumBodies() * 4 * sizeof(float));
+               memcpy(vel, _vel, m_nbody->getNumBodies() * 4 * sizeof(float));
+       }
+
+       void setArrays(const float *pos, const float *vel) {
+               int sz = config.numBodies * 4 * sizeof(float);
+               if (pos != m_hPos)
+                       memcpy(m_hPos, pos, sz);
+               if (vel != m_hVel)
+                       memcpy(m_hVel, vel, sz);
+               m_nbody->setArray(BODYSYSTEM_POSITION, m_hPos);
+               m_nbody->setArray(BODYSYSTEM_VELOCITY, m_hVel);
+               resetRenderer();
+       }
+
+       void finalize();
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/nbodycuda/nbodycuda.cu b/cinelerra-5.1/plugins/nbodycuda/nbodycuda.cu
new file mode 100644 (file)
index 0000000..b82c79f
--- /dev/null
@@ -0,0 +1,35 @@
+#include <cuda_runtime.h>
+#include <cuda_gl_interop.h>
+#include "helper_cuda.h"
+#include "helper_gl.h"
+
+#include "nbodycuda.h"
+
+void N_BodyCuda::init()
+{
+       checkCudaErrors(cudaEventCreate(&startEvent));
+       checkCudaErrors(cudaEventCreate(&stopEvent));
+       checkCudaErrors(cudaEventCreate(&hostMemSyncEvent));
+}
+
+void N_BodyCuda::init_dev()
+{
+//     int dev_id = findCudaDevice(argc, (const char **)argv);
+       int dev_id = gpuGetMaxGflopsDeviceId();
+       checkCudaErrors(cudaSetDevice(dev_id));
+       cudaDeviceProp deviceProp;
+       checkCudaErrors(cudaGetDeviceProperties(&deviceProp, dev_id));
+printf("GPU Device %d: \"%s\" with compute capability %d.%d\n",
+  dev_id, deviceProp.name, deviceProp.major, deviceProp.minor);
+       version = deviceProp.major * 10 + deviceProp.minor;
+       numSMs = deviceProp.multiProcessorCount;
+}
+
+
+void N_BodyCuda::finish()
+{
+       checkCudaErrors(cudaEventDestroy(startEvent));
+       checkCudaErrors(cudaEventDestroy(stopEvent));
+       checkCudaErrors(cudaEventDestroy(hostMemSyncEvent));
+}
+
diff --git a/cinelerra-5.1/plugins/nbodycuda/nbodycuda.h b/cinelerra-5.1/plugins/nbodycuda/nbodycuda.h
new file mode 100644 (file)
index 0000000..b1a9cb0
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __NBODYCUDA_H__
+#define __NBODYCUDA_H__
+
+#include <vector>
+template <typename T>
+void read_tipsy_file(std::vector<T> &bodyPositions, std::vector<T> &bodyVelocities,
+               std::vector<int> &bodiesIDs, const std::string &fileName,
+               int &NTotal, int &NFirst, int &NSecond, int &NThird)
+{
+}
+
+#include <5_Simulations/nbody/bodysystem.h>
+#include <5_Simulations/nbody/bodysystemcuda.h>
+
+class N_BodyCuda
+{
+public:
+       N_BodyCuda();
+       ~N_BodyCuda();
+       void init_dev();
+       void init();
+       void finish();
+
+       int version, numSMs;
+
+       cudaEvent_t startEvent, stopEvent, hostMemSyncEvent;
+       void start_event() { cudaEventRecord(startEvent, 0); }
+       void stop_event() { cudaEventRecord(stopEvent, 0); }
+       void draw_event() { cudaEventRecord(hostMemSyncEvent, 0); }
+};
+
+class N_BodySystem : public BodySystemCUDA<float>
+{
+public:
+       N_BodySystem(int n_bodies, int n_devs, int blockSize)
+        : BodySystemCUDA<float>(n_bodies, n_devs, blockSize, 1) {}
+       N_BodySystem() {};
+       virtual void loadTipsyFile(const std::string &filename) {}
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/nbodycuda/nbodywindow.C b/cinelerra-5.1/plugins/nbodycuda/nbodywindow.C
new file mode 100644 (file)
index 0000000..c5c7766
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "cwindow.h"
+#include "cwindowgui.h"
+#include "language.h"
+#include "nbody.h"
+#include "nbodywindow.h"
+#include "mwindow.h"
+#include "mwindowgui.h"
+#include "pluginserver.h"
+#include "theme.h"
+
+static const char *display_modes[] = {
+       N_("point"),
+       N_("sprite"),
+       N_("color"),
+};
+static const int num_display_modes = sizeof(display_modes)/sizeof(*display_modes);
+
+N_BodyWindow::N_BodyWindow(N_BodyMain *plugin)
+ : PluginClientWindow(plugin, 240, 200, 240, 200, 0)
+{
+       this->plugin = plugin; 
+       press_x = press_y = 0;
+       button_no = 0;
+       pending_config = 0;
+}
+
+N_BodyWindow::~N_BodyWindow()
+{
+}
+
+void N_BodyWindow::create_objects()
+{
+       int x = 10, y = 10, pad = 5;
+       int x1 = 100;
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x,y, _("NBody"), MEDIUMFONT, YELLOW));
+       y += title->get_h() + 2*pad;
+       add_subwindow(title = new BC_Title(x,y, _("set demo:")));
+       set_demo = new N_BodySetDemo(this, x1,y, "0");
+       set_demo->create_objects();
+       y += set_demo->get_h() + pad;
+       add_subwindow(title = new BC_Title(x,y, _("draw mode:")));
+       set_mode = new N_BodySetMode(this, x1,y, _(display_modes[plugin->config.mode]));
+       set_mode->create_objects();
+       y += set_mode->get_h() + pad;
+       add_subwindow(title = new BC_Title(x,y, _("numBodies:")));
+       char text[BCSTRLEN];
+       sprintf(text, "%d", plugin->config.numBodies);
+       num_bodies = new N_BodyNumBodies(this, x1,y, text);
+       num_bodies->create_objects();
+       y += num_bodies->get_h() + pad;
+       add_subwindow(drag = new N_BodyDrag(this, x, y));
+       y += drag->get_h() + pad;
+       add_subwindow(reset = new N_BodyReset(this, x, y));
+       show_window();
+}
+
+void N_BodyWindow::update_gui()
+{
+       set_mode->update(_(display_modes[plugin->config.mode]));
+       char text[BCSTRLEN];
+       sprintf(text, "%d", plugin->config.numBodies);
+       num_bodies->update(text);
+}
+
+
+void N_BodyWindow::send_configure_change()
+{
+       pending_config = 0;
+       plugin->send_configure_change();
+}
+
+int N_BodyWindow::grab_event(XEvent *event)
+{
+       int ret = do_grab_event(event);
+       if( pending_config && !grab_event_count() )
+               send_configure_change();
+       return ret;
+}
+
+int N_BodyWindow::do_grab_event(XEvent *event)
+{
+       switch( event->type ) {
+       case ButtonPress: break;
+       case ButtonRelease: break;
+       case MotionNotify: break;
+       default:
+               return 0;
+       }
+
+       MWindow *mwindow = plugin->server->mwindow;
+       CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
+       CWindowCanvas *canvas = cwindow_gui->canvas;
+       int cursor_x, cursor_y;
+       cwindow_gui->get_relative_cursor(cursor_x, cursor_y);
+       cursor_x -= canvas->view_x;
+       cursor_y -= canvas->view_y;
+       float output_x = cursor_x, output_y = cursor_y;
+       canvas->canvas_to_output(mwindow->edl, 0, output_x, output_y);
+
+       if( !button_no ) {
+               if( cursor_x < 0 || cursor_x >= canvas->view_w ||
+                   cursor_y < 0 || cursor_y >= canvas->view_h )
+                       return 0;
+       }
+
+       switch( event->type ) {
+       case ButtonPress:
+               if( button_no ) return 0;
+               press_x = output_x;  press_y = output_y;
+               button_no = event->xbutton.button;
+               break;
+       case ButtonRelease:
+               if( !button_no ) return 0;
+               button_no = 0;
+               return 1;
+       case MotionNotify: {
+               if( !button_no ) return 0;
+               N_BodyConfig &config = plugin->config;
+               double dx = (double)(press_x - output_x);
+               double dy = (double)(press_y - output_y);
+               press_x = output_x;  press_y = output_y;
+               switch( button_no ) {
+               case LEFT_BUTTON: {
+                       config.trans[0] += dx / 5.0f;
+                       config.trans[1] -= dy / 5.0f;
+                       break; }
+               case MIDDLE_BUTTON: {
+                       double s = 0.5f * fabs(config.trans[2]);
+                       if( s < 0.1 ) s = 0.1;
+                       config.trans[2] += (dy / 100.0f) * s;
+                       break; }
+               case RIGHT_BUTTON: {
+                       config.rot[0] += dy / 5.0f;
+                       config.rot[1] += dx / 5.0f;
+                       break; }
+               }
+               pending_config = 1;
+               break; }
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+void N_BodyWindow::done_event(int result)
+{
+       ungrab(client->server->mwindow->cwindow->gui);
+}
+
+N_BodyDrag::N_BodyDrag(N_BodyWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, 0, _("Drag"))
+{
+       this->gui = gui;
+}
+int N_BodyDrag::handle_event()
+{
+       CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui;
+       int value = get_value();
+       if( value ) {
+               if( !gui->grab(cwindow_gui) ) {
+                       update(value = 0);
+                       flicker(10,50);
+               }
+       }
+       else
+               gui->ungrab(cwindow_gui);
+       return 1;
+}
+
+N_BodySetMode::N_BodySetMode(N_BodyWindow *gui, int x, int y, const char *text)
+ : BC_PopupTextBox(gui, 0, text, x, y, 100, 160)
+{
+       this->gui = gui;
+}
+
+void N_BodySetMode::create_objects()
+{
+       BC_PopupTextBox::create_objects();
+       for( int i=0; i<num_display_modes; ++i )
+               mode_items.append(new BC_ListBoxItem(_(display_modes[i])));
+       update_list(&mode_items);
+}
+
+int N_BodySetMode::handle_event()
+{
+       N_BodyMain *plugin = gui->plugin;
+       plugin->config.mode = get_number();
+       plugin->send_configure_change();
+       return 1;
+}
+
+
+N_BodySetDemo::N_BodySetDemo(N_BodyWindow *gui, int x, int y, const char *text)
+ : BC_PopupTextBox(gui, 0, text, x, y, 100, 160)
+{
+       this->gui = gui;
+}
+
+void N_BodySetDemo::create_objects()
+{
+       BC_PopupTextBox::create_objects();
+       for( int i=0; i<N_BodyParams::num_demos; ++i ) {
+               char text[BCSTRLEN];  sprintf(text,"%d",i);
+               demo_items.append(new BC_ListBoxItem(text));
+       }
+       update_list(&demo_items);
+}
+
+int N_BodySetDemo::handle_event()
+{
+       N_BodyMain *plugin = gui->plugin;
+       plugin->selectDemo(get_number());
+       gui->update_gui();
+       plugin->send_configure_change();
+       return 1;
+}
+
+N_BodyNumBodies::N_BodyNumBodies(N_BodyWindow *gui, int x, int y, const char *text)
+ : BC_PopupTextBox(gui, 0, text, x, y, 100, 160)
+{
+       this->gui = gui;
+}
+
+void N_BodyNumBodies::create_objects()
+{
+       BC_PopupTextBox::create_objects();
+       for( int i=0; i<8; ++i ) {
+               char text[BCSTRLEN];  sprintf(text,"%d",1<<(i+6));
+               num_body_items.append(new BC_ListBoxItem(text));
+       }
+       update_list(&num_body_items);
+}
+
+int N_BodyNumBodies::handle_event()
+{
+       N_BodyMain *plugin = gui->plugin;
+       int i = get_number();
+       int n = i >= 0 ? (1 << (i+6)) : atoi(get_text());
+       bclamp(n, 0x10,0x4000);
+       plugin->config.numBodies = n;
+       plugin->send_configure_change();
+       return 1;
+}
+
+N_BodyReset::N_BodyReset(N_BodyWindow *gui, int x, int y)
+ : BC_GenericButton(x, y, _("Reset"))
+{
+       this->gui = gui;
+}
+N_BodyReset::~N_BodyReset()
+{
+}
+
+int N_BodyReset::handle_event()
+{
+       N_BodyMain *plugin = gui->plugin;
+       plugin->config.reset();
+       gui->update_gui();
+       gui->send_configure_change();
+       return 1;
+}
+
diff --git a/cinelerra-5.1/plugins/nbodycuda/nbodywindow.h b/cinelerra-5.1/plugins/nbodycuda/nbodywindow.h
new file mode 100644 (file)
index 0000000..b4b04c0
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2014 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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 2 of the License, or
+ * (at your option) 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.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef NBODYCUDAWINDOW_H
+#define NBODYCUDAWINDOW_H
+
+
+#include "guicast.h"
+#include "nbody.h"
+
+class N_BodyDrag;
+class N_BodyReset;
+class NBodyModeItems;
+class N_BodySetMode;
+class NBodyDemoItems;
+class N_BodySetDemo;
+class NBodyNumBodyItems;
+class N_BodyNumBodies;
+class N_BodyWindow;
+
+class N_BodyDrag : public BC_CheckBox
+{
+public:
+       N_BodyDrag(N_BodyWindow *gui, int x, int y);
+
+       int handle_event();
+       N_BodyWindow *gui;
+};
+
+class N_BodyReset : public BC_GenericButton
+{
+public:
+       N_BodyReset(N_BodyWindow *gui, int x, int y);
+       ~N_BodyReset();
+       int handle_event();
+
+       N_BodyWindow *gui;
+};
+
+class NBodyModeItems : public ArrayList<BC_ListBoxItem*>
+{
+public:
+       NBodyModeItems() {} 
+       ~NBodyModeItems() { remove_all_objects(); }
+};
+
+class N_BodySetMode : public BC_PopupTextBox
+{
+public:
+       N_BodySetMode(N_BodyWindow *gui, int x, int y, const char *text);
+       void create_objects();
+       int handle_event();
+
+       N_BodyWindow *gui;
+       NBodyModeItems mode_items;
+};
+
+class NBodyDemoItems : public ArrayList<BC_ListBoxItem*>
+{
+public:
+       NBodyDemoItems() {} 
+       ~NBodyDemoItems() { remove_all_objects(); }
+};
+
+class N_BodySetDemo : public BC_PopupTextBox
+{
+public:
+       N_BodySetDemo(N_BodyWindow *gui, int x, int y, const char *text);
+       void create_objects();
+       int handle_event();
+
+       N_BodyWindow *gui;
+       NBodyDemoItems demo_items;
+};
+
+class NBodyNumBodyItems : public ArrayList<BC_ListBoxItem*>
+{
+public:
+       NBodyNumBodyItems() {} 
+       ~NBodyNumBodyItems() { remove_all_objects(); }
+};
+
+class N_BodyNumBodies : public BC_PopupTextBox
+{
+public:
+       N_BodyNumBodies(N_BodyWindow *gui, int x, int y, const char *text);
+       void create_objects();
+       int handle_event();
+
+       N_BodyWindow *gui;
+       NBodyNumBodyItems num_body_items;
+};
+
+
+class N_BodyWindow : public PluginClientWindow
+{
+public:
+       N_BodyWindow(N_BodyMain *plugin);
+       ~N_BodyWindow();
+
+       void create_objects();
+       void update_gui();
+
+       int grab_event(XEvent *event);
+       int do_grab_event(XEvent *event);
+       void done_event(int result);
+       void send_configure_change();
+
+       N_BodyMain *plugin;
+       N_BodySetMode *set_mode;
+       N_BodySetDemo *set_demo;
+       N_BodyNumBodies *num_bodies;
+       N_BodyDrag *drag;
+       N_BodyReset *reset;
+
+       int press_x, press_y;
+       int button_no, pending_config;
+};
+
+#endif
diff --git a/cinelerra-5.1/plugins/nbodycuda/renders.C b/cinelerra-5.1/plugins/nbodycuda/renders.C
new file mode 100644 (file)
index 0000000..82d669d
--- /dev/null
@@ -0,0 +1 @@
+#include "5_Simulations/nbody/render_particles.cpp"
index 2c658a22948b0c48c54a4ceef2ef8969d0863f5c..61188c4000c57a0e9d15c9522746fc3f63154325 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/cin_icon_rec.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/cin_icon_rec.png differ
index c693d1b1781b3e664cdaf5068900984589a778b1..525815bbdd9af8db233ee08edf3c66226e94332a 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/cin_icon_vwin.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/cin_icon_vwin.png differ
index 75af9274ff328caeac1909f53b95d8b3ed57dcc7..1384edc9ae232930b7c072fd2e10005c5ef92d87 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/heroine_icon.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/heroine_icon.png differ
index 63a3c45badc613f7fbb420fb534c07db553c3fb1..7215c03f9e0a37bb50de2f1e6f3d20e40772d245 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/in_checked.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/in_checked.png differ
index 759df58fb1606066593e49815a880d89ae62743c..9318fb7d7a305c0ed64e05d93f11c065e4d950ac 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/in_checkedhi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/in_checkedhi.png differ
index 9ad33eac3a078df17fe4d71eb8dcd21f4b78b075..62e0c9493640a90f890aa392648fc2fc4f825c7b 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/in_dn.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/in_dn.png differ
index c020c3360f80a4227a75bb3416917796c4fefd82..59d58aaf480506027e051b2a0520b58ffff214cd 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/in_hi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/in_hi.png differ
index 6bdccf327052b8cefb779a26ca37c6df9cb2b5cf..6a8bb8c37d1a40baec07a5360abf008373e3ef1a 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/in_up.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/in_up.png differ
index 960cfbc69366557b8e5d32e35741334b2288c279..9a99cc2eff43cefee4e61a458937a70ccfccdb71 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/inpoint.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/inpoint.png differ
index ada0e5b072bbc22d54fe667ff469c9f90c61a0b4..3b6016d317db1b0f232740bba6c255adea600099 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/label_checked.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/label_checked.png differ
index 43334e9a0ae53249247d025837131bb86ca4a436..1f7b260ffdcb9cc2e57e49c8066ee55485563231 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/label_checkedhi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/label_checkedhi.png differ
index d3c7ca8a5fd50107650e77f97e8821ed71a48614..11cc3e7a84bc522276326d90a4152a7426935699 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_dn.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_dn.png differ
index e7769c3b997745392546554e4ad55624904f8c46..f697b71bd68eb29d339e697f55ff3abd0f97426d 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_up.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_up.png differ
index c521b8c154f828a9cdbef853dc24c68de109ec95..7ae1f93d80f21f2b2ef31abc7c5ef61cd68cd58f 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_uphi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/labeltoggle_uphi.png differ
index b2289b00513547a72d3f354d78ce4aa404da9e6a..0f1eb065051b8323e72ebf0e20a9745f9af7a3b0 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/out_checked.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/out_checked.png differ
index d6a181fdeacf8f2baea17b1b3660c7f2b2e7d2f3..d3e551be35646e117e075308d665454b96dcc0f2 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/out_checkedhi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/out_checkedhi.png differ
index 983d99421eadec8578c471ff3ed2a316c907ea4d..62b714ec42d32661231fef1257bd8c17594de6de 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/out_dn.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/out_dn.png differ
index 2143e29daccdcc3b7f81bb01942779c41694c377..260bc41a5fc4137d5f60e91802f9aecfef2005ad 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/out_hi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/out_hi.png differ
index 4800f3b51baec099d8c7b5195f8177082eb5864e..718d0ce25dc149f83456bb9d2c007695c3bb7542 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/out_up.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/out_up.png differ
index 5b027021e2a9f7074fc52f25072c75467efc99a9..db68b7924beaf20793ec26dc48a5f3dc8e0dd23d 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/outpoint.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/outpoint.png differ
index 0a2989d3d1633975f64ae1541edd25b8386be7a1..0ad7f75db14c3af27f4bbc4b5741f292a1dd127f 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/pot_dn.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/pot_dn.png differ
index 0a00a5f749e027908dbaf63e966345425e53aab3..70902f725e968ed536d08e848f7dc0b90db7ece2 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/pot_hi.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/pot_hi.png differ
index ab98ced7ddfd0a3a1fd0d216837c2b319f8a4192..4517f244e691aa7f618ddd4dcb49ec0e142293cf 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_cakewalk/data/pot_up.png and b/cinelerra-5.1/plugins/theme_cakewalk/data/pot_up.png differ
index 046a560b44cbc6b28d662ff607ff47b6167ea4e3..acaf4efacd63f73daa047da170aac9d0d8cbf3b6 100644 (file)
@@ -113,6 +113,7 @@ ffmpeg.cfg_params= \
        --enable-pthreads --enable-gpl --disable-ffplay \
        $(if $(WANT_VAAPI),--enable-vaapi,--disable-vaapi) \
        $(if $(WANT_VDPAU),--enable-vdpau,--disable-vdpau) \
+       $(if $(WANT_NV), --enable-nvenc --enable-nvdec) \
        $(call if_pkg,twolame,--enable-libtwolame) \
        $(call if_pkg,openjpeg,--enable-libopenjpeg) \
        $(call if_pkg,lame,--enable-libmp3lame) \
@@ -125,6 +126,7 @@ ffmpeg.cfg_params= \
        $(call if_pkg,x264,--enable-libx264) \
        $(call if_pkg,x265,--enable-libx265) \
        --extra-cflags="\
+               $(if $(WANT_NV), $(inc_ffnvcodec)) \
                $(call inc_path,twolame,libtwolame) \
                $(call inc_path,lame,include) \
                $(call inc_path,libaom,usr/local/include) \
@@ -289,7 +291,9 @@ $(call rules,$(call std-build,djbfft))
 $(call rules,$(call std-build,audiofile))
 $(call rules,$(call std-build,encore))
 $(call rules,$(call std-build,esound,audiofile))
-$(call rules,$(call std-build,ffmpeg, twolame lame openjpeg opus libtheora x264 x265 libvpx libaom libwebp))
+$(call rules,$(call std-build,ffmpeg, twolame lame openjpeg opus \
+       libtheora x264 x265 libvpx libaom libwebp \
+       $(if $(WANT_NV), ffnvcodec)))
 $(call rules,$(call std-build,fftw))
 $(call rules,$(call std-build,flac,libogg))
 $(call rules,$(call std-build,giflib))
@@ -325,6 +329,7 @@ $(call rules,$(call std-build,sord, serd))
 $(call rules,$(call std-build,sratom, serd sord lv2))
 $(call rules,$(call std-build,lilv, lv2 sratom serd sord))
 $(call rules,$(call std-build,suil, lv2))
+$(call rules,$(call std-build,ffnvcodec))
 
 # specialize festival, multiple tarballs
 festival:
index b998f81423e7b39d596fefada66ee0e0255c3bfd..2b0c152b947b92175ff6e1a026a15d586059d642 100644 (file)
@@ -36,6 +36,7 @@ https://github.com/swh/ladspa/releases/tag/v0.4.17, plugin.org.uk
 https://archive.mozilla.org/pub/opus/opus-1.3.tar.gz
 https://github.com/webmproject/libwebp = libwebp-1.0.2
 https://github.com/mozilla/aom = libaom-v1.0.0
+git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
 
 https://gitlab.com/drobilla/lv2/-/archive/v1.16.0/lv2-v1.16.0.tar.gz
 http://download.drobilla.net/suil-0.10.2.tar.bz2
diff --git a/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz b/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz
new file mode 100644 (file)
index 0000000..00bc94a
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz differ