| 1 | // N.B. Any locking should be handled by the parent.
|
|---|
| 2 |
|
|---|
| 3 | using namespace std;
|
|---|
| 4 |
|
|---|
| 5 | // MythTV General headers
|
|---|
| 6 | #include "mythcontext.h"
|
|---|
| 7 |
|
|---|
| 8 | // MythTV videout headers
|
|---|
| 9 | #include "util-opengl.h"
|
|---|
| 10 | #include "util-x11.h"
|
|---|
| 11 |
|
|---|
| 12 | #define LOC QString("OpenglCtx: ")
|
|---|
| 13 | #define LOC_ERR QString("OpenglCtx Error: ")
|
|---|
| 14 |
|
|---|
| 15 | #ifndef GL_TEXTURE_RECTANGLE_ARB
|
|---|
| 16 | #define GL_TEXTURE_RECTANGLE_ARB 0x84F5
|
|---|
| 17 | #endif
|
|---|
| 18 |
|
|---|
| 19 | #ifndef GL_TEXTURE_RECTANGLE_EXT
|
|---|
| 20 | #define GL_TEXTURE_RECTANGLE_EXT 0x84F5
|
|---|
| 21 | #endif
|
|---|
| 22 |
|
|---|
| 23 | #ifndef GL_TEXTURE_RECTANGLE_NV
|
|---|
| 24 | #define GL_TEXTURE_RECTANGLE_NV 0x84F5
|
|---|
| 25 | #endif
|
|---|
| 26 |
|
|---|
| 27 | OpenglContext::OpenglContext() :
|
|---|
| 28 | m_texture( GL_TEXTURE_2D ),
|
|---|
| 29 | m_display(NULL), m_screen_num(0),
|
|---|
| 30 | m_window(0), m_visual(NULL),
|
|---|
| 31 | m_context(NULL), m_visible(true),
|
|---|
| 32 | m_supported(SUPP_NONE), m_max_tex_size(0),
|
|---|
| 33 | m_textures_enabled(FALSE)
|
|---|
| 34 | {
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | OpenglContext::~OpenglContext()
|
|---|
| 38 | {
|
|---|
| 39 | if (m_context && m_window)
|
|---|
| 40 | {
|
|---|
| 41 | DeletePrograms();
|
|---|
| 42 | DeleteTextures();
|
|---|
| 43 | DeleteFrameBuffers();
|
|---|
| 44 | }
|
|---|
| 45 | if (m_context)
|
|---|
| 46 | glXDestroyContext(m_display, m_context);
|
|---|
| 47 | if (m_window)
|
|---|
| 48 | XDestroyWindow(m_display, m_window);
|
|---|
| 49 | if (m_visual)
|
|---|
| 50 | XFree(m_visual);
|
|---|
| 51 | }
|
|---|
| 52 |
|
|---|
| 53 | bool OpenglContext::Create(Window window, int width, int height, bool visible)
|
|---|
| 54 | {
|
|---|
| 55 | m_visible = visible;
|
|---|
| 56 | m_display = MythXOpenDisplay();
|
|---|
| 57 | if (!m_display)
|
|---|
| 58 | {
|
|---|
| 59 | VERBOSE(VB_PLAYBACK, LOC_ERR + "Failed to open display.");
|
|---|
| 60 | return false;
|
|---|
| 61 | }
|
|---|
| 62 | m_screen_num = DefaultScreen(m_display);
|
|---|
| 63 | if (!CheckGlx() ||
|
|---|
| 64 | !GetVisual() ||
|
|---|
| 65 | !CreateWindow(window, width, height) ||
|
|---|
| 66 | !CreateContext())
|
|---|
| 67 | return false;
|
|---|
| 68 |
|
|---|
| 69 | VERBOSE(VB_PLAYBACK, LOC + QString("Created window%1 and context.")
|
|---|
| 70 | .arg(m_visible ? "" : " (Offscreen)"));
|
|---|
| 71 | return true;
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | void OpenglContext::Init(void)
|
|---|
| 75 | {
|
|---|
| 76 | MakeCurrent(true);
|
|---|
| 77 | m_extensions= reinterpret_cast<const char *>(glGetString( GL_EXTENSIONS ));
|
|---|
| 78 | glGetIntegerv( GL_MAX_TEXTURE_SIZE, &m_max_tex_size );
|
|---|
| 79 | MakeCurrent(false);
|
|---|
| 80 | if (m_max_tex_size == 0)
|
|---|
| 81 | m_max_tex_size = 512;
|
|---|
| 82 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 83 | QString("Maximum supported texture size: %1 x %2")
|
|---|
| 84 | .arg(m_max_tex_size).arg(m_max_tex_size));
|
|---|
| 85 | m_supported += EnableFrameBufs();
|
|---|
| 86 | m_supported += EnableFragProgs();
|
|---|
| 87 | m_supported += EnableTextureRects();
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | void OpenglContext::MakeCurrent(bool current)
|
|---|
| 91 | {
|
|---|
| 92 | if (current)
|
|---|
| 93 | {
|
|---|
| 94 | bool yes = glXMakeCurrent( m_display, m_window, m_context );
|
|---|
| 95 | if (!yes)
|
|---|
| 96 | VERBOSE(VB_PLAYBACK, LOC + "Could not make context current.");
|
|---|
| 97 | }
|
|---|
| 98 | else
|
|---|
| 99 | glXMakeCurrent( m_display, None, NULL );
|
|---|
| 100 | }
|
|---|
| 101 |
|
|---|
| 102 | void OpenglContext::SwapBuffers(void)
|
|---|
| 103 | {
|
|---|
| 104 | if (!m_visible)
|
|---|
| 105 | return;
|
|---|
| 106 | MakeCurrent(true);
|
|---|
| 107 | glXSwapBuffers(m_display, m_window);
|
|---|
| 108 | MakeCurrent(false);
|
|---|
| 109 | }
|
|---|
| 110 |
|
|---|
| 111 | void OpenglContext::EnableTextures(void)
|
|---|
| 112 | {
|
|---|
| 113 | if (m_textures_enabled)
|
|---|
| 114 | return;
|
|---|
| 115 | m_textures_enabled = true;
|
|---|
| 116 | MakeCurrent(true);
|
|---|
| 117 | glEnable( m_texture );
|
|---|
| 118 | MakeCurrent(false);
|
|---|
| 119 | }
|
|---|
| 120 |
|
|---|
| 121 | int OpenglContext::EnableTextureRects(void)
|
|---|
| 122 | {
|
|---|
| 123 | if (m_extensions.contains("GL_NV_texture_rectangle"))
|
|---|
| 124 | {
|
|---|
| 125 | VERBOSE(VB_PLAYBACK, LOC + "Using NV NPOT texture extension.");
|
|---|
| 126 | m_texture = GL_TEXTURE_RECTANGLE_NV;
|
|---|
| 127 | }
|
|---|
| 128 | else if (m_extensions.contains("GL_ARB_texture_rectangle"))
|
|---|
| 129 | {
|
|---|
| 130 | VERBOSE(VB_PLAYBACK, LOC + "Using ARB NPOT texture extension.");
|
|---|
| 131 | m_texture = GL_TEXTURE_RECTANGLE_ARB;
|
|---|
| 132 | }
|
|---|
| 133 | else if (m_extensions.contains("GL_EXT_texture_rectangle"))
|
|---|
| 134 | {
|
|---|
| 135 | VERBOSE(VB_PLAYBACK, LOC + "Using EXT NPOT texture extension.");
|
|---|
| 136 | m_texture = GL_TEXTURE_RECTANGLE_EXT;
|
|---|
| 137 | }
|
|---|
| 138 | else
|
|---|
| 139 | {
|
|---|
| 140 | VERBOSE(VB_PLAYBACK, LOC + "NPOT textures not available.");
|
|---|
| 141 | return 0;
|
|---|
| 142 | }
|
|---|
| 143 |
|
|---|
| 144 | return SUPP_RECT;
|
|---|
| 145 | }
|
|---|
| 146 |
|
|---|
| 147 | int OpenglContext::EnableFragProgs(void)
|
|---|
| 148 | {
|
|---|
| 149 | if (!m_extensions.contains("GL_ARB_fragment_program"))
|
|---|
| 150 | {
|
|---|
| 151 | VERBOSE(VB_PLAYBACK, LOC + "GL_ARB_fragment_program unavailable.");
|
|---|
| 152 | return 0;
|
|---|
| 153 | }
|
|---|
| 154 | m_glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)
|
|---|
| 155 | glXGetProcAddress("glGenProgramsARB");
|
|---|
| 156 | m_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)
|
|---|
| 157 | glXGetProcAddress("glBindProgramARB");
|
|---|
| 158 | m_glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)
|
|---|
| 159 | glXGetProcAddress("glProgramStringARB");
|
|---|
| 160 | m_glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC)
|
|---|
| 161 | glXGetProcAddress("glProgramEnvParameter4fARB");
|
|---|
| 162 | m_glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)
|
|---|
| 163 | glXGetProcAddress("glDeleteProgramsARB");
|
|---|
| 164 | m_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)
|
|---|
| 165 | glXGetProcAddress("glGetProgramivARB");
|
|---|
| 166 |
|
|---|
| 167 | if (!m_glGenProgramsARB ||
|
|---|
| 168 | !m_glBindProgramARB ||
|
|---|
| 169 | !m_glProgramStringARB ||
|
|---|
| 170 | !m_glDeleteProgramsARB ||
|
|---|
| 171 | !m_glGetProgramivARB ||
|
|---|
| 172 | !m_glProgramEnvParameter4fARB)
|
|---|
| 173 | {
|
|---|
| 174 | VERBOSE(VB_PLAYBACK, LOC + "Couldn't get proc address");
|
|---|
| 175 | return 0;
|
|---|
| 176 | }
|
|---|
| 177 | VERBOSE(VB_PLAYBACK, LOC + "Fragment programs supported.");
|
|---|
| 178 | return SUPP_PROG;
|
|---|
| 179 | }
|
|---|
| 180 |
|
|---|
| 181 | int OpenglContext::EnableFrameBufs(void)
|
|---|
| 182 | {
|
|---|
| 183 | if (!m_extensions.contains("GL_EXT_framebuffer_object"))
|
|---|
| 184 | {
|
|---|
| 185 | VERBOSE(VB_PLAYBACK, LOC + "GL_EXT_framebuffer_object unavailable.");
|
|---|
| 186 | return 0;
|
|---|
| 187 | }
|
|---|
| 188 | m_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
|
|---|
| 189 | glXGetProcAddress("glGenFramebuffersEXT");
|
|---|
| 190 | m_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
|
|---|
| 191 | glXGetProcAddress("glBindFramebufferEXT");
|
|---|
| 192 | m_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
|
|---|
| 193 | glXGetProcAddress("glFramebufferTexture2DEXT");
|
|---|
| 194 | m_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
|
|---|
| 195 | glXGetProcAddress("glCheckFramebufferStatusEXT");
|
|---|
| 196 | m_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
|
|---|
| 197 | glXGetProcAddress("glDeleteFramebuffersEXT");
|
|---|
| 198 |
|
|---|
| 199 | if (!m_glGenFramebuffersEXT ||
|
|---|
| 200 | !m_glBindFramebufferEXT ||
|
|---|
| 201 | !m_glFramebufferTexture2DEXT ||
|
|---|
| 202 | !m_glDeleteFramebuffersEXT ||
|
|---|
| 203 | !m_glCheckFramebufferStatusEXT)
|
|---|
| 204 | {
|
|---|
| 205 | VERBOSE(VB_PLAYBACK, LOC + "Couldn't get proc address");
|
|---|
| 206 | return 0;
|
|---|
| 207 | }
|
|---|
| 208 | VERBOSE(VB_PLAYBACK, LOC + "Frame Buffer Objects supported.");
|
|---|
| 209 | return SUPP_FBUF;
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | void OpenglContext::CreateTexture(GLuint *tex)
|
|---|
| 213 | {
|
|---|
| 214 | MakeCurrent(true);
|
|---|
| 215 | glGenTextures( 1, tex );
|
|---|
| 216 | SetupTextureFilters(tex, GL_LINEAR);
|
|---|
| 217 | textures.push_back(*tex);
|
|---|
| 218 | MakeCurrent(false);
|
|---|
| 219 | }
|
|---|
| 220 |
|
|---|
| 221 | bool OpenglContext::SetupTexture(QSize size, GLuint *tex, int filt)
|
|---|
| 222 | {
|
|---|
| 223 | scratchspace = new unsigned char[(size.width()
|
|---|
| 224 | * size.height() * 4) + 4];
|
|---|
| 225 | memset(scratchspace, 0 , size.width() * size.height() * 4);
|
|---|
| 226 |
|
|---|
| 227 | GLint check;
|
|---|
| 228 | MakeCurrent(true);
|
|---|
| 229 |
|
|---|
| 230 | SetupTextureFilters(tex, filt);
|
|---|
| 231 | glTexImage2D( m_texture, 0, GL_RGBA8,
|
|---|
| 232 | size.width(), size.height(),
|
|---|
| 233 | 0, GL_RGB , GL_UNSIGNED_BYTE, scratchspace );
|
|---|
| 234 | glGetTexLevelParameteriv(m_texture, 0, GL_TEXTURE_WIDTH, &check);
|
|---|
| 235 | MakeCurrent(false);
|
|---|
| 236 | delete scratchspace;
|
|---|
| 237 | if (check !=size.width())
|
|---|
| 238 | return false;
|
|---|
| 239 | return true;
|
|---|
| 240 | }
|
|---|
| 241 |
|
|---|
| 242 | void OpenglContext::SetupTextureFilters(GLuint *tex, int filt)
|
|---|
| 243 | {
|
|---|
| 244 | glBindTexture( m_texture, *tex );
|
|---|
| 245 | glTexParameteri (m_texture, GL_TEXTURE_MIN_FILTER, filt);
|
|---|
| 246 | glTexParameteri (m_texture, GL_TEXTURE_MAG_FILTER, filt);
|
|---|
| 247 | glTexParameteri (m_texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|---|
| 248 | glTexParameteri (m_texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|---|
| 249 | }
|
|---|
| 250 |
|
|---|
| 251 | void OpenglContext::DeleteTexture(GLuint *tex)
|
|---|
| 252 | {
|
|---|
| 253 | MakeCurrent(true);
|
|---|
| 254 | vector<GLuint>::iterator it;
|
|---|
| 255 | for (it = textures.begin(); it !=textures.end(); it++)
|
|---|
| 256 | {
|
|---|
| 257 | if (*(it) == *tex)
|
|---|
| 258 | {
|
|---|
| 259 | glDeleteTextures( 1, tex);
|
|---|
| 260 | textures.erase(it);
|
|---|
| 261 | break;
|
|---|
| 262 | }
|
|---|
| 263 | }
|
|---|
| 264 | MakeCurrent(false);
|
|---|
| 265 | }
|
|---|
| 266 |
|
|---|
| 267 | void OpenglContext::DeleteTextures(void)
|
|---|
| 268 | {
|
|---|
| 269 | MakeCurrent(true);
|
|---|
| 270 | vector<GLuint>::iterator it;
|
|---|
| 271 | for (it = textures.begin(); it !=textures.end(); it++)
|
|---|
| 272 | glDeleteTextures( 1, &(*(it)));
|
|---|
| 273 | textures.clear();
|
|---|
| 274 | MakeCurrent(false);
|
|---|
| 275 | }
|
|---|
| 276 |
|
|---|
| 277 | bool OpenglContext::CreateProgram(QString *program, GLuint *prog)
|
|---|
| 278 | {
|
|---|
| 279 | bool success = true;
|
|---|
| 280 | GLint error;
|
|---|
| 281 | MakeCurrent(true);
|
|---|
| 282 | m_glGenProgramsARB ( 1, prog );
|
|---|
| 283 | m_glBindProgramARB ( GL_FRAGMENT_PROGRAM_ARB, *prog );
|
|---|
| 284 | m_glProgramStringARB ( GL_FRAGMENT_PROGRAM_ARB,
|
|---|
| 285 | GL_PROGRAM_FORMAT_ASCII_ARB,
|
|---|
| 286 | program->length(), program->latin1() );
|
|---|
| 287 |
|
|---|
| 288 | glGetIntegerv ( GL_PROGRAM_ERROR_POSITION_ARB, &error );
|
|---|
| 289 | if (error != -1)
|
|---|
| 290 | {
|
|---|
| 291 | VERBOSE(VB_PLAYBACK, LOC_ERR +
|
|---|
| 292 | QString("Fragment Program compile error: position %1:'%2'")
|
|---|
| 293 | .arg(error).arg(program->mid(error)));
|
|---|
| 294 | success = false;
|
|---|
| 295 | }
|
|---|
| 296 | m_glGetProgramivARB( GL_FRAGMENT_PROGRAM_ARB,
|
|---|
| 297 | GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &error );
|
|---|
| 298 | if (error != 1)
|
|---|
| 299 | {
|
|---|
| 300 | VERBOSE(VB_PLAYBACK, LOC_ERR +
|
|---|
| 301 | QString("Fragment program exceeds hardware capabilities."));
|
|---|
| 302 | success = false;
|
|---|
| 303 | }
|
|---|
| 304 |
|
|---|
| 305 | if (success)
|
|---|
| 306 | programs.push_back(*prog);
|
|---|
| 307 | else
|
|---|
| 308 | m_glDeleteProgramsARB( 1, prog );
|
|---|
| 309 | MakeCurrent(false);
|
|---|
| 310 | return success;
|
|---|
| 311 | }
|
|---|
| 312 |
|
|---|
| 313 | void OpenglContext::DeleteProgram(GLuint *prog)
|
|---|
| 314 | {
|
|---|
| 315 | MakeCurrent(true);
|
|---|
| 316 | vector<GLuint>::iterator it;
|
|---|
| 317 | for (it = programs.begin(); it !=programs.end(); it++)
|
|---|
| 318 | {
|
|---|
| 319 | if (*(it) == *prog)
|
|---|
| 320 | {
|
|---|
| 321 | m_glDeleteProgramsARB( 1, prog);
|
|---|
| 322 | programs.erase(it);
|
|---|
| 323 | break;
|
|---|
| 324 | }
|
|---|
| 325 | }
|
|---|
| 326 | MakeCurrent(false);
|
|---|
| 327 | }
|
|---|
| 328 |
|
|---|
| 329 |
|
|---|
| 330 | void OpenglContext::DeletePrograms(void)
|
|---|
| 331 | {
|
|---|
| 332 | MakeCurrent(true);
|
|---|
| 333 | vector<GLuint>::iterator it;
|
|---|
| 334 | for (it = programs.begin(); it !=programs.end(); it++)
|
|---|
| 335 | m_glDeleteProgramsARB( 1, &(*(it)));
|
|---|
| 336 | MakeCurrent(false);
|
|---|
| 337 | programs.clear();
|
|---|
| 338 | }
|
|---|
| 339 |
|
|---|
| 340 | bool OpenglContext::CreateFrameBuffer(GLuint *buf, GLuint *tex,
|
|---|
| 341 | int width, int height)
|
|---|
| 342 | {
|
|---|
| 343 | SetupTextureFilters(tex, GL_LINEAR);
|
|---|
| 344 | MakeCurrent(true);
|
|---|
| 345 | glPushAttrib (GL_VIEWPORT_BIT);
|
|---|
| 346 | glViewport( 0, 0, width, height);
|
|---|
| 347 | m_glGenFramebuffersEXT( 1, buf );
|
|---|
| 348 | m_glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *buf );
|
|---|
| 349 | glBindTexture( m_texture, *tex );
|
|---|
| 350 | glTexImage2D( m_texture, 0, GL_RGBA8,
|
|---|
| 351 | (GLint)width,
|
|---|
| 352 | (GLint)height, 0,
|
|---|
| 353 | GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|---|
| 354 | m_glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT,
|
|---|
| 355 | GL_COLOR_ATTACHMENT0_EXT, m_texture, *tex, 0 );
|
|---|
| 356 | GLenum status;
|
|---|
| 357 | status = m_glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
|
|---|
| 358 | m_glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
|
|---|
| 359 | glPopAttrib ();
|
|---|
| 360 | bool success = false;
|
|---|
| 361 | switch(status)
|
|---|
| 362 | {
|
|---|
| 363 | case GL_FRAMEBUFFER_COMPLETE_EXT:
|
|---|
| 364 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 365 | QString("Created frame buffer object (%1x%2).")
|
|---|
| 366 | .arg(width).arg(height));
|
|---|
| 367 | success = true;
|
|---|
| 368 | break;
|
|---|
| 369 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
|---|
| 370 | VERBOSE(VB_PLAYBACK, LOC + "Frame buffer incomplete_ATTACHMENT");
|
|---|
| 371 | break;
|
|---|
| 372 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
|---|
| 373 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 374 | "Frame buffer incomplete_MISSING_ATTACHMENT");
|
|---|
| 375 | break;
|
|---|
| 376 | case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
|
|---|
| 377 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 378 | "Frame buffer incomplete_DUPLICATE_ATTACHMENT");
|
|---|
| 379 | break;
|
|---|
| 380 | case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
|---|
| 381 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 382 | "Frame buffer incomplete_DIMENSIONS_EXT");
|
|---|
| 383 | break;
|
|---|
| 384 | case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
|---|
| 385 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 386 | "Frame buffer incomplete_FORMATS_EXT");
|
|---|
| 387 | break;
|
|---|
| 388 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
|---|
| 389 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 390 | "Frame buffer incomplete_DRAW_BUFFER_EXT");
|
|---|
| 391 | break;
|
|---|
| 392 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
|---|
| 393 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 394 | "Frame buffer incomplete_READ_BUFFER_EXT");
|
|---|
| 395 | break;
|
|---|
| 396 | case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
|---|
| 397 | VERBOSE(VB_PLAYBACK, LOC + "Frame buffer unsupported.");
|
|---|
| 398 | break;
|
|---|
| 399 | default:
|
|---|
| 400 | VERBOSE(VB_PLAYBACK, LOC +
|
|---|
| 401 | QString("Unknown frame buffer error %1.").arg(status));
|
|---|
| 402 | }
|
|---|
| 403 | if (success)
|
|---|
| 404 | framebuffers.push_back(*buf);
|
|---|
| 405 | else
|
|---|
| 406 | m_glDeleteFramebuffersEXT( 1, buf );
|
|---|
| 407 | MakeCurrent(false);
|
|---|
| 408 | return success;
|
|---|
| 409 | }
|
|---|
| 410 |
|
|---|
| 411 | void OpenglContext::DeleteFrameBuffer(GLuint *buf)
|
|---|
| 412 | {
|
|---|
| 413 | MakeCurrent(true);
|
|---|
| 414 | vector<GLuint>::iterator it;
|
|---|
| 415 | for (it = framebuffers.begin(); it !=framebuffers.end(); it++)
|
|---|
| 416 | {
|
|---|
| 417 | if (*(it) == *buf)
|
|---|
| 418 | {
|
|---|
| 419 | m_glDeleteFramebuffersEXT( 1, buf);
|
|---|
| 420 | framebuffers.erase(it);
|
|---|
| 421 | break;
|
|---|
| 422 | }
|
|---|
| 423 | }
|
|---|
| 424 | MakeCurrent(false);
|
|---|
| 425 | }
|
|---|
| 426 |
|
|---|
| 427 | void OpenglContext::DeleteFrameBuffers(void)
|
|---|
| 428 | {
|
|---|
| 429 | MakeCurrent(true);
|
|---|
| 430 | vector<GLuint>::iterator it;
|
|---|
| 431 | for (it = framebuffers.begin(); it !=framebuffers.end(); it++)
|
|---|
| 432 | m_glDeleteFramebuffersEXT( 1, &(*(it)));
|
|---|
| 433 | framebuffers.clear();
|
|---|
| 434 | MakeCurrent(false);
|
|---|
| 435 | }
|
|---|
| 436 |
|
|---|
| 437 | bool OpenglContext::CheckGlx(void)
|
|---|
| 438 | {
|
|---|
| 439 | int ndummy;
|
|---|
| 440 | if (!glXQueryExtension(m_display, &ndummy, &ndummy))
|
|---|
| 441 | {
|
|---|
| 442 | VERBOSE(VB_PLAYBACK, LOC_ERR + "OpenGL extension not present.");
|
|---|
| 443 | return false;
|
|---|
| 444 | }
|
|---|
| 445 | return true;
|
|---|
| 446 | }
|
|---|
| 447 |
|
|---|
| 448 | bool OpenglContext::GetVisual(void)
|
|---|
| 449 | {
|
|---|
| 450 | int attribList[] = {GLX_RGBA, GLX_DEPTH_SIZE, 0, GLX_DOUBLEBUFFER, 1,
|
|---|
| 451 | GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
|
|---|
| 452 | GLX_BLUE_SIZE, 1, None};
|
|---|
| 453 | m_visual = glXChooseVisual(m_display, m_screen_num, attribList);
|
|---|
| 454 | if (m_visual == NULL)
|
|---|
| 455 | {
|
|---|
| 456 | // see if we can can get a visual WITH depth buffer
|
|---|
| 457 | int withdepth[] = {GLX_RGBA,
|
|---|
| 458 | GLX_DOUBLEBUFFER, 1, GLX_RED_SIZE, 1,
|
|---|
| 459 | GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None};
|
|---|
| 460 | m_visual = glXChooseVisual(m_display, m_screen_num, withdepth);
|
|---|
| 461 | if (m_visual == NULL)
|
|---|
| 462 | {
|
|---|
| 463 | VERBOSE(VB_PLAYBACK, LOC_ERR + "No appropriate visual found");
|
|---|
| 464 | return false;
|
|---|
| 465 | }
|
|---|
| 466 | }
|
|---|
| 467 | return true;
|
|---|
| 468 | }
|
|---|
| 469 |
|
|---|
| 470 | bool OpenglContext::CreateWindow( Window winid, int width, int height)
|
|---|
| 471 | {
|
|---|
| 472 | XSetWindowAttributes swa;
|
|---|
| 473 | swa.colormap = XCreateColormap(m_display,
|
|---|
| 474 | RootWindow(m_display, m_visual->screen),
|
|---|
| 475 | m_visual->visual, AllocNone);
|
|---|
| 476 | if (swa.colormap == 0)
|
|---|
| 477 | {
|
|---|
| 478 | VERBOSE(VB_PLAYBACK, LOC_ERR + "Failed to create colormap");
|
|---|
| 479 | return false;
|
|---|
| 480 | }
|
|---|
| 481 | m_window = XCreateWindow(m_display, winid, 0, 0,
|
|---|
| 482 | m_visible ? width : 1, m_visible ? height : 1,
|
|---|
| 483 | 0, m_visual->depth,
|
|---|
| 484 | InputOutput, m_visual->visual, CWColormap, &swa);
|
|---|
| 485 | if (m_window == 0)
|
|---|
| 486 | {
|
|---|
| 487 | VERBOSE(VB_PLAYBACK, LOC_ERR + "Failed to create window");
|
|---|
| 488 | return false;
|
|---|
| 489 | }
|
|---|
| 490 | if (m_visible)
|
|---|
| 491 | XMapWindow(m_display, m_window);
|
|---|
| 492 | return true;
|
|---|
| 493 | }
|
|---|
| 494 |
|
|---|
| 495 | bool OpenglContext::CreateContext(void)
|
|---|
| 496 | {
|
|---|
| 497 | m_context = glXCreateContext(m_display, m_visual, None, GL_TRUE);
|
|---|
| 498 | if (m_context == NULL)
|
|---|
| 499 | {
|
|---|
| 500 | VERBOSE(VB_PLAYBACK, LOC_ERR + "Failed to create Glx context");
|
|---|
| 501 | return false;
|
|---|
| 502 | }
|
|---|
| 503 |
|
|---|
| 504 | if (!glXMakeCurrent(m_display, m_window, m_context))
|
|---|
| 505 | {
|
|---|
| 506 | VERBOSE(VB_PLAYBACK, LOC_ERR + "Failed to make Glx context current.");
|
|---|
| 507 | return false;
|
|---|
| 508 | }
|
|---|
| 509 | glXMakeCurrent(m_display, None, NULL);
|
|---|
| 510 | return true;
|
|---|
| 511 | }
|
|---|
| 512 |
|
|---|
| 513 | __GLXextFuncPtr OpenglContext::glXGetProcAddress(const char * const procName)
|
|---|
| 514 | {
|
|---|
| 515 | __GLXextFuncPtr ret = glXGetProcAddressARB((const GLubyte *) procName);
|
|---|
| 516 | if (!ret)
|
|---|
| 517 | {
|
|---|
| 518 | VERBOSE(VB_PLAYBACK,
|
|---|
| 519 | QString("Error: glXGetProcAddressARB unable to find %1")
|
|---|
| 520 | .arg(procName));
|
|---|
| 521 | }
|
|---|
| 522 | return ret;
|
|---|
| 523 | }
|
|---|