perf.data
*.dot
demo
+make_bundled_shaders
+bundled_shaders.cpp
effect_chain_test
compute_shader_test
gamma_compression_effect_test
# strive towards having a rock-stable ABI, but at least the soversion will increase
# whenever it breaks, so that you will not have silent failures, and distribution package
# management can run its course.
-movit_ltversion = 8:2:0
-movit_version = 1.6.2
+movit_ltversion = 8:5:0
+movit_version = 1.7.1
prefix = @prefix@
exec_prefix = @exec_prefix@
includedir = @includedir@
libdir = @libdir@
datarootdir = @datarootdir@
-datadir = @datadir@
top_builddir = @top_builddir@
with_demo_app = @with_demo_app@
with_benchmark = @with_benchmark@
# Unit tests.
TESTS=effect_chain_test fp16_test $(TESTED_INPUTS:=_test) $(TESTED_EFFECTS:=_test)
-LIB_OBJS=effect_util.o util.o effect.o effect_chain.o init.o resource_pool.o ycbcr.o $(INPUTS:=.o) $(EFFECTS:=.o)
+LIB_OBJS=effect_util.o util.o effect.o effect_chain.o init.o resource_pool.o ycbcr.o bundled_shaders.o $(INPUTS:=.o) $(EFFECTS:=.o)
# Default target:
all: libmovit.la $(TESTS)
$(TESTS): %: %.o $(TEST_OBJS) libmovit.la
$(LIBTOOL) --mode=link $(CXX) $(LDFLAGS) -o $@ $^ $(TEST_LDLIBS)
-OWN_OBJS=$(DEMO_OBJS) $(LIB_OBJS) $(OWN_TEST_OBJS) $(TESTS:=.o)
-OBJS=$(DEMO_OBJS) $(LIB_OBJS) $(TEST_OBJS) $(TESTS:=.o)
+OWN_OBJS=$(DEMO_OBJS) $(LIB_OBJS) $(OWN_TEST_OBJS) $(TESTS:=.o) make_bundled_shaders.o
+OBJS=$(DEMO_OBJS) $(LIB_OBJS) $(TEST_OBJS) $(TESTS:=.o) make_bundled_shaders.o
# A small demo program.
demo: libmovit.la $(DEMO_OBJS)
clean:
$(LIBTOOL) --mode=clean $(RM) demo $(TESTS) libmovit.la $(OBJS) $(OBJS:.o=.lo)
- $(RM) $(OBJS:.o=.gcno) $(OBJS:.o=.gcda) $(DEPS) step*.dot chain*.frag
+ $(LIBTOOL) --mode=clean $(RM) $(MAKE_BUNDLE_OBJS) $(MAKE_BUNDLE_OBJS:.o=.lo) make_bundled_shaders bundled_shaders.cpp
+ $(RM) $(OBJS:.o=.gcno) $(OBJS:.o=.gcda) $(MAKE_BUNDLE_OBJS:.o=.gcno) $(MAKE_BUNDLE_OBJS:.o=.gcda) $(DEPS) step*.dot chain*.frag
$(RM) -r movit.info coverage/ .libs/
distclean: clean
MISSING_SHADERS += fft_convolution_effect.frag fft_input.frag
SHADERS := $(filter-out $(MISSING_SHADERS),$(SHADERS))
+# A program to compile all the shaders into one bundle that we can link into the library.
+MAKE_BUNDLE_OBJS=make_bundled_shaders.o util.o init.o resource_pool.o
+make_bundled_shaders: $(MAKE_BUNDLE_OBJS)
+ $(LIBTOOL) --mode=link $(CXX) $(LDFLAGS) -o make_bundled_shaders $(MAKE_BUNDLE_OBJS) -lepoxy
+bundled_shaders.cpp: make_bundled_shaders $(SHADERS)
+ ./make_bundled_shaders $(SHADERS) > $@
+
install: libmovit.la
$(MKDIR) -p $(DESTDIR)$(libdir)/
$(LIBTOOL) --mode=install $(INSTALL) -m 0644 libmovit.la $(DESTDIR)$(libdir)/
$(MKDIR) -p $(DESTDIR)$(includedir)/movit/
$(INSTALL) -m 0644 $(HDRS) $(DESTDIR)$(includedir)/movit/
- $(MKDIR) -p $(DESTDIR)$(datadir)/movit/
- $(INSTALL) -m 0644 $(SHADERS) $(DESTDIR)$(datadir)/movit/
$(MKDIR) -p $(DESTDIR)$(libdir)/pkgconfig/
$(INSTALL) -m 644 movit.pc $(DESTDIR)$(libdir)/pkgconfig/
DISTDIR=movit-$(movit_version)
-OTHER_DIST_FILES=add.frag autogen.sh blue.frag configure.ac d65.h identity.frag invert_effect.frag Makefile.in mipmap_needing_effect.frag downscale2x.frag downscale2x.comp mirror.comp identity.comp movit.pc.in README NEWS test_util.h widgets.h
+OTHER_DIST_FILES=add.frag autogen.sh blue.frag configure.ac d65.h identity.frag invert_effect.frag Makefile.in mipmap_needing_effect.frag downscale2x.frag downscale2x.comp mirror.comp identity.comp movit.pc.in README NEWS test_util.h widgets.h bundled_shaders.h
dist:
$(MKDIR) $(DISTDIR)
+Movit 1.7.1, July 22nd, 2023
+
+ - Fix a bug when compiling in shaders, that could cause errors
+ with certain shader compilers. Reported by Stefano Rivera.
+
+
+Movit 1.7.0, July 15th, 2023
+
+ - Compile shaders into the library. It is now allowed to give ""
+ as the data directory, which will use the compiled-in shaders.
+ Most users should probably just do that.
+
+ - Use exact sRGB matrix values for COLORSPACE_sRGB.
+
+
+Movit 1.6.3, July 7th, 2019
+
+ - Various bugfixes.
+
+
Movit 1.6.2, March 18th, 2018
- Various bugfixes.
OK, you need
-* A C++11 compiler. GCC will do. (I haven't tried Windows, but it
+* A C++14 compiler. GCC will do. (I haven't tried Windows, but it
works fine on Linux and OS X, and Movit is not very POSIX-bound.)
* GNU Make.
* A GPU capable of running OpenGL 3.0 or newer. GLES3 (for mobile devices)
--- /dev/null
+#ifndef _MOVIT_BUNDLED_SHADERS_H
+#define _MOVIT_BUNDLED_SHADERS_H 1
+
+// Shader files that are compiled into the library.
+
+namespace movit {
+
+struct BundledShader {
+ const char *filename; // nullptr for end.
+ size_t offset; // Into shader_bundle.
+ size_t length;
+};
+extern BundledShader bundled_shaders[];
+extern const char *shader_bundle;
+
+} // namespace movit
+
+#endif // _MOVIT_BUNDLED_SHADERS_H
if (space == COLORSPACE_XYZ) {
return Matrix3d::Identity();
}
+ if (space == COLORSPACE_sRGB) {
+ // sRGB is not defined by the color primaries, but by concrete
+ // forward and inverse matrices that are rounded-off versions
+ // of the Rec. 709 color space (see
+ // https://photosauce.net/blog/post/what-makes-srgb-a-special-color-space).
+ // We're not compliant with the inverse matrix, since we'd be
+ // too accurate (sRGB is specified for 8-bit only); however,
+ // results should be very close in practice (and even closer to
+ // scRGB's inverse matrix, which is a higher-accuracy inversion of
+ // the same forward matrix).
+ return Matrix3d{
+ { 0.4124, 0.3576, 0.1805 },
+ { 0.2126, 0.7152, 0.0722 },
+ { 0.0193, 0.1192, 0.9505 }
+ };
+ }
double x_R, x_G, x_B;
double y_R, y_G, y_B;
switch (space) {
- case COLORSPACE_REC_709: // And sRGB.
+ case COLORSPACE_REC_709:
x_R = rec709_x_R; x_G = rec709_x_G; x_B = rec709_x_B;
y_R = rec709_y_R; y_G = rec709_y_G; y_B = rec709_y_B;
break;
};
float out_data[4 * 5];
- EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
+ EffectChainTester tester(data, 1, 5, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR, GL_RGBA32F);
tester.run(out_data, GL_RGBA, COLORSPACE_XYZ, GAMMA_LINEAR);
// Black should stay black.
EXPECT_NEAR(0.150, blue_x, 1e-3);
EXPECT_NEAR(0.060, blue_y, 1e-3);
EXPECT_FLOAT_EQ(1.0f, out_data[4 * 4 + 3]);
+
+ // The forward matrix should be exactly as specified in the standard,
+ // up to floating-point precision. (We're not compliant with the
+ // inverse matrix, but we should be very close.)
+ EXPECT_FLOAT_EQ(0.4124f, out_data[2 * 4 + 0]);
+ EXPECT_FLOAT_EQ(0.2126f, out_data[2 * 4 + 1]);
+ EXPECT_FLOAT_EQ(0.0193f, out_data[2 * 4 + 2]);
+
+ EXPECT_FLOAT_EQ(0.3576f, out_data[3 * 4 + 0]);
+ EXPECT_FLOAT_EQ(0.7152f, out_data[3 * 4 + 1]);
+ EXPECT_FLOAT_EQ(0.1192f, out_data[3 * 4 + 2]);
+
+ EXPECT_FLOAT_EQ(0.1805f, out_data[4 * 4 + 0]);
+ EXPECT_FLOAT_EQ(0.0722f, out_data[4 * 4 + 1]);
+ EXPECT_FLOAT_EQ(0.9505f, out_data[4 * 4 + 2]);
}
TEST(ColorspaceConversionEffectTest, Rec601_525_Primaries) {
PKG_CHECK_MODULES([epoxy], [epoxy])
PKG_CHECK_MODULES([FFTW3], [fftw3])
-CXXFLAGS="$CXXFLAGS -std=gnu++11"
+CXXFLAGS="$CXXFLAGS -std=gnu++14"
# Needed for unit tests and the demo app.
with_demo_app=yes
enum Colorspace {
COLORSPACE_INVALID = -1, // For internal use.
- COLORSPACE_sRGB = 0,
- COLORSPACE_REC_709 = 0, // Same as sRGB.
+ COLORSPACE_REC_709 = 0,
COLORSPACE_REC_601_525 = 1,
COLORSPACE_REC_601_625 = 2,
COLORSPACE_XYZ = 3, // Mostly useful for testing and debugging.
COLORSPACE_REC_2020 = 4,
+ COLORSPACE_sRGB = 5, // Used to be same as COLORSPACE_REC_709.
};
enum GammaCurve {
// succeeded.
//
// The first parameter gives which directory to read .frag files from.
-// This is a temporary hack until we add something more solid.
+// If you use "", or the file isn't found, a compiled-in version will
+// be used instead (if it exists). Most users should probably use ""
+// unless you need backwards compatibility with Movit 1.6.3 or older.
//
// The second parameter specifies whether debugging is on or off.
// If it is on, Movit will write intermediate graphs and the final
--- /dev/null
+#include <stdio.h>
+#include <string>
+#include <vector>
+#include "util.h"
+#include "bundled_shaders.h"
+
+using namespace std;
+using namespace movit;
+
+namespace movit {
+
+// We need a fake (empty) list of shaders, since we reuse read_file().
+BundledShader bundled_shaders[] = {
+ { nullptr, 0, 0 }
+};
+const char *shader_bundle = "";
+extern string *movit_data_directory;
+
+} // namespace movit
+
+int main(int argc, char **argv)
+{
+ std::vector<BundledShader> shaders;
+ std::string bundle;
+
+ movit_data_directory = new string(".");
+
+ for (int i = 1; i < argc; ++i) {
+ string contents = read_file(argv[i]);
+ shaders.push_back(BundledShader{ argv[i], /*offset=*/bundle.size(), /*length=*/contents.size() });
+ bundle += contents;
+ }
+
+ printf("// Autogenerated by make_bundled_shaders.cpp. Do not edit by hand!\n");
+ printf("#include <string>\n");
+ printf("#include \"bundled_shaders.h\"\n");
+ printf("\n");
+ printf("namespace movit {\n");
+ printf("\n");
+ printf("BundledShader bundled_shaders[] = {\n");
+ for (const BundledShader &shader : shaders) {
+ printf("\t{ \"%s\", %zu, %zu },\n", shader.filename, shader.offset, shader.length);
+ }
+ printf("\t{ nullptr, 0, 0 }\n");
+ printf("};\n");
+ printf("const char *shader_bundle = \"");
+ for (unsigned char ch : bundle) {
+ if (ch == '\n') {
+ printf("\\n");
+ } else if (ch == '\t') {
+ printf("\\t");
+ } else if (ch == '"') {
+ printf("\\\"");
+ } else if (ch == '\\') {
+ printf("\\\\");
+ } else if (!isprint(ch)) {
+ printf("\\%o", ch);
+ } else {
+ printf("%c", ch);
+ }
+ }
+ printf("\";\n");
+ printf("\n");
+ printf("} // namespace movit\n");
+}
#include <string>
#include <Eigen/Core>
+#include "bundled_shaders.h"
#include "fp16.h"
#include "init.h"
#include "util.h"
}
}
+string read_file_from_bundle(const string &filename)
+{
+ for (const BundledShader *shader = bundled_shaders; shader->filename != nullptr; ++shader) {
+ if (shader->filename == filename) {
+ return string(shader_bundle + shader->offset, shader->length);
+ }
+ }
+ return ""; // Not found.
+}
+
string read_file(const string &filename)
{
+ string contents_from_bundle = read_file_from_bundle(filename);
+
+ // If no data directory has been given, we read only from the bundle.
+ if (*movit_data_directory == "") {
+ if (contents_from_bundle.empty()) {
+ fprintf(stderr, "%s: Shader not compiled in, and no data directory has been given.\n", filename.c_str());
+ exit(1);
+ } else {
+ return contents_from_bundle;
+ }
+ }
+
+ // If we're given a data directory, we still support reading from the bundle,
+ // but a successful read from the file system takes priority.
const string full_pathname = *movit_data_directory + "/" + filename;
FILE *fp = fopen(full_pathname.c_str(), "r");
if (fp == nullptr) {
+ if (!contents_from_bundle.empty()) {
+ return contents_from_bundle;
+ }
perror(full_pathname.c_str());
exit(1);
}
int ret = fseek(fp, 0, SEEK_END);
if (ret == -1) {
+ if (!contents_from_bundle.empty()) {
+ fclose(fp);
+ return contents_from_bundle;
+ }
perror("fseek(SEEK_END)");
exit(1);
}
ret = fseek(fp, 0, SEEK_SET);
if (ret == -1) {
+ if (!contents_from_bundle.empty()) {
+ fclose(fp);
+ return contents_from_bundle;
+ }
perror("fseek(SEEK_SET)");
exit(1);
}
str.resize(size);
ret = fread(&str[0], size, 1, fp);
if (ret == -1) {
+ if (!contents_from_bundle.empty()) {
+ fclose(fp);
+ return contents_from_bundle;
+ }
perror("fread");
exit(1);
}
if (ret == 0) {
+ if (!contents_from_bundle.empty()) {
+ fclose(fp);
+ return contents_from_bundle;
+ }
fprintf(stderr, "Short read when trying to read %d bytes from %s\n",
size, full_pathname.c_str());
exit(1);
// changes, even within git versions. There is no specific version
// documentation outside the regular changelogs, though.
-#define MOVIT_VERSION 37
+#define MOVIT_VERSION 39
#endif // !defined(_MOVIT_VERSION_H)