+ for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
+ if (vgl->use_multitexture)
+ vgl->ActiveTextureARB(GL_TEXTURE0_ARB + j);
+ glBindTexture(vgl->tex_target, vgl->texture[0][j]);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, picture->p[j].i_pitch / picture->p[j].i_pixel_pitch);
+ glTexSubImage2D(vgl->tex_target, 0,
+ 0, 0,
+ vgl->fmt.i_width * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den,
+ vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den,
+ vgl->tex_format, vgl->tex_type, picture->p[j].p_pixels);
+ }
+
+ int last_count = vgl->region_count;
+ gl_region_t *last = vgl->region;
+
+ vgl->region_count = 0;
+ vgl->region = NULL;
+
+ if (subpicture) {
+
+ int count = 0;
+ for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next)
+ count++;
+
+ vgl->region_count = count;
+ vgl->region = calloc(count, sizeof(*vgl->region));
+
+ if (vgl->use_multitexture)
+ vgl->ActiveTextureARB(GL_TEXTURE0_ARB + 0);
+ int i = 0;
+ for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next, i++) {
+ gl_region_t *glr = &vgl->region[i];
+
+ glr->format = GL_RGBA;
+ glr->type = GL_UNSIGNED_BYTE;
+ glr->width = r->fmt.i_visible_width;
+ glr->height = r->fmt.i_visible_height;
+ glr->alpha = (float)subpicture->i_alpha * r->i_alpha / 255 / 255;
+ glr->left = 2.0 * (r->i_x ) / subpicture->i_original_picture_width - 1.0;
+ glr->top = -2.0 * (r->i_y ) / subpicture->i_original_picture_height + 1.0;
+ glr->right = 2.0 * (r->i_x + r->fmt.i_visible_width ) / subpicture->i_original_picture_width - 1.0;
+ glr->bottom = -2.0 * (r->i_y + r->fmt.i_visible_height) / subpicture->i_original_picture_height + 1.0;
+
+ glr->texture = 0;
+ for (int j = 0; j < last_count; j++) {
+ if (last[j].texture &&
+ last[j].width == glr->width &&
+ last[j].height == glr->height &&
+ last[j].format == glr->format &&
+ last[j].type == glr->type) {
+ glr->texture = last[j].texture;
+ memset(&last[j], 0, sizeof(last[j]));
+ break;
+ }
+ }
+
+ const int pixels_offset = r->fmt.i_y_offset * r->p_picture->p->i_pitch +
+ r->fmt.i_x_offset * r->p_picture->p->i_pixel_pitch;
+ if (glr->texture) {
+ glBindTexture(GL_TEXTURE_2D, glr->texture);
+ /* TODO set GL_UNPACK_ALIGNMENT */
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, 0, glr->width, glr->height,
+ glr->format, glr->type, &r->p_picture->p->p_pixels[pixels_offset]);
+ } else {
+ glGenTextures(1, &glr->texture);
+ glBindTexture(GL_TEXTURE_2D, glr->texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ /* TODO set GL_UNPACK_ALIGNMENT */
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
+ glTexImage2D(GL_TEXTURE_2D, 0, glr->format,
+ glr->width, glr->height, 0, glr->format, glr->type,
+ &r->p_picture->p->p_pixels[pixels_offset]);
+ }
+ }
+ }
+ for (int i = 0; i < last_count; i++) {
+ if (last[i].texture)
+ glDeleteTextures(1, &last[i].texture);
+ }
+ free(last);