Split inputs into a separate class (descending from Effect) instead of handling them...
[movit] / input.cpp
1 #define GL_GLEXT_PROTOTYPES 1
2
3 #include <string.h>
4 #include <GL/gl.h>
5 #include <GL/glext.h>
6 #include <assert.h>
7
8 #include "input.h"
9 #include "util.h"
10
11 Input::Input(ImageFormat image_format, unsigned width, unsigned height)
12         : image_format(image_format),
13           needs_update(false),
14           use_srgb_texture_format(false),
15           needs_mipmaps(false),
16           width(width),
17           height(height)
18 {
19         register_int("use_srgb_texture_format", &use_srgb_texture_format);
20         register_int("needs_mipmaps", &needs_mipmaps);
21 }
22
23 void Input::finalize()
24 {
25         // Translate the input format to OpenGL's enums.
26         GLenum internal_format;
27         if (use_srgb_texture_format) {
28                 internal_format = GL_SRGB8;
29         } else {
30                 internal_format = GL_RGBA8;
31         }
32         if (image_format.pixel_format == FORMAT_RGB) {
33                 format = GL_RGB;
34                 bytes_per_pixel = 3;
35         } else if (image_format.pixel_format == FORMAT_RGBA) {
36                 format = GL_RGBA;
37                 bytes_per_pixel = 4;
38         } else if (image_format.pixel_format == FORMAT_BGR) {
39                 format = GL_BGR;
40                 bytes_per_pixel = 3;
41         } else if (image_format.pixel_format == FORMAT_BGRA) {
42                 format = GL_BGRA;
43                 bytes_per_pixel = 4;
44         } else {
45                 assert(false);
46         }
47
48         // Create PBO to hold the texture holding the input image, and then the texture itself.
49         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 2);
50         check_error();
51         glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * bytes_per_pixel, NULL, GL_STREAM_DRAW);
52         check_error();
53         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
54         check_error();
55         
56         glGenTextures(1, &texture_num);
57         check_error();
58         glBindTexture(GL_TEXTURE_2D, texture_num);
59         check_error();
60         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
61         check_error();
62         // Intel/Mesa seems to have a broken glGenerateMipmap() for non-FBO textures, so do it here
63         // instead of calling glGenerateMipmap().
64         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, needs_mipmaps);
65         check_error();
66         glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
67         check_error();
68
69         needs_update = false;
70 }
71         
72 void Input::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
73 {
74         if (needs_update) {
75                 // Copy the pixel data into the PBO.
76                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 2);
77                 check_error();
78                 void *mapped_pbo = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
79                 memcpy(mapped_pbo, pixel_data, width * height * bytes_per_pixel);
80                 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
81                 check_error();
82
83                 // Re-upload the texture from the PBO.
84                 glActiveTexture(GL_TEXTURE0);
85                 check_error();
86                 glBindTexture(GL_TEXTURE_2D, texture_num);
87                 check_error();
88                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
89                 check_error();
90                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
91                 check_error();
92                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
93                 check_error();
94                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
95                 check_error();
96
97                 needs_update = false;
98         }
99
100         // Bind it to a sampler.
101         set_uniform_int(glsl_program_num, prefix, "tex", *sampler_num);
102         ++*sampler_num;
103 }
104
105 std::string Input::output_fragment_shader()
106 {
107         return read_file("input.frag");
108 }