Skip to content
Permalink
Browse files

Add initial GLSL video rendering support.

This is currently YUV to RGB colourspace conversion only (with the full
range of picture adjustments) - hardware deinterlacers will follow.

Still disabled by default.
  • Loading branch information
Mark Kendall
Mark Kendall committed Dec 18, 2010
1 parent af97999 commit c0d8c2201f6d4259f8f3676e3db3cb9979b3082d
@@ -649,19 +649,24 @@ bool OpenGLVideo::AddDeinterlacer(const QString &deinterlacer)
uint OpenGLVideo::AddFragmentProgram(OpenGLFilterType name,
QString deint, FrameScanType field)
{
if (!(gl_features & kGLExtFragProg))
uint ret = 0;
if (gl_context->GetProfile() == kGLHighProfile)
{
VERBOSE(VB_PLAYBACK, LOC_ERR + "Fragment programs not supported");
return 0;
QString vertex, fragment;
GetProgramStrings(vertex, fragment, name, deint, field);
return gl_context->CreateShaderObject(vertex, fragment);
}

QString program = GetProgramString(name, deint, field);

uint ret;
if (gl_context->CreateFragmentProgram(program, ret))
return ret;

return 0;
else if (gl_context->GetProfile() == kGLLegacyProfile)
{
QString program = GetProgramString(name, deint, field);
if (gl_context->CreateFragmentProgram(program, ret))
return ret;
}
else
{
VERBOSE(VB_PLAYBACK, LOC_ERR + "No OpenGL shader/program support");
}
return ret;
}

/**
@@ -1030,7 +1035,7 @@ void OpenGLVideo::PrepareFrame(bool topfieldfirst, FrameScanType scan,
}

if (type == kGLFilterYUV2RGB)
gl_context->SetFragmentParams(program, colourSpace->GetMatrix());
gl_context->SetProgramParams(program, colourSpace->GetMatrix());

gl_context->DrawBitmap(textures, texture_count, target, &trect, &vrect,
program);
@@ -1554,6 +1559,36 @@ QString OpenGLVideo::GetProgramString(OpenGLFilterType name,
return ret;
}

static const QString YUV2RGBVertexShader =
"GLSL_DEFINES"
"attribute vec4 a_color;\n"
"attribute vec2 a_texcoord0;\n"
"varying vec2 v_texcoord0;\n"
"void main() {\n"
" gl_Position = ftransform();\n"
" v_texcoord0 = a_texcoord0;\n"
"}\n";

static const QString YUV2RGBFragmentShader =
"GLSL_DEFINES"
"uniform sampler2D s_texture0;\n"
"uniform mat4 m_colourMatrix;\n"
"varying vec2 v_texcoord0;\n"
"void main(void)\n"
"{\n"
" vec4 yuva = texture2D(s_texture0, v_texcoord0);\n"
" vec4 res = vec4(yuva.arb, 1.0) * m_colourMatrix;\n"
" gl_FragColor = vec4(res.rgb, yuva.g);\n"
"}\n";

void OpenGLVideo::GetProgramStrings(QString &vertex, QString &fragment,
OpenGLFilterType filter,
QString deint, FrameScanType field)
{
vertex = YUV2RGBVertexShader;
fragment = YUV2RGBFragmentShader;
}

uint OpenGLVideo::ParseOptions(QString options)
{
uint ret = kGLMaxFeat - 1;
@@ -90,6 +90,10 @@ class OpenGLVideo
QString GetProgramString(OpenGLFilterType filter,
QString deint = QString::null,
FrameScanType field = kScan_Progressive);
void GetProgramStrings(QString &vertex, QString &fragment,
OpenGLFilterType filter,
QString deint = QString::null,
FrameScanType field = kScan_Progressive);
static QString FilterToString(OpenGLFilterType filter);
static OpenGLFilterType StringToFilter(const QString &filter);
QSize GetTextureSize(const QSize &size);
@@ -1172,7 +1172,51 @@ void MythRenderOpenGL::DrawBitmapHigh(uint *textures, uint texture_count,
const QRectF *src, const QRectF *dst,
uint prog)
{
if (prog && !m_shader_objects.contains(prog))
prog = 0;
if (prog == 0)
prog = m_shaders[kShaderDefault];

uint first = textures[0];

EnableShaderObject(prog);
SetBlend(false);

EnableTextures(first);
uint active_tex = 0;
for (uint i = 0; i < texture_count; i++)
{
if (m_textures.contains(textures[i]))
{
ActiveTexture(GL_TEXTURE0 + active_tex++);
glBindTexture(m_textures[textures[i]].m_type, textures[i]);
}
}

m_glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_textures[first].m_vbo);
UpdateTextureVertices(first, src, dst);
m_glBufferDataARB(GL_ARRAY_BUFFER_ARB, kVertexSize, NULL, GL_STREAM_DRAW);
void* target = m_glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY);
if (target)
memcpy(target, m_textures[first].m_vertex_data, kVertexSize);
m_glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);

m_glEnableVertexAttribArray(VERTEX_INDEX);
m_glEnableVertexAttribArray(TEXTURE_INDEX);

m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
VERTEX_SIZE * sizeof(GLfloat),
(const void *) kVertexOffset);
m_glVertexAttrib4f(COLOR_INDEX, 1.0, 1.0, 1.0, 1.0);
m_glVertexAttribPointer(TEXTURE_INDEX, TEXTURE_SIZE, GL_FLOAT, GL_FALSE,
TEXTURE_SIZE * sizeof(GLfloat),
(const void *) kTextureOffset);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

m_glDisableVertexAttribArray(TEXTURE_INDEX);
m_glDisableVertexAttribArray(VERTEX_INDEX);
m_glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}

void MythRenderOpenGL::DrawRectLegacy(const QRect &area, bool drawFill,
@@ -1366,6 +1410,8 @@ void MythRenderOpenGL::InitProcs(void)
GetProcAddress("glGetUniformLocationARB");
m_glUniform4f = (MYTH_GLUNIFORM4F)
GetProcAddress("glUniform4fARB");
m_glUniformMatrix4fv = (MYTH_GLUNIFORMMATRIX4FV)
GetProcAddress("glUniformMatrix4fvARB");
m_glVertexAttribPointer = (MYTH_GLVERTEXATTRIBPOINTER)
GetProcAddress("glVertexAttribPointer");
m_glEnableVertexAttribArray = (MYTH_GLENABLEVERTEXATTRIBARRAY)
@@ -1447,7 +1493,8 @@ void MythRenderOpenGL::InitFeatures(void)
m_glUseProgram && m_glGetInfoLog &&
m_glDetachObject && m_glGetObjectParameteriv &&
m_glDeleteObject && m_glGetUniformLocation &&
m_glUniform4f && m_glVertexAttribPointer &&
m_glUniform4f && m_glUniformMatrix4fv &&
m_glVertexAttribPointer &&
m_glEnableVertexAttribArray &&
m_glDisableVertexAttribArray &&
m_glBindAttribLocation &&
@@ -1594,6 +1641,7 @@ void MythRenderOpenGL::ResetProcs(void)
m_glDeleteObject = NULL;
m_glGetUniformLocation = NULL;
m_glUniform4f = NULL;
m_glUniformMatrix4fv = NULL;
m_glVertexAttribPointer = NULL;
m_glEnableVertexAttribArray = NULL;
m_glDisableVertexAttribArray = NULL;
@@ -2068,19 +2116,27 @@ uint MythRenderOpenGL::GetBufferSize(QSize size, uint fmt, uint type)
return size.width() * size.height() * bpp * bytes;
}

void MythRenderOpenGL::SetFragmentParams(uint fp, void* vals)
void MythRenderOpenGL::SetProgramParams(uint prog, void* vals)
{
makeCurrent();
const float *v = (float*)vals;

EnableFragmentProgram(fp);

float *v = (float*)vals;
m_glProgramLocalParameter4fARB(
GL_FRAGMENT_PROGRAM_ARB, 0, v[0], v[1], v[2], v[3]);
m_glProgramLocalParameter4fARB(
GL_FRAGMENT_PROGRAM_ARB, 1, v[4], v[5], v[6], v[7]);
m_glProgramLocalParameter4fARB(
GL_FRAGMENT_PROGRAM_ARB, 2, v[8], v[9], v[10], v[11]);
if (kGLLegacyProfile == m_profile)
{
EnableFragmentProgram(prog);
m_glProgramLocalParameter4fARB(
GL_FRAGMENT_PROGRAM_ARB, 0, v[0], v[1], v[2], v[3]);
m_glProgramLocalParameter4fARB(
GL_FRAGMENT_PROGRAM_ARB, 1, v[4], v[5], v[6], v[7]);
m_glProgramLocalParameter4fARB(
GL_FRAGMENT_PROGRAM_ARB, 2, v[8], v[9], v[10], v[11]);
}
else if (kGLHighProfile == m_profile)
{
EnableShaderObject(prog);
GLint loc = m_glGetUniformLocation(prog, "m_colourMatrix");
m_glUniformMatrix4fv(loc, 1, GL_FALSE, v);
}

doneCurrent();
}
@@ -79,6 +79,7 @@ class MPUBLIC MythRenderOpenGL : public QGLContext, public MythRender

void Init(void);

GLProfile GetProfile(void) { return m_profile; }
int GetMaxTextureSize(void) { return m_max_tex_size; }
uint GetFeatures(void) { return m_exts_supported; }
void SetFeatures(uint features);
@@ -116,7 +117,7 @@ class MPUBLIC MythRenderOpenGL : public QGLContext, public MythRender
bool CreateFragmentProgram(const QString &program, uint &prog);
void DeleteFragmentProgram(uint prog);
void EnableFragmentProgram(int fp);
void SetFragmentParams(uint fp, void* vals);
void SetProgramParams(uint prog, void* vals);

uint CreateShaderObject(const QString &vert, const QString &frag);
void DeleteShaderObject(uint obj);
@@ -274,6 +275,7 @@ class MPUBLIC MythRenderOpenGL : public QGLContext, public MythRender
MYTH_GLDELETEOBJECT m_glDeleteObject;
MYTH_GLGETUNIFORMLOCATION m_glGetUniformLocation;
MYTH_GLUNIFORM4F m_glUniform4f;
MYTH_GLUNIFORMMATRIX4FV m_glUniformMatrix4fv;
MYTH_GLVERTEXATTRIBPOINTER m_glVertexAttribPointer;
MYTH_GLENABLEVERTEXATTRIBARRAY m_glEnableVertexAttribArray;
MYTH_GLDISABLEVERTEXATTRIBARRAY m_glDisableVertexAttribArray;
@@ -226,6 +226,8 @@ typedef GLint ( * MYTH_GLGETUNIFORMLOCATION)
(GLuint program, const char *name);
typedef void ( * MYTH_GLUNIFORM4F)
(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
typedef void ( * MYTH_GLUNIFORMMATRIX4FV)
(GLint location, GLint size, GLboolean transpose, const GLfloat *values);
typedef void ( * MYTH_GLVERTEXATTRIBPOINTER)
(GLuint index, GLint size, GLenum type, GLboolean normalize,
GLsizei stride, const GLvoid *ptr);

0 comments on commit c0d8c22

Please sign in to comment.
You can’t perform that action at this time.