- textures.push_back(tex);
- return tex.tex_num;
-}
-
-void TexturePool::release_texture(GLuint tex_num)
-{
- for (Texture &tex : textures) {
- if (tex.tex_num == tex_num) {
- assert(tex.in_use);
- tex.in_use = false;
- return;
- }
- }
- assert(false);
-}
-
-// OpenGL uses a bottom-left coordinate system, .flo files use a top-left coordinate system.
-void flip_coordinate_system(float *dense_flow, unsigned width, unsigned height)
-{
- for (unsigned i = 0; i < width * height; ++i) {
- dense_flow[i * 2 + 1] = -dense_flow[i * 2 + 1];
- }
-}
-
-// Not relevant for RGB.
-void flip_coordinate_system(uint8_t *dense_flow, unsigned width, unsigned height)
-{
-}
-
-void write_flow(const char *filename, const float *dense_flow, unsigned width, unsigned height)
-{
- FILE *flowfp = fopen(filename, "wb");
- fprintf(flowfp, "FEIH");
- fwrite(&width, 4, 1, flowfp);
- fwrite(&height, 4, 1, flowfp);
- for (unsigned y = 0; y < height; ++y) {
- int yy = height - y - 1;
- fwrite(&dense_flow[yy * width * 2], width * 2 * sizeof(float), 1, flowfp);
- }
- fclose(flowfp);
-}
-
-// Not relevant for RGB.
-void write_flow(const char *filename, const uint8_t *dense_flow, unsigned width, unsigned height)
-{
- assert(false);
-}
-
-void write_ppm(const char *filename, const float *dense_flow, unsigned width, unsigned height)
-{
- FILE *fp = fopen(filename, "wb");
- fprintf(fp, "P6\n%d %d\n255\n", width, height);
- for (unsigned y = 0; y < unsigned(height); ++y) {
- int yy = height - y - 1;
- for (unsigned x = 0; x < unsigned(width); ++x) {
- float du = dense_flow[(yy * width + x) * 2 + 0];
- float dv = dense_flow[(yy * width + x) * 2 + 1];
-
- uint8_t r, g, b;
- flow2rgb(du, dv, &r, &g, &b);
- putc(r, fp);
- putc(g, fp);
- putc(b, fp);
- }
- }
- fclose(fp);
-}
-
-void write_ppm(const char *filename, const uint8_t *rgba, unsigned width, unsigned height)
-{
- unique_ptr<uint8_t[]> rgb_line(new uint8_t[width * 3 + 1]);
-
- FILE *fp = fopen(filename, "wb");
- fprintf(fp, "P6\n%d %d\n255\n", width, height);
- for (unsigned y = 0; y < height; ++y) {
- unsigned y2 = height - 1 - y;
- for (size_t x = 0; x < width; ++x) {
- memcpy(&rgb_line[x * 3], &rgba[(y2 * width + x) * 4], 4);
- }
- fwrite(rgb_line.get(), width * 3, 1, fp);
- }
- fclose(fp);
-}
-
-struct FlowType {
- using type = float;
- static constexpr GLenum gl_format = GL_RG;
- static constexpr GLenum gl_type = GL_FLOAT;
- static constexpr int num_channels = 2;
-};
-
-struct RGBAType {
- using type = uint8_t;
- static constexpr GLenum gl_format = GL_RGBA;
- static constexpr GLenum gl_type = GL_UNSIGNED_BYTE;
- static constexpr int num_channels = 4;
-};
-
-template <class Type>
-void finish_one_read(GLuint width, GLuint height)
-{
- using T = typename Type::type;
- constexpr int bytes_per_pixel = Type::num_channels * sizeof(T);
-
- assert(!reads_in_progress.empty());
- ReadInProgress read = reads_in_progress.front();
- reads_in_progress.pop_front();
-
- unique_ptr<T[]> flow(new typename Type::type[width * height * Type::num_channels]);
- void *buf = glMapNamedBufferRange(read.pbo, 0, width * height * bytes_per_pixel, GL_MAP_READ_BIT); // Blocks if the read isn't done yet.
- memcpy(flow.get(), buf, width * height * bytes_per_pixel); // TODO: Unneeded for RGBType, since flip_coordinate_system() does nothing.:
- glUnmapNamedBuffer(read.pbo);
- spare_pbos.push(read.pbo);
-
- flip_coordinate_system(flow.get(), width, height);
- if (!read.flow_filename.empty()) {
- write_flow(read.flow_filename.c_str(), flow.get(), width, height);
- fprintf(stderr, "%s %s -> %s\n", read.filename0.c_str(), read.filename1.c_str(), read.flow_filename.c_str());
- }
- if (!read.ppm_filename.empty()) {
- write_ppm(read.ppm_filename.c_str(), flow.get(), width, height);
- }
-}
-
-template <class Type>
-void schedule_read(GLuint tex, GLuint width, GLuint height, const char *filename0, const char *filename1, const char *flow_filename, const char *ppm_filename)
-{
- using T = typename Type::type;
- constexpr int bytes_per_pixel = Type::num_channels * sizeof(T);
-
- if (spare_pbos.empty()) {
- finish_one_read<Type>(width, height);