00001
00002
00003 #include "util-opengl.h"
00004 #include "frame.h"
00005
00006 PFNGLGENPROGRAMSARBPROC gMythGLGenProgramsARB = NULL;
00007 PFNGLBINDPROGRAMARBPROC gMythGLBindProgramARB = NULL;
00008 PFNGLPROGRAMSTRINGARBPROC gMythGLProgramStringARB = NULL;
00009 PFNGLPROGRAMENVPARAMETER4FARBPROC gMythGLProgramEnvParameter4fARB = NULL;
00010 PFNGLDELETEPROGRAMSARBPROC gMythGLDeleteProgramsARB = NULL;
00011 PFNGLGETPROGRAMIVARBPROC gMythGLGetProgramivARB = NULL;
00012
00013 MYTH_GLGENFRAMEBUFFERSEXTPROC gMythGLGenFramebuffersEXT = NULL;
00014 MYTH_GLBINDFRAMEBUFFEREXTPROC gMythGLBindFramebufferEXT = NULL;
00015 MYTH_GLFRAMEBUFFERTEXTURE2DEXTPROC gMythGLFramebufferTexture2DEXT = NULL;
00016 MYTH_GLCHECKFRAMEBUFFERSTATUSEXTPROC gMythGLCheckFramebufferStatusEXT = NULL;
00017 MYTH_GLDELETEFRAMEBUFFERSEXTPROC gMythGLDeleteFramebuffersEXT = NULL;
00018
00019 PFNGLXGETVIDEOSYNCSGIPROC gMythGLXGetVideoSyncSGI = NULL;
00020 PFNGLXWAITVIDEOSYNCSGIPROC gMythGLXWaitVideoSyncSGI = NULL;
00021
00022 bool init_opengl(void)
00023 {
00024 static bool is_initialized = false;
00025 static QMutex init_lock;
00026
00027 QMutexLocker locker(&init_lock);
00028 if (is_initialized)
00029 return true;
00030
00031 is_initialized = true;
00032
00033 gMythGLGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)
00034 get_gl_proc_address("glGenProgramsARB");
00035 gMythGLBindProgramARB = (PFNGLBINDPROGRAMARBPROC)
00036 get_gl_proc_address("glBindProgramARB");
00037 gMythGLProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)
00038 get_gl_proc_address("glProgramStringARB");
00039 gMythGLProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC)
00040 get_gl_proc_address("glProgramEnvParameter4fARB");
00041 gMythGLDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)
00042 get_gl_proc_address("glDeleteProgramsARB");
00043 gMythGLGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)
00044 get_gl_proc_address("glGetProgramivARB");
00045
00046 gMythGLGenFramebuffersEXT = (MYTH_GLGENFRAMEBUFFERSEXTPROC)
00047 get_gl_proc_address("glGenFramebuffersEXT");
00048 gMythGLBindFramebufferEXT = (MYTH_GLBINDFRAMEBUFFEREXTPROC)
00049 get_gl_proc_address("glBindFramebufferEXT");
00050 gMythGLFramebufferTexture2DEXT = (MYTH_GLFRAMEBUFFERTEXTURE2DEXTPROC)
00051 get_gl_proc_address("glFramebufferTexture2DEXT");
00052 gMythGLCheckFramebufferStatusEXT =
00053 (MYTH_GLCHECKFRAMEBUFFERSTATUSEXTPROC)
00054 get_gl_proc_address("glCheckFramebufferStatusEXT");
00055 gMythGLDeleteFramebuffersEXT = (MYTH_GLDELETEFRAMEBUFFERSEXTPROC)
00056 get_gl_proc_address("glDeleteFramebuffersEXT");
00057
00058 gMythGLXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)
00059 get_gl_proc_address("glXGetVideoSyncSGI");
00060 gMythGLXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)
00061 get_gl_proc_address("glXWaitVideoSyncSGI");
00062
00063 return true;
00064 }
00065
00066 bool get_glx_version(Display *XJ_disp, uint &major, uint &minor)
00067 {
00068
00069 static bool has_run = false;
00070 static int static_major = 0;
00071 static int static_minor = 0;
00072 static int static_ret = false;
00073 static QMutex get_glx_version_lock;
00074 QMutexLocker locker(&get_glx_version_lock);
00075
00076 int ret, errbase, eventbase, gl_major, gl_minor;
00077
00078 if (has_run)
00079 {
00080 major = static_major;
00081 minor = static_minor;
00082 return static_ret;
00083 }
00084
00085 major = minor = 0;
00086 has_run = true;
00087
00088 X11S(ret = glXQueryExtension(XJ_disp, &errbase, &eventbase));
00089 if (!ret)
00090 return false;
00091
00092
00093
00094
00095
00096
00097
00098 Display *tmp_disp = MythXOpenDisplay();
00099 X11S(ret = glXQueryVersion(tmp_disp, &gl_major, &gl_minor));
00100 XCloseDisplay(tmp_disp);
00101
00102 if (!ret)
00103 return false;
00104
00105 static_major = major = gl_major;
00106 static_minor = minor = gl_minor;
00107 static_ret = true;
00108
00109 return true;
00110 }
00111
00112 int const *get_attr_cfg(FrameBufferType type)
00113 {
00114 static const int render_rgba_config[] =
00115 {
00116 GLX_CONFIG_CAVEAT, GLX_NONE,
00117 GLX_RENDER_TYPE, GLX_RGBA_BIT,
00118 GLX_RED_SIZE, 5,
00119 GLX_GREEN_SIZE, 5,
00120 GLX_BLUE_SIZE, 5,
00121 GLX_DOUBLEBUFFER, 1,
00122 GLX_STEREO, 0,
00123 GLX_LEVEL, 0,
00124 GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
00125 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
00126 None
00127 };
00128
00129 static const int simple_rgba_config[] =
00130 {
00131 GLX_RGBA,
00132 GLX_RED_SIZE, 5,
00133 GLX_GREEN_SIZE, 5,
00134 GLX_BLUE_SIZE, 5,
00135 GLX_DOUBLEBUFFER, 1,
00136 None
00137 };
00138
00139 int const * attr_config = simple_rgba_config;
00140
00141 if (kRenderRGBA == type)
00142 attr_config = render_rgba_config;
00143
00144 if (kSimpleRGBA == type)
00145 attr_config = simple_rgba_config;
00146
00147 return attr_config;
00148 }
00149
00150
00151 GLXFBConfig get_fbuffer_cfg(Display *XJ_disp, int XJ_screen_num,
00152 const int *attr_fbconfig)
00153 {
00154
00155
00156 GLXFBConfig cfg = 0;
00157 GLXFBConfig *cfgs = NULL;
00158 int num = 0;
00159
00160 X11L;
00161
00162 cfgs = glXChooseFBConfig(XJ_disp, XJ_screen_num, attr_fbconfig, &num);
00163
00164 if (num)
00165 {
00166 cfg = cfgs[0];
00167
00168
00169 for (int i = 0; i < num; i++)
00170 {
00171 int value;
00172 glXGetFBConfigAttrib(XJ_disp, cfgs[i], GLX_DEPTH_SIZE, &value);
00173 if (!value)
00174 {
00175 cfg = cfgs[i];
00176 break;
00177 }
00178 }
00179 }
00180
00181 XFree(cfgs);
00182
00183 X11U;
00184
00185 return cfg;
00186 }
00187
00188 GLXPbuffer get_pbuffer(Display *XJ_disp,
00189 GLXFBConfig glx_fbconfig,
00190 const QSize &video_dim)
00191 {
00192 int attrib_pbuffer[16];
00193 bzero(attrib_pbuffer, sizeof(int) * 16);
00194 attrib_pbuffer[0] = GLX_PBUFFER_WIDTH;
00195 attrib_pbuffer[1] = video_dim.width();
00196 attrib_pbuffer[2] = GLX_PBUFFER_HEIGHT;
00197 attrib_pbuffer[3] = video_dim.height();
00198 attrib_pbuffer[4] = GLX_PRESERVED_CONTENTS;
00199 attrib_pbuffer[5] = 0;
00200
00201 GLXPbuffer tmp = 0;
00202
00203 #ifdef GLX_VERSION_1_3
00204 X11S(tmp = glXCreatePbuffer(XJ_disp, glx_fbconfig, attrib_pbuffer));
00205 #endif // GLX_VERSION_1_3
00206
00207 return tmp;
00208 }
00209
00210 Window get_gl_window(Display *XJ_disp,
00211 Window XJ_curwin,
00212 XVisualInfo *visInfo,
00213 const QSize &window_size,
00214 bool map_window)
00215 {
00216 X11L;
00217
00218 XSetWindowAttributes attributes;
00219 attributes.colormap = XCreateColormap(
00220 XJ_disp, XJ_curwin, visInfo->visual, AllocNone);
00221
00222 Window gl_window = XCreateWindow(
00223 XJ_disp, XJ_curwin, 0, 0, window_size.width(), window_size.height(), 0,
00224 visInfo->depth, InputOutput, visInfo->visual, CWColormap, &attributes);
00225
00226 if (map_window)
00227 XMapWindow(XJ_disp, gl_window);
00228
00229 XFree(visInfo);
00230
00231 X11U;
00232
00233 return gl_window;
00234 }
00235
00236 GLXWindow get_glx_window(Display *XJ_disp, GLXFBConfig glx_fbconfig,
00237 Window gl_window, GLXContext glx_context,
00238 GLXPbuffer glx_pbuffer, const QSize &window_size)
00239 {
00240 X11L;
00241
00242 GLXWindow glx_window = glXCreateWindow(
00243 XJ_disp, glx_fbconfig, gl_window, NULL);
00244
00245 glXMakeContextCurrent(XJ_disp, glx_window, glx_pbuffer, glx_context);
00246
00247 glDrawBuffer(GL_BACK_LEFT);
00248 glReadBuffer(GL_FRONT_LEFT);
00249 glClearColor(0.0, 0.0, 0.0, 0.0);
00250 glShadeModel(GL_FLAT);
00251 glEnable(GL_TEXTURE_RECTANGLE_NV);
00252
00253 glViewport(0, 0, window_size.width(), window_size.height());
00254 glMatrixMode(GL_PROJECTION);
00255 glLoadIdentity();
00256
00257 glOrtho(0, window_size.width(), 0, window_size.height(), -2, 2);
00258 glMatrixMode(GL_MODELVIEW);
00259 glLoadIdentity();
00260
00261 glFinish();
00262
00263 glXMakeContextCurrent(XJ_disp, None, None, NULL);
00264
00265 X11U;
00266
00267 return glx_window;
00268 }
00269
00270 void copy_pixels_to_texture(const unsigned char *buf,
00271 int buffer_format,
00272 const QSize &buffer_size,
00273 int texture,
00274 int texture_type)
00275 {
00276 glBindTexture(texture_type, texture);
00277
00278 uint format;
00279 switch (buffer_format)
00280 {
00281 case FMT_YV12:
00282 format = GL_LUMINANCE;
00283 break;
00284 case FMT_RGB24:
00285 format = GL_RGB;
00286 break;
00287 case FMT_RGBA32:
00288 format = GL_RGBA;
00289 break;
00290 case FMT_ALPHA:
00291 format = GL_ALPHA;
00292 break;
00293 default:
00294 return;
00295 }
00296
00297 glTexSubImage2D(
00298 texture_type,
00299 0, 0, 0,
00300 buffer_size.width(), buffer_size.height(),
00301 format, GL_UNSIGNED_BYTE,
00302 buf);
00303 }
00304
00305 __GLXextFuncPtr get_gl_proc_address(const QString &procName)
00306 {
00307 __GLXextFuncPtr ret = NULL;
00308
00309 #if USING_GLX_PROC_ADDR_ARB
00310 X11S(ret = glXGetProcAddressARB((const GLubyte*)procName.latin1()));
00311 #elif GLX_VERSION_1_4
00312 X11S(ret = glXGetProcAddress((const GLubyte*)procName.latin1()));
00313 #elif GLX_ARB_get_proc_address
00314 X11S(ret = glXGetProcAddressARB((const GLubyte*)procName.latin1()));
00315 #elif GLX_EXT_get_proc_address
00316 X11S(ret = glXGetProcAddressEXT((const GLubyte*)procName.latin1()));
00317 #endif
00318
00319 return ret;
00320 }
00321
00322 int get_gl_texture_rect_type(const QString &ext)
00323 {
00324 init_opengl();
00325
00326 if (ext.contains("GL_NV_texture_rectangle"))
00327 return GL_TEXTURE_RECTANGLE_NV;
00328 else if (ext.contains("GL_ARB_texture_rectangle"))
00329 return GL_TEXTURE_RECTANGLE_ARB;
00330 else if (ext.contains("GL_EXT_texture_rectangle"))
00331 return GL_TEXTURE_RECTANGLE_EXT;
00332
00333 return 0;
00334 }
00335
00336 bool has_gl_fbuffer_object_support(const QString &ext)
00337 {
00338 init_opengl();
00339
00340 if (!ext.contains("GL_EXT_framebuffer_object"))
00341 return false;
00342
00343 return (gMythGLGenFramebuffersEXT &&
00344 gMythGLBindFramebufferEXT &&
00345 gMythGLFramebufferTexture2DEXT &&
00346 gMythGLDeleteFramebuffersEXT &&
00347 gMythGLCheckFramebufferStatusEXT);
00348 }
00349
00350 bool has_gl_fragment_program_support(const QString &ext)
00351 {
00352 init_opengl();
00353
00354 if (!ext.contains("GL_ARB_fragment_program"))
00355 return false;
00356
00357 return (gMythGLGenProgramsARB &&
00358 gMythGLBindProgramARB &&
00359 gMythGLProgramStringARB &&
00360 gMythGLDeleteProgramsARB &&
00361 gMythGLGetProgramivARB &&
00362 gMythGLProgramEnvParameter4fARB);
00363 }
00364
00365 bool has_glx_video_sync_support(const QString &glx_ext)
00366 {
00367 init_opengl();
00368
00369 if (!glx_ext.contains("GLX_SGI_video_sync"))
00370 return false;
00371
00372 return gMythGLXGetVideoSyncSGI && gMythGLXWaitVideoSyncSGI;
00373 }