const DisplayResVector& DisplayResX::GetVideoModes(void) const { if (m_video_modes.size()) return m_video_modes; Display *display = NULL; XRRScreenConfiguration *cfg = GetScreenConfig(display); if (!cfg) return m_video_modes; int num_sizes, num_rates; XRRScreenSize *sizes = NULL; X11S(sizes = XRRConfigSizes(cfg, &num_sizes)); for (int i = 0; i < num_sizes; ++i) { short *rates = NULL; X11S(rates = XRRRates(display, DefaultScreen(display), i, &num_rates)); DisplayResScreen scr(sizes[i].width, sizes[i].height, sizes[i].mwidth, sizes[i].mheight, rates, num_rates); m_video_modes.push_back(scr); } m_video_modes_unsorted = m_video_modes; sort(m_video_modes.begin(), m_video_modes.end()); X11L; XRRFreeScreenConfigInfo(cfg); XCloseDisplay(display); X11U; return m_video_modes; }
XvMCOSD::XvMCOSD(Display *disp, int port, int surface_type_id, int xvmc_surf_flags) : XJ_disp(disp), XJ_width(0), XJ_height(0), xv_port(port), osd_palette(NULL), osd_xv_image(NULL), osd_subpict_mode(NO_SUBPICTURE), osd_subpict_clear_color(0), osd_subpict_alloc(false) { bzero(&osd_subpict, sizeof(osd_subpict)); // subpicture init int num = 0; XvImageFormatValues *xvfmv = NULL; X11S(xvfmv = XvMCListSubpictureTypes(XJ_disp, xv_port, surface_type_id, &num)); for (int i = (xvfmv) ? 0 : num; i < num; i++) { if (GUID_IA44_PACKED == xvfmv[i].id || GUID_AI44_PACKED == xvfmv[i].id) { osd_subpict_info = xvfmv[i]; bool be = (XVMC_BACKEND_SUBPICTURE & xvmc_surf_flags); osd_subpict_mode = (be) ? BACKEND_SUBPICTURE : BLEND_SUBPICTURE; break; } } if (xvfmv) X11S(XFree(xvfmv)); }
__GLXextFuncPtr get_gl_proc_address(const QString &procName) { __GLXextFuncPtr ret = NULL; #if USING_GLX_PROC_ADDR_ARB X11S(ret = glXGetProcAddressARB((const GLubyte*)procName.latin1())); #elif GLX_VERSION_1_4 X11S(ret = glXGetProcAddress((const GLubyte*)procName.latin1())); #elif GLX_ARB_get_proc_address X11S(ret = glXGetProcAddressARB((const GLubyte*)procName.latin1())); #elif GLX_EXT_get_proc_address X11S(ret = glXGetProcAddressEXT((const GLubyte*)procName.latin1())); #endif return ret; }
bool get_glx_version(Display *XJ_disp, uint &major, uint &minor) { // Crashes Unichrome-based system if it is run more than once. -- Tegue static bool has_run = false; static int static_major = 0; static int static_minor = 0; static int static_ret = false; static QMutex get_glx_version_lock; QMutexLocker locker(&get_glx_version_lock); int ret, errbase, eventbase, gl_major, gl_minor; if (has_run) { major = static_major; minor = static_minor; return static_ret; } major = minor = 0; has_run = true; X11S(ret = glXQueryExtension(XJ_disp, &errbase, &eventbase)); if (!ret) return false; // Unfortunately, nVidia drivers up into the 9xxx series have // a bug that causes them to SEGFAULT MythTV when we call // XCloseDisplay later on, if we query the GLX version of a // display pointer and then use that display pointer for // something other than OpenGL. So we open a separate // connection to the X server here just to query the GLX version. Display *tmp_disp = MythXOpenDisplay(); X11S(ret = glXQueryVersion(tmp_disp, &gl_major, &gl_minor)); XCloseDisplay(tmp_disp); if (!ret) return false; static_major = major = gl_major; static_minor = minor = gl_minor; static_ret = true; return true; }
void XvMCOSD::CompositeOSD(VideoFrame* frame, VideoFrame* osdframe) { if (!osd_subpict_alloc) return; X11L; XvMCCompositeSubpicture(XJ_disp, &osd_subpict, osd_xv_image, 0, 0, XJ_width, XJ_height, 0, 0); // delay sync until after getnextfreeframe... XvMCFlushSubpicture(XJ_disp, &osd_subpict); X11U; if (osd_subpict_mode == BLEND_SUBPICTURE && osdframe) { xvmc_render_state_t *render = GetRender(frame); xvmc_render_state_t *osdren = GetRender(osdframe); X11S(XvMCSyncSubpicture(XJ_disp, &osd_subpict)); VideoOutputXv::SyncSurface(frame); X11L; XvMCBlendSubpicture2(XJ_disp, render->p_surface, osdren->p_surface, &osd_subpict, 0, 0, XJ_width, XJ_height, 0, 0, XJ_width, XJ_height); XvMCFlushSurface(XJ_disp, osdren->p_surface); X11U; } else if (osd_subpict_mode == BACKEND_SUBPICTURE) { X11L; XvMCSyncSubpicture(XJ_disp, &osd_subpict); XvMCBlendSubpicture(XJ_disp, GetRender(frame)->p_surface, &osd_subpict, 0, 0, XJ_width, XJ_height, 0, 0, XJ_width, XJ_height); XvMCFlushSurface(XJ_disp, GetRender(frame)->p_surface); X11U; } }
GLXPbuffer get_pbuffer(Display *XJ_disp, GLXFBConfig glx_fbconfig, const QSize &video_dim) { int attrib_pbuffer[16]; bzero(attrib_pbuffer, sizeof(int) * 16); attrib_pbuffer[0] = GLX_PBUFFER_WIDTH; attrib_pbuffer[1] = video_dim.width(); attrib_pbuffer[2] = GLX_PBUFFER_HEIGHT; attrib_pbuffer[3] = video_dim.height(); attrib_pbuffer[4] = GLX_PRESERVED_CONTENTS; attrib_pbuffer[5] = 0; GLXPbuffer tmp = 0; #ifdef GLX_VERSION_1_3 X11S(tmp = glXCreatePbuffer(XJ_disp, glx_fbconfig, attrib_pbuffer)); #endif // GLX_VERSION_1_3 return tmp; }
void XvMCOSD::DeleteBuffer() { if (!osd_subpict_alloc) return; X11L; XvMCDestroySubpicture(XJ_disp, &osd_subpict); XShmDetach(XJ_disp, &XJ_osd_shm_info); shmdt(XJ_osd_shm_info.shmaddr); osd_subpict_alloc = false; XFree(osd_xv_image); XFlush(XJ_disp); X11U; usleep(50); X11S(XSync(XJ_disp, false)); if (osd_palette) delete [] osd_palette; }
bool XvMCTextures::Init(Display *disp, Window XJ_curwin, int XJ_screen_num, const QSize &video_dim, const QSize &window_size) { VERBOSE(VB_IMPORTANT, LOC + "Init"); if (!disp) { VERBOSE(VB_IMPORTANT, LOC_ERR + "Init() no display!"); return false; } XJ_disp = disp; if (!init_opengl()) { VERBOSE(VB_PLAYBACK, LOC_ERR + "Failed to initialize OpenGL support."); return false; } uint major = 0, minor = 0; if (!get_glx_version(XJ_disp, major, minor)) { VERBOSE(VB_PLAYBACK, LOC_ERR + "GLX extension not present."); return false; } if ((1 == major) && (minor < 3)) { VERBOSE(VB_PLAYBACK, LOC_ERR + QString( "Need GLX 1.3 or better, have %1.%2") .arg(major).arg(minor)); return false; } if (!glx_fbconfig) { glx_fbconfig = get_fbuffer_cfg( XJ_disp, XJ_screen_num, get_attr_cfg(kRenderRGBA)); } if (glx_fbconfig) glx_pbuffer = get_pbuffer(XJ_disp, glx_fbconfig, video_dim); if (!glx_context) X11S(glx_context = glXCreateNewContext(XJ_disp, glx_fbconfig, GLX_RGBA_TYPE, NULL, 1)); XVisualInfo *vis_info; vis_info = glXGetVisualFromFBConfig(XJ_disp, glx_fbconfig); gl_window = get_gl_window(XJ_disp, XJ_curwin, vis_info, window_size, true); glx_window = get_glx_window(XJ_disp, glx_fbconfig, gl_window, glx_context, glx_pbuffer, window_size); glXMakeContextCurrent(XJ_disp, glx_window, glx_pbuffer, glx_context); glCheck(); glXMakeContextCurrent(XJ_disp, None, None, NULL); gl_vid_textures = create_textures( XJ_disp, glx_window, glx_context, glx_pbuffer, video_dim, 1); gl_vid_tex_size.resize(gl_vid_textures.size()); gl_osd_textures = create_textures( XJ_disp, glx_window, glx_context, glx_pbuffer, video_dim, 1); gl_osd_tex_size.resize(gl_vid_textures.size()); XSync(XJ_disp, 0); gl_display_size = window_size; gl_video_size = video_dim; glXMakeContextCurrent(XJ_disp, glx_window, glx_pbuffer, glx_context); glCheck(); glXMakeContextCurrent(XJ_disp, None, None, NULL); VERBOSE(VB_IMPORTANT, LOC + QString("InitXvMCGL: video_size: %1x%2 vis_size: %3x%4") .arg(gl_video_size.width()).arg(gl_video_size.height()) .arg(gl_display_size.width()).arg(gl_display_size.height())); VERBOSE(VB_IMPORTANT, LOC <<endl <<"glx_fbconfig: "<<glx_fbconfig<<endl <<"gl_window: "<<gl_window<<endl <<"glx_window: "<<glx_window<<endl <<"gl_vid_tex: "<<gl_vid_textures[0]<<endl <<"gl_osd_tex: "<<gl_osd_textures[0]<<endl); return true; }
void XvMCOSD::CreateBuffer(XvMCContext &xvmc_ctx, int width, int height) { if (NO_SUBPICTURE == osd_subpict_mode) { VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed because " "no subpicture is available"); osd_subpict_alloc = false; return; } XJ_width = width; XJ_height = height; osd_subpict_clear_color = 0; int ret = Success; X11S(ret = XvMCCreateSubpicture(XJ_disp, &xvmc_ctx, &osd_subpict, XJ_width, XJ_height, osd_subpict_info.id)); if (ret != Success) { VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed on XvMCCreateSubpicture"); osd_subpict_mode = NO_SUBPICTURE; osd_subpict_alloc = false; return; } X11L; XvMCClearSubpicture(XJ_disp, &osd_subpict, 0, 0, XJ_width, XJ_height, osd_subpict_clear_color); osd_xv_image = XvShmCreateImage(XJ_disp, xv_port, osd_subpict_info.id, NULL, XJ_width, XJ_height, &XJ_osd_shm_info); X11U; if (!osd_xv_image) { VERBOSE(VB_IMPORTANT, "XvMCOSD::CreateBuffer() failed on XvShmCreateImage"); osd_subpict_mode = NO_SUBPICTURE; osd_subpict_alloc = false; return; } XJ_osd_shm_info.shmid = shmget(IPC_PRIVATE, osd_xv_image->data_size, IPC_CREAT | 0777); XJ_osd_shm_info.shmaddr = (char *)shmat(XJ_osd_shm_info.shmid, 0, 0); XJ_osd_shm_info.readOnly = False; osd_xv_image->data = XJ_osd_shm_info.shmaddr; X11S(XShmAttach(XJ_disp, &XJ_osd_shm_info)); shmctl(XJ_osd_shm_info.shmid, IPC_RMID, 0); if (osd_subpict.num_palette_entries > 0) { int snum = osd_subpict.num_palette_entries; int seb = osd_subpict.entry_bytes; osd_palette = new unsigned char[snum * seb]; for (int i = 0; i < snum; i++) { int Y = i * (1 << osd_subpict_info.y_sample_bits) / snum; int U = 1 << (osd_subpict_info.u_sample_bits - 1); int V = 1 << (osd_subpict_info.v_sample_bits - 1); for (int j = 0; j < seb; j++) { switch (osd_subpict.component_order[j]) { case 'U': osd_palette[i * seb + j] = U; break; case 'V': osd_palette[i * seb + j] = V; break; case 'Y': default: osd_palette[i * seb + j] = Y; break; } } } X11S(XvMCSetSubpicturePalette(XJ_disp, &osd_subpict, osd_palette)); } osd_subpict_alloc = true; }