Mercurial > mplayer.hg
changeset 9569:894d02a6469e
vo_xover is a new vo that should make easy to have x11 support for
all overlay based vo.
Add support for xover to tdfx_vid. Sometimes the display flash bcs
the x server fuckup the overlay settings :( Not so bad as it only append
when i switch the focused window here.
author | albeu |
---|---|
date | Wed, 12 Mar 2003 15:04:05 +0000 |
parents | ed8827c95386 |
children | 602264261d3e |
files | configure libvo/video_out.c libvo/video_out.h libvo/vo_tdfx_vid.c libvo/vo_xover.c |
diffstat | 5 files changed, 555 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/configure Wed Mar 12 14:58:55 2003 +0000 +++ b/configure Wed Mar 12 15:04:05 2003 +0000 @@ -2486,8 +2486,8 @@ fi if test "$_x11" = yes ; then _def_x11='#define HAVE_X11 1' - _vosrc="$_vosrc x11_common.c vo_x11.c" - _vomodules="x11 $_vomodules" + _vosrc="$_vosrc x11_common.c vo_x11.c vo_xover.c" + _vomodules="x11 xover $_vomodules" else _def_x11='#undef HAVE_X11' _inc_x11='' @@ -3198,8 +3198,8 @@ if test "$_dxr2" = auto; then _dxr2=no for _inc_dxr2 in "$_inc_dxr2" \ - "-I /usr/local/include/dxr2" \ - "-I /usr/include/dxr2"; do + "-I/usr/local/include/dxr2" \ + "-I/usr/include/dxr2"; do cat > $TMPC << EOF #include <dxr2ioctl.h> int main(void) { return 0; }
--- a/libvo/video_out.c Wed Mar 12 14:58:55 2003 +0000 +++ b/libvo/video_out.c Wed Mar 12 15:04:05 2003 +0000 @@ -52,6 +52,7 @@ extern vo_functions_t video_out_mga; extern vo_functions_t video_out_xmga; extern vo_functions_t video_out_x11; +extern vo_functions_t video_out_xover; extern vo_functions_t video_out_xv; extern vo_functions_t video_out_gl; extern vo_functions_t video_out_gl2; @@ -131,6 +132,7 @@ #endif #ifdef HAVE_X11 &video_out_x11, + &video_out_xover, #endif #ifdef HAVE_GL &video_out_gl,
--- a/libvo/video_out.h Wed Mar 12 14:58:55 2003 +0000 +++ b/libvo/video_out.h Wed Mar 12 15:04:05 2003 +0000 @@ -55,6 +55,20 @@ // ... 21 #define VOCTRL_START_SLICE 21 +// Vo can be used by xover +#define VOCTRL_XOVERLAY_SUPPORT 22 + +#define VOCTRL_XOVERLAY_SET_COLORKEY 24 +typedef struct { + uint32_t x11; // The raw x11 color + uint16_t r,g,b; +} mp_colorkey_t; + +#define VOCTRL_XOVERLAY_SET_WIN 23 +typedef struct { + int x,y; + int w,h; +} mp_win_t; #define VO_TRUE 1 #define VO_FALSE 0 @@ -66,6 +80,7 @@ #define VOFLAG_MODESWITCHING 0x02 #define VOFLAG_SWSCALE 0x04 #define VOFLAG_FLIPPING 0x08 +#define VOFLAG_XOVERLAY_SUB_VO 0x10000 typedef struct vo_info_s {
--- a/libvo/vo_tdfx_vid.c Wed Mar 12 14:58:55 2003 +0000 +++ b/libvo/vo_tdfx_vid.c Wed Mar 12 15:04:05 2003 +0000 @@ -35,6 +35,7 @@ #include "video_out.h" #include "video_out_internal.h" #include "aspect.h" +#include "mp_msg.h" #include "fastmemcpy.h" #include "drivers/tdfx_vid.h" @@ -42,7 +43,7 @@ static vo_info_t info = { - "tdfx_vid video output", + "tdfx vid", "tdfx_vid", "Albeu", "" @@ -71,6 +72,7 @@ static uint32_t buffer_stride[3]; static int use_overlay = 1; +static tdfx_vid_overlay_t tdfx_ov; // FIXME static void clear_screen(void) { @@ -147,6 +149,11 @@ printf("Flip\n"); #endif if(use_overlay) { + // TDFX_VID_OVERLAY_ON does nothing if the overlay is alredy on + if(!ioctl(tdfx_fd,TDFX_VID_OVERLAY_ON)) { // X11 killed the overlay :( + if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&tdfx_ov)) + mp_msg(MSGT_VO, MSGL_ERR, "tdfx_vid: set_overlay failed\n"); + } // These formats need conversion switch(src_fmt) { case IMGFMT_BGR8: @@ -230,24 +237,25 @@ if(tdfx_fd < 0) return 1; - - if(!vo_screenwidth) - vo_screenwidth = tdfx_cfg.screen_width; - if(!vo_screenheight) - vo_screenheight = tdfx_cfg.screen_height; - - aspect_save_orig(width,height); - aspect_save_prescale(d_width,d_height); - aspect_save_screenres(vo_screenwidth,vo_screenheight); - - if(fullscreen&0x01) { /* -fs */ - aspect(&d_width,&d_height,A_ZOOM); - vo_fs = VO_TRUE; - } else { - aspect(&d_width,&d_height,A_NOZOOM); - vo_fs = VO_FALSE; + // When we are run as sub vo we must follow the size gaven to us + if(!(fullscreen & VOFLAG_XOVERLAY_SUB_VO)) { + if(!vo_screenwidth) + vo_screenwidth = tdfx_cfg.screen_width; + if(!vo_screenheight) + vo_screenheight = tdfx_cfg.screen_height; + + aspect_save_orig(width,height); + aspect_save_prescale(d_width,d_height); + aspect_save_screenres(vo_screenwidth,vo_screenheight); + + if(fullscreen&0x01) { /* -fs */ + aspect(&d_width,&d_height,A_ZOOM); + vo_fs = VO_TRUE; + } else { + aspect(&d_width,&d_height,A_NOZOOM); + vo_fs = VO_FALSE; + } } - src_width = width; src_height = height; buffer_size = 0; @@ -325,8 +333,8 @@ ov.format = ov_fmt; ov.dst_width = dst_width; ov.dst_height = dst_height; - ov.dst_x = 0; - ov.dst_y = 0; + ov.dst_x = vo_dx; + ov.dst_y = vo_dy; ov.use_colorkey = 0; if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&ov)) { @@ -334,6 +342,7 @@ use_overlay = 0; break; } + tdfx_ov = ov; if(use_overlay == 1) { if(ioctl(tdfx_fd,TDFX_VID_OVERLAY_ON)) { printf("tdfx_vid: Overlay on failed\n"); @@ -609,6 +618,32 @@ return VO_TRUE; } +static uint32_t set_window(mp_win_t* w) { + if(!use_overlay) return VO_FALSE; + + tdfx_ov.dst_x = w->x; + tdfx_ov.dst_y = w->y; + tdfx_ov.dst_width = w->w; + tdfx_ov.dst_height = w->h; + + if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&tdfx_ov)) + mp_msg(MSGT_VO, MSGL_V, "tdfx_vid: set window failed\n"); + + return VO_TRUE; +} + +static uint32_t set_colorkey(mp_colorkey_t* colork) { + if(!use_overlay) return VO_FALSE; + + tdfx_ov.colorkey[0] = tdfx_ov.colorkey[1] = colork->x11; + tdfx_ov.use_colorkey = 1; + tdfx_ov.invert_colorkey = 0; + + if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&tdfx_ov)) + mp_msg(MSGT_VO, MSGL_V, "tdfx_vid: set colorkey failed\n"); + + return VO_TRUE; +} static uint32_t control(uint32_t request, void *data, ...) { @@ -623,6 +658,12 @@ return start_slice(data); case VOCTRL_FULLSCREEN: return fullscreen(); + case VOCTRL_XOVERLAY_SUPPORT: + return VO_TRUE; + case VOCTRL_XOVERLAY_SET_COLORKEY: + return set_colorkey(data); + case VOCTRL_XOVERLAY_SET_WIN: + return set_window(data); } return VO_NOTIMPL; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libvo/vo_xover.c Wed Mar 12 15:04:05 2003 +0000 @@ -0,0 +1,473 @@ +/* + VIDIX accelerated overlay in a X window + + (C) Alex Beregszaszi & Zoltan Ponekker & Nick Kurshev + + WS window manager by Pontscho/Fresh! + + Based on vo_gl.c and vo_vesa.c and vo_xmga.c (.so mastah! ;)) +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#include "config.h" +#include "video_out.h" +#include "video_out_internal.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +//#include <X11/keysym.h> + +#ifdef HAVE_XINERAMA +#include <X11/extensions/Xinerama.h> +#endif + +#include "x11_common.h" +#include "aspect.h" +#include "mp_msg.h" + +#include "../mplayer.h" /* exit_player() */ + +#ifdef HAVE_NEW_GUI +#include "../Gui/interface.h" +#endif + + +static vo_info_t info = +{ + "General X11 driver for overlay capable vo's", + "xover", + "Albeu", + "" +}; + +LIBVO_EXTERN(xover) + +#define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */ + +/* X11 related variables */ +/* Colorkey handling */ +static XGCValues mGCV; +static uint32_t fgColor; +static uint32_t bgColor; + +/* Image parameters */ +static uint32_t image_width; +static uint32_t image_height; +static uint32_t image_format; + +/* Window parameters */ +static uint32_t window_x, window_y; +static uint32_t window_width, window_height; + +/* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */ +static uint32_t drwX, drwY, drwWidth, drwHeight, drwBorderWidth, + drwDepth, drwcX, drwcY, dwidth, dheight; + +#ifdef HAVE_XINERAMA +extern int xinerama_screen; +#endif + +static vo_functions_t* sub_vo = NULL; + + +static void set_window(int force_update) +{ + Window mRoot; + if ( WinID ) + { + XGetGeometry(mDisplay, vo_window, &mRoot, &drwX, &drwY, &drwWidth, + &drwHeight, &drwBorderWidth, &drwDepth); + drwX = drwY = 0; + + XTranslateCoordinates(mDisplay, vo_window, mRoot, 0, 0, + &drwcX, &drwcY, &mRoot); + aspect(&dwidth,&dheight,A_NOZOOM); + if (!vo_fs) + mp_msg(MSGT_VO, MSGL_V, "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n", + drwcX, drwcY, drwX, drwY, drwWidth, drwHeight); + + /* following stuff copied from vo_xmga.c */ + } + else + { + aspect(&dwidth,&dheight,A_NOZOOM); + drwcX=drwX=vo_dx; drwcY=drwY=vo_dy; drwWidth=vo_dwidth; drwHeight=vo_dheight; + } + +#if X11_FULLSCREEN + if (vo_fs) + { + aspect(&dwidth,&dheight,A_ZOOM); + drwX = (vo_screenwidth - ((int)dwidth > vo_screenwidth ? vo_screenwidth : dwidth)) / 2; + drwcX = drwX; + drwY = (vo_screenheight - ((int)dheight > vo_screenheight ? vo_screenheight : dheight)) / 2; + drwcY = drwY; + drwWidth = ((int)dwidth > vo_screenwidth ? vo_screenwidth : dwidth); + drwHeight = ((int)dheight > vo_screenheight ? vo_screenheight : dheight); + mp_msg(MSGT_VO, MSGL_V, "[xvidix-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n", + drwcX, drwcY, drwX, drwY, drwWidth, drwHeight); + } +#endif + + vo_dwidth=drwWidth; vo_dheight=drwHeight; + +#ifdef HAVE_XINERAMA + if (XineramaIsActive(mDisplay)) + { + XineramaScreenInfo *screens; + int num_screens; + int i = 0; + + screens = XineramaQueryScreens(mDisplay, &num_screens); + + /* find the screen we are on */ + while (i<num_screens && + ((screens[i].x_org < (int)drwcX) || + (screens[i].y_org < (int)drwcY) || + (screens[i].x_org + screens[i].width >= (int)drwcX) || + (screens[i].y_org + screens[i].height >= (int)drwcY))) + { + i++; + } + + if(i<num_screens) + { + /* save the screen we are on */ + xinerama_screen = i; + } else { + /* oops.. couldnt find the screen we are on + * because the upper left corner left the + * visual range. assume we are still on the + * same screen + */ + i = xinerama_screen; + } + + /* set drwcX and drwcY to the right values */ + drwcX = drwcX - screens[i].x_org; + drwcY = drwcY - screens[i].y_org; + XFree(screens); + } +#endif + + if ( vo_panscan > 0.0f && vo_fs ) + { + drwcX-=vo_panscan_x >> 1; + drwcY-=vo_panscan_y >> 1; + drwX-=vo_panscan_x >> 1; + drwY-=vo_panscan_y >> 1; + drwWidth+=vo_panscan_x; + drwHeight+=vo_panscan_y; + } + + /* set new values in VIDIX */ + if (force_update || (window_x != drwcX) || (window_y != drwcY) || + (window_width != drwWidth) || (window_height != drwHeight)) + { + mp_win_t w; + // do a backup of window coordinates + w.x = window_x = drwcX; + w.y = window_y = drwcY; + vo_dx = drwcX; + vo_dy = drwcY; + w.w = window_width = drwWidth; + w.h = window_height = drwHeight; + + if(sub_vo->control(VOCTRL_XOVERLAY_SET_WIN,&w) != VO_TRUE) + mp_msg(MSGT_VO, MSGL_ERR, "xvidx: set_overlay failed\n"); + + mp_msg(MSGT_VO, MSGL_V, "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx, vo_dy, window_width, window_height); + } + + /* mDrawColorKey: */ + + /* fill drawable with specified color */ + XSetBackground( mDisplay,vo_gc,bgColor ); + XClearWindow( mDisplay,vo_window ); + XSetForeground(mDisplay, vo_gc, fgColor); + XFillRectangle(mDisplay, vo_window, vo_gc, drwX, drwY, drwWidth, + (vo_fs ? drwHeight - 1 : drwHeight)); + /* flush, update drawable */ + XFlush(mDisplay); + + return; +} + +/* connect to server, create and map window, + * allocate colors and (shared) memory + */ +static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, + uint32_t d_height, uint32_t flags, char *title, uint32_t format) +{ + XVisualInfo vinfo; + // XSizeHints hint; + XSetWindowAttributes xswa; + unsigned long xswamask; + XWindowAttributes attribs; + int window_depth; + mp_colorkey_t colork; + char _title[255]; + + sprintf(_title,"MPlayer %s X11 Overlay",sub_vo->info->name); + title = _title; + + panscan_init(); + + image_height = height; + image_width = width; + image_format = format; + vo_mouse_autohide=1; + + aspect_save_orig(width, height); + aspect_save_prescale(d_width, d_height); + aspect_save_screenres(vo_screenwidth, vo_screenheight); + + vo_dx = 0; + vo_dy = 0; + window_width = d_width; + window_height = d_height; + + /* from xmga.c */ + bgColor = 0x0L; + switch(vo_depthonscreen) + { + case 32: + case 24: + fgColor = 0x00ff00ffL; + break; + case 16: + fgColor = 0xf81fL; + break; + case 15: + fgColor = 0x7c1fL; + break; + default: + mp_msg(MSGT_VO, MSGL_ERR, "Sorry, this (%d) color depth is not supported\n", + vo_depthonscreen); + } + + aspect(&d_width, &d_height, A_NOZOOM); + + vo_dx=( vo_screenwidth - d_width ) / 2; vo_dy=( vo_screenheight - d_height ) / 2; + vo_dwidth=d_width; vo_dheight=d_height; + +#ifdef HAVE_NEW_GUI + if(use_gui) guiGetEvent( guiSetShVideo,0 ); // the GUI will set up / resize the window + else + { +#endif + +#ifdef X11_FULLSCREEN + if ( ( flags&1 )||(flags & 0x04) ) aspect(&d_width, &d_height, A_ZOOM); +#endif + dwidth = d_width; + dheight = d_height; + /* Make the window */ + XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &attribs); + + /* from vo_x11 */ + window_depth = attribs.depth; + if ((window_depth != 15) && (window_depth != 16) && (window_depth != 24) + && (window_depth != 32)) + window_depth = 24; + XMatchVisualInfo(mDisplay, mScreen, window_depth, TrueColor, &vinfo); + + xswa.background_pixel = BlackPixel(mDisplay, mScreen); + xswa.border_pixel = 0; + xswa.colormap = XCreateColormap(mDisplay, RootWindow(mDisplay, mScreen), + vinfo.visual, AllocNone); + xswa.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | PropertyChangeMask | + ((WinID==0)?0:(ButtonPressMask | ButtonReleaseMask | PointerMotionMask)); + xswamask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + if (WinID >= 0) + { + vo_window = WinID ? ((Window)WinID) : RootWindow(mDisplay, mScreen); + if ( WinID ) + { + XUnmapWindow(mDisplay, vo_window); + XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa); + vo_x11_selectinput_witherr( mDisplay,vo_window,StructureNotifyMask | KeyPressMask | PropertyChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ExposureMask ); + } else XSelectInput( mDisplay,vo_window,ExposureMask ); + } + else + { + if ( vo_window == None ) + { + vo_window = XCreateWindow(mDisplay, RootWindow(mDisplay, mScreen), + vo_dx, vo_dy, window_width, window_height, xswa.border_pixel, + vinfo.depth, InputOutput, vinfo.visual, xswamask, &xswa); + + vo_x11_classhint(mDisplay, vo_window, "xvidix"); + vo_hidecursor(mDisplay, vo_window); + vo_x11_sizehint( vo_dx,vo_dy,vo_dwidth,vo_dheight,0 ); + + XStoreName(mDisplay, vo_window, title); + XMapWindow(mDisplay, vo_window); + + if ( flags&1 ) vo_x11_fullscreen(); + +#ifdef HAVE_XINERAMA + vo_x11_xinerama_move(mDisplay, vo_window); +#endif + } else if ( !(flags&1) ) XMoveResizeWindow( mDisplay,vo_window,vo_dx,vo_dy,vo_dwidth,vo_dheight ); + } + + if ( vo_gc != None ) XFreeGC( mDisplay,vo_gc ); + vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &mGCV); +#ifdef HAVE_NEW_GUI + } +#endif + + if ( ( !WinID )&&( flags&1 ) ) { vo_dx=0; vo_dy=0; vo_dwidth=vo_screenwidth; vo_dheight=vo_screenheight; vo_fs=1; } + + if(sub_vo->config(image_width,image_height,vo_dwidth,vo_dheight, + flags | VOFLAG_XOVERLAY_SUB_VO,NULL,format)) { + mp_msg(MSGT_VO, MSGL_ERR, "xover: sub vo config failed\n"); + return 1; + } + colork.x11 = fgColor; + colork.r = 255; + colork.g = 0; + colork.b = 255; + if(sub_vo->control(VOCTRL_XOVERLAY_SET_COLORKEY,&colork) != VO_TRUE) + mp_msg(MSGT_VO, MSGL_WARN, "xover: set_colorkey failed\n"); + + set_window(1); + + XFlush(mDisplay); + XSync(mDisplay, False); + + panscan_calc(); + + saver_off(mDisplay); /* turning off screen saver */ + + vo_config_count++; + + return(0); +} + +static void check_events(void) +{ + const int event = vo_x11_check_events(mDisplay); + + if ((event & VO_EVENT_RESIZE) || (event & VO_EVENT_EXPOSE)) + set_window(0); + sub_vo->check_events(); + return; +} + +/* draw_osd, flip_page, draw_slice, draw_frame should be + overwritten with vidix functions (vosub_vidix.c) */ +static void draw_osd(void) +{ + mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo draw_osd!\n"); +} + +static void flip_page(void) +{ + mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo flip_page!\n"); +} + +static uint32_t draw_slice(uint8_t *src[], int stride[], + int w, int h, int x, int y) +{ + UNUSED(src); + UNUSED(stride); + UNUSED(w); + UNUSED(h); + UNUSED(x); + UNUSED(y); + mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo draw_slice!\n"); + return 1; +} + +static uint32_t draw_frame(uint8_t *src[]) +{ + UNUSED(src); + mp_msg(MSGT_VO, MSGL_FATAL, "xover error: didn't used sub vo draw_frame!\n"); + return 1; +} + +static void uninit(void) +{ + if(!vo_config_count) return; + if(sub_vo) sub_vo->uninit(); + sub_vo = NULL; + saver_on(mDisplay); /* screen saver back on */ + vo_x11_uninit(); + // Restore our callbacks + video_out_xover.draw_frame = draw_frame; + video_out_xover.draw_slice = draw_slice; + video_out_xover.flip_page = flip_page; + video_out_xover.draw_osd = draw_osd; +} + +static uint32_t preinit(const char *arg) +{ + int i; + + if(!arg) { + mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay need a subdriver\n"); + return 1; + } + + for(i = 0 ; video_out_drivers[i] != NULL ; i++) { + if(!strcmp(video_out_drivers[i]->info->short_name,arg) && + strcmp(video_out_drivers[i]->info->short_name,"xover")) + break; + } + if(!video_out_drivers[i]) { + mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay: Subdriver %s not found\n"); + return 1; + } + if(video_out_drivers[i]->control(VOCTRL_XOVERLAY_SUPPORT,NULL) != VO_TRUE) { + mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay: %s doesn't support XOverlay\n"); + return 1; + } + // X11 init + if (!vo_init()) return VO_FALSE; + if(video_out_drivers[i]->preinit(NULL)) { + mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay: Subvo init failed\n"); + return 1; + } + sub_vo = video_out_drivers[i]; + // Setup the sub vo callbacks + video_out_xover.draw_frame = sub_vo->draw_frame; + video_out_xover.draw_slice = sub_vo->draw_slice; + video_out_xover.flip_page = sub_vo->flip_page; + video_out_xover.draw_osd = sub_vo->draw_osd; + return 0; +} + +static uint32_t control(uint32_t request, void *data, ...) +{ + if(!sub_vo) return VO_ERROR; + switch (request) { + case VOCTRL_GUISUPPORT: + return VO_TRUE; + case VOCTRL_GET_PANSCAN: + if ( !vo_config_count || !vo_fs ) return VO_FALSE; + return VO_TRUE; + case VOCTRL_FULLSCREEN: + vo_x11_fullscreen(); + case VOCTRL_SET_PANSCAN: + if ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) + { + panscan_calc(); + set_window(0); + } + return VO_TRUE; + default: + // Safe atm bcs nothing use more than 1 arg + return sub_vo->control(request,data); + } + return VO_NOTIMPL; +}