+
+void ChromaSubsampler::create_uyvy(GLuint y_tex, GLuint cbcr_tex, unsigned width, unsigned height, GLuint dst_tex)
+{
+ GLuint vao;
+ glGenVertexArrays(1, &vao);
+ check_error();
+
+ glBindVertexArray(vao);
+ check_error();
+
+ GLuint fbo = resource_pool->create_fbo(dst_tex);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glViewport(0, 0, width/2, height);
+ check_error();
+
+ glUseProgram(uyvy_program_num);
+ check_error();
+
+ glUniform1i(uyvy_y_texture_sampler_uniform, 0);
+ check_error();
+ glUniform1i(uyvy_cbcr_texture_sampler_uniform, 1);
+ check_error();
+
+ glActiveTexture(GL_TEXTURE0);
+ check_error();
+ glBindTexture(GL_TEXTURE_2D, y_tex);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ check_error();
+
+ glActiveTexture(GL_TEXTURE1);
+ check_error();
+ glBindTexture(GL_TEXTURE_2D, cbcr_tex);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ check_error();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ check_error();
+
+ float y_offset_0[] = { -0.5f / width, 0.0f };
+ float y_offset_1[] = { 0.5f / width, 0.0f };
+ float cbcr_offset0[] = { -1.0f / width, 0.0f };
+ float cbcr_offset1[] = { -0.0f / width, 0.0f };
+ set_uniform_vec2(uyvy_program_num, "foo", "luma_offset_0", y_offset_0);
+ set_uniform_vec2(uyvy_program_num, "foo", "luma_offset_1", y_offset_1);
+ set_uniform_vec2(uyvy_program_num, "foo", "chroma_offset_0", cbcr_offset0);
+ set_uniform_vec2(uyvy_program_num, "foo", "chroma_offset_1", cbcr_offset1);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ check_error();
+
+ for (GLint attr_index : { uyvy_position_attribute_index, uyvy_texcoord_attribute_index }) {
+ if (attr_index == -1) continue;
+ glEnableVertexAttribArray(attr_index);
+ check_error();
+ glVertexAttribPointer(attr_index, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ check_error();
+ }
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ check_error();
+
+ for (GLint attr_index : { uyvy_position_attribute_index, uyvy_texcoord_attribute_index }) {
+ if (attr_index == -1) continue;
+ glDisableVertexAttribArray(attr_index);
+ check_error();
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ check_error();
+ glUseProgram(0);
+ check_error();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ check_error();
+
+ resource_pool->release_fbo(fbo);
+ glDeleteVertexArrays(1, &vao);
+}