: image_format(image_format),
ycbcr_format(ycbcr_format),
needs_update(false),
+ needs_pbo_recreate(false),
finalized(false),
needs_mipmaps(false),
width(width),
height(height)
{
+ pbos[0] = pbos[1] = pbos[2] = 0;
+ texture_num[0] = texture_num[1] = texture_num[2] = 0;
+
pitch[0] = pitch[1] = pitch[2] = width;
assert(width % ycbcr_format.chroma_subsampling_x == 0);
register_int("needs_mipmaps", &needs_mipmaps);
}
+YCbCrInput::~YCbCrInput()
+{
+ if (pbos[0] != 0) {
+ glDeleteBuffers(3, pbos);
+ check_error();
+ }
+ if (texture_num[0] != 0) {
+ glDeleteTextures(3, texture_num);
+ check_error();
+ }
+}
+
void YCbCrInput::finalize()
{
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ check_error();
+
// Create PBOs to hold the textures holding the input image, and then the texture itself.
glGenBuffers(3, pbos);
check_error();
glBindTexture(GL_TEXTURE_2D, texture_num[channel]);
check_error();
- if (needs_update) {
+ if (needs_update || needs_pbo_recreate) {
// Copy the pixel data into the PBO.
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbos[channel]);
check_error();
+
+ if (needs_pbo_recreate) {
+ // The pitch has changed; we need to reallocate this PBO.
+ glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, pitch[channel] * heights[channel], NULL, GL_STREAM_DRAW);
+ check_error();
+ }
+
void *mapped_pbo = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
memcpy(mapped_pbo, pixel_data[channel], pitch[channel] * heights[channel]);
+
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
check_error();
*sampler_num += 3;
needs_update = false;
+ needs_pbo_recreate = false;
}
std::string YCbCrInput::output_fragment_shader()