Skip to content

Commit

Permalink
Add initial GLSL video rendering support.
Browse files Browse the repository at this point in the history
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 committed Dec 18, 2010
1 parent af97999 commit c0d8c22
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 24 deletions.
59 changes: 47 additions & 12 deletions mythtv/libs/libmythtv/openglvideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions mythtv/libs/libmythtv/openglvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
78 changes: 67 additions & 11 deletions mythtv/libs/libmythui/mythrender_opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
4 changes: 3 additions & 1 deletion mythtv/libs/libmythui/mythrender_opengl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions mythtv/libs/libmythui/mythrender_opengl_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit c0d8c22

Please sign in to comment.