00001 #include "mythrender_opengl1.h"
00002
00003 #define LOC QString("OpenGL1: ")
00004
00005 MythRenderOpenGL1::MythRenderOpenGL1(const QGLFormat& format, QPaintDevice* device)
00006 : MythRenderOpenGL(format, device, kRenderOpenGL1)
00007 {
00008 ResetVars();
00009 ResetProcs();
00010 }
00011
00012 MythRenderOpenGL1::MythRenderOpenGL1(const QGLFormat& format)
00013 : MythRenderOpenGL(format, kRenderOpenGL1)
00014 {
00015 ResetVars();
00016 ResetProcs();
00017 }
00018
00019 MythRenderOpenGL1::~MythRenderOpenGL1()
00020 {
00021 if (!isValid())
00022 return;
00023 makeCurrent();
00024 DeleteOpenGLResources();
00025 doneCurrent();
00026 }
00027
00028 void MythRenderOpenGL1::Init2DState(void)
00029 {
00030 glShadeModel(GL_FLAT);
00031 glDisable(GL_POLYGON_SMOOTH);
00032 glDisable(GL_LINE_SMOOTH);
00033 glDisable(GL_POINT_SMOOTH);
00034 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
00035 MythRenderOpenGL::Init2DState();
00036 }
00037
00038 void MythRenderOpenGL1::ResetVars(void)
00039 {
00040 MythRenderOpenGL::ResetVars();
00041 m_active_prog = 0;
00042 m_color = 0x00000000;
00043 }
00044
00045 void MythRenderOpenGL1::ResetProcs(void)
00046 {
00047 MythRenderOpenGL::ResetProcs();
00048 m_glGenProgramsARB = NULL;
00049 m_glBindProgramARB = NULL;
00050 m_glProgramStringARB = NULL;
00051 m_glProgramLocalParameter4fARB = NULL;
00052 m_glDeleteProgramsARB = NULL;
00053 m_glGetProgramivARB = NULL;
00054 }
00055
00056 bool MythRenderOpenGL1::InitFeatures(void)
00057 {
00058 m_exts_supported = kGLFeatNone;
00059
00060 static bool fragmentprog = true;
00061 static bool check = true;
00062 if (check)
00063 {
00064 check = false;
00065 fragmentprog = !getenv("OPENGL_NOFRAGPROG");
00066 if (!fragmentprog)
00067 LOG(VB_GENERAL, LOG_INFO, LOC + "Disabling fragment programs.");
00068 }
00069
00070 if (m_extensions.contains("GL_ARB_fragment_program") &&
00071 m_glGenProgramsARB && m_glBindProgramARB &&
00072 m_glProgramStringARB && m_glDeleteProgramsARB &&
00073 m_glGetProgramivARB && m_glProgramLocalParameter4fARB &&
00074 fragmentprog)
00075 {
00076 m_exts_supported += kGLExtFragProg;
00077 LOG(VB_GENERAL, LOG_INFO, LOC + "Fragment program support available");
00078 }
00079
00080 return MythRenderOpenGL::InitFeatures();
00081 }
00082
00083 void MythRenderOpenGL1::InitProcs(void)
00084 {
00085 MythRenderOpenGL::InitProcs();
00086
00087 m_glGenProgramsARB = (MYTH_GLGENPROGRAMSARBPROC)
00088 GetProcAddress("glGenProgramsARB");
00089 m_glBindProgramARB = (MYTH_GLBINDPROGRAMARBPROC)
00090 GetProcAddress("glBindProgramARB");
00091 m_glProgramStringARB = (MYTH_GLPROGRAMSTRINGARBPROC)
00092 GetProcAddress("glProgramStringARB");
00093 m_glProgramLocalParameter4fARB = (MYTH_GLPROGRAMLOCALPARAMETER4FARBPROC)
00094 GetProcAddress("glProgramLocalParameter4fARB");
00095 m_glDeleteProgramsARB = (MYTH_GLDELETEPROGRAMSARBPROC)
00096 GetProcAddress("glDeleteProgramsARB");
00097 m_glGetProgramivARB = (MYTH_GLGETPROGRAMIVARBPROC)
00098 GetProcAddress("glGetProgramivARB");
00099 }
00100
00101 void MythRenderOpenGL1::SetColor(int r, int g, int b, int a)
00102 {
00103 uint32_t tmp = (r << 24) + (g << 16) + (b << 8) + a;
00104 if (tmp == m_color)
00105 return;
00106
00107 m_color = tmp;
00108 makeCurrent();
00109 glColor4f(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
00110 doneCurrent();
00111 }
00112
00113 uint MythRenderOpenGL1::CreateShaderObject(const QString &vert, const QString &frag)
00114 {
00115 (void)vert;
00116 if (!(m_exts_used & kGLExtFragProg))
00117 return 0;
00118
00119 bool success = true;
00120 GLint error;
00121
00122 makeCurrent();
00123
00124 QByteArray tmp = frag.toAscii();
00125
00126 GLuint glfp;
00127 m_glGenProgramsARB(1, &glfp);
00128 m_glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, glfp);
00129 m_glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
00130 GL_PROGRAM_FORMAT_ASCII_ARB,
00131 tmp.length(), tmp.constData());
00132
00133 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error);
00134 if (error != -1)
00135 {
00136 LOG(VB_PLAYBACK, LOG_ERR, LOC +
00137 QString("Fragment Program compile error: position %1:'%2'")
00138 .arg(error).arg(frag.mid(error)));
00139
00140 success = false;
00141 }
00142 m_glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
00143 GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &error);
00144 if (error != 1)
00145 {
00146 LOG(VB_PLAYBACK, LOG_ERR, LOC +
00147 "Fragment program exceeds hardware capabilities.");
00148
00149 success = false;
00150 }
00151
00152 if (success)
00153 {
00154 LOG(VB_PLAYBACK, LOG_DEBUG, "\n" + frag + "\n");
00155 m_programs.push_back(glfp);
00156 }
00157 else
00158 m_glDeleteProgramsARB(1, &glfp);
00159
00160 Flush(true);
00161 doneCurrent();
00162 return glfp;
00163 }
00164
00165 void MythRenderOpenGL1::DeleteShaderObject(uint fp)
00166 {
00167 if (!m_programs.contains(fp))
00168 return;
00169
00170 makeCurrent();
00171 QVector<GLuint>::iterator it;
00172 for (it = m_programs.begin(); it != m_programs.end(); ++it)
00173 {
00174 if (*it == fp)
00175 {
00176 m_glDeleteProgramsARB(1, &(*it));
00177 m_programs.erase(it);
00178 break;
00179 }
00180 }
00181 Flush(true);
00182 doneCurrent();
00183 }
00184
00185 void MythRenderOpenGL1::EnableShaderObject(uint obj)
00186 {
00187 if ((!obj && !m_active_prog) ||
00188 (obj && (obj == m_active_prog)))
00189 return;
00190
00191 makeCurrent();
00192
00193 if (!obj && m_active_prog)
00194 {
00195 glDisable(GL_FRAGMENT_PROGRAM_ARB);
00196 m_active_prog = 0;
00197 doneCurrent();
00198 return;
00199 }
00200
00201 if (!m_programs.contains(obj))
00202 return;
00203
00204 if (!m_active_prog)
00205 glEnable(GL_FRAGMENT_PROGRAM_ARB);
00206
00207 if (obj != m_active_prog)
00208 {
00209 m_glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, obj);
00210 m_active_prog = obj;
00211 }
00212
00213 doneCurrent();
00214 }
00215
00216 void MythRenderOpenGL1::SetShaderParams(uint obj, void* vals,
00217 const char* uniform)
00218 {
00219 makeCurrent();
00220 const float *v = (float*)vals;
00221
00222 EnableShaderObject(obj);
00223 m_glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,
00224 0, v[0], v[1], v[2], v[3]);
00225 m_glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,
00226 1, v[4], v[5], v[6], v[7]);
00227 m_glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,
00228 2, v[8], v[9], v[10], v[11]);
00229
00230 doneCurrent();
00231 }
00232
00233 uint MythRenderOpenGL1::CreateHelperTexture(void)
00234 {
00235 if (!m_glTexImage1D)
00236 {
00237 LOG(VB_GENERAL, LOG_WARNING, LOC + "glTexImage1D not available.");
00238 return 0;
00239 }
00240
00241 makeCurrent();
00242
00243 uint width = m_max_tex_size;
00244 uint tmp_tex = CreateTexture(QSize(width, 1), false,
00245 GL_TEXTURE_1D, GL_FLOAT, GL_RGBA,
00246 GL_RGBA16, GL_NEAREST, GL_REPEAT);
00247
00248 if (!tmp_tex)
00249 {
00250 DeleteTexture(tmp_tex);
00251 return 0;
00252 }
00253
00254 float *buf = NULL;
00255 buf = new float[m_textures[tmp_tex].m_data_size];
00256 float *ref = buf;
00257
00258 for (uint i = 0; i < width; i++)
00259 {
00260 float x = (((float)i) + 0.5f) / (float)width;
00261 StoreBicubicWeights(x, ref);
00262 ref += 4;
00263 }
00264 StoreBicubicWeights(0, buf);
00265 StoreBicubicWeights(1, &buf[(width - 1) << 2]);
00266
00267 EnableTextures(tmp_tex);
00268 glBindTexture(m_textures[tmp_tex].m_type, tmp_tex);
00269 m_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, width, 0, GL_RGBA, GL_FLOAT, buf);
00270
00271 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00272 QString("Created bicubic helper texture (%1 samples)") .arg(width));
00273 delete [] buf;
00274 doneCurrent();
00275 return tmp_tex;
00276 }
00277
00278 void MythRenderOpenGL1::DeleteOpenGLResources(void)
00279 {
00280 LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting OpenGL Resources");
00281 DeleteShaders();
00282 MythRenderOpenGL::DeleteOpenGLResources();
00283 }
00284
00285 void MythRenderOpenGL1::SetMatrixView(void)
00286 {
00287 glMatrixMode(GL_PROJECTION);
00288 glLoadIdentity();
00289 glOrtho(m_viewport.left(), m_viewport.left() + m_viewport.width(),
00290 m_viewport.top() + m_viewport.height(), m_viewport.top(), 1, -1);
00291 glMatrixMode(GL_MODELVIEW);
00292 glLoadIdentity();
00293 }
00294
00295 void MythRenderOpenGL1::PushTransformation(const UIEffects &fx, QPointF ¢er)
00296 {
00297 makeCurrent();
00298 glPushMatrix();
00299 glTranslatef(center.x(), center.y(), 0.0);
00300 glScalef(fx.hzoom, fx.vzoom, 1.0);
00301 glRotatef(fx.angle, 0, 0, 1);
00302 glTranslatef(-center.x(), -center.y(), 0.0);
00303 doneCurrent();
00304 }
00305
00306 void MythRenderOpenGL1::PopTransformation(void)
00307 {
00308 makeCurrent();
00309 glPopMatrix();
00310 doneCurrent();
00311 }
00312
00313 void MythRenderOpenGL1::DeleteShaders(void)
00314 {
00315 QVector<GLuint>::iterator it;
00316 for (it = m_programs.begin(); it != m_programs.end(); ++it)
00317 m_glDeleteProgramsARB(1, &(*(it)));
00318 m_programs.clear();
00319 Flush(true);
00320 }
00321
00322 void MythRenderOpenGL1::DrawBitmapPriv(uint tex, const QRect *src,
00323 const QRect *dst, uint prog, int alpha,
00324 int red, int green, int blue)
00325 {
00326 if (prog && !m_programs.contains(prog))
00327 prog = 0;
00328
00329 EnableShaderObject(prog);
00330 SetBlend(true);
00331 SetColor(red, green, blue, alpha);
00332
00333 glEnableClientState(GL_VERTEX_ARRAY);
00334 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00335 EnableTextures(tex);
00336 glBindTexture(m_textures[tex].m_type, tex);
00337 UpdateTextureVertices(tex, src, dst);
00338 glVertexPointer(2, GL_FLOAT, 0, m_textures[tex].m_vertex_data);
00339 glTexCoordPointer(2, GL_FLOAT, 0, m_textures[tex].m_vertex_data + TEX_OFFSET);
00340 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00341 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00342 glDisableClientState(GL_VERTEX_ARRAY);
00343 }
00344
00345 void MythRenderOpenGL1::DrawBitmapPriv(uint *textures, uint texture_count,
00346 const QRectF *src, const QRectF *dst,
00347 uint prog)
00348 {
00349 if (prog && !m_programs.contains(prog))
00350 prog = 0;
00351
00352 uint first = textures[0];
00353
00354 EnableShaderObject(prog);
00355 SetBlend(false);
00356 SetColor(255, 255, 255, 255);
00357
00358 glEnableClientState(GL_VERTEX_ARRAY);
00359 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00360 EnableTextures(first);
00361 uint active_tex = 0;
00362 for (uint i = 0; i < texture_count; i++)
00363 {
00364 if (m_textures.contains(textures[i]))
00365 {
00366 ActiveTexture(GL_TEXTURE0 + active_tex++);
00367 glBindTexture(m_textures[textures[i]].m_type, textures[i]);
00368 }
00369 }
00370
00371 UpdateTextureVertices(first, src, dst);
00372 glVertexPointer(2, GL_FLOAT, 0, m_textures[first].m_vertex_data);
00373 glTexCoordPointer(2, GL_FLOAT, 0, m_textures[first].m_vertex_data + TEX_OFFSET);
00374 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00375
00376 ActiveTexture(GL_TEXTURE0);
00377 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00378 glDisableClientState(GL_VERTEX_ARRAY);
00379 }
00380
00381 void MythRenderOpenGL1::DrawRectPriv(const QRect &area, const QBrush &fillBrush,
00382 const QPen &linePen, int alpha)
00383 {
00384 SetBlend(true);
00385 DisableTextures();
00386 EnableShaderObject(0);
00387 glEnableClientState(GL_VERTEX_ARRAY);
00388
00389 int lineWidth = linePen.width();
00390 QRect r(area.left() + lineWidth, area.top() + lineWidth,
00391 area.width() - (lineWidth * 2), area.height() - (lineWidth * 2));
00392
00393 if (fillBrush.style() != Qt::NoBrush)
00394 {
00395 int a = 255 * (((float)alpha / 255.0f) *
00396 ((float)fillBrush.color().alpha() / 255.0f));
00397 SetColor(fillBrush.color().red(), fillBrush.color().green(),
00398 fillBrush.color().blue(), a);
00399 GLfloat *vertices = GetCachedVertices(GL_TRIANGLE_STRIP, r);
00400 glVertexPointer(2, GL_FLOAT, 0, vertices);
00401 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00402 }
00403
00404 if (linePen.style() != Qt::NoPen)
00405 {
00406 int a = 255 * (((float)alpha / 255.0f) *
00407 ((float)linePen.color().alpha() / 255.0f));
00408 SetColor(linePen.color().red(), linePen.color().green(),
00409 linePen.color().blue(), a);
00410 glLineWidth(linePen.width());
00411 GLfloat *vertices = GetCachedVertices(GL_LINE_LOOP, r);
00412 glVertexPointer(2, GL_FLOAT, 0, vertices);
00413 glDrawArrays(GL_LINE_LOOP, 0, 4);
00414 }
00415
00416 glDisableClientState(GL_VERTEX_ARRAY);
00417 }