/*****************************************************************************
* opengl.c: OpenGL and OpenGL ES output common code
*****************************************************************************
- * Copyright (C) 2004-2011 VLC authors and VideoLAN
+ * Copyright (C) 2004-2012 VLC authors and VideoLAN
* Copyright (C) 2009, 2011 Laurent Aimar
*
* Authors: Cyril Deguet <asmax@videolan.org>
* Eric Petit <titer@m0k.org>
* Cedric Cocquebert <cedric.cocquebert@supelec.fr>
* Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ * Ilkka Ollakka <ileoo@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <vlc_opengl.h>
#include "opengl.h"
-// Define USE_OPENGL_ES to the GL ES Version you want to select
-/* RV16 */
-#ifndef GL_UNSIGNED_SHORT_5_6_5
-# define GL_UNSIGNED_SHORT_5_6_5 0x8363
-#endif
#ifndef GL_CLAMP_TO_EDGE
# define GL_CLAMP_TO_EDGE 0x812F
#endif
# 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)*
# define PFNGLCLIENTACTIVETEXTUREPROC typeof(glClientActiveTexture)*
#if USE_OPENGL_ES
# define GL_UNPACK_ROW_LENGTH 0
+# import <CoreFoundation/CoreFoundation.h>
#endif
#endif
/* Shader variables commands*/
- PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
- PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
+ PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
+ PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
+ PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
+ PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
PFNGLUNIFORM4FVPROC Uniform4fv;
PFNGLUNIFORM4FPROC Uniform4f;
PFNGLACTIVETEXTUREPROC ActiveTexture;
PFNGLCLIENTACTIVETEXTUREPROC ClientActiveTexture;
bool use_multitexture;
+
+ /* Non-power-of-2 texture size support */
+ bool supports_npot;
};
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);
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;
+#else
+ bool supports_shaders = false;
+#ifdef __APPLE__
+ if( kCFCoreFoundationVersionNumber >= 786. )
+ supports_shaders = true;
+#endif
+#endif
- const char *ogl_version = glGetString(GL_VERSION);
- float f_ogl_version = atof(ogl_version);
- bool supports_shaders = f_ogl_version >= 2.0f;
GLint max_texture_units = 0;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
/* Initialize with default chroma */
vgl->fmt = *fmt;
-#if USE_OPENGL_ES
- vgl->fmt.i_chroma = VLC_CODEC_RGB16;
-# if defined(WORDS_BIGENDIAN)
- vgl->fmt.i_rmask = 0x001f;
- vgl->fmt.i_gmask = 0x07e0;
- vgl->fmt.i_bmask = 0xf800;
-# else
- vgl->fmt.i_rmask = 0xf800;
- vgl->fmt.i_gmask = 0x07e0;
- vgl->fmt.i_bmask = 0x001f;
-# endif
- vgl->tex_target = GL_TEXTURE_2D;
- vgl->tex_format = GL_RGB;
- vgl->tex_internal = GL_RGB;
- vgl->tex_type = GL_UNSIGNED_SHORT_5_6_5;
-#else
vgl->fmt.i_chroma = VLC_CODEC_RGB32;
# if defined(WORDS_BIGENDIAN)
vgl->fmt.i_rmask = 0xff000000;
vgl->tex_format = GL_RGBA;
vgl->tex_internal = GL_RGBA;
vgl->tex_type = GL_UNSIGNED_BYTE;
-#endif
/* Use YUV if possible and needed */
bool need_fs_yuv = false;
float yuv_range_correction = 1.0;
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");
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 )
{
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 */
/* 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;"
// 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);
if( link_status == GL_FALSE )
{
- fprintf( stderr, "Unable to use program %d", i );
+ fprintf( stderr, "Unable to use program %d\n", i );
free( vgl );
return NULL;
}
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;
right[0], top[0]
};
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- vgl->ActiveTexture( GL_TEXTURE0);
- vgl->ClientActiveTexture( GL_TEXTURE0);
- glEnable(vgl->tex_target);
- glBindTexture(vgl->tex_target, vgl->texture[0][0]);
+ for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
+ vgl->ActiveTexture( GL_TEXTURE0 + j );
+ vgl->ClientActiveTexture( GL_TEXTURE0 + j );
+
+ 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 );
+
glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
- glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisable(vgl->tex_target);
+ 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,
for( unsigned j = 0; j < vgl->chroma->plane_count; j++)
{
+ char *attribute = NULL;
const GLfloat texCoord[] = {
left[j], top[j],
left[j], bottom[j],
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,
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 );
}
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];
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);