|
MythTV
0.26-pre
|
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 ¢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 }
1.7.6.1