[vlc-devel] [PATCH] OpenGL: implement by-hand unpack row functionality

Ilkka Ollakka ileoo at videolan.org
Thu Oct 4 13:23:20 CEST 2012


This uses multiple memcpy so it is really slow, but it should
be faster than uploading line by line to gpu.
---
 modules/video_output/opengl.c | 42 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 37 insertions(+), 5 deletions(-)

diff --git a/modules/video_output/opengl.c b/modules/video_output/opengl.c
index f099f63..133bb98 100644
--- a/modules/video_output/opengl.c
+++ b/modules/video_output/opengl.c
@@ -181,6 +181,9 @@ struct vout_display_opengl_t {
 
     /* Non-power-of-2 texture size support */
     bool supports_npot;
+
+    /* UNPACK_ROW_LENGTH supported */
+    bool supports_unpack;
 };
 
 static inline int GetAlignedSize(unsigned size)
@@ -334,6 +337,13 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->supports_npot = HasExtension( extensions, "GL_ARB_texture_non_power_of_two" ) ||
                          HasExtension( extensions, "GL_APPLE_texture_2D_limited_npot" );
 
+#if GL_UNPACK_ROW_LENGTH
+    vgl->supports_unpack = true;
+#else
+    /* Some opengl ES 2 devices have UNPACK_ROW_LENGTH supported via extension, check that */
+    vgl->supports_unpack = HasExtension( extensions, "EXT_unpack_subimage");
+#endif
+
     if( !vgl->CreateShader || !vgl->ShaderSource || !vgl->CreateProgram )
     {
         fprintf(stderr, "Looks like you don't have all the opengl we need. Driver is %s, giving up\n", glGetString(GL_VERSION));
@@ -662,12 +672,37 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
             vgl->ClientActiveTexture(GL_TEXTURE0 + 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,
+        if( vgl->supports_unpack )
+        {
+          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);
+        } else if ( (picture->p[j].i_pitch / picture->p[j].i_pixel_pitch) != (vgl->fmt.i_width  * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den) ) {
+          uint8_t *new_plane = malloc(  picture->p[j].i_pitch*picture->p[j].i_pixel_pitch *vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den);
+          uint8_t *destination = new_plane;
+          const uint8_t *source = picture->p[j].p_pixels;
+          for( unsigned height = 0; height < vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den; height++ )
+          {
+             memcpy( destination, source, vgl->fmt.i_width  * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den );
+             source +=  picture->p[j].i_pitch*picture->p[j].i_pixel_pitch;
+             destination += vgl->fmt.i_width  * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den;
+          }
+          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, new_plane );
+          free( new_plane );
+        } else {
+          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;
@@ -827,7 +862,6 @@ static void draw_with_shaders( vout_display_opengl_t *vgl, float *left, float *t
             right[j], bottom[j],
         };
         vgl->ActiveTexture( GL_TEXTURE0+j);
-        vgl->ClientActiveTexture( GL_TEXTURE0+j);
         glEnable(vgl->tex_target);
         glBindTexture(vgl->tex_target, vgl->texture[0][j]);
         if(asprintf( &attribute, "MultiTexCoord%1d", j ) == -1 )
@@ -839,7 +873,6 @@ static void draw_with_shaders( vout_display_opengl_t *vgl, float *left, float *t
         attribute = NULL;
     }
     vgl->ActiveTexture(GL_TEXTURE0 + 0);
-    vgl->ClientActiveTexture(GL_TEXTURE0 + 0);
     vgl->EnableVertexAttribArray( vgl->GetAttribLocation( vgl->program[0], "vertex_position"));
     vgl->VertexAttribPointer( vgl->GetAttribLocation( vgl->program[0], "vertex_position"), 2, GL_FLOAT, 0, 0, vertexCoord);
 
@@ -898,7 +931,6 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
     }
 
     vgl->ActiveTexture(GL_TEXTURE0 + 0);
-    vgl->ClientActiveTexture(GL_TEXTURE0 + 0);
     glEnable(GL_TEXTURE_2D);
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-- 
1.7.12.1




More information about the vlc-devel mailing list