MythTV  master
mythrender_opengl2.cpp
Go to the documentation of this file.
1 #include "mythrender_opengl2.h"
2 
3 #include <QPainter>
4 
5 #include <cmath>
6 
7 #define LOC QString("OpenGL2: ")
8 
9 static inline int __glCheck__(const QString &loc, const char* fileName, int n)
10 {
11  int error = glGetError();
12  if (error)
13  {
14  LOG(VB_GENERAL, LOG_ERR, QString("%1: %2 @ %3, %4")
15  .arg(loc).arg(error).arg(fileName).arg(n));
16  }
17  return error;
18 }
19 #define glCheck() __glCheck__(LOC, __FILE__, __LINE__)
20 
21 #define VERTEX_INDEX 0
22 #define COLOR_INDEX 1
23 #define TEXTURE_INDEX 2
24 #define VERTEX_SIZE 2
25 #define TEXTURE_SIZE 2
26 
27 static const GLuint kVertexOffset = 0;
28 static const GLuint kTextureOffset = 8 * sizeof(GLfloat);
29 static const GLuint kVertexSize = 16 * sizeof(GLfloat);
30 
31 static const QString kDefaultVertexShader =
32 "GLSL_DEFINES"
33 "attribute vec2 a_position;\n"
34 "attribute vec4 a_color;\n"
35 "attribute vec2 a_texcoord0;\n"
36 "varying vec4 v_color;\n"
37 "varying vec2 v_texcoord0;\n"
38 "uniform mat4 u_projection;\n"
39 "uniform mat4 u_transform;\n"
40 "void main() {\n"
41 " gl_Position = u_projection * u_transform * vec4(a_position, 0.0, 1.0);\n"
42 " v_texcoord0 = a_texcoord0;\n"
43 " v_color = a_color;\n"
44 "}\n";
45 
46 static const QString kDefaultFragmentShader =
47 "GLSL_DEFINES"
48 "uniform GLSL_SAMPLER s_texture0;\n"
49 "varying vec4 v_color;\n"
50 "varying vec2 v_texcoord0;\n"
51 "void main(void)\n"
52 "{\n"
53 " gl_FragColor = GLSL_TEXTURE(s_texture0, v_texcoord0) * v_color;\n"
54 "}\n";
55 
56 static const QString kSimpleVertexShader =
57 "GLSL_DEFINES"
58 "attribute vec2 a_position;\n"
59 "attribute vec4 a_color;\n"
60 "varying vec4 v_color;\n"
61 "uniform mat4 u_projection;\n"
62 "uniform mat4 u_transform;\n"
63 "void main() {\n"
64 " gl_Position = u_projection * u_transform * vec4(a_position, 0.0, 1.0);\n"
65 " v_color = a_color;\n"
66 "}\n";
67 
68 static const QString kSimpleFragmentShader =
69 "GLSL_DEFINES"
70 "varying vec4 v_color;\n"
71 "void main(void)\n"
72 "{\n"
73 " gl_FragColor = v_color;\n"
74 "}\n";
75 
76 static const QString kDrawVertexShader =
77 "GLSL_DEFINES"
78 "attribute vec2 a_position;\n"
79 "attribute vec4 a_color;\n"
80 "varying vec4 v_color;\n"
81 "varying vec2 v_position;\n"
82 "uniform mat4 u_projection;\n"
83 "uniform mat4 u_transform;\n"
84 "void main() {\n"
85 " gl_Position = u_projection * u_transform * vec4(a_position, 0.0, 1.0);\n"
86 " v_color = a_color;\n"
87 " v_position = a_position;\n"
88 "}\n";
89 
90 static const QString kCircleFragmentShader =
91 "GLSL_DEFINES"
92 "varying vec4 v_color;\n"
93 "varying vec2 v_position;\n"
94 "uniform mat4 u_parameters;\n"
95 "void main(void)\n"
96 "{\n"
97 " float dis = distance(v_position.xy, u_parameters[0].xy);\n"
98 " float mult = smoothstep(u_parameters[0].z, u_parameters[0].w, dis);\n"
99 " gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
100 "}\n";
101 
102 static const QString kCircleEdgeFragmentShader =
103 "GLSL_DEFINES"
104 "varying vec4 v_color;\n"
105 "varying vec2 v_position;\n"
106 "uniform mat4 u_parameters;\n"
107 "void main(void)\n"
108 "{\n"
109 " float dis = distance(v_position.xy, u_parameters[0].xy);\n"
110 " float rad = u_parameters[0].z;\n"
111 " float wid = u_parameters[0].w;\n"
112 " float mult = smoothstep(rad + wid, rad + (wid - 1.0), dis) * smoothstep(rad - (wid + 1.0), rad - wid, dis);\n"
113 " gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
114 "}\n";
115 
116 static const QString kVertLineFragmentShader =
117 "GLSL_DEFINES"
118 "varying vec4 v_color;\n"
119 "varying vec2 v_position;\n"
120 "uniform mat4 u_parameters;\n"
121 "void main(void)\n"
122 "{\n"
123 " float dis = abs(u_parameters[0].x - v_position.x);\n"
124 " float y = u_parameters[0].y * 2.0;\n"
125 " float mult = smoothstep(y, y - 0.1, dis) * smoothstep(-0.1, 0.0, dis);\n"
126 " gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
127 "}\n";
128 
129 static const QString kHorizLineFragmentShader =
130 "GLSL_DEFINES"
131 "varying vec4 v_color;\n"
132 "varying vec2 v_position;\n"
133 "uniform mat4 u_parameters;\n"
134 "void main(void)\n"
135 "{\n"
136 " float dis = abs(u_parameters[0].x - v_position.y);\n"
137 " float x = u_parameters[0].y * 2.0;\n"
138 " float mult = smoothstep(x, x - 0.1, dis) * smoothstep(-0.1, 0.0, dis);\n"
139 " gl_FragColor = v_color * vec4(1.0, 1.0, 1.0, mult);\n"
140 "}\n";
141 
143 {
144  public:
146  : m_vertex_shader(vert), m_fragment_shader(frag) { }
147  MythGLShaderObject() = default;
148 
149  GLuint m_vertex_shader {0};
150  GLuint m_fragment_shader {0};
151 };
152 
154  QPaintDevice* device,
156  : MythRenderOpenGL(format, device, type)
157 {
160 }
161 
163  : MythRenderOpenGL(format, type)
164 {
167 }
168 
170 {
171  if (!isValid())
172  return;
173  makeCurrent();
175  doneCurrent();
176 }
177 
179 {
181 }
182 
184 {
186  m_projection.fill(0);
187  m_parameters.fill(0);
188  memset(m_shaders, 0, sizeof(m_shaders));
189  m_active_obj = 0;
190  m_transforms.clear();
191  m_transforms.push(QMatrix4x4());
192  m_map.clear();
193 }
194 
196 {
198 
199  m_glCreateShader = nullptr;
200  m_glShaderSource = nullptr;
201  m_glCompileShader = nullptr;
202  m_glGetShaderiv = nullptr;
203  m_glGetShaderInfoLog = nullptr;
204  m_glCreateProgram = nullptr;
205  m_glAttachShader = nullptr;
206  m_glLinkProgram = nullptr;
207  m_glUseProgram = nullptr;
208  m_glDeleteProgram = nullptr;
209  m_glGetProgramInfoLog = nullptr;
210  m_glGetProgramiv = nullptr;
211  m_glDetachShader = nullptr;
212  m_glDeleteShader = nullptr;
213  m_glGetUniformLocation = nullptr;
214  m_glUniform1i = nullptr;
215  m_glUniformMatrix4fv = nullptr;
216  m_glVertexAttribPointer = nullptr;
217  m_glEnableVertexAttribArray = nullptr;
219  m_glBindAttribLocation = nullptr;
220  m_glVertexAttrib4f = nullptr;
221 }
222 
224 {
226 
227  static bool glslshaders = true;
228  static bool check = true;
229  if (check)
230  {
231  check = false;
232  glslshaders = !getenv("OPENGL_NOGLSL");
233  if (!glslshaders)
234  LOG(VB_GENERAL, LOG_INFO, LOC + "Disabling GLSL.");
235  }
236 
237  // These should all be present for a valid OpenGL2.0/ES installation
251  m_glVertexAttrib4f && glslshaders)
252  {
253  LOG(VB_GENERAL, LOG_INFO, LOC + "GLSL supported");
255  }
256 
258 
259  // After rect texture support
260  if (m_exts_supported & kGLSL)
261  {
264  }
265 
266  return true;
267 }
268 
270 {
272 
273  // GLSL version
274  m_GLSLVersion = "#version 110\n";
275  m_qualifiers = QString();
276 
278  GetProcAddress("glCreateShader");
280  GetProcAddress("glShaderSource");
282  GetProcAddress("glCompileShader");
284  GetProcAddress("glGetShaderiv");
286  GetProcAddress("glGetShaderInfoLog");
288  GetProcAddress("glDeleteProgram");
290  GetProcAddress("glCreateProgram");
292  GetProcAddress("glAttachShader");
294  GetProcAddress("glLinkProgram");
296  GetProcAddress("glUseProgram");
298  GetProcAddress("glGetProgramInfoLog");
300  GetProcAddress("glGetProgramiv");
302  GetProcAddress("glDetachShader");
304  GetProcAddress("glDeleteShader");
306  GetProcAddress("glGetUniformLocation");
308  GetProcAddress("glUniform1i");
310  GetProcAddress("glUniformMatrix4fv");
312  GetProcAddress("glVertexAttribPointer");
314  GetProcAddress("glEnableVertexAttribArray");
316  GetProcAddress("glDisableVertexAttribArray");
318  GetProcAddress("glBindAttribLocation");
320  GetProcAddress("glVertexAttrib4f");
321 }
322 
324  GLuint index, GLint size, GLenum type, GLboolean normalize,
325  GLsizei stride, const GLuint value)
326 {
327 #pragma GCC diagnostic push
328 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
329  m_glVertexAttribPointer(index, size, type, normalize,
330  stride, (const char *)value);
331 #pragma GCC diagnostic pop
332 }
333 
335  const QString &fragment)
336 {
337  if (!(m_exts_supported & kGLSL))
338  return 0;
339 
340  OpenGLLocker locker(this);
341 
342  uint result = 0;
343  QString vert_shader = vertex.isEmpty() ? kDefaultVertexShader : vertex;
344  QString frag_shader = fragment.isEmpty() ? kDefaultFragmentShader: fragment;
345 
346  OptimiseShaderSource(vert_shader);
347  OptimiseShaderSource(frag_shader);
348 
349  result = m_glCreateProgram();
350  if (!result)
351  return 0;
352 
353  MythGLShaderObject object(CreateShader(GL_VERTEX_SHADER, vert_shader),
354  CreateShader(GL_FRAGMENT_SHADER, frag_shader));
355  m_shader_objects.insert(result, object);
356 
357  if (!ValidateShaderObject(result))
358  {
359  DeleteShaderObject(result);
360  return 0;
361  }
362 
363  return result;
364 }
365 
367 {
368  OpenGLLocker locker(this);
369 
370  if (!m_shader_objects.contains(obj))
371  return;
372 
373  GLuint vertex = m_shader_objects[obj].m_vertex_shader;
374  GLuint fragment = m_shader_objects[obj].m_fragment_shader;
375  m_glDetachShader(obj, vertex);
376  m_glDetachShader(obj, fragment);
377  m_glDeleteShader(vertex);
378  m_glDeleteShader(fragment);
379  m_glDeleteProgram(obj);
380  m_shader_objects.remove(obj);
381  m_map.clear();
382 
383  Flush(true);
384 }
385 
387 {
388  OpenGLLocker locker(this);
389 
390  if (obj == m_active_obj)
391  return;
392 
393  if (!obj && m_active_obj)
394  {
395  m_glUseProgram(0);
396  m_active_obj = 0;
397  return;
398  }
399 
400  if (!m_shader_objects.contains(obj))
401  return;
402 
403  m_glUseProgram(obj);
404  m_active_obj = obj;
405 }
406 
407 void MythRenderOpenGL2::SetShaderParams(uint obj, const QMatrix4x4 &m,
408  const char* uniform)
409 {
410  if (!(m_exts_supported & kGLSL))
411  return;
412 
413  OpenGLLocker locker(this);
414 
415  EnableShaderObject(obj);
416 
417  QString tag = QString("%1-%2").arg(obj).arg(uniform);
418  map_t::iterator it = m_map.find(tag);
419  if (it == m_map.end())
420  m_map.insert(tag, m);
421  else if (!qFuzzyCompare(m, it.value()))
422  it.value() = m;
423  else
424  return;
425  GLint loc = m_glGetUniformLocation(obj, uniform);
426  if (loc != -1)
427  m_glUniformMatrix4fv(loc, 1, GL_FALSE, GLMatrix4x4(m));
428 }
429 
430 void MythRenderOpenGL2::DrawBitmapPriv(uint tex, const QRect *src,
431  const QRect *dst, uint prog, int alpha,
432  int red, int green, int blue)
433 {
434  if (prog && !m_shader_objects.contains(prog))
435  prog = 0;
436  if (prog == 0)
437  prog = m_shaders[kShaderDefault];
438 
439  SetShaderParams(prog, m_projection, "u_projection");
440  SetShaderParams(prog, m_transforms.top(), "u_transform");
441  SetBlend(true);
442 
443  EnableTextures(tex);
444 
445  GLint loc = m_glGetUniformLocation(prog, "s_texture0");
446  if (loc != -1)
447  m_glUniform1i(loc, 0);
448 
450  glBindTexture(m_textures[tex].m_type, tex);
451 
453  UpdateTextureVertices(tex, src, dst);
455  {
458  if (target)
459  memcpy(target, m_textures[tex].m_vertex_data, kVertexSize);
461  }
462  else
463  {
465  }
466 
469 
471  VERTEX_SIZE * sizeof(GLfloat),
472  kVertexOffset);
473  m_glVertexAttrib4f(COLOR_INDEX, red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0);
475  TEXTURE_SIZE * sizeof(GLfloat),
477 
478  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
479  glCheck();
480 
484 }
485 
486 void MythRenderOpenGL2::DrawBitmapPriv(uint *textures, uint texture_count,
487  const QRectF *src, const QRectF *dst,
488  uint prog)
489 {
490  if (prog && !m_shader_objects.contains(prog))
491  prog = 0;
492  if (prog == 0)
493  prog = m_shaders[kShaderDefault];
494 
495  uint first = textures[0];
496 
497  SetShaderParams(prog, m_projection, "u_projection");
498  SetShaderParams(prog, m_transforms.top(), "u_transform");
499  SetBlend(false);
500 
501  EnableTextures(first);
502  uint active_tex = 0;
503  for (uint i = 0; i < texture_count; i++)
504  {
505  if (m_textures.contains(textures[i]))
506  {
507  QString uniform = QString("s_texture%1").arg(active_tex);
508  GLint loc = m_glGetUniformLocation(prog, qPrintable(uniform));
509  if (loc != -1)
510  m_glUniform1i(loc, active_tex);
511 
512  ActiveTexture(GL_TEXTURE0 + active_tex++);
513  glBindTexture(m_textures[textures[i]].m_type, textures[i]);
514  }
515  }
516 
518  UpdateTextureVertices(first, src, dst);
520  {
523  if (target)
524  memcpy(target, m_textures[first].m_vertex_data, kVertexSize);
526  }
527  else
528  {
530  }
531 
534 
536  VERTEX_SIZE * sizeof(GLfloat),
537  kVertexOffset);
538  m_glVertexAttrib4f(COLOR_INDEX, 1.0, 1.0, 1.0, 1.0);
540  TEXTURE_SIZE * sizeof(GLfloat),
542 
543  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
544 
548 }
549 
550 void MythRenderOpenGL2::DrawRectPriv(const QRect &area, const QBrush &fillBrush,
551  const QPen &linePen, int alpha)
552 {
553  DrawRoundRectPriv(area, 1, fillBrush, linePen, alpha);
554 }
555 
556 void MythRenderOpenGL2::DrawRoundRectPriv(const QRect &area, int cornerRadius,
557  const QBrush &fillBrush,
558  const QPen &linePen, int alpha)
559 {
560  int lineWidth = linePen.width();
561  int halfline = lineWidth / 2;
562  int rad = cornerRadius - halfline;
563 
564  if ((area.width() / 2) < rad)
565  rad = area.width() / 2;
566 
567  if ((area.height() / 2) < rad)
568  rad = area.height() / 2;
569  int dia = rad * 2;
570 
571  QRect r(area.left(), area.top(), area.width(), area.height());
572 
573  QRect tl(r.left(), r.top(), rad, rad);
574  QRect tr(r.left() + r.width() - rad, r.top(), rad, rad);
575  QRect bl(r.left(), r.top() + r.height() - rad, rad, rad);
576  QRect br(r.left() + r.width() - rad, r.top() + r.height() - rad, rad, rad);
577 
578  SetBlend(true);
579  DisableTextures();
580 
582 
583  if (fillBrush.style() != Qt::NoBrush)
584  {
585  // Get the shaders
586  int elip = m_shaders[kShaderCircle];
587  int fill = m_shaders[kShaderSimple];
588 
589  // Set the fill color
591  fillBrush.color().red() / 255.0,
592  fillBrush.color().green() / 255.0,
593  fillBrush.color().blue() / 255.0,
594  (fillBrush.color().alpha() / 255.0) * (alpha / 255.0));
595 
596  // Set the radius
597  m_parameters(2,0) = rad;
598  m_parameters(3,0) = rad - 1.0;
599 
600  // Enable the Circle shader
601  SetShaderParams(elip, m_projection, "u_projection");
602  SetShaderParams(elip, m_transforms.top(), "u_transform");
603 
604  // Draw the top left segment
605  m_parameters(0,0) = tl.left() + rad;
606  m_parameters(1,0) = tl.top() + rad;
607 
608  SetShaderParams(elip, m_parameters, "u_parameters");
609  GetCachedVBO(GL_TRIANGLE_STRIP, tl);
611  VERTEX_SIZE * sizeof(GLfloat),
612  kVertexOffset);
613  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
614 
615  // Draw the top right segment
616  m_parameters(0,0) = tr.left();
617  m_parameters(1,0) = tr.top() + rad;
618  SetShaderParams(elip, m_parameters, "u_parameters");
619  GetCachedVBO(GL_TRIANGLE_STRIP, tr);
621  VERTEX_SIZE * sizeof(GLfloat),
622  kVertexOffset);
623  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
624 
625  // Draw the bottom left segment
626  m_parameters(0,0) = bl.left() + rad;
627  m_parameters(1,0) = bl.top();
628  SetShaderParams(elip, m_parameters, "u_parameters");
629  GetCachedVBO(GL_TRIANGLE_STRIP, bl);
631  VERTEX_SIZE * sizeof(GLfloat),
632  kVertexOffset);
633  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
634 
635  // Draw the bottom right segment
636  m_parameters(0,0) = br.left();
637  m_parameters(1,0) = br.top();
638  SetShaderParams(elip, m_parameters, "u_parameters");
639  GetCachedVBO(GL_TRIANGLE_STRIP, br);
641  VERTEX_SIZE * sizeof(GLfloat),
642  kVertexOffset);
643  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
644 
645  // Fill the remaining areas
646  QRect main(r.left() + rad, r.top(), r.width() - dia, r.height());
647  QRect left(r.left(), r.top() + rad, rad, r.height() - dia);
648  QRect right(r.left() + r.width() - rad, r.top() + rad, rad, r.height() - dia);
649 
650  SetShaderParams(fill, m_projection, "u_projection");
651  SetShaderParams(fill, m_transforms.top(), "u_transform");
652 
653  GetCachedVBO(GL_TRIANGLE_STRIP, main);
655  VERTEX_SIZE * sizeof(GLfloat),
656  kVertexOffset);
657  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
658  GetCachedVBO(GL_TRIANGLE_STRIP, left);
660  VERTEX_SIZE * sizeof(GLfloat),
661  kVertexOffset);
662  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
663  GetCachedVBO(GL_TRIANGLE_STRIP, right);
665  VERTEX_SIZE * sizeof(GLfloat),
666  kVertexOffset);
667  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
669  }
670 
671  if (linePen.style() != Qt::NoPen)
672  {
673  // Get the shaders
674  int edge = m_shaders[kShaderCircleEdge];
675  int vline = m_shaders[kShaderVertLine];
676  int hline = m_shaders[kShaderHorizLine];
677 
678  // Set the line color
680  linePen.color().red() / 255.0,
681  linePen.color().green() / 255.0,
682  linePen.color().blue() / 255.0,
683  (linePen.color().alpha() / 255.0) * (alpha / 255.0));
684 
685  // Set the radius and width
686  m_parameters(2,0) = rad - lineWidth / 2.0;
687  m_parameters(3,0) = lineWidth / 2.0;
688 
689  // Enable the edge shader
690  SetShaderParams(edge, m_projection, "u_projection");
691  SetShaderParams(edge, m_transforms.top(), "u_transform");
692 
693  // Draw the top left edge segment
694  m_parameters(0,0) = tl.left() + rad;
695  m_parameters(1,0) = tl.top() + rad;
696  SetShaderParams(edge, m_parameters, "u_parameters");
697  GetCachedVBO(GL_TRIANGLE_STRIP, tl);
699  VERTEX_SIZE * sizeof(GLfloat),
700  kVertexOffset);
701  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
702 
703  // Draw the top right edge segment
704  m_parameters(0,0) = tr.left();
705  m_parameters(1,0) = tr.top() + rad;
706  SetShaderParams(edge, m_parameters, "u_parameters");
707  GetCachedVBO(GL_TRIANGLE_STRIP, tr);
709  VERTEX_SIZE * sizeof(GLfloat),
710  kVertexOffset);
711  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
712 
713  // Draw the bottom left edge segment
714  m_parameters(0,0) = bl.left() + rad;
715  m_parameters(1,0) = bl.top();
716  SetShaderParams(edge, m_parameters, "u_parameters");
717  GetCachedVBO(GL_TRIANGLE_STRIP, bl);
719  VERTEX_SIZE * sizeof(GLfloat),
720  kVertexOffset);
721  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
722 
723  // Draw the bottom right edge segment
724  m_parameters(0,0) = br.left();
725  m_parameters(1,0) = br.top();
726  SetShaderParams(edge, m_parameters, "u_parameters");
727  GetCachedVBO(GL_TRIANGLE_STRIP, br);
729  VERTEX_SIZE * sizeof(GLfloat),
730  kVertexOffset);
731  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
732 
733  // Vertical lines
734  SetShaderParams(vline, m_projection, "u_projection");
735  SetShaderParams(vline, m_transforms.top(), "u_transform");
736 
737  m_parameters(1,0) = lineWidth / 2.0;
738  QRect vl(r.left(), r.top() + rad,
739  lineWidth, r.height() - dia);
740 
741  // Draw the left line segment
742  m_parameters(0,0) = vl.left() + lineWidth;
743  SetShaderParams(vline, m_parameters, "u_parameters");
744  GetCachedVBO(GL_TRIANGLE_STRIP, vl);
746  VERTEX_SIZE * sizeof(GLfloat),
747  kVertexOffset);
748  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
749 
750  // Draw the right line segment
751  vl.translate(r.width() - lineWidth, 0);
752  m_parameters(0,0) = vl.left();
753  SetShaderParams(vline, m_parameters, "u_parameters");
754  GetCachedVBO(GL_TRIANGLE_STRIP, vl);
756  VERTEX_SIZE * sizeof(GLfloat),
757  kVertexOffset);
758  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
759 
760  // Horizontal lines
761  SetShaderParams(hline, m_projection, "u_projection");
762  SetShaderParams(hline, m_transforms.top(), "u_transform");
763  QRect hl(r.left() + rad, r.top(),
764  r.width() - dia, lineWidth);
765 
766  // Draw the top line segment
767  m_parameters(0,0) = hl.top() + lineWidth;
768  SetShaderParams(hline, m_parameters, "u_parameters");
769  GetCachedVBO(GL_TRIANGLE_STRIP, hl);
771  VERTEX_SIZE * sizeof(GLfloat),
772  kVertexOffset);
773  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
774 
775  // Draw the bottom line segment
776  hl.translate(0, r.height() - lineWidth);
777  m_parameters(0,0) = hl.top();
778  SetShaderParams(hline, m_parameters, "u_parameters");
779  GetCachedVBO(GL_TRIANGLE_STRIP, hl);
781  VERTEX_SIZE * sizeof(GLfloat),
782  kVertexOffset);
783  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
784 
786  }
787 
789 }
790 
792 {
805 }
806 
808 {
809  for (int i = 0; i < kShaderCount; i++)
810  {
812  m_shaders[i] = 0;
813  }
814 }
815 
816 uint MythRenderOpenGL2::CreateShader(int type, const QString &source)
817 {
818  uint result = m_glCreateShader(type);
819  QByteArray src = source.toLatin1();
820  const char* tmp[1] = { src.constData() };
821  m_glShaderSource(result, 1, tmp, nullptr);
822  m_glCompileShader(result);
823  GLint compiled;
824  m_glGetShaderiv(result, GL_COMPILE_STATUS, &compiled);
825  if (!compiled)
826  {
827  GLint length = 0;
828  m_glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);
829  if (length > 1)
830  {
831  char *log = (char*)malloc(sizeof(char) * length);
832  m_glGetShaderInfoLog(result, length, nullptr, log);
833  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to compile shader.");
834  LOG(VB_GENERAL, LOG_ERR, log);
835  LOG(VB_GENERAL, LOG_ERR, source);
836  free(log);
837  }
838  m_glDeleteShader(result);
839  result = 0;
840  }
841  return result;
842 }
843 
845 {
846  if (!m_shader_objects.contains(obj))
847  return false;
848  if (!m_shader_objects[obj].m_fragment_shader ||
849  !m_shader_objects[obj].m_vertex_shader)
850  return false;
851 
852  m_glAttachShader(obj, m_shader_objects[obj].m_fragment_shader);
853  m_glAttachShader(obj, m_shader_objects[obj].m_vertex_shader);
854  m_glBindAttribLocation(obj, VERTEX_INDEX, "a_position");
855  m_glBindAttribLocation(obj, COLOR_INDEX, "a_color");
856  m_glBindAttribLocation(obj, TEXTURE_INDEX, "a_texcoord0");
857  m_glLinkProgram(obj);
858  return CheckObjectStatus(obj);
859 }
860 
862 {
863  int ok;
864 #ifdef GL_LINK_STATUS
865  m_glGetProgramiv(obj, GL_LINK_STATUS, &ok);
866 #else
868 #endif
869  if (ok > 0)
870  return true;
871 
872  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to link shader object.");
873  int infologLength = 0;
874  int charsWritten = 0;
875  char *infoLog;
876 #ifdef GL_INFO_LOG_LENGTH
877  m_glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &infologLength);
878 #else
879  m_glGetProgramiv(obj, GL_OBJECT_INFO_LOG_LENGTH, &infologLength);
880 #endif
881  if (infologLength > 0)
882  {
883  infoLog = (char *)malloc(infologLength);
884  m_glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
885  LOG(VB_GENERAL, LOG_ERR, QString("\n\n%1").arg(infoLog));
886  free(infoLog);
887  }
888  return false;
889 }
890 
892 {
893  QString extensions = "";
894  QString sampler = "sampler2D";
895  QString texture = "texture2D";
896 
897  if ((m_exts_used & kGLExtRect) && source.contains("GLSL_SAMPLER"))
898  {
899  extensions += "#extension GL_ARB_texture_rectangle : enable\n";
900  sampler += "Rect";
901  texture += "Rect";
902  }
903 
904  source.replace("GLSL_SAMPLER", sampler);
905  source.replace("GLSL_TEXTURE", texture);
906  source.replace("GLSL_DEFINES", m_GLSLVersion + extensions + m_qualifiers);
907 
908  LOG(VB_GENERAL, LOG_DEBUG, "\n" + source);
909 }
910 
912 {
913  LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting OpenGL Resources");
917 }
918 
920 {
921  m_projection.setToIdentity();
922  m_projection.ortho(m_viewport);
923 }
924 
925 void MythRenderOpenGL2::PushTransformation(const UIEffects &fx, QPointF &center)
926 {
927  QMatrix4x4 newtop = m_transforms.top();
928  if (fx.m_hzoom != 1.0F || fx.m_vzoom != 1.0F || fx.m_angle != 0.0F)
929  {
930  newtop.translate(center.x(), center.y());
931  newtop.scale(fx.m_hzoom, fx.m_vzoom);
932  newtop.rotate(fx.m_angle, 0, 0, 1);
933  newtop.translate(-center.x(), -center.y());
934  }
935  m_transforms.push(newtop);
936 }
937 
939 {
940  m_transforms.pop();
941 }
942 
944 {
945  QHash<GLuint, MythGLShaderObject>::iterator it;
946  for (it = m_shader_objects.begin(); it != m_shader_objects.end(); ++it)
947  {
948  GLuint object = it.key();
949  GLuint vertex = it.value().m_vertex_shader;
950  GLuint fragment = it.value().m_fragment_shader;
951  m_glDetachShader(object, vertex);
952  m_glDetachShader(object, fragment);
953  m_glDeleteShader(vertex);
954  m_glDeleteShader(fragment);
955  m_glDeleteProgram(object);
956  }
957  m_shader_objects.clear();
958  m_map.clear();
959  Flush(true);
960 }
MYTH_GLGETPROGRAMIVPROC m_glGetProgramiv
QStack< QMatrix4x4 > m_transforms
MYTH_GLVERTEXATTRIB4FPROC m_glVertexAttrib4f
#define GL_OBJECT_INFO_LOG_LENGTH
void(* MYTH_GLUSEPROGRAMPROC)(GLuint program)
void(* MYTH_GLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index)
static const QString kSimpleVertexShader
static const GLuint kVertexSize
MYTH_GLGETSHADERIVPROC m_glGetShaderiv
void SetBlend(bool enable)
void DrawRoundRectPriv(const QRect &area, int cornerRadius, const QBrush &fillBrush, const QPen &linePen, int alpha) override
MYTH_GLATTACHSHADERPROC m_glAttachShader
#define COLOR_INDEX
static const QString kCircleEdgeFragmentShader
MYTH_GLDISABLEVERTEXATTRIBARRAYPROC m_glDisableVertexAttribArray
void(* MYTH_GLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLcharARB *name)
void Init2DState(void) override
void(* MYTH_GLSHADERSOURCEPROC)(GLuint shader, int numOfStrings, const char **strings, const int *lenOfStrings)
MYTH_GLCREATESHADERPROC m_glCreateShader
static const QString kDefaultFragmentShader
MYTH_GLUNIFORMMATRIX4FVPROC m_glUniformMatrix4fv
MYTH_GLBUFFERDATAPROC m_glBufferData
static void error(const char *str,...)
Definition: vbi.c:42
MYTH_GLMAPBUFFERPROC m_glMapBuffer
MYTH_GLUSEPROGRAMPROC m_glUseProgram
MYTH_GLBINDBUFFERPROC m_glBindBuffer
static const QString kSimpleFragmentShader
void GetCachedVBO(GLuint type, const QRect &area)
#define GL_WRITE_ONLY
unsigned int uint
Definition: compat.h:140
void(* MYTH_GLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalize, GLsizei stride, const GLvoid *ptr)
#define LOC
#define TEXTURE_SIZE
MYTH_GLGETUNIFORMLOCATIONPROC m_glGetUniformLocation
void(* MYTH_GLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
static guint32 * tmp
Definition: goom_core.c:35
unsigned char r
Definition: ParseText.cpp:329
void PopTransformation(void) override
void ResetVars(void) override
void(* MYTH_GLLINKPROGRAMPROC)(GLuint program)
static const GLuint kVertexOffset
MythGLShaderObject(uint vert, uint frag)
RenderType m_type
uint CreateShaderObject(const QString &vert, const QString &frag) override
void PushTransformation(const UIEffects &fx, QPointF &center) override
QHash< GLuint, MythGLShaderObject > m_shader_objects
uint CreateShader(int type, const QString &source)
#define glCheck()
void SetMatrixView(void) override
void * GetProcAddress(const QString &proc) const
GLuint(* MYTH_GLCREATESHADERPROC)(GLenum shaderType)
bool ValidateShaderObject(uint obj)
MythGLShaderObject()=default
void Flush(bool use_fence)
void DeleteShaders(void) override
void doneCurrent() override
void DrawBitmapPriv(uint tex, const QRect *src, const QRect *dst, uint prog, int alpha, int red, int green, int blue) override
#define GL_STREAM_DRAW
MYTH_GLCREATEPROGRAMPROC m_glCreateProgram
void(* MYTH_GLGETSHADERINFOLOGPROC)(GLuint shader, GLint maxlength, GLint *length, GLchar *infolog)
#define GL_OBJECT_LINK_STATUS
void InitProcs(void) override
static const QString kDefaultVertexShader
MYTH_GLUNMAPBUFFERPROC m_glUnmapBuffer
virtual bool InitFeatures(void)
#define GL_TEXTURE0
void(* MYTH_GLDELETESHADERPROC)(GLuint id)
void(* MYTH_GLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint *params)
#define GL_VERTEX_SHADER
def log(debug, txt)
Definition: utilities.py:5
class QGLFormat MythRenderFormat
MYTH_GLUNIFORM1IPROC m_glUniform1i
GLint(* MYTH_GLGETUNIFORMLOCATIONPROC)(GLuint program, const char *name)
#define GL_ARRAY_BUFFER
MYTH_GLLINKPROGRAMPROC m_glLinkProgram
QHash< GLuint, MythGLTexture > m_textures
MYTH_GLCOMPILESHADERPROC m_glCompileShader
static const QString kDrawVertexShader
#define VERTEX_INDEX
MYTH_GLDELETESHADERPROC m_glDeleteShader
MYTH_GLDELETEPROGRAMPROC m_glDeleteProgram
void DrawRectPriv(const QRect &area, const QBrush &fillBrush, const QPen &linePen, int alpha) override
void(* MYTH_GLATTACHSHADERPROC)(GLuint program, GLuint shader)
void makeCurrent() override
MYTH_GLENABLEVERTEXATTRIBARRAYPROC m_glEnableVertexAttribArray
MYTH_GLGETSHADERINFOLOGPROC m_glGetShaderInfoLog
void SetShaderParams(uint obj, const QMatrix4x4 &m, const char *uniform) override
void(* MYTH_GLENABLEVERTEXATTRIBARRAYPROC)(GLuint index)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
GLuint(* MYTH_GLCREATEPROGRAMPROC)(void)
MYTH_GLGETPROGRAMINFOLOGPROC m_glGetProgramInfoLog
bool CheckObjectStatus(uint obj)
#define VERTEX_SIZE
void EnableShaderObject(uint obj) override
void(* MYTH_GLGETPROGRAMINFOLOGPROC)(GLuint object, int maxLen, int *len, char *log)
uint m_shaders[kShaderCount]
bool InitFeatures(void) override
void ActiveTexture(int active_tex)
void DeleteOpenGLResources(void) override
#define GL_COMPILE_STATUS
void(* MYTH_GLCOMPILESHADERPROC)(GLuint shader)
void DeleteShaderObject(uint obj) override
void(* MYTH_GLUNIFORM1IPROC)(GLint location, GLint)
void(* MYTH_GLDETACHSHADERPROC)(GLuint program, GLuint shader)
void m_glVertexAttribPointerI(GLuint index, GLint size, GLenum type, GLboolean normalize, GLsizei stride, const GLuint value)
MYTH_GLDETACHSHADERPROC m_glDetachShader
static const QString kCircleFragmentShader
void EnableTextures(uint tex, uint tex_type=0)
MythRenderOpenGL2(const MythRenderFormat &format, QPaintDevice *device, RenderType type=kRenderOpenGL2)
#define TEXTURE_INDEX
virtual void ResetVars(void)
static const QString kHorizLineFragmentShader
MYTH_GLBINDATTRIBLOCATIONPROC m_glBindAttribLocation
RenderType
void(* MYTH_GLUNIFORMMATRIX4FVPROC)(GLint location, GLint size, GLboolean transpose, const GLfloat *values)
virtual void Init2DState(void)
virtual void ResetProcs(void)
GLMatrix4x4 is a helper class to convert between QT and GT 4x4 matrices.
void(* MYTH_GLDELETEPROGRAMPROC)(GLuint shader)
void ResetProcs(void) override
MYTH_GLSHADERSOURCEPROC m_glShaderSource
MYTH_GLVERTEXATTRIBPOINTERPROC m_glVertexAttribPointer
#define GL_FRAGMENT_SHADER
void(* MYTH_GLGETPROGRAMIVPROC)(GLuint object, GLenum type, int *param)
static int __glCheck__(const QString &loc, const char *fileName, int n)
#define GL_INFO_LOG_LENGTH
static const QString kVertLineFragmentShader
bool UpdateTextureVertices(uint tex, const QRect *src, const QRect *dst)
void OptimiseShaderSource(QString &source)
virtual void DeleteOpenGLResources(void)
virtual void InitProcs(void)
static const GLuint kTextureOffset