8 #include "effect_util.h"
9 #include "resource_pool.h"
12 #include "ycbcr_input.h"
14 using namespace Eigen;
19 YCbCrInput::YCbCrInput(const ImageFormat &image_format,
20 const YCbCrFormat &ycbcr_format,
21 unsigned width, unsigned height)
22 : image_format(image_format),
23 ycbcr_format(ycbcr_format),
28 pbos[0] = pbos[1] = pbos[2] = 0;
29 texture_num[0] = texture_num[1] = texture_num[2] = 0;
31 assert(width % ycbcr_format.chroma_subsampling_x == 0);
32 pitch[0] = widths[0] = width;
33 pitch[1] = widths[1] = width / ycbcr_format.chroma_subsampling_x;
34 pitch[2] = widths[2] = width / ycbcr_format.chroma_subsampling_x;
36 assert(height % ycbcr_format.chroma_subsampling_y == 0);
38 heights[1] = height / ycbcr_format.chroma_subsampling_y;
39 heights[2] = height / ycbcr_format.chroma_subsampling_y;
41 pixel_data[0] = pixel_data[1] = pixel_data[2] = NULL;
44 YCbCrInput::~YCbCrInput()
46 for (unsigned channel = 0; channel < 3; ++channel) {
47 if (texture_num[channel] != 0) {
48 resource_pool->release_2d_texture(texture_num[channel]);
53 void YCbCrInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsigned *sampler_num)
55 for (unsigned channel = 0; channel < 3; ++channel) {
56 glActiveTexture(GL_TEXTURE0 + *sampler_num + channel);
59 if (texture_num[channel] == 0) {
60 // (Re-)upload the texture.
61 texture_num[channel] = resource_pool->create_2d_texture(GL_R8, widths[channel], heights[channel]);
62 glBindTexture(GL_TEXTURE_2D, texture_num[channel]);
64 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
66 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbos[channel]);
68 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
70 glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch[channel]);
72 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widths[channel], heights[channel], GL_RED, GL_UNSIGNED_BYTE, pixel_data[channel]);
74 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
76 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
78 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
81 glBindTexture(GL_TEXTURE_2D, texture_num[channel]);
86 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
90 set_uniform_int(glsl_program_num, prefix, "tex_y", *sampler_num + 0);
91 set_uniform_int(glsl_program_num, prefix, "tex_cb", *sampler_num + 1);
92 set_uniform_int(glsl_program_num, prefix, "tex_cr", *sampler_num + 2);
97 string YCbCrInput::output_fragment_shader()
100 Matrix3d ycbcr_to_rgb;
101 compute_ycbcr_matrix(ycbcr_format, offset, &ycbcr_to_rgb);
105 frag_shader = output_glsl_mat3("PREFIX(inv_ycbcr_matrix)", ycbcr_to_rgb);
106 frag_shader += output_glsl_vec3("PREFIX(offset)", offset[0], offset[1], offset[2]);
108 float cb_offset_x = compute_chroma_offset(
109 ycbcr_format.cb_x_position, ycbcr_format.chroma_subsampling_x, widths[1]);
110 float cb_offset_y = compute_chroma_offset(
111 ycbcr_format.cb_y_position, ycbcr_format.chroma_subsampling_y, heights[1]);
112 frag_shader += output_glsl_vec2("PREFIX(cb_offset)", cb_offset_x, cb_offset_y);
114 float cr_offset_x = compute_chroma_offset(
115 ycbcr_format.cr_x_position, ycbcr_format.chroma_subsampling_x, widths[2]);
116 float cr_offset_y = compute_chroma_offset(
117 ycbcr_format.cr_y_position, ycbcr_format.chroma_subsampling_y, heights[2]);
118 frag_shader += output_glsl_vec2("PREFIX(cr_offset)", cr_offset_x, cr_offset_y);
120 frag_shader += read_file("ycbcr_input.frag");
124 void YCbCrInput::invalidate_pixel_data()
126 for (unsigned channel = 0; channel < 3; ++channel) {
127 if (texture_num[channel] != 0) {
128 resource_pool->release_2d_texture(texture_num[channel]);
129 texture_num[channel] = 0;
134 bool YCbCrInput::set_int(const std::string& key, int value)
136 if (key == "needs_mipmaps") {
137 // We currently do not support this.
140 return Effect::set_int(key, value);