MythTV  0.26-pre
mythrender_opengl2.cpp
Go to the documentation of this file.
00001 #include "math.h"
00002 #include "mythrender_opengl2.h"
00003 
00004 #define LOC QString("OpenGL2: ")
00005 
00006 class GLMatrix
00007 {
00008   public:
00009     GLMatrix()
00010     {
00011         setToIdentity();
00012     }
00013 
00014     void setToIdentity(void)
00015     {
00016         for (int i = 0; i < 4; i++)
00017             for (int j = 0; j < 4; j++)
00018                 m[i][j] = (i == j) ? 1.0f : 0.0f;
00019     }
00020 
00021     void rotate(int degrees)
00022     {
00023         float rotation = degrees * (M_PI / 180.0);
00024         GLMatrix rotate;
00025         rotate.m[0][0] = rotate.m[1][1] = cos(rotation);
00026         rotate.m[0][1] = sin(rotation);
00027         rotate.m[1][0] = -rotate.m[0][1];
00028         this->operator *=(rotate);
00029     }
00030 
00031     void scale(float horizontal, float vertical)
00032     {
00033         GLMatrix scale;
00034         scale.m[0][0] = horizontal;
00035         scale.m[1][1] = vertical;
00036         this->operator *=(scale);
00037     }
00038 
00039     void translate(float x, float y)
00040     {
00041         GLMatrix translate;
00042         translate.m[3][0] = x;
00043         translate.m[3][1] = y;
00044         this->operator *=(translate);
00045     }
00046 
00047     GLMatrix & operator*=(const GLMatrix &r)
00048     {
00049         for (int i = 0; i < 4; i++)
00050             product(i, r);
00051         return *this;
00052     }
00053 
00054     void product(int row, const GLMatrix &r)
00055     {
00056         float t0, t1, t2, t3;
00057         t0 = m[row][0] * r.m[0][0] + m[row][1] * r.m[1][0] + m[row][2] * r.m[2][0] + m[row][3] * r.m[3][0];
00058         t1 = m[row][0] * r.m[0][1] + m[row][1] * r.m[1][1] + m[row][2] * r.m[2][1] + m[row][3] * r.m[3][1];
00059         t2 = m[row][0] * r.m[0][2] + m[row][1] * r.m[1][2] + m[row][2] * r.m[2][2] + m[row][3] * r.m[3][2];
00060         t3 = m[row][0] * r.m[0][3] + m[row][1] * r.m[1][3] + m[row][2] * r.m[2][3] + m[row][3] * r.m[3][3];
00061         m[row][0] = t0; m[row][1] = t1; m[row][2] = t2; m[row][3] = t3;
00062     }
00063 
00064     float m[4][4];
00065 };
00066 
00067 #define VERTEX_INDEX  0
00068 #define COLOR_INDEX   1
00069 #define TEXTURE_INDEX 2
00070 #define VERTEX_SIZE   2
00071 #define TEXTURE_SIZE  2
00072 
00073 static const GLuint kVertexOffset  = 0;
00074 static const GLuint kTextureOffset = 8 * sizeof(GLfloat);
00075 static const GLuint kVertexSize    = 16 * sizeof(GLfloat);
00076 
00077 static const QString kDefaultVertexShader =
00078 "GLSL_DEFINES"
00079 "attribute vec2 a_position;\n"
00080 "attribute vec4 a_color;\n"
00081 "attribute vec2 a_texcoord0;\n"
00082 "varying   vec4 v_color;\n"
00083 "varying   vec2 v_texcoord0;\n"
00084 "uniform   mat4 u_projection;\n"
00085 "uniform   mat4 u_transform;\n"
00086 "void main() {\n"
00087 "    gl_Position = u_projection * u_transform * vec4(a_position, 0.0, 1.0);\n"
00088 "    v_texcoord0 = a_texcoord0;\n"
00089 "    v_color     = a_color;\n"
00090 "}\n";
00091 
00092 static const QString kDefaultFragmentShader =
00093 "GLSL_DEFINES"
00094 "uniform GLSL_SAMPLER s_texture0;\n"
00095 "varying vec4 v_color;\n"
00096 "varying vec2 v_texcoord0;\n"
00097 "void main(void)\n"
00098 "{\n"
00099 "    gl_FragColor = GLSL_TEXTURE(s_texture0, v_texcoord0) * v_color;\n"
00100 "}\n";
00101 
00102 static const QString kSimpleVertexShader =
00103 "GLSL_DEFINES"
00104 "attribute vec2 a_position;\n"
00105 "attribute vec4 a_color;\n"
00106 "varying   vec4 v_color;\n"
00107 "uniform   mat4 u_projection;\n"
00108 "uniform   mat4 u_transform;\n"
00109 "void main() {\n"
00110 "    gl_Position = u_projection * u_transform * vec4(a_position, 0.0, 1.0);\n"
00111 "    v_color     = a_color;\n"
00112 "}\n";
00113 
00114 static const QString kSimpleFragmentShader =
00115 "GLSL_DEFINES"
00116 "varying vec4 v_color;\n"
00117 "void main(void)\n"
00118 "{\n"
00119 "    gl_FragColor = v_color;\n"
00120 "}\n";
00121 
00122 static const QString kDrawVertexShader =
00123 "GLSL_DEFINES"
00124 "attribute vec2 a_position;\n"
00125 "attribute vec4 a_color;\n"
00126 "varying   vec4 v_color;\n"
00127 "varying   vec2 v_position;\n"
00128 "uniform   mat4 u_projection;\n"
00129 "uniform   mat4 u_transform;\n"
00130 "void main() {\n"
00131 "    gl_Position = u_projection * u_transform * vec4(a_position, 0.0, 1.0);\n"
00132 "    v_color     = a_color;\n"
00133 "    v_position  = a_position;\n"
00134 "}\n";
00135 
00136 static const QString kCircleFragmentShader =
00137 "GLSL_DEFINES"
00138 "varying vec4 v_color;\n"
00139 "varying vec2 v_position;\n"
00140 "uniform mat4 u_parameters;\n"
00141 "void main(void)\n"
00142 "{\n"
00143 "    float dis = distance(v_position.xy, u_parameters[0].xy);\n"
00144 "    float mult = smoothstep(u_parameters[0].z, u_parameters[0].w, dis);\n"
00145 "    gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
00146 "}\n";
00147 
00148 static const QString kCircleEdgeFragmentShader =
00149 "GLSL_DEFINES"
00150 "varying vec4 v_color;\n"
00151 "varying vec2 v_position;\n"
00152 "uniform mat4 u_parameters;\n"
00153 "void main(void)\n"
00154 "{\n"
00155 "    float dis = distance(v_position.xy, u_parameters[0].xy);\n"
00156 "    float rad = u_parameters[0].z;\n"
00157 "    float wid = u_parameters[0].w;\n"
00158 "    float mult = smoothstep(rad + wid, rad + (wid - 1.0), dis) * smoothstep(rad - (wid + 1.0), rad - wid, dis);\n"
00159 "    gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
00160 "}\n";
00161 
00162 static const QString kVertLineFragmentShader =
00163 "GLSL_DEFINES"
00164 "varying vec4 v_color;\n"
00165 "varying vec2 v_position;\n"
00166 "uniform mat4 u_parameters;\n"
00167 "void main(void)\n"
00168 "{\n"
00169 "    float dis = abs(u_parameters[0].x - v_position.x);\n"
00170 "    float y = u_parameters[0].y * 2.0;\n"
00171 "    float mult = smoothstep(y, y - 0.1, dis) * smoothstep(-0.1, 0.0, dis);\n"
00172 "    gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
00173 "}\n";
00174 
00175 static const QString kHorizLineFragmentShader =
00176 "GLSL_DEFINES"
00177 "varying vec4 v_color;\n"
00178 "varying vec2 v_position;\n"
00179 "uniform mat4 u_parameters;\n"
00180 "void main(void)\n"
00181 "{\n"
00182 "    float dis = abs(u_parameters[0].x - v_position.y);\n"
00183 "    float x = u_parameters[0].y * 2.0;\n"
00184 "    float mult = smoothstep(x, x - 0.1, dis) * smoothstep(-0.1, 0.0, dis);\n"
00185 "    gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
00186 "}\n";
00187 
00188 class MythGLShaderObject
00189 {
00190   public:
00191     MythGLShaderObject(uint vert, uint frag)
00192       : m_vertex_shader(vert), m_fragment_shader(frag) { }
00193     MythGLShaderObject()
00194       : m_vertex_shader(0), m_fragment_shader(0) { }
00195 
00196     GLuint m_vertex_shader;
00197     GLuint m_fragment_shader;
00198 };
00199 
00200 MythRenderOpenGL2::MythRenderOpenGL2(const QGLFormat& format,
00201                                      QPaintDevice* device,
00202                                      RenderType type)
00203   : MythRenderOpenGL(format, device, type)
00204 {
00205     ResetVars();
00206     ResetProcs();
00207 }
00208 
00209 MythRenderOpenGL2::MythRenderOpenGL2(const QGLFormat& format, RenderType type)
00210   : MythRenderOpenGL(format, type)
00211 {
00212     ResetVars();
00213     ResetProcs();
00214 }
00215 
00216 MythRenderOpenGL2::~MythRenderOpenGL2()
00217 {
00218     if (!isValid())
00219         return;
00220     makeCurrent();
00221     DeleteOpenGLResources();
00222     doneCurrent();
00223 }
00224 
00225 void MythRenderOpenGL2::Init2DState(void)
00226 {
00227     MythRenderOpenGL::Init2DState();
00228 }
00229 
00230 void MythRenderOpenGL2::ResetVars(void)
00231 {
00232     MythRenderOpenGL::ResetVars();
00233     memset(m_projection, 0, sizeof(m_projection));
00234     memset(m_parameters, 0, sizeof(m_parameters));
00235     memset(m_shaders, 0, sizeof(m_shaders));
00236     m_active_obj = 0;
00237     m_transforms.clear();
00238     m_transforms.push(GLMatrix());
00239 }
00240 
00241 void MythRenderOpenGL2::ResetProcs(void)
00242 {
00243     MythRenderOpenGL::ResetProcs();
00244 
00245     m_glCreateShader = NULL;
00246     m_glShaderSource = NULL;
00247     m_glCompileShader = NULL;
00248     m_glGetShaderiv = NULL;
00249     m_glGetShaderInfoLog = NULL;
00250     m_glCreateProgram = NULL;
00251     m_glAttachShader = NULL;
00252     m_glLinkProgram = NULL;
00253     m_glUseProgram = NULL;
00254     m_glGetProgramInfoLog = NULL;
00255     m_glGetProgramiv = NULL;
00256     m_glDetachShader = NULL;
00257     m_glDeleteShader = NULL;
00258     m_glGetUniformLocation = NULL;
00259     m_glUniform4f = NULL;
00260     m_glUniformMatrix4fv = NULL;
00261     m_glVertexAttribPointer = NULL;
00262     m_glEnableVertexAttribArray = NULL;
00263     m_glDisableVertexAttribArray = NULL;
00264     m_glBindAttribLocation = NULL;
00265     m_glVertexAttrib4f = NULL;
00266 }
00267 
00268 bool MythRenderOpenGL2::InitFeatures(void)
00269 {
00270     m_exts_supported = kGLFeatNone;
00271 
00272     static bool glslshaders = true;
00273     static bool check       = true;
00274     if (check)
00275     {
00276         check = false;
00277         glslshaders = !getenv("OPENGL_NOGLSL");
00278         if (!glslshaders)
00279             LOG(VB_GENERAL, LOG_INFO, LOC + "Disabling GLSL.");
00280     }
00281 
00282     // These should all be present for a valid OpenGL2.0/ES installation
00283     if (m_glShaderSource  && m_glCreateShader &&
00284         m_glCompileShader && m_glGetShaderiv &&
00285         m_glGetShaderInfoLog &&
00286         m_glCreateProgram &&
00287         m_glAttachShader  && m_glLinkProgram &&
00288         m_glUseProgram    && m_glGetProgramInfoLog &&
00289         m_glDetachShader  && m_glGetProgramiv &&
00290         m_glDeleteShader  && m_glGetUniformLocation &&
00291         m_glUniform4f     && m_glUniformMatrix4fv &&
00292         m_glVertexAttribPointer &&
00293         m_glEnableVertexAttribArray &&
00294         m_glDisableVertexAttribArray &&
00295         m_glBindAttribLocation &&
00296         m_glVertexAttrib4f && glslshaders)
00297     {
00298         LOG(VB_GENERAL, LOG_INFO, LOC + "GLSL supported");
00299         m_exts_supported += kGLSL;
00300     }
00301 
00302     MythRenderOpenGL::InitFeatures();
00303 
00304     // After rect texture support
00305     if (m_exts_supported & kGLSL)
00306     {
00307         DeleteDefaultShaders();
00308         CreateDefaultShaders();
00309     }
00310 
00311     return true;
00312 }
00313 
00314 void MythRenderOpenGL2::InitProcs(void)
00315 {
00316     MythRenderOpenGL::InitProcs();
00317 
00318     // GLSL version
00319     m_GLSLVersion = "#version 110\n";
00320     m_qualifiers = QString();
00321 
00322     m_glCreateShader = (MYTH_GLCREATESHADERPROC)
00323         GetProcAddress("glCreateShader");
00324     m_glShaderSource = (MYTH_GLSHADERSOURCEPROC)
00325         GetProcAddress("glShaderSource");
00326     m_glCompileShader = (MYTH_GLCOMPILESHADERPROC)
00327         GetProcAddress("glCompileShader");
00328     m_glGetShaderiv = (MYTH_GLGETSHADERIVPROC)
00329         GetProcAddress("glGetShaderiv");
00330     m_glGetShaderInfoLog = (MYTH_GLGETSHADERINFOLOGPROC)
00331         GetProcAddress("glGetShaderInfoLog");
00332     m_glDeleteProgram = (MYTH_GLDELETEPROGRAMPROC)
00333         GetProcAddress("glDeleteProgram");
00334     m_glCreateProgram = (MYTH_GLCREATEPROGRAMPROC)
00335         GetProcAddress("glCreateProgram");
00336     m_glAttachShader = (MYTH_GLATTACHSHADERPROC)
00337         GetProcAddress("glAttachShader");
00338     m_glLinkProgram = (MYTH_GLLINKPROGRAMPROC)
00339         GetProcAddress("glLinkProgram");
00340     m_glUseProgram = (MYTH_GLUSEPROGRAMPROC)
00341         GetProcAddress("glUseProgram");
00342     m_glGetProgramInfoLog = (MYTH_GLGETPROGRAMINFOLOGPROC)
00343         GetProcAddress("glGetProgramInfoLog");
00344     m_glGetProgramiv = (MYTH_GLGETPROGRAMIVPROC)
00345         GetProcAddress("glGetProgramiv");
00346     m_glDetachShader = (MYTH_GLDETACHSHADERPROC)
00347         GetProcAddress("glDetachShader");
00348     m_glDeleteShader = (MYTH_GLDELETESHADERPROC)
00349         GetProcAddress("glDeleteShader");
00350     m_glGetUniformLocation = (MYTH_GLGETUNIFORMLOCATIONPROC)
00351         GetProcAddress("glGetUniformLocation");
00352     m_glUniform4f = (MYTH_GLUNIFORM4FPROC)
00353         GetProcAddress("glUniform4f");
00354     m_glUniformMatrix4fv = (MYTH_GLUNIFORMMATRIX4FVPROC)
00355         GetProcAddress("glUniformMatrix4fv");
00356     m_glVertexAttribPointer = (MYTH_GLVERTEXATTRIBPOINTERPROC)
00357         GetProcAddress("glVertexAttribPointer");
00358     m_glEnableVertexAttribArray = (MYTH_GLENABLEVERTEXATTRIBARRAYPROC)
00359         GetProcAddress("glEnableVertexAttribArray");
00360     m_glDisableVertexAttribArray = (MYTH_GLDISABLEVERTEXATTRIBARRAYPROC)
00361         GetProcAddress("glDisableVertexAttribArray");
00362     m_glBindAttribLocation = (MYTH_GLBINDATTRIBLOCATIONPROC)
00363         GetProcAddress("glBindAttribLocation");
00364     m_glVertexAttrib4f = (MYTH_GLVERTEXATTRIB4FPROC)
00365         GetProcAddress("glVertexAttrib4f");
00366 }
00367 
00368 uint MythRenderOpenGL2::CreateShaderObject(const QString &vertex,
00369                                           const QString &fragment)
00370 {
00371     if (!(m_exts_supported & kGLSL))
00372         return 0;
00373 
00374     OpenGLLocker locker(this);
00375 
00376     uint result = 0;
00377     QString vert_shader = vertex.isEmpty() ? kDefaultVertexShader : vertex;
00378     QString frag_shader = fragment.isEmpty() ? kDefaultFragmentShader: fragment;
00379     vert_shader.detach();
00380     frag_shader.detach();
00381 
00382     OptimiseShaderSource(vert_shader);
00383     OptimiseShaderSource(frag_shader);
00384 
00385     result = m_glCreateProgram();
00386     if (!result)
00387         return 0;
00388 
00389     MythGLShaderObject object(CreateShader(GL_VERTEX_SHADER, vert_shader),
00390                               CreateShader(GL_FRAGMENT_SHADER, frag_shader));
00391     m_shader_objects.insert(result, object);
00392 
00393     if (!ValidateShaderObject(result))
00394     {
00395         DeleteShaderObject(result);
00396         return 0;
00397     }
00398 
00399     return result;
00400 }
00401 
00402 void MythRenderOpenGL2::DeleteShaderObject(uint obj)
00403 {
00404     if (!m_shader_objects.contains(obj))
00405         return;
00406 
00407     makeCurrent();
00408 
00409     GLuint vertex   = m_shader_objects[obj].m_vertex_shader;
00410     GLuint fragment = m_shader_objects[obj].m_fragment_shader;
00411     m_glDetachShader(obj, vertex);
00412     m_glDetachShader(obj, fragment);
00413     m_glDeleteShader(vertex);
00414     m_glDeleteShader(fragment);
00415     m_glDeleteProgram(obj);
00416     m_shader_objects.remove(obj);
00417 
00418     Flush(true);
00419     doneCurrent();
00420 }
00421 
00422 void MythRenderOpenGL2::EnableShaderObject(uint obj)
00423 {
00424     if (obj == m_active_obj)
00425         return;
00426 
00427     if (!obj && m_active_obj)
00428     {
00429         makeCurrent();
00430         m_glUseProgram(0);
00431         m_active_obj = 0;
00432         doneCurrent();
00433         return;
00434     }
00435 
00436     if (!m_shader_objects.contains(obj))
00437         return;
00438 
00439     makeCurrent();
00440     m_glUseProgram(obj);
00441     m_active_obj = obj;
00442     doneCurrent();
00443 }
00444 
00445 void MythRenderOpenGL2::SetShaderParams(uint obj, void* vals,
00446                                         const char* uniform)
00447 {
00448     makeCurrent();
00449     const float *v = (float*)vals;
00450 
00451     EnableShaderObject(obj);
00452     GLint loc = m_glGetUniformLocation(obj, uniform);
00453     m_glUniformMatrix4fv(loc, 1, GL_FALSE, v);
00454     doneCurrent();
00455 }
00456 
00457 void MythRenderOpenGL2::DrawBitmapPriv(uint tex, const QRect *src,
00458                                        const QRect *dst, uint prog, int alpha,
00459                                        int red, int green, int blue)
00460 {
00461     if (prog && !m_shader_objects.contains(prog))
00462         prog = 0;
00463     if (prog == 0)
00464         prog = m_shaders[kShaderDefault];
00465 
00466     EnableShaderObject(prog);
00467     SetShaderParams(prog, &m_projection[0][0], "u_projection");
00468     SetShaderParams(prog, &m_transforms.top().m[0][0], "u_transform");
00469     SetBlend(true);
00470 
00471     EnableTextures(tex);
00472     glBindTexture(m_textures[tex].m_type, tex);
00473 
00474     m_glBindBuffer(GL_ARRAY_BUFFER, m_textures[tex].m_vbo);
00475     UpdateTextureVertices(tex, src, dst);
00476     m_glBufferData(GL_ARRAY_BUFFER, kVertexSize, NULL, GL_STREAM_DRAW);
00477     void* target = m_glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
00478     if (target)
00479         memcpy(target, m_textures[tex].m_vertex_data, kVertexSize);
00480     m_glUnmapBuffer(GL_ARRAY_BUFFER);
00481 
00482     m_glEnableVertexAttribArray(VERTEX_INDEX);
00483     m_glEnableVertexAttribArray(TEXTURE_INDEX);
00484 
00485     m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00486                             VERTEX_SIZE * sizeof(GLfloat),
00487                             (const void *) kVertexOffset);
00488     m_glVertexAttrib4f(COLOR_INDEX, red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0);
00489     m_glVertexAttribPointer(TEXTURE_INDEX, TEXTURE_SIZE, GL_FLOAT, GL_FALSE,
00490                             TEXTURE_SIZE * sizeof(GLfloat),
00491                             (const void *) kTextureOffset);
00492 
00493     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00494 
00495     m_glDisableVertexAttribArray(TEXTURE_INDEX);
00496     m_glDisableVertexAttribArray(VERTEX_INDEX);
00497     m_glBindBuffer(GL_ARRAY_BUFFER, 0);
00498 }
00499 
00500 
00501 
00502 void MythRenderOpenGL2::DrawBitmapPriv(uint *textures, uint texture_count,
00503                                        const QRectF *src, const QRectF *dst,
00504                                        uint prog)
00505 {
00506     if (prog && !m_shader_objects.contains(prog))
00507         prog = 0;
00508     if (prog == 0)
00509         prog = m_shaders[kShaderDefault];
00510 
00511     uint first = textures[0];
00512 
00513     EnableShaderObject(prog);
00514     SetShaderParams(prog, &m_projection[0][0], "u_projection");
00515     SetShaderParams(prog, &m_transforms.top().m[0][0], "u_transform");
00516     SetBlend(false);
00517 
00518     EnableTextures(first);
00519     uint active_tex = 0;
00520     for (uint i = 0; i < texture_count; i++)
00521     {
00522         if (m_textures.contains(textures[i]))
00523         {
00524             ActiveTexture(GL_TEXTURE0 + active_tex++);
00525             glBindTexture(m_textures[textures[i]].m_type, textures[i]);
00526         }
00527     }
00528 
00529     m_glBindBuffer(GL_ARRAY_BUFFER, m_textures[first].m_vbo);
00530     UpdateTextureVertices(first, src, dst);
00531     m_glBufferData(GL_ARRAY_BUFFER, kVertexSize, NULL, GL_STREAM_DRAW);
00532     void* target = m_glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
00533     if (target)
00534         memcpy(target, m_textures[first].m_vertex_data, kVertexSize);
00535     m_glUnmapBuffer(GL_ARRAY_BUFFER);
00536 
00537     m_glEnableVertexAttribArray(VERTEX_INDEX);
00538     m_glEnableVertexAttribArray(TEXTURE_INDEX);
00539 
00540     m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00541                             VERTEX_SIZE * sizeof(GLfloat),
00542                             (const void *) kVertexOffset);
00543     m_glVertexAttrib4f(COLOR_INDEX, 1.0, 1.0, 1.0, 1.0);
00544     m_glVertexAttribPointer(TEXTURE_INDEX, TEXTURE_SIZE, GL_FLOAT, GL_FALSE,
00545                             TEXTURE_SIZE * sizeof(GLfloat),
00546                             (const void *) kTextureOffset);
00547 
00548     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00549 
00550     m_glDisableVertexAttribArray(TEXTURE_INDEX);
00551     m_glDisableVertexAttribArray(VERTEX_INDEX);
00552     m_glBindBuffer(GL_ARRAY_BUFFER, 0);
00553 }
00554 
00555 void MythRenderOpenGL2::DrawRectPriv(const QRect &area, const QBrush &fillBrush,
00556                                      const QPen &linePen, int alpha)
00557 {
00558     DrawRoundRectPriv(area, 1, fillBrush, linePen, alpha);
00559 }
00560 
00561 void MythRenderOpenGL2::DrawRoundRectPriv(const QRect &area, int cornerRadius,
00562                                           const QBrush &fillBrush,
00563                                           const QPen &linePen, int alpha)
00564 {
00565     int lineWidth = linePen.width();
00566     int halfline  = lineWidth / 2;
00567     int rad = cornerRadius - halfline;
00568 
00569     if ((area.width() / 2) < rad)
00570         rad = area.width() / 2;
00571 
00572     if ((area.height() / 2) < rad)
00573         rad = area.height() / 2;
00574     int dia = rad * 2;
00575 
00576 
00577     QRect r(area.left() + halfline, area.top() + halfline,
00578             area.width() - (halfline * 2), area.height() - (halfline * 2));
00579 
00580     QRect tl(r.left(),  r.top(), rad, rad);
00581     QRect tr(r.left() + r.width() - rad, r.top(), rad, rad);
00582     QRect bl(r.left(),  r.top() + r.height() - rad, rad, rad);
00583     QRect br(r.left() + r.width() - rad, r.top() + r.height() - rad, rad, rad);
00584 
00585     SetBlend(true);
00586     DisableTextures();
00587 
00588     m_glEnableVertexAttribArray(VERTEX_INDEX);
00589 
00590     if (fillBrush.style() != Qt::NoBrush)
00591     {
00592         // Get the shaders
00593         int elip = m_shaders[kShaderCircle];
00594         int fill = m_shaders[kShaderSimple];
00595 
00596         // Set the fill color
00597         m_glVertexAttrib4f(COLOR_INDEX,
00598                            fillBrush.color().red() / 255.0,
00599                            fillBrush.color().green() / 255.0,
00600                            fillBrush.color().blue() / 255.0,
00601                           (fillBrush.color().alpha() / 255.0) * (alpha / 255.0));
00602 
00603         // Set the radius
00604         m_parameters[0][2] = rad;
00605         m_parameters[0][3] = rad - 1.0;
00606 
00607         // Enable the Circle shader
00608         SetShaderParams(elip, &m_projection[0][0], "u_projection");
00609         SetShaderParams(elip, &m_transforms.top().m[0][0], "u_transform");
00610 
00611         // Draw the top left segment
00612         m_parameters[0][0] = tl.left() + rad;
00613         m_parameters[0][1] = tl.top() + rad;
00614         SetShaderParams(elip, &m_parameters[0][0], "u_parameters");
00615         GetCachedVBO(GL_TRIANGLE_STRIP, tl);
00616         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00617                                 VERTEX_SIZE * sizeof(GLfloat),
00618                                (const void *) kVertexOffset);
00619         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00620 
00621         // Draw the top right segment
00622         m_parameters[0][0] = tr.left();
00623         m_parameters[0][1] = tr.top() + rad;
00624         SetShaderParams(elip, &m_parameters[0][0], "u_parameters");
00625         GetCachedVBO(GL_TRIANGLE_STRIP, tr);
00626         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00627                                 VERTEX_SIZE * sizeof(GLfloat),
00628                                (const void *) kVertexOffset);
00629         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00630 
00631         // Draw the bottom left segment
00632         m_parameters[0][0] = bl.left() + rad;
00633         m_parameters[0][1] = bl.top();
00634         SetShaderParams(elip, &m_parameters[0][0], "u_parameters");
00635         GetCachedVBO(GL_TRIANGLE_STRIP, bl);
00636         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00637                                 VERTEX_SIZE * sizeof(GLfloat),
00638                                (const void *) kVertexOffset);
00639         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00640 
00641         // Draw the bottom right segment
00642         m_parameters[0][0] = br.left();
00643         m_parameters[0][1] = br.top();
00644         SetShaderParams(elip, &m_parameters[0][0], "u_parameters");
00645         GetCachedVBO(GL_TRIANGLE_STRIP, br);
00646         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00647                                 VERTEX_SIZE * sizeof(GLfloat),
00648                                (const void *) kVertexOffset);
00649         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00650 
00651         // Fill the remaining areas
00652         QRect main(r.left() + rad, r.top(), r.width() - dia, r.height());
00653         QRect left(r.left(), r.top() + rad, rad, r.height() - dia);
00654         QRect right(r.left() + r.width() - rad, r.top() + rad, rad, r.height() - dia);
00655 
00656         EnableShaderObject(fill);
00657         SetShaderParams(fill, &m_projection[0][0], "u_projection");
00658         SetShaderParams(fill, &m_transforms.top().m[0][0], "u_transform");
00659 
00660         GetCachedVBO(GL_TRIANGLE_STRIP, main);
00661         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00662                                 VERTEX_SIZE * sizeof(GLfloat),
00663                                (const void *) kVertexOffset);
00664         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00665         GetCachedVBO(GL_TRIANGLE_STRIP, left);
00666         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00667                                 VERTEX_SIZE * sizeof(GLfloat),
00668                                (const void *) kVertexOffset);
00669         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00670         GetCachedVBO(GL_TRIANGLE_STRIP, right);
00671         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00672                                 VERTEX_SIZE * sizeof(GLfloat),
00673                                (const void *) kVertexOffset);
00674         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00675         m_glBindBuffer(GL_ARRAY_BUFFER, 0);
00676     }
00677 
00678     if (linePen.style() != Qt::NoPen)
00679     {
00680         // Get the shaders
00681         int edge = m_shaders[kShaderCircleEdge];
00682         int vline = m_shaders[kShaderVertLine];
00683         int hline = m_shaders[kShaderHorizLine];
00684 
00685         // Set the line color
00686         m_glVertexAttrib4f(COLOR_INDEX,
00687                            linePen.color().red() / 255.0,
00688                            linePen.color().green() / 255.0,
00689                            linePen.color().blue() / 255.0,
00690                           (linePen.color().alpha() / 255.0) * (alpha / 255.0));
00691 
00692         // Set the radius and width
00693         m_parameters[0][2] = rad - lineWidth / 2.0;
00694         m_parameters[0][3] = lineWidth / 2.0;
00695 
00696         // Enable the edge shader
00697         SetShaderParams(edge, &m_projection[0][0], "u_projection");
00698         SetShaderParams(edge, &m_transforms.top().m[0][0], "u_transform");
00699 
00700         // Draw the top left edge segment
00701         m_parameters[0][0] = tl.left() + rad;
00702         m_parameters[0][1] = tl.top() + rad;
00703         SetShaderParams(edge, &m_parameters[0][0], "u_parameters");
00704         GetCachedVBO(GL_TRIANGLE_STRIP, tl);
00705         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00706                                 VERTEX_SIZE * sizeof(GLfloat),
00707                                (const void *) kVertexOffset);
00708         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00709 
00710         // Draw the top right edge segment
00711         m_parameters[0][0] = tr.left();
00712         m_parameters[0][1] = tr.top() + rad;
00713         SetShaderParams(edge, &m_parameters[0][0], "u_parameters");
00714         GetCachedVBO(GL_TRIANGLE_STRIP, tr);
00715         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00716                                 VERTEX_SIZE * sizeof(GLfloat),
00717                                (const void *) kVertexOffset);
00718         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00719 
00720         // Draw the bottom left edge segment
00721         m_parameters[0][0] = bl.left() + rad;
00722         m_parameters[0][1] = bl.top();
00723         SetShaderParams(edge, &m_parameters[0][0], "u_parameters");
00724         GetCachedVBO(GL_TRIANGLE_STRIP, bl);
00725         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00726                                 VERTEX_SIZE * sizeof(GLfloat),
00727                                (const void *) kVertexOffset);
00728         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00729 
00730         // Draw the bottom right edge segment
00731         m_parameters[0][0] = br.left();
00732         m_parameters[0][1] = br.top();
00733         SetShaderParams(edge, &m_parameters[0][0], "u_parameters");
00734         GetCachedVBO(GL_TRIANGLE_STRIP, br);
00735         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00736                                 VERTEX_SIZE * sizeof(GLfloat),
00737                                (const void *) kVertexOffset);
00738         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00739 
00740         // Vertical lines
00741         SetShaderParams(vline, &m_projection[0][0], "u_projection");
00742         SetShaderParams(vline, &m_transforms.top().m[0][0], "u_transform");
00743 
00744         m_parameters[0][1] = lineWidth / 2.0;
00745         QRect vl(r.left(), r.top() + rad,
00746                  lineWidth, r.height() - dia);
00747 
00748         // Draw the left line segment
00749         m_parameters[0][0] = vl.left() + lineWidth;
00750         SetShaderParams(vline, &m_parameters[0][0], "u_parameters");
00751         GetCachedVBO(GL_TRIANGLE_STRIP, vl);
00752         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00753                                 VERTEX_SIZE * sizeof(GLfloat),
00754                                (const void *) kVertexOffset);
00755         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00756 
00757         // Draw the right line segment
00758         vl.translate(r.width() - lineWidth, 0);
00759         m_parameters[0][0] = vl.left();
00760         SetShaderParams(vline, &m_parameters[0][0], "u_parameters");
00761         GetCachedVBO(GL_TRIANGLE_STRIP, vl);
00762         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00763                                 VERTEX_SIZE * sizeof(GLfloat),
00764                                (const void *) kVertexOffset);
00765         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00766 
00767         // Horizontal lines
00768         SetShaderParams(hline, &m_projection[0][0], "u_projection");
00769         SetShaderParams(hline, &m_transforms.top().m[0][0], "u_transform");
00770         QRect hl(r.left() + rad, r.top(),
00771                  r.width() - dia, lineWidth);
00772 
00773         // Draw the top line segment
00774         m_parameters[0][0] = hl.top() + lineWidth;
00775         SetShaderParams(hline, &m_parameters[0][0], "u_parameters");
00776         GetCachedVBO(GL_TRIANGLE_STRIP, hl);
00777         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00778                                 VERTEX_SIZE * sizeof(GLfloat),
00779                                (const void *) kVertexOffset);
00780         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00781 
00782         // Draw the bottom line segment
00783         hl.translate(0, r.height() - lineWidth);
00784         m_parameters[0][0] = hl.top();
00785         SetShaderParams(hline, &m_parameters[0][0], "u_parameters");
00786         GetCachedVBO(GL_TRIANGLE_STRIP, hl);
00787         m_glVertexAttribPointer(VERTEX_INDEX, VERTEX_SIZE, GL_FLOAT, GL_FALSE,
00788                                 VERTEX_SIZE * sizeof(GLfloat),
00789                                (const void *) kVertexOffset);
00790         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00791 
00792         m_glBindBuffer(GL_ARRAY_BUFFER, 0);
00793     }
00794 
00795     m_glDisableVertexAttribArray(VERTEX_INDEX);
00796 }
00797 
00798 void MythRenderOpenGL2::CreateDefaultShaders(void)
00799 {
00800     m_shaders[kShaderSimple]  = CreateShaderObject(kSimpleVertexShader,
00801                                                    kSimpleFragmentShader);
00802     m_shaders[kShaderDefault] = CreateShaderObject(kDefaultVertexShader,
00803                                                    kDefaultFragmentShader);
00804     m_shaders[kShaderCircle]  = CreateShaderObject(kDrawVertexShader,
00805                                                    kCircleFragmentShader);
00806     m_shaders[kShaderCircleEdge] = CreateShaderObject(kDrawVertexShader,
00807                                                    kCircleEdgeFragmentShader);
00808     m_shaders[kShaderVertLine]   = CreateShaderObject(kDrawVertexShader,
00809                                                    kVertLineFragmentShader);
00810     m_shaders[kShaderHorizLine]  = CreateShaderObject(kDrawVertexShader,
00811                                                    kHorizLineFragmentShader);
00812 }
00813 
00814 void MythRenderOpenGL2::DeleteDefaultShaders(void)
00815 {
00816     for (int i = 0; i < kShaderCount; i++)
00817     {
00818         DeleteShaderObject(m_shaders[i]);
00819         m_shaders[i] = 0;
00820     }
00821 }
00822 
00823 uint MythRenderOpenGL2::CreateShader(int type, const QString &source)
00824 {
00825     uint result = m_glCreateShader(type);
00826     QByteArray src = source.toAscii();
00827     const char* tmp[1] = { src.constData() };
00828     m_glShaderSource(result, 1, tmp, NULL);
00829     m_glCompileShader(result);
00830     GLint compiled;
00831     m_glGetShaderiv(result, GL_COMPILE_STATUS, &compiled);
00832     if (!compiled)
00833     {
00834         GLint length = 0;
00835         m_glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);
00836         if (length > 1)
00837         {
00838             char *log = (char*)malloc(sizeof(char) * length);
00839             m_glGetShaderInfoLog(result, length, NULL, log);
00840             LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to compile shader.");
00841             LOG(VB_GENERAL, LOG_ERR, log);
00842             LOG(VB_GENERAL, LOG_ERR, source);
00843             free(log);
00844         }
00845         m_glDeleteShader(result);
00846         result = 0;
00847     }
00848     return result;
00849 }
00850 
00851 bool MythRenderOpenGL2::ValidateShaderObject(uint obj)
00852 {
00853     if (!m_shader_objects.contains(obj))
00854         return false;
00855     if (!m_shader_objects[obj].m_fragment_shader ||
00856         !m_shader_objects[obj].m_vertex_shader)
00857         return false;
00858 
00859     m_glAttachShader(obj, m_shader_objects[obj].m_fragment_shader);
00860     m_glAttachShader(obj, m_shader_objects[obj].m_vertex_shader);
00861     m_glBindAttribLocation(obj, VERTEX_INDEX,  "a_position");
00862     m_glBindAttribLocation(obj, COLOR_INDEX,   "a_color");
00863     m_glBindAttribLocation(obj, TEXTURE_INDEX, "a_texcoord0");
00864     m_glLinkProgram(obj);
00865     return CheckObjectStatus(obj);
00866 }
00867 
00868 bool MythRenderOpenGL2::CheckObjectStatus(uint obj)
00869 {
00870     int ok;
00871     m_glGetProgramiv(obj, GL_OBJECT_LINK_STATUS, &ok);
00872     if (ok > 0)
00873         return true;
00874 
00875     LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to link shader object.");
00876     int infologLength = 0;
00877     int charsWritten  = 0;
00878     char *infoLog;
00879     m_glGetProgramiv(obj, GL_OBJECT_INFO_LOG_LENGTH, &infologLength);
00880     if (infologLength > 0)
00881     {
00882         infoLog = (char *)malloc(infologLength);
00883         m_glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
00884         LOG(VB_GENERAL, LOG_ERR, QString("\n\n%1").arg(infoLog));
00885         free(infoLog);
00886     }
00887     return false;
00888 }
00889 
00890 void MythRenderOpenGL2::OptimiseShaderSource(QString &source)
00891 {
00892     QString extensions = "";
00893     QString sampler = "sampler2D";
00894     QString texture = "texture2D";
00895 
00896     if ((m_exts_used & kGLExtRect) && source.contains("GLSL_SAMPLER"))
00897     {
00898         extensions += "#extension GL_ARB_texture_rectangle : enable\n";
00899         sampler += "Rect";
00900         texture += "Rect";
00901     }
00902 
00903     source.replace("GLSL_SAMPLER", sampler);
00904     source.replace("GLSL_TEXTURE", texture);
00905     source.replace("GLSL_DEFINES", m_GLSLVersion + extensions + m_qualifiers);
00906 
00907     LOG(VB_GENERAL, LOG_DEBUG, "\n" + source);
00908 }
00909 
00910 void MythRenderOpenGL2::DeleteOpenGLResources(void)
00911 {
00912     LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting OpenGL Resources");
00913     DeleteDefaultShaders();
00914     DeleteShaders();
00915     MythRenderOpenGL::DeleteOpenGLResources();
00916 }
00917 
00918 void MythRenderOpenGL2::SetMatrixView(void)
00919 {
00920     float left   = m_viewport.left();
00921     float top    = m_viewport.top();
00922     float right  = m_viewport.left() + m_viewport.width();
00923     float bottom = m_viewport.top()  + m_viewport.height();
00924     memset(m_projection, 0, sizeof(m_projection));
00925     if (right <= 0 || bottom <= 0)
00926         return;
00927     m_projection[0][0] = 2.0 / (right - left);
00928     m_projection[1][1] = 2.0 / (top - bottom);
00929     m_projection[2][2] = 1.0;
00930     m_projection[3][0] = -((right + left) / (right - left));
00931     m_projection[3][1] = -((top + bottom) / (top - bottom));
00932     m_projection[3][3] = 1.0;
00933 }
00934 
00935 void MythRenderOpenGL2::PushTransformation(const UIEffects &fx, QPointF &center)
00936 {
00937     GLMatrix newtop = m_transforms.top();
00938     if (fx.hzoom != 1.0 || fx.vzoom != 1.0 || fx.angle != 0.0)
00939     {
00940         newtop.translate(-center.x(), -center.y());
00941         newtop.scale(fx.hzoom, fx.vzoom);
00942         newtop.rotate(fx.angle);
00943         newtop.translate(center.x(), center.y());
00944     }
00945     m_transforms.push(newtop);
00946 }
00947 
00948 void MythRenderOpenGL2::PopTransformation(void)
00949 {
00950     m_transforms.pop();
00951 }
00952 
00953 void MythRenderOpenGL2::DeleteShaders(void)
00954 {
00955     QHash<GLuint, MythGLShaderObject>::iterator it;
00956     for (it = m_shader_objects.begin(); it != m_shader_objects.end(); ++it)
00957     {
00958         GLuint object   = it.key();
00959         GLuint vertex   = it.value().m_vertex_shader;
00960         GLuint fragment = it.value().m_fragment_shader;
00961         m_glDetachShader(object, vertex);
00962         m_glDetachShader(object, fragment);
00963         m_glDeleteShader(vertex);
00964         m_glDeleteShader(fragment);
00965         m_glDeleteProgram(object);
00966     }
00967     m_shader_objects.clear();
00968     Flush(true);
00969 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends