X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=util.cpp;h=085461988ed5f40440f1f2a478f704982d7f6a9d;hp=54c815cc2be0f7e45967bcfddabea04cd4060639;hb=HEAD;hpb=532dc15e43ee8c26de0e9f13bc56d92b4a6b1379 diff --git a/util.cpp b/util.cpp index 54c815c..0854619 100644 --- a/util.cpp +++ b/util.cpp @@ -9,6 +9,7 @@ #include #include +#include "bundled_shaders.h" #include "fp16.h" #include "init.h" #include "util.h" @@ -84,18 +85,49 @@ void hsv2rgb_normalized(float h, float s, float v, float *r, float *g, float *b) } } +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 == NULL) { + 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); } @@ -104,6 +136,10 @@ string read_file(const string &filename) 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); } @@ -112,10 +148,18 @@ string read_file(const string &filename) 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); @@ -157,7 +201,19 @@ GLuint compile_shader(const string &shader_src, GLenum type) GLint status; glGetShaderiv(obj, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { - fprintf(stderr, "Failed to compile shader: %s\n", shader_src.c_str()); + // Add some line numbers to easier identify compile errors. + string src_with_lines = "/* 1 */ "; + size_t lineno = 1; + for (char ch : shader_src) { + src_with_lines.push_back(ch); + if (ch == '\n') { + char buf[32]; + snprintf(buf, sizeof(buf), "/* %3zu */ ", ++lineno); + src_with_lines += buf; + } + } + + fprintf(stderr, "Failed to compile shader:\n%s\n", src_with_lines.c_str()); exit(1); } @@ -219,59 +275,6 @@ string output_glsl_vec3(const string &name, float x, float y, float z) return ss.str(); } -template -void combine_two_samples(float w1, float w2, float pos1, float pos1_pos2_diff, float inv_pos1_pos2_diff, float num_subtexels, float inv_num_subtexels, - DestFloat *offset, DestFloat *total_weight, float *sum_sq_error) -{ - assert(movit_initialized); - assert(w1 * w2 >= 0.0f); // Should not have differing signs. - float z; // Normalized 0..1 between pos1 and pos2. - if (fabs(w1 + w2) < 1e-6) { - z = 0.5f; - } else { - z = w2 / (w1 + w2); - } - - // Round to the desired precision. Note that this might take z outside the 0..1 range. - *offset = from_fp32(pos1 + z * pos1_pos2_diff); - z = (to_fp32(*offset) - pos1) * inv_pos1_pos2_diff; - - // Round to the minimum number of bits we have measured earlier. - // The card will do this for us anyway, but if we know what the real z - // is, we can pick a better total_weight below. - z = lrintf(z * num_subtexels) * inv_num_subtexels; - - // Choose total weight w so that we minimize total squared error - // for the effective weights: - // - // e = (w(1-z) - a)² + (wz - b)² - // - // Differentiating by w and setting equal to zero: - // - // 2(w(1-z) - a)(1-z) + 2(wz - b)z = 0 - // w(1-z)² - a(1-z) + wz² - bz = 0 - // w((1-z)² + z²) = a(1-z) + bz - // w = (a(1-z) + bz) / ((1-z)² + z²) - // - // If z had infinite precision, this would simply reduce to w = w1 + w2. - *total_weight = from_fp32((w1 + z * (w2 - w1)) / (z * z + (1 - z) * (1 - z))); - - if (sum_sq_error != NULL) { - float err1 = to_fp32(*total_weight) * (1 - z) - w1; - float err2 = to_fp32(*total_weight) * z - w2; - *sum_sq_error = err1 * err1 + err2 * err2; - } -} - -// Explicit instantiations. -template -void combine_two_samples(float w1, float w2, float pos1, float pos1_pos2_diff, float inv_pos1_pos2_diff, float num_subtexels, float inv_num_subtexels, - float *offset, float *total_weight, float *sum_sq_error); - -template -void combine_two_samples(float w1, float w2, float pos1, float pos1_pos2_diff, float inv_pos1_pos2_diff, float num_subtexels, float inv_num_subtexels, - fp16_int_t *offset, fp16_int_t *total_weight, float *sum_sq_error); - GLuint generate_vbo(GLint size, GLenum type, GLsizeiptr data_size, const GLvoid *data) { GLuint vbo; @@ -347,7 +350,7 @@ void *get_gl_context_identifier() return (void *)wglGetCurrentContext(); #else void *ret = (void *)eglGetCurrentContext(); - if (ret != NULL) { + if (ret != nullptr) { return ret; } return (void *)glXGetCurrentContext();