]> git.sesse.net Git - vlc/blobdiff - modules/video_output/opengl.c
transcode: actually do the audio encode flushing
[vlc] / modules / video_output / opengl.c
index 667e937d3fe3ca5b266d819e5e5ec633b2b5eaca..f099f63f7fb5b736514f7df7371e4e67e8676511 100644 (file)
@@ -52,6 +52,8 @@
 #   define PFNGLGETSHADERINFOLOGPROC         typeof(glGetShaderInfoLog)*
 #   define PFNGLGETUNIFORMLOCATIONPROC       typeof(glGetUniformLocation)*
 #   define PFNGLGETATTRIBLOCATIONPROC        typeof(glGetAttribLocation)*
+#   define PFNGLVERTEXATTRIBPOINTERPROC      typeof(glVertexAttribPointer)*
+#   define PFNGLENABLEVERTEXATTRIBARRAYPROC  typeof(glEnableVertexAttribArray)*
 #   define PFNGLUNIFORM4FVPROC               typeof(glUniform4fv)*
 #   define PFNGLUNIFORM4FPROC                typeof(glUniform4f)*
 #   define PFNGLUNIFORM3IPROC                typeof(glUniform3i)*
@@ -141,8 +143,10 @@ struct vout_display_opengl_t {
 
     /* Shader variables commands*/
 
-    PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
-    PFNGLGETATTRIBLOCATIONPROC  GetAttribLocation;
+    PFNGLGETUNIFORMLOCATIONPROC      GetUniformLocation;
+    PFNGLGETATTRIBLOCATIONPROC       GetAttribLocation;
+    PFNGLVERTEXATTRIBPOINTERPROC     VertexAttribPointer;
+    PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
 
     PFNGLUNIFORM4FVPROC   Uniform4fv;
     PFNGLUNIFORM4FPROC    Uniform4f;
@@ -174,6 +178,9 @@ struct vout_display_opengl_t {
     PFNGLACTIVETEXTUREPROC  ActiveTexture;
     PFNGLCLIENTACTIVETEXTUREPROC  ClientActiveTexture;
     bool use_multitexture;
+
+    /* Non-power-of-2 texture size support */
+    bool supports_npot;
 };
 
 static inline int GetAlignedSize(unsigned size)
@@ -186,24 +193,6 @@ static inline int GetAlignedSize(unsigned size)
 #if !USE_OPENGL_ES
 static bool IsLuminance16Supported(int target)
 {
-#if defined(MACOS_OPENGL)
-    /* OpenGL 1.x on OS X does _not_ support 16bit shaders, but pretends to.
-     * That's why we enforce return false here, even though the actual code below
-     * would return true.
-     * This fixes playback of 10bit content on the Intel GMA 950 chipset, which is
-     * the only "GPU" supported by 10.6 and 10.7 with just an OpenGL 1.4 driver.
-     *
-     * Presumely, this also improves playback on the GMA 3100, GeForce FX 5200,
-     * GeForce4 Ti, GeForce3, GeForce2 MX/4 MX and the Radeon 8500 when
-     * running OS X 10.5. */
-    const GLubyte * p_glversion;
-    float f_glversion;
-    p_glversion = glGetString (GL_VERSION);
-    sscanf((char *)p_glversion, "%f", &f_glversion);
-    if (f_glversion < 2)
-        return false;
-#endif
-
     GLuint texture;
 
     glGenTextures(1, &texture);
@@ -240,6 +229,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
         return NULL;
     }
 
+    const char *extensions = (const char *)glGetString(GL_EXTENSIONS);
 #if !USE_OPENGL_ES
     const unsigned char *ogl_version = glGetString(GL_VERSION);
     bool supports_shaders = strverscmp((const char *)ogl_version, "2.0") >= 0;
@@ -303,18 +293,6 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
             list++;
         }
     }
-#if (defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__)) && defined (__APPLE__)
-    /* This is a work-around for dated PowerPC-based Macs, which run OpenGL 1.3 only and don't
-     * support the GL_ARB_fragment_program extension.
-     * Affected devices are all Macs built between 2002 and 2005 with an ATI Radeon 7500,
-     * an ATI Radeon 9200 or a NVIDIA GeForceFX 5200 Ultra. */
-    else
-    {
-        vgl->tex_format   = GL_YCBCR_422_APPLE;
-        vgl->tex_type     = GL_UNSIGNED_SHORT_8_8_APPLE;
-        vgl->fmt.i_chroma = VLC_CODEC_YUYV;
-    }
-#endif
 
     vgl->GenBuffers    = (PFNGLGENBUFFERSPROC)vlc_gl_GetProcAddress(vgl->gl, "glGenBuffers");
     vgl->BindBuffer    = (PFNGLBINDBUFFERPROC)vlc_gl_GetProcAddress(vgl->gl, "glBindBuffer");
@@ -326,29 +304,35 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->ShaderSource  = (PFNGLSHADERSOURCEPROC)vlc_gl_GetProcAddress(vgl->gl, "glShaderSource");
     vgl->CompileShader = (PFNGLCOMPILESHADERPROC)vlc_gl_GetProcAddress(vgl->gl, "glCompileShader");
     vgl->AttachShader  = (PFNGLATTACHSHADERPROC)vlc_gl_GetProcAddress(vgl->gl, "glAttachShader");
-    vgl->GetProgramiv   = (PFNGLGETPROGRAMIVPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetProgramiv");
-    vgl->GetProgramInfoLog   = (PFNGLGETPROGRAMINFOLOGPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetProgramInfoLog");
+
+    vgl->GetProgramiv  = (PFNGLGETPROGRAMIVPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetProgramiv");
     vgl->GetShaderiv   = (PFNGLGETSHADERIVPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetShaderiv");
+    vgl->GetProgramInfoLog  = (PFNGLGETPROGRAMINFOLOGPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetProgramInfoLog");
     vgl->GetShaderInfoLog   = (PFNGLGETSHADERINFOLOGPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetShaderInfoLog");
+
     vgl->DetachShader  = (PFNGLDETACHSHADERPROC)vlc_gl_GetProcAddress(vgl->gl, "glDetachShader");
     vgl->DeleteShader  = (PFNGLDELETESHADERPROC)vlc_gl_GetProcAddress(vgl->gl, "glDeleteShader");
 
     vgl->GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetUniformLocation");
     vgl->GetAttribLocation  = (PFNGLGETATTRIBLOCATIONPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetAttribLocation");
+    vgl->VertexAttribPointer= (PFNGLVERTEXATTRIBPOINTERPROC)vlc_gl_GetProcAddress(vgl->gl, "glVertexAttribPointer");
+    vgl->EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)vlc_gl_GetProcAddress(vgl->gl, "glEnableVertexAttribArray");
     vgl->Uniform4fv    = (PFNGLUNIFORM4FVPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform4fv");
     vgl->Uniform4f     = (PFNGLUNIFORM4FPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform4f");
     vgl->Uniform3i     = (PFNGLUNIFORM3IPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform3i");
     vgl->Uniform1i     = (PFNGLUNIFORM1IPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform1i");
 
     vgl->CreateProgram = (PFNGLCREATEPROGRAMPROC)vlc_gl_GetProcAddress(vgl->gl, "glCreateProgram");
-    vgl->LinkProgram = (PFNGLLINKPROGRAMPROC)vlc_gl_GetProcAddress(vgl->gl, "glLinkProgram");
-    vgl->UseProgram = (PFNGLUSEPROGRAMPROC)vlc_gl_GetProcAddress(vgl->gl, "glUseProgram");
+    vgl->LinkProgram   = (PFNGLLINKPROGRAMPROC)vlc_gl_GetProcAddress(vgl->gl, "glLinkProgram");
+    vgl->UseProgram    = (PFNGLUSEPROGRAMPROC)vlc_gl_GetProcAddress(vgl->gl, "glUseProgram");
     vgl->DeleteProgram = (PFNGLDELETEPROGRAMPROC)vlc_gl_GetProcAddress(vgl->gl, "glDeleteProgram");
     vgl->ActiveTexture = (PFNGLACTIVETEXTUREPROC)vlc_gl_GetProcAddress(vgl->gl, "glActiveTexture");
     vgl->ClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)vlc_gl_GetProcAddress(vgl->gl, "glClientActiveTexture");
 
     vgl->chroma = vlc_fourcc_GetChromaDescription(vgl->fmt.i_chroma);
     vgl->use_multitexture = vgl->chroma->plane_count > 1;
+    vgl->supports_npot = HasExtension( extensions, "GL_ARB_texture_non_power_of_two" ) ||
+                         HasExtension( extensions, "GL_APPLE_texture_2D_limited_npot" );
 
     if( !vgl->CreateShader || !vgl->ShaderSource || !vgl->CreateProgram )
     {
@@ -362,8 +346,14 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
         int w = vgl->fmt.i_width  * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den;
         int h = vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den;
-        vgl->tex_width[j]  = w;
-        vgl->tex_height[j] = h;
+        if( vgl->supports_npot )
+        {
+            vgl->tex_width[j]  = w;
+            vgl->tex_height[j] = h;
+        } else {
+            vgl->tex_width[j]  = GetAlignedSize(w);
+            vgl->tex_height[j] = GetAlignedSize(h);
+        }
     }
 
     /* Build fragment program if needed */
@@ -394,16 +384,15 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
             /* Basic linear YUV -> RGB conversion using bilinear interpolation */
             const char *template_glsl_yuv =
                 "#version 120\n"
-                "uniform sampler2D Texture0;"
-                "uniform sampler2D Texture1;"
-                "uniform sampler2D Texture2;"
+                "uniform sampler2D Texture[3];"
                 "uniform vec4      coefficient[4];"
+                "varying vec4      TexCoord0,TexCoord1,TexCoord2;"
 
                 "void main(void) {"
                 " vec4 x,y,z,result;"
-                " x  = texture2D(Texture0, gl_TexCoord[0].st);"
-                " %c = texture2D(Texture1, gl_TexCoord[1].st);"
-                " %c = texture2D(Texture2, gl_TexCoord[2].st);"
+                " x  = texture2D(Texture[0], TexCoord0.st);"
+                " %c = texture2D(Texture[1], TexCoord1.st);"
+                " %c = texture2D(Texture[2], TexCoord2.st);"
 
                 " result = x * coefficient[0] + coefficient[3];"
                 " result = (y * coefficient[1]) + result;"
@@ -429,20 +418,24 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
             // Basic vertex shader that we use in both cases
             const char *vertexShader =
             "#version 120\n"
+            "varying   vec4 TexCoord0,TexCoord1, TexCoord2;"
+            "attribute vec4 MultiTexCoord0,MultiTexCoord1,MultiTexCoord2;"
+            "attribute vec4 vertex_position;"
             "void main() {"
-            " gl_TexCoord[0] = gl_MultiTexCoord0;"
-            " gl_TexCoord[1] = gl_MultiTexCoord1;"
-            " gl_TexCoord[2] = gl_MultiTexCoord2;"
-            " gl_Position = ftransform(); }";
+            " TexCoord0 = MultiTexCoord0;"
+            " TexCoord1 = MultiTexCoord1;"
+            " TexCoord2 = MultiTexCoord2;"
+            " gl_Position = vertex_position; }";
 
             // Dummy shader for text overlay
             const char *helloShader =
             "#version 120\n"
-            "uniform sampler2D Texture0;"
+            "uniform sampler2D Texture[3];"
             "uniform vec4 fillColor;"
+            "varying vec4 TexCoord0,TexCoord1,TexCoord2;"
             "void main()"
             "{ "
-            "  gl_FragColor = texture2D(Texture0, gl_TexCoord[0].st)*fillColor;}";
+            "  gl_FragColor = texture2D(Texture[0], TexCoord0.st)*fillColor;}";
 
             vgl->shader[2] = vgl->CreateShader( GL_VERTEX_SHADER );
             vgl->ShaderSource( vgl->shader[2], 1, (const GLchar **)&vertexShader, NULL);
@@ -705,6 +698,11 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
             glr->type   = GL_UNSIGNED_BYTE;
             glr->width  = r->fmt.i_visible_width;
             glr->height = r->fmt.i_visible_height;
+            if(!vgl->supports_npot )
+            {
+                glr->width  = GetAlignedSize( glr->width );
+                glr->height = GetAlignedSize( glr->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;
@@ -779,35 +777,38 @@ static void draw_without_shaders( vout_display_opengl_t *vgl, float *left, float
         right[0], top[0]
     };
 
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-    glEnable(GL_VERTEX_ARRAY);
-    glEnable(GL_TEXTURE_COORD_ARRAY);
+    for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
+       vgl->ActiveTexture( GL_TEXTURE0 + j );
+       vgl->ClientActiveTexture( GL_TEXTURE0 + j );
 
-    vgl->ActiveTexture( GL_TEXTURE0);
-    vgl->ClientActiveTexture( GL_TEXTURE0);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+       glEnable(vgl->tex_target);
+
+       glBindTexture(vgl->tex_target, vgl->texture[0][j]);
+       glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
+    }
+    vgl->ActiveTexture( GL_TEXTURE0 );
+    vgl->ClientActiveTexture( GL_TEXTURE0 );
 
-    glEnable(vgl->tex_target);
-    glBindTexture(vgl->tex_target, vgl->texture[0][0]);
     glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
-    glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 
-    glDisable(vgl->tex_target);
-    glDisable(GL_TEXTURE_COORD_ARRAY);
-    glDisable(GL_VERTEX_ARRAY);
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    glDisableClientState(GL_VERTEX_ARRAY);
+    for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
+       vgl->ActiveTexture( GL_TEXTURE0 + j );
+       vgl->ClientActiveTexture( GL_TEXTURE0 + j );
+       glDisable(vgl->tex_target);
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       glDisableClientState(GL_VERTEX_ARRAY);
+    }
+    vgl->ActiveTexture( GL_TEXTURE0 );
+    vgl->ClientActiveTexture( GL_TEXTURE0 );
 }
 
 static void draw_with_shaders( vout_display_opengl_t *vgl, float *left, float *top, float *right, float *bottom )
 {
-    vgl->UseProgram(vgl->program[0]);
-    vgl->Uniform4fv( vgl->GetUniformLocation( vgl->program[0], "coefficient" ), 4, vgl->local_value);
-    vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[0], "Texture0" ), 0);
-    vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[0], "Texture1" ), 1);
-    vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[0], "Texture2" ), 2);
 
     const GLfloat vertexCoord[] = {
         -1.0, 1.0,
@@ -818,6 +819,7 @@ static void draw_with_shaders( vout_display_opengl_t *vgl, float *left, float *t
 
     for( unsigned j = 0; j < vgl->chroma->plane_count; j++)
     {
+        char *attribute = NULL;
         const GLfloat texCoord[] = {
             left[j], top[j],
             left[j], bottom[j],
@@ -827,26 +829,21 @@ static void draw_with_shaders( vout_display_opengl_t *vgl, float *left, float *t
         vgl->ActiveTexture( GL_TEXTURE0+j);
         vgl->ClientActiveTexture( GL_TEXTURE0+j);
         glEnable(vgl->tex_target);
-        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
         glBindTexture(vgl->tex_target, vgl->texture[0][j]);
-        glTexCoordPointer(2, GL_FLOAT, 0, texCoord);
-    }
-    vgl->ActiveTexture(GL_TEXTURE0 + 0);
-    vgl->ClientActiveTexture(GL_TEXTURE0 + 0);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
-    glDrawArrays( GL_TRIANGLE_STRIP, 0, 4);
-    glDisableClientState(GL_VERTEX_ARRAY);
+        if(asprintf( &attribute, "MultiTexCoord%1d", j ) == -1 )
+            return;
 
-    for( int j = vgl->chroma->plane_count; j >= 0;j--)
-    {
-        vgl->ActiveTexture( GL_TEXTURE0+j);
-        vgl->ClientActiveTexture( GL_TEXTURE0+j);
-        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+        vgl->EnableVertexAttribArray( vgl->GetAttribLocation(vgl->program[0], attribute ) );
+        vgl->VertexAttribPointer( vgl->GetAttribLocation( vgl->program[0], attribute ), 2, GL_FLOAT, 0, 0, texCoord);
+        free( attribute );
+        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);
+
+    glDrawArrays( GL_TRIANGLE_STRIP, 0, 4);
 }
 
 int vout_display_opengl_Display(vout_display_opengl_t *vgl,
@@ -887,10 +884,15 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
 
     if( vgl->program[0] )
     {
+        vgl->UseProgram(vgl->program[0]);
+        vgl->Uniform4fv( vgl->GetUniformLocation( vgl->program[0], "coefficient" ), 4, vgl->local_value);
+        vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[0], "Texture[0]" ), 0);
+        vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[0], "Texture[1]" ), 1);
+        vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[0], "Texture[2]" ), 2);
         draw_with_shaders( vgl, left, top ,right, bottom );
         // Change the program for overlays
         vgl->UseProgram(vgl->program[1]);
-        vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[1], "Texture0" ), 0);
+        vgl->Uniform1i( vgl->GetUniformLocation( vgl->program[1], "Texture[0]" ), 0);
     } else {
         draw_without_shaders( vgl, left, top, right, bottom );
     }
@@ -900,7 +902,6 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
     glEnable(GL_TEXTURE_2D);
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glEnableClientState(GL_VERTEX_ARRAY);
 
     for (int i = 0; i < vgl->region_count; i++) {
         gl_region_t *glr = &vgl->region[i];
@@ -917,26 +918,34 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
             1.0, 1.0,
         };
 
+        glBindTexture(GL_TEXTURE_2D, glr->texture);
         if( vgl->program[0] )
         {
             vgl->Uniform4f( vgl->GetUniformLocation( vgl->program[1], "fillColor"), 1.0f, 1.0f, 1.0f, glr->alpha);
+            vgl->EnableVertexAttribArray( vgl->GetAttribLocation( vgl->program[1], "MultiTexCoord0") );
+            vgl->VertexAttribPointer( vgl->GetAttribLocation( vgl->program[1], "MultiTexCoord0"), 2, GL_FLOAT, 0, 0, textureCoord);
+            vgl->EnableVertexAttribArray( vgl->GetAttribLocation( vgl->program[1], "vertex_position"));
+            vgl->VertexAttribPointer( vgl->GetAttribLocation( vgl->program[1], "vertex_position"), 2, GL_FLOAT, 0, 0, vertexCoord);
         }
         else
         {
+            glEnableClientState(GL_VERTEX_ARRAY);
             glColor4f( 1.0f, 1.0f, 1.0f, glr->alpha );
             glEnable(GL_TEXTURE_COORD_ARRAY);
             glEnable(GL_VERTEX_ARRAY);
+            glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
         }
 
-        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-        glBindTexture(GL_TEXTURE_2D, glr->texture);
-        glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
-        glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
         glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
-        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+        if( !vgl->program[0] )
+        {
+            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+            glDisableClientState(GL_VERTEX_ARRAY);
+        }
     }
-    glDisableClientState(GL_VERTEX_ARRAY);
     glDisable(GL_BLEND);
     glDisable(GL_TEXTURE_2D);