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
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
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
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
00593 int elip = m_shaders[kShaderCircle];
00594 int fill = m_shaders[kShaderSimple];
00595
00596
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
00604 m_parameters[0][2] = rad;
00605 m_parameters[0][3] = rad - 1.0;
00606
00607
00608 SetShaderParams(elip, &m_projection[0][0], "u_projection");
00609 SetShaderParams(elip, &m_transforms.top().m[0][0], "u_transform");
00610
00611
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
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
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
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
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
00681 int edge = m_shaders[kShaderCircleEdge];
00682 int vline = m_shaders[kShaderVertLine];
00683 int hline = m_shaders[kShaderHorizLine];
00684
00685
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
00693 m_parameters[0][2] = rad - lineWidth / 2.0;
00694 m_parameters[0][3] = lineWidth / 2.0;
00695
00696
00697 SetShaderParams(edge, &m_projection[0][0], "u_projection");
00698 SetShaderParams(edge, &m_transforms.top().m[0][0], "u_transform");
00699
00700
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
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
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
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
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
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
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
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
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
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 ¢er)
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 }