diff options
-rw-r--r-- | HISTORY | 3 | ||||
-rw-r--r-- | README | 73 | ||||
-rw-r--r-- | xine_sxfe_frontend.c | 178 |
3 files changed, 224 insertions, 30 deletions
@@ -26,6 +26,9 @@ VDR Plugin 'xineliboutput' Revision History - H.264 updates - Added support for .ass subtitles to media player (Thanks to zaverel) - Added support for .smi subtitles to media player +- Added OpenGL HUD OSD support: HUD OSD without compositing / window manager + (thanks to grueni75) +- Added tearing-free OpenGL video output support with high-quality OSD (thanks to grueni75) 2011-07-10: Version 1.0.7 (branch-1_0_x) Backported bugfixes from CVS trunk: @@ -37,6 +37,8 @@ Requirements - X server with Composite and Xrender extensions, compositing window manager or composite manager (xcompmgr). (Required for HUD OSD to blend high-quality OSD using graphics hardware) + - X server with OpenGL support + (Required for OpenGL video output and OpenGL HUD OSD) - libextractor 0.5.20 or later (http://libextractor.sourceforge.net). (used for media file metadata extraction in media player) - libjpeg for grabbing in JPEG format @@ -244,20 +246,56 @@ HUD OSD OSD is scaled and blended using hardware, so it adds no extra CPU overhead. OSD is always blended to output (display) resolution, so it remains sharp and detailed even with low-resolution video. + It can also support transparency in the same way as full-featured + DVB cards. HUD OSD must be enabled with command-line option (--hud). Scaling options can be configured in xineliboutput plugin setup menu, OSD settings page. + There are three possible configurations for using HUD OSD. First one + is to use a X server with composite / Xrender extensions and a composite + manager. This is the default when the hud is enabled with --hud. The + second one is to use a X server with XShape support. This configuration + is enabled with the --hud=shape option. The third one is to use a + X server with OpenGL support. The option --hud=opengl enables this + configuration. + + The first configuration requires a composite manager to get transparency + support. The second configuration can be used if the composite manager + slows down the video play back. The HUD OSD has the same quality, but + does not support transparency. + + The third configuration does not require the composite/Xrender extension. + Hence, it can also be used with VDPAU NVIDIA graphic cards that produce + video tearing with enabled composite extension. OpenGL is only used if + the OSD is displayed. For video playback, the normal output to a window + via the xine-lib is used. Therefore, normal video playback is as smooth + as the xine-lib playback allows. OpenGL playback requires additional + computing power from the cpu and graphic card, and can result in + occasionally frame drops. If your hardware configuration is powerful + enough, you can also try to use the --opengl option. It does both pure + video playback and OSD drawing via OpenGL. The advantage is that there + are no frame drops if the OSD opens and closes, because there is no + switching between window-based and OpenGL-based playback. + Requirements: - - X server with Composite and Xrender extensions. - Composite extension must be enabled in Xorg config. - - Composite window manager (compiz, beryl, or properly configured xfce4, metacity, ...) - or separate composite manager (xcompmgr). + - First configuration (--hud): + - X server with Composite and Xrender extensions. + Composite extension must be enabled in Xorg config. + - Composite window manager (compiz, beryl, or properly configured xfce4, metacity, ...) + or separate composite manager (xcompmgr) for transparency support. + - Second configuration (--hud=xshape) + - X server with Composite, Xrender and XShape extension. + - no window manager required. + - Third configuration (--hud=opengl or --opengl) + - X server with OpenGL support + - no window manager required. - Compatible graphics hardware and drivers. HUD OSD has been tested with: nVidia GF FX5700LE (driver version 169.09) Intel G965 (GMA-X3000) (driver version 2.2.1, textured XVideo) + nVidia GT 425M (driver version 290.10, VDPAU) metacity 2.23.2 xcompmgr 1.1.3 @@ -266,13 +304,40 @@ HUD OSD - Drawing video (even without OSD) may be slower when composite extension is enabled. + - A composite window manager can also slow down the video playback. In + case of problems, switch off the window manager to see if playback + improves. + - Try to adjust OSD size and offsets to get rid of possible graphical corruption. - For true HD-resolution OSD VDR needs to be patched. + - OpenGL-based HUD requires that the xine-lib video out driver + supports redirecting video frames to a pixmap. VDPAU is known + to work (tested with changeset 11949:0e68b56727d6 from 2011-12-21 of + xine-lib 1.2). XV does currently not support it. + + - If you see black frames when opening the HUD with the --hud=opengl + option: The video out driver frees all resources when the + request to switch to a pixmap arrives. This clean up can also + include clearing the window, resulting in a black frame until the + OpenGL drawing takes over. The VDPAU output drivers behaves in + this way. There are two options to fix this: Either enable the + BackingStore of the X-Server (Option "BackingStore" TRUE in the + Device Section for NVIDIA cards) or patch the xine-lib to not + immediately free the resources. There is an example patch for VDPAU + included in the patches directory (xinelib_vdpau_black_frame.patch). + Please note that enabling the backing store might also require + to enable the Composite extension. + + - Tearing free OpenGL playback / HUD requires that the "Sync to VBLank" + option is set. For nvidia cards, this can be done via the command + "nvidia-settings -a SyncToVBlank=1" + HUD OSD was contributed by Antti Seppälä and Rolf Ahrenberg. + HUD OSD XShape and OpenGL extensions were contributed by Matthias Grünewald. Using with xine-ui (xine, fbxine, gxine, ...) diff --git a/xine_sxfe_frontend.c b/xine_sxfe_frontend.c index 73a68461..67b2d698 100644 --- a/xine_sxfe_frontend.c +++ b/xine_sxfe_frontend.c @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: xine_sxfe_frontend.c,v 1.170 2011-10-27 07:26:21 phintuka Exp $ + * $Id: xine_sxfe_frontend.c,v 1.171 2012-01-19 12:50:01 phintuka Exp $ * */ @@ -155,8 +155,10 @@ typedef struct sxfe_s { uint8_t dragging : 1; uint8_t hud; uint8_t xshape_hud : 1; + uint8_t opengl_xshape_available : 1; uint8_t opengl_always : 1; uint8_t opengl_hud : 1; + uint8_t opengl_osd_texture_img_updated : 1; uint8_t gui_hotkeys : 1; uint8_t no_x_kbd : 1; @@ -180,6 +182,11 @@ typedef struct sxfe_s { pthread_t opengl_drawing_thread; pthread_mutex_t opengl_redraw_mutex; pthread_cond_t opengl_redraw_cv; + uint32_t opengl_redraw_request_nr; + uint32_t opengl_redraw_served_nr; + pthread_mutex_t opengl_redraw_finished_mutex; + pthread_cond_t opengl_redraw_finished_cv; + pthread_mutex_t opengl_osd_texture_img_mutex; Pixmap video_frame_pixmap; GC video_frame_gc; GLuint video_frame_texture; @@ -198,6 +205,7 @@ typedef struct sxfe_s { Xrender_Surf *surf_img; Xrender_Surf *surf_back_img; uint32_t *hud_img_mem; + uint32_t *opengl_osd_texture_img; GC gc; Window hud_window; # ifdef HAVE_XSHM @@ -212,16 +220,20 @@ typedef struct sxfe_s { #ifdef HAVE_OPENGL +#if 0 typedef int (*GLXGetVideoSyncProc) (unsigned int *count); typedef int (*GLXWaitVideoSyncProc) (int divisor, int remainder, unsigned int *count); +#endif typedef void (*GLXBindTexImageProc) (Display *display, GLXDrawable drawable, int buffer, int *attribList); +#if 0 GLXGetVideoSyncProc getVideoSync; GLXWaitVideoSyncProc waitVideoSync; +#endif GLXBindTexImageProc bindTexImage; #endif @@ -778,10 +790,34 @@ static void hud_osd_draw(sxfe_t *this, const struct osd_command_s *cmd) int w = cmd->dirty_area.x2 - cmd->dirty_area.x1 + 1; int h = cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1; int mask_changed; + int i, j; + uint32_t value; Xrender_Surf *dst_surf = this->surf_back_img ? this->surf_back_img : this->surf_win; Window dst_win = this->surf_back_img ? this->surf_back_img->draw : this->hud_window; + // If opengl is used: Just construct the bitmap + // The scaling is done in the opengl thread + if (this->opengl_always || this->opengl_hud) { + + // Create the sub image + hud_fill_img_memory(this->hud_img_mem, HUD_MAX_WIDTH, + this->shape_mask_mem, HUD_MAX_WIDTH, + &mask_changed, cmd); + + // Copy the image to the texture and inform the opengl thread + pthread_mutex_lock(&this->opengl_osd_texture_img_mutex); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + value = this->hud_img_mem[(y+i)*HUD_MAX_WIDTH+x+j]; + this->opengl_osd_texture_img[(y+i)*this->osd_width+x+j] = (value<<8)|((value>>24)&0xFF); + } + } + this->opengl_osd_texture_img_updated = 1; + pthread_mutex_unlock(&this->opengl_osd_texture_img_mutex); + + } else { + #ifdef HAVE_XSHM if (this->completion_event != -1) { hud_fill_img_memory((uint32_t*)(this->hud_img->data), HUD_MAX_WIDTH, @@ -843,6 +879,7 @@ static void hud_osd_draw(sxfe_t *this, const struct osd_command_s *cmd) x, y, 0, 0, x, y, w, h); XFlush(this->display); + } } static void hud_osd_set_video_window(sxfe_t *this, const struct osd_command_s *cmd) @@ -885,6 +922,8 @@ static void hud_osd_hide(sxfe_t *this) this->hud_visible = 0; this->video_win_active = 0; + if (this->hud) { + #ifdef HAVE_XSHAPE if (this->xshape_hud) { XUnmapWindow(this->display, this->hud_window); @@ -902,6 +941,7 @@ static void hud_osd_hide(sxfe_t *this) 0, 0, this->osd_width+2, this->osd_height+2); XFlush(this->display); + } } static void hud_osd_show(sxfe_t *this) @@ -912,6 +952,14 @@ static void hud_osd_show(sxfe_t *this) this->hud_visible = 1; this->video_win_active = 0; + if ((this->opengl_always) || (this->opengl_hud)) { + pthread_mutex_lock(&this->opengl_osd_texture_img_mutex); + memset((void*)this->opengl_osd_texture_img,0,sizeof(uint32_t)*this->osd_width*this->osd_height); + this->opengl_osd_texture_img_updated=1; + pthread_mutex_unlock(&this->opengl_osd_texture_img_mutex); + } + + if (this->hud) { XSetForeground(this->display, this->gc, 0x00000000); XFillRectangle(this->display, this->surf_img->draw, this->gc, 0, 0, this->osd_width+2, this->osd_height+2); @@ -928,6 +976,7 @@ static void hud_osd_show(sxfe_t *this) XMapWindow(this->display, this->hud_window); } #endif + } XFlush(this->display); } @@ -936,7 +985,7 @@ static int hud_osd_command(frontend_t *this_gen, struct osd_command_s *cmd) { sxfe_t *this = (sxfe_t*)this_gen; - if(this && this->hud && cmd) { + if(this && (this->hud || this->opengl_always || this->opengl_hud) && cmd) { XLockDisplay(this->display); switch(cmd->cmd) { case OSD_Nop: /* Do nothing ; used to initialize delay_ms counter */ @@ -952,6 +1001,13 @@ static int hud_osd_command(frontend_t *this_gen, struct osd_command_s *cmd) this->osd_width = (cmd->w > 0) ? cmd->w : OSD_DEF_WIDTH; this->osd_height = (cmd->h > 0) ? cmd->h : OSD_DEF_HEIGHT; + if ((this->opengl_always) || (this->opengl_hud)) { + pthread_mutex_lock(&this->opengl_osd_texture_img_mutex); + free(this->opengl_osd_texture_img); + this->opengl_osd_texture_img = malloc(sizeof(uint32_t) * this->osd_width * this->osd_height); + pthread_mutex_unlock(&this->opengl_osd_texture_img_mutex); + } + hud_osd_show(this); break; @@ -1005,6 +1061,7 @@ static int hud_osd_command(frontend_t *this_gen, struct osd_command_s *cmd) void opengl_trigger_drawing_thread(sxfe_t *this) { pthread_mutex_lock(&this->opengl_redraw_mutex); + this->opengl_redraw_request_nr++; pthread_cond_signal(&this->opengl_redraw_cv); pthread_mutex_unlock(&this->opengl_redraw_mutex); } @@ -1024,6 +1081,12 @@ static void hud_frame_output_cb (void *data, // Inform the opengl drawing thread if (this->opengl_always || this->opengl_hud) { opengl_trigger_drawing_thread(this); + + // Wait until the thrad is finished + pthread_mutex_lock(&this->opengl_redraw_finished_mutex); + if (this->opengl_redraw_request_nr!=this->opengl_redraw_served_nr) + pthread_cond_wait(&this->opengl_redraw_finished_cv, &this->opengl_redraw_finished_mutex); + pthread_mutex_unlock(&this->opengl_redraw_finished_mutex); } #endif @@ -1172,7 +1235,7 @@ static int hud_osd_open(sxfe_t *this) this->surf_win = xrender_surf_adopt(this->display, this->hud_window, this->hud_vis, HUD_MAX_WIDTH, HUD_MAX_HEIGHT); this->surf_img = xrender_surf_new(this->display, this->hud_window, this->hud_vis, HUD_MAX_WIDTH, HUD_MAX_HEIGHT, 1); - if (this->xshape_hud || this->opengl_hud || this->opengl_always) + if (this->xshape_hud) this->surf_back_img = xrender_surf_new(this->display, this->hud_window, this->hud_vis, DisplayWidth(this->display, this->screen), DisplayHeight(this->display, this->screen), 1); @@ -1506,6 +1569,7 @@ static int opengl_init_dl(sxfe_t *this) if (glXGetProcAddressARB) { +#if 0 if (!(waitVideoSync = (void *)glXGetProcAddressARB((unsigned char *)"glXWaitVideoSyncSGI"))) { LOGMSG("glXGetProcAddressARB(glXWaitVideoSyncSGI) failed"); goto error; @@ -1514,6 +1578,7 @@ static int opengl_init_dl(sxfe_t *this) LOGMSG("glXGetProcAddressARB(glXGetVideoSyncSGI) failed"); goto error; } +#endif if (!(bindTexImage = (void *)glXGetProcAddressARB((unsigned char *)"glXBindTexImageEXT"))) { LOGMSG("glXGetProcAddressARB(glXBindTexImageEXT) failed"); goto error; @@ -1529,6 +1594,7 @@ static int opengl_init_dl(sxfe_t *this) LOGMSG("opengl_init(): can not get pointer to glXBindTexImageEXT"); goto error; } +#if 0 getVideoSync = dlsym(dlhand,"glXGetVideoSyncSGI"); if (dlerror() != NULL) { LOGMSG("opengl_init(): can not get pointer to glXGetVideoSyncSGI"); @@ -1539,6 +1605,7 @@ static int opengl_init_dl(sxfe_t *this) LOGMSG("opengl_init(): can not get pointer to glXWaitVideoSyncSGI"); goto error; } +#endif } dlclose(dlhand); @@ -1634,11 +1701,13 @@ static int opengl_init(sxfe_t *this) return -1; } LOGVERBOSE("Found texture from pixmap extension"); +#if 0 if (!strstr (glxExtensions, "GLX_SGI_video_sync")) { LOGMSG("No sgi video sync extension"); return -1; } LOGVERBOSE("Found sgi video sync extension"); +#endif // Get handles to important functions if (opengl_init_dl(this) < 0) { @@ -1720,10 +1789,10 @@ static int opengl_init(sxfe_t *this) bindTexImage (this->display, glxpixmap, GLX_FRONT_LEFT_EXT, NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glxpixmap = glXCreatePixmap (this->display, fbcroot, this->surf_back_img->draw, pixmapAttribs); + //glxpixmap = glXCreatePixmap (this->display, fbcroot, this->surf_back_img->draw, pixmapAttribs); glGenTextures (1, &this->osd_texture); glBindTexture (GL_TEXTURE_2D, this->osd_texture); - bindTexImage (this->display, glxpixmap, GLX_FRONT_LEFT_EXT, NULL); + //bindTexImage (this->display, glxpixmap, GLX_FRONT_LEFT_EXT, NULL); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1758,7 +1827,7 @@ static void opengl_deinit(sxfe_t *this) static void *opengl_draw_frame_thread(void *arg) { sxfe_t *this=(sxfe_t *) arg; - int unsigned sync; + //int unsigned sync; int draw_frame = 0, window_mapped = 0, keep_osd_open = 0; int prev_hud_visible = 0; int16_t video_x0, video_y0, video_x1, video_y1; @@ -1771,6 +1840,7 @@ static void *opengl_draw_frame_thread(void *arg) XRectangle xrect; XDouble video_tex_width, video_tex_height; int first_frame = 1; + //struct timeval t; XLockDisplay (this->display); if (opengl_init(this) < 0) { @@ -1784,9 +1854,11 @@ static void *opengl_draw_frame_thread(void *arg) // Wait for trigger pthread_mutex_lock(&this->opengl_redraw_mutex); + if (this->opengl_redraw_served_nr == this->opengl_redraw_request_nr) { pthread_cond_wait(&this->opengl_redraw_cv, &this->opengl_redraw_mutex); + } pthread_mutex_unlock(&this->opengl_redraw_mutex); - count++; + //time_measure_start(&t); // Check if we should exit if (this->opengl_deinit) @@ -1808,7 +1880,7 @@ static void *opengl_draw_frame_thread(void *arg) // Set the shape of the opengl window #ifdef HAVE_XSHAPE - if (this->xshape_hud) + if (this->opengl_xshape_available) XShapeCombineRectangles(this->display, this->opengl_window, ShapeBounding, 0, 0, &xrect, 1, ShapeSet, 0); #endif } @@ -1833,20 +1905,21 @@ static void *opengl_draw_frame_thread(void *arg) LOGVERBOSE("osd_alpha=%.2f keep_osd_open=%d", osd_alpha, keep_osd_open); // Decide if we need to do something - draw_frame = (this->hud_visible || keep_osd_open || this->opengl_always); + draw_frame = (this->hud_visible || window_mapped || this->opengl_always); if ((this->opengl_hud && this->hud_visible && !prev_hud_visible) || (this->opengl_always && first_frame)) { LOGDBG("redirecting video to opengl frame texture"); xine_port_send_gui_data(this->x.video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void*) this->video_frame_pixmap); draw_frame = 0; // first frame not yet available in pixmap + count = 0; osd_alpha -= 2*osd_alpha_step; // delay the osd } if (this->opengl_hud && !this->hud_visible && prev_hud_visible && !keep_osd_open && !this->opengl_always) { LOGDBG("redirecting video to window"); xine_port_send_gui_data(this->x.video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void*) this->window[this->fullscreen ? 1 : 0]); - draw_frame = 1; // draw the last frame + count = 0; } if (draw_frame) { LOGVERBOSE("drawing frame nr %d", count); @@ -1868,8 +1941,8 @@ static void *opengl_draw_frame_thread(void *arg) } osd_x0 = win_x; osd_y0 = win_y; - osd_x1 = osd_x0 + this->screen_width - 1; - osd_y1 = osd_y0 + this->screen_height - 1; + osd_x1 = osd_x0 + win_width - 1; + osd_y1 = osd_y0 + win_height - 1; video_y0 = (this->screen_height - 1) - video_y0; video_y1 = (this->screen_height - 1) - video_y1; osd_y0 = (this->screen_height - 1) - osd_y0; @@ -1886,8 +1959,22 @@ static void *opengl_draw_frame_thread(void *arg) glTexCoord2f(0.0, 0.0); glVertex3f(video_x0, video_y0, 0.0); glEnd(); if (this->hud_visible || keep_osd_open) { - glColor4f(1.0f, 1.0f, 1.0f, osd_alpha); + + // Check if we need to update the image glBindTexture (GL_TEXTURE_2D, this->osd_texture); + pthread_mutex_lock(&this->opengl_osd_texture_img_mutex); + if (this->opengl_osd_texture_img_updated) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->osd_width, this->osd_height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, this->opengl_osd_texture_img); + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + LOGERR("Can't update hud image texture"); + } + this->opengl_osd_texture_img_updated = 0; + } + pthread_mutex_unlock(&this->opengl_osd_texture_img_mutex); + + // Draw the hud + glColor4f(1.0f, 1.0f, 1.0f, osd_alpha); glBegin(GL_QUADS); glTexCoord2f(0.0, 1.0); glVertex3f(osd_x0, osd_y1 , 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(osd_x1, osd_y1, 0.0); @@ -1897,10 +1984,9 @@ static void *opengl_draw_frame_thread(void *arg) } glXSwapBuffers(this->display, this->opengl_window); XUnlockDisplay(this->display); + count++; } - if ((this->hud_visible && prev_hud_visible && !window_mapped) || (first_frame && this->opengl_always)) { - (*getVideoSync) (&sync); - (*waitVideoSync) (2, (sync + 1) % 2, &sync); // ensure that window shows correct frame + if ((this->hud_visible && count==2 && !window_mapped) || (first_frame && this->opengl_always)) { LOGDBG("mapping opengl window"); XLockDisplay(this->display); XRaiseWindow (this->display, this->opengl_window); @@ -1908,7 +1994,7 @@ static void *opengl_draw_frame_thread(void *arg) XUnlockDisplay(this->display); window_mapped = 1; } - if (!this->hud_visible && !prev_hud_visible && window_mapped && !keep_osd_open && !this->opengl_always) { + if (!this->hud_visible && count==3 && window_mapped && !keep_osd_open && !this->opengl_always) { LOGDBG("unmapping opengl window"); XLockDisplay(this->display); XLowerWindow (this->display, this->opengl_window); @@ -1920,6 +2006,14 @@ static void *opengl_draw_frame_thread(void *arg) prev_hud_visible = this->hud_visible; } first_frame = 0; + //LOGVERBOSE("drawing time = %d",time_measure_end(&t)); + + // Drawing is finished + pthread_mutex_lock(&this->opengl_redraw_finished_mutex); + this->opengl_redraw_served_nr++; + pthread_cond_signal(&this->opengl_redraw_finished_cv); + pthread_mutex_unlock(&this->opengl_redraw_finished_mutex); + } // Free resources @@ -1932,10 +2026,33 @@ static int opengl_start(sxfe_t *this) LOGDBG("sxfe_display_open: starting opengl drawing thread"); pthread_mutex_init(&this->opengl_redraw_mutex, NULL); pthread_cond_init(&this->opengl_redraw_cv, NULL); + this->opengl_redraw_request_nr = 0; + this->opengl_redraw_served_nr = 0; + pthread_mutex_init(&this->opengl_redraw_finished_mutex, NULL); + pthread_cond_init(&this->opengl_redraw_finished_cv, NULL); + pthread_mutex_init(&this->opengl_osd_texture_img_mutex, NULL); pthread_attr_t attr; + struct sched_param param; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - if (pthread_create(&this->opengl_drawing_thread, NULL, opengl_draw_frame_thread, (void *)this)) { + pthread_attr_getschedparam(&attr, ¶m); + param.sched_priority = sched_get_priority_min(SCHED_OTHER); + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + this->x.vis_x11.frame_output_cb = hud_frame_output_cb; // ensure that the opengl drawing thread gets triggered + this->fe.xine_osd_command = hud_osd_command; // opengl thread needs to get updated with the new hud image + this->hud_img_mem = malloc(4 * HUD_MAX_WIDTH * HUD_MAX_HEIGHT); + this->osd_width = OSD_DEF_WIDTH; + this->osd_height = OSD_DEF_HEIGHT; + this->opengl_osd_texture_img = malloc(sizeof(uint32_t) * this->osd_width * this->osd_height); + memset((void*)this->opengl_osd_texture_img,0,sizeof(uint32_t)*this->osd_width*this->osd_height); + this->opengl_osd_texture_img_updated = 0; + int dummy; + if (XShapeQueryExtension(this->display, &dummy, &dummy)) + this->opengl_xshape_available = 1; + else + this->opengl_xshape_available = 0; + if (pthread_create(&this->opengl_drawing_thread, &attr, opengl_draw_frame_thread, (void *)this)) { pthread_attr_destroy(&attr); LOGERR("sxfe_display_open: can not start OpenGL drawing thread"); this->opengl_always = this->opengl_hud = 0; /* avoid pthread_join segfault */ @@ -2148,19 +2265,26 @@ static int sxfe_display_open(frontend_t *this_gen, XUnlockDisplay (this->display); + + // Shall opengl or xrender be used? + if (this->opengl_always || this->opengl_hud) { + +#ifdef HAVE_OPENGL + // Start the drawing thread + this->hud = 0; + if (!opengl_start(this)) + return 0; +#endif + + } else { + #ifdef HAVE_XRENDER // Init the osd window if (!hud_osd_open(this)) return 0; +#endif -# ifdef HAVE_OPENGL - // Start the drawing thread - if (this->opengl_always || this->opengl_hud) { - if (!opengl_start(this)) - return 0; } -# endif // HAVE_OPENGL -#endif // HAVE_XRENDER return 1; } @@ -2661,6 +2785,8 @@ static void sxfe_display_close(frontend_t *this_gen) if (pthread_join(this->opengl_drawing_thread, &status)) { LOGERR("sxfe_display_close: can not join opengl drawing thread!"); } + free(this->hud_img_mem); + free(this->opengl_osd_texture_img); } #endif @@ -2730,7 +2856,7 @@ static int sxfe_xine_play(frontend_t *this_gen) int result = this->fe_xine_play(this_gen); #ifdef HAVE_XRENDER - if (result && this->x.input_plugin && this->hud) { + if (result && this->x.input_plugin && (this->hud || this->opengl_always || this->opengl_hud)) { LOGDBG("sxfe_xine_play: Enabling HUD OSD"); this->x.input_plugin->f.fe_handle = this_gen; this->x.input_plugin->f.intercept_osd = hud_osd_command; |