diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/video_out/Makefile.am | 2 | ||||
-rw-r--r-- | src/video_out/video_out_syncfb.c | 1504 |
2 files changed, 710 insertions, 796 deletions
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 490b77304..af60b26aa 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -34,7 +34,7 @@ xineplug_vo_out_xshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ xineplug_vo_out_xshm_la_LIBADD = $(X_LIBS) -lXext xineplug_vo_out_xshm_la_LDFLAGS = -avoid-version -module -xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c +xineplug_vo_out_syncfb_la_SOURCES = alphablend.c video_out_syncfb.c xineplug_vo_out_syncfb_la_LDFLAGS = -avoid-version -module xineplug_vo_out_aa_la_SOURCES = video_out_aa.c diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c index a2226db8c..3d3ba9ce6 100644 --- a/src/video_out/video_out_syncfb.c +++ b/src/video_out/video_out_syncfb.c @@ -1,8 +1,8 @@ -/* - * Copyright (C) 2000 the xine project - * +/* + * Copyright (C) 2000, 2001 the xine project + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -12,20 +12,23 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_syncfb.c,v 1.16 2001/10/22 00:52:10 guenter Exp $ + * $Id: video_out_syncfb.c,v 1.17 2001/11/03 00:13:11 matt2000 Exp $ * - * video_out_syncfb.c, Matrox G400 video extension interface for xine - * - * based on video_out_mga code from - * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - * - * xine-specific code by Joachim Koenig <joachim.koenig@gmx.net> - * Underlaying window by Matthias Dahl <matthew2k@web.de> + * video_out_syncfb.c, SyncFB (for Matrox G200/G400 cards) interface for xine + * + * based on video_out_xv.c by (see file for original authors) + * + * with lot's of code from: + * video_out_syncfb.c by Joachim Koenig <joachim.koenig@gmx.net> + * and by Matthias Oelmann <mao@well.com> + * video_out_mga by Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * tied togehter with lot of clue for xine by Matthias Dahl <matthew2k@web.de> * */ @@ -33,821 +36,718 @@ #include "config.h" #endif +#include <X11/Xutil.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.h> - -#include <sys/ioctl.h> #include <unistd.h> -#include <fcntl.h> -#include <sys/mman.h> - -#include <sys/ipc.h> -#include <sys/shm.h> -#include <sys/time.h> - -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -#if defined(__linux__) -#include <linux/config.h> /* Check for DEVFS */ -#endif -#if defined(__sun) -#include <sys/ioccom.h> -#endif +#include "video_out_syncfb.h" +#include "monitor.h" #include "video_out.h" #include "video_out_x11.h" -#include "video_out_syncfb.h" #include "xine_internal.h" #include "alphablend.h" - -#include "monitor.h" -#include "configfile.h" - -#define MWM_HINTS_DECORATIONS (1L << 1) -#define PROP_MWM_HINTS_ELEMENTS 5 -typedef struct _mwmhints { - uint32_t flags; - uint32_t functions; - uint32_t decorations; - int32_t input_mode; - uint32_t status; -} MWMHints; - -// extern Window gVideoWin; -// extern Pixmap gXineLogo; -// extern int gXineLogoWidth, gXineLogoHeight; +#include "memcpy.h" uint32_t xine_debug; -typedef struct mga_frame_s { +typedef struct { + int value; + int min; + int max; + char *key; +} syncfb_property_t; + +typedef struct { vo_frame_t vo_frame; - int width, height, ratio_code, format; - int id; + int width, height, ratio_code, format, id; +} syncfb_frame_t; + +typedef struct { + vo_driver_t vo_driver; + config_values_t *config; + + /* X11 related stuff */ + Display *display; + Drawable drawable; + GC gc; + XColor black; + int screen; + + int virtual_screen_width; + int virtual_screen_height; + int screen_depth; -} mga_frame_t; + syncfb_property_t props[VO_NUM_PROPERTIES]; + vo_overlay_t *overlay; -typedef struct _display { - int width; - int height; - int depth; - int default_screen; -} display; + // syncfb module related stuff + int fd; // file descriptor of the syncfb device + int palette; // palette the syncfb module is using + int overlay_state; // 0 = off, 1 = on + uint8_t* video_mem; // mmapped video memory -typedef struct _window { - char title[20]; + syncfb_config_t syncfb_config; + syncfb_capability_t capabilities; + syncfb_buffer_info_t bufinfo; - Window clasped_window; - int visibility; -} window; - -typedef struct _mga_globals { - - syncfb_config_t mga_vid_config; - syncfb_capability_t caps; - syncfb_buffer_info_t bufinfo; - syncfb_param_t param; - Display *lDisplay; - Display *gDisplay; - uint8_t *vid_data, *frame0, *frame1; - int next_frame; - int fd; - uint32_t bespitch; - - int bFullscreen; - int bIsFullscreen; - int image_width; - int image_height; - int image_xoff; - int image_yoff; - int orig_width; /* image size correct. by ratio */ - int orig_height; - int dest_width; - int dest_height; - int fourcc_format; - int interlaced; - - uint32_t ratio; - int user_ratio, user_ratio_changed; - -// XvImage *cur_image; - - int bLogoMode; - - int bright_min, bright_current, bright_max; - int cont_min, cont_current, cont_max; - - int overlay_state; - - void *user_data; + /* size / aspect ratio calculations */ + int delivered_width; /* everything is set up for + these frame dimensions */ + int delivered_height; /* the dimension as they come + from the decoder */ + int delivered_ratio_code; + double ratio_factor; /* output frame must fullfill: + height = width * ratio_factor */ + int output_width; /* frames will appear in this + size (pixels) on screen */ + int output_height; + int output_xoffset; + int output_yoffset; + + int frame_width; + int frame_height; + + int deinterlace_enabled; + + /* display anatomy */ + double display_ratio; /* given by visual parameter + from init function */ + + void *user_data; /* gui callback */ - void (*request_dest_size) (void *user_data, - int video_width, int video_height, - int *dest_x, int *dest_y, - int *dest_height, int *dest_width); - -} mga_globals; + void (*request_dest_size) (void *user_data, + int video_width, int video_height, + int *dest_x, int *dest_y, + int *dest_height, int *dest_width); +} syncfb_driver_t; -mga_globals _mga_priv; -display _display; -window _window; +int gX11Fail; -int nLocks; - - - -static int _mga_write_frame_g400 (uint8_t *src[]) +// +// internal video_out_syncfb functions +// +static void write_frame_YUV422(syncfb_driver_t* this, syncfb_frame_t* frame, uint_8* y, uint_8* cr, uint_8* cb) { - uint8_t *dest; - int h; - uint8_t *y = src[0]; - uint8_t *cb = src[1]; - uint8_t *cr = src[2]; - - dest = _mga_priv.vid_data; - - if (_mga_priv.fourcc_format == IMGFMT_YUY2) { - for (h=0; h < _mga_priv.mga_vid_config.src_height; h++) { - memcpy(dest, y, _mga_priv.mga_vid_config.src_width*2); - y += _mga_priv.mga_vid_config.src_width*2; - dest += _mga_priv.bespitch*2; - } - return 0; - } - - - for (h=0; h < _mga_priv.mga_vid_config.src_height; h++) { - memcpy(dest, y, _mga_priv.mga_vid_config.src_width); - y += _mga_priv.mga_vid_config.src_width; - dest += _mga_priv.bespitch; - } - - - for (h=0; h < _mga_priv.mga_vid_config.src_height/2; h++) { - memcpy(dest, cb, _mga_priv.mga_vid_config.src_width/2); - cb += _mga_priv.mga_vid_config.src_width/2; - dest += _mga_priv.bespitch/2; - } - - dest = _mga_priv.vid_data + _mga_priv.bespitch * _mga_priv.mga_vid_config.src_height * 3 / 2; - - for (h=0; h < _mga_priv.mga_vid_config.src_height/2; h++) { - memcpy(dest, cr, _mga_priv.mga_vid_config.src_width/2); - cr += _mga_priv.mga_vid_config.src_width/2; - dest += _mga_priv.bespitch/2; - } - - return 0; -} + uint_8* crp; + uint_8* cbp; + uint_32* dest32; + int h,w; + + int src_width = frame->width; + int src_height = frame->height; + int bespitch = (frame->width + 31) & ~31; + dest32 = (uint_32 *)(this->video_mem + this->bufinfo.offset); + for(h=0; h < src_height/2; h++) { + cbp = cb; + crp = cr; + + for(w=0; w < src_width/2; w++) { + *dest32++ = (*y) + ((*cr)<<8) + ((*(y+1))<<16) + ((*cb)<<24); + y++; y++; cb++; cr++; + } -static void setup_window_mga () { - int ww=0, wh=0; - float aspect; - - XWindowAttributes wattr; - - XGetWindowAttributes(_mga_priv.lDisplay, DefaultRootWindow(_mga_priv.lDisplay), &wattr); - - _display.width = wattr.width; - _display.height = wattr.height; - _display.depth = wattr.depth; - - ww = _display.width ; - wh = _display.height; - -xprintf(VERBOSE|VIDEO,"setup_window_mga: unscaled size should be %d x %d \n",_mga_priv.orig_width,_mga_priv.orig_height); -printf("setup_window_mga: unscaled size should be %d x %d \n",_mga_priv.orig_width,_mga_priv.orig_height); - - if (_mga_priv.bFullscreen) { + dest32 += (bespitch - src_width) / 2; - /* - * zoom to fullscreen - */ + for(w=0; w < src_width/2; w++) { + *dest32++ = (*y) + ((*crp)<<8) + ((*(y+1))<<16) + ((*cbp)<<24); + y++; y++; cbp++; crp++; + } + + dest32 += (bespitch - src_width) / 2; + } +} - if (_mga_priv.orig_width != ww) { - aspect = (float) _mga_priv.orig_width / (float) _mga_priv.orig_height ; +static void write_frame_YUV420P2(syncfb_driver_t* this, syncfb_frame_t* frame, uint_8* y, uint_8* cr, uint_8* cb) +{ + uint_8* dest; + int h; + + register uint_32 *tmp32; + register uint_8 *rcr; + register uint_8 *rcb; + register int w; + + int src_width = frame->width; + int src_height = frame->height; + int bespitch = (frame->width + 31) & ~31; + + rcr = cr; + rcb = cb; + + dest = this->video_mem + this->bufinfo.offset_p2; + for(h=0; h < src_height/2; h++) { + tmp32 = (uint_32 *)dest; + w = src_width/8; + + while (w--) { + *tmp32++ = (*rcr++) | (*rcb++)<<8 | (*rcr++)<<16 | (*rcb++)<<24; + *tmp32++ = (*rcr++) | (*rcb++)<<8 | (*rcr++)<<16 | (*rcb++)<<24; + } + + dest += bespitch; + } - _mga_priv.dest_width = ww; - _mga_priv.dest_height = ww / aspect; + dest = this->video_mem + this->bufinfo.offset; - if (_mga_priv.dest_height > wh) { + for(h=0; h < src_height; h++) { + fast_memcpy(dest, y, src_width); + y += src_width; + dest += bespitch; + } +} - _mga_priv.dest_width = wh * aspect; - _mga_priv.dest_height = wh; - } +static void write_frame_YUV420P3(syncfb_driver_t* this, syncfb_frame_t* frame, uint_8* y, uint_8* cr, uint_8* cb) +{ + uint_8* dest; + int h; - } else { + int src_width = frame->width; + int src_height = frame->height; + + int bespitch = (frame->width + 31) & ~31; + dest = this->video_mem + this->bufinfo.offset; - _mga_priv.dest_width = _mga_priv.orig_width ; - _mga_priv.dest_height = _mga_priv.orig_height ; + for(h=0; h < src_height; h++) { + fast_memcpy(dest, y, src_width); + y += src_width; + dest += bespitch; + } - } - _mga_priv.image_xoff = ( ww - _mga_priv.dest_width) / 2; - _mga_priv.image_yoff = ( wh - _mga_priv.dest_height) / 2; + dest = this->video_mem + this->bufinfo.offset_p2; + for(h=0; h < src_height/2; h++) { + fast_memcpy(dest, cr, src_width/2); + cr += src_width/2; + dest += bespitch/2; + } + dest = this->video_mem + this->bufinfo.offset_p3; + for(h=0; h < src_height/2; h++) { + fast_memcpy(dest, cb, src_width/2); + cb += src_width/2; + dest += bespitch/2; + } +} - _mga_priv.bIsFullscreen = 1; +static void write_frame_sfb(syncfb_driver_t* this, syncfb_frame_t* frame) +{ + uint8_t *src[3]; + src[0] = frame->vo_frame.base[0]; + src[1] = frame->vo_frame.base[1]; + src[2] = frame->vo_frame.base[2]; + + if(this->palette == VIDEO_PALETTE_YUV422) { + write_frame_YUV422(this, frame, src[0], src[1], src[2]); + } else if(this->palette == VIDEO_PALETTE_YUV420P2) { + write_frame_YUV420P2(this, frame, src[0], src[1], src[2]); + } else if(this->palette == VIDEO_PALETTE_YUV420P3) { + write_frame_YUV420P3(this, frame, src[0], src[1], src[2]); + } +} - } else { +static void syncfb_adapt_to_output_area(syncfb_driver_t* this, + int dest_x, int dest_y, + int dest_width, int dest_height) +{ + Window temp_window; + int posx, posy; - /* - * zoom to mpeg1 to double size - */ - -// if (_mga_priv.orig_width < 600) { -// _mga_priv.dest_width = _mga_priv.orig_width *2; -// _mga_priv.dest_height = _mga_priv.orig_height *2; -// } else { - - if (_mga_priv.orig_width > ww) { - aspect = (float) _mga_priv.orig_width / (float) _mga_priv.orig_height ; + XLockDisplay(this->display); + + XTranslateCoordinates(this->display, this->drawable, DefaultRootWindow(this->display), 0, 0, &posx, &posy, &temp_window); + + if(((double) dest_width / this->ratio_factor) < dest_height) { + this->output_width = dest_width; + this->output_height = (double) dest_width / this->ratio_factor; + this->output_xoffset = dest_x; + this->output_yoffset = dest_y + (dest_height - this->output_height) / 2; + } else { + this->output_width = (double) dest_height * this->ratio_factor; + this->output_height = dest_height; + this->output_xoffset = dest_x + (dest_width - this->output_width) / 2; + this->output_yoffset = dest_y; + } + + /* + * set up the syncfb module + */ + + if(ioctl(this->fd, SYNCFB_OFF)) + printf("video_out_syncfb: error. (off ioctl failed)\n"); + else + this->overlay_state = 0; + + // in case we have the window somewhere *off* the desktop, this *could* + // cause some screen corruption... so better leave things deactivated. + if(posx >= 0 && posy >= 0) { + if(ioctl(this->fd, SYNCFB_GET_CONFIG, &this->syncfb_config)) + printf("video_out_syncfb: error. (get_config ioctl failed)\n"); + + this->syncfb_config.syncfb_mode = SYNCFB_FEATURE_BLOCK_REQUEST | SYNCFB_FEATURE_SCALE | SYNCFB_FEATURE_OFFSET; + + this->syncfb_config.src_palette = this->palette; + + this->syncfb_config.fb_screen_size = this->virtual_screen_width * this->virtual_screen_height * (this->screen_depth / 8); + this->syncfb_config.src_width = this->frame_width; + this->syncfb_config.src_height = this->frame_height; - _mga_priv.dest_width = ww; - _mga_priv.dest_height = ww / aspect; + this->syncfb_config.image_width = this->output_width; + this->syncfb_config.image_height = this->output_height; - if (_mga_priv.dest_height > wh) { - _mga_priv.dest_width = wh * aspect; - _mga_priv.dest_height = wh; - } + this->syncfb_config.image_xorg = posx+this->output_xoffset; + this->syncfb_config.image_yorg = posy+this->output_yoffset; - } else { - _mga_priv.dest_width = _mga_priv.orig_width ; - _mga_priv.dest_height = _mga_priv.orig_height ; - } -// } + this->syncfb_config.image_offset_left = 0; // FIXME: what's this about?! + this->syncfb_config.image_offset_right= 0; // FIXME: what's this about?! - _mga_priv.bIsFullscreen = 0; + this->syncfb_config.image_offset_top = 0; // FIXME: what's this about?! + this->syncfb_config.image_offset_bot = 0; // FIXME: what's this about?! - _mga_priv.image_xoff = ( ww - _mga_priv.dest_width) / 2; - _mga_priv.image_yoff = ( wh - _mga_priv.dest_height) / 2; + this->syncfb_config.default_repeat = 2; - } - xprintf(VERBOSE|VIDEO,"Calculated size should be %d x %d xoff %d yoff %d Display Is %d x %d\n",_mga_priv.dest_width,_mga_priv.dest_height,_mga_priv.image_xoff,_mga_priv.image_yoff,ww,wh); - printf("Calculated size should be %d x %d xoff %d yoff %d Display Is %d x %d\n",_mga_priv.dest_width,_mga_priv.dest_height,_mga_priv.image_xoff,_mga_priv.image_yoff,ww,wh); - - if (ioctl(_mga_priv.fd,SYNCFB_GET_CAPS,&_mga_priv.caps)) perror("Error in config ioctl"); - xprintf(VERBOSE|VIDEO,"Syncfb device name is '%s'\n", _mga_priv.caps.name); - xprintf(VERBOSE|VIDEO,"Memory size is %ld \n", _mga_priv.caps.memory_size); + if(ioctl(this->fd,SYNCFB_SET_CONFIG,&this->syncfb_config)) + printf("video_out_syncfb: error. (set_config ioctl failed)\n"); + + if(ioctl(this->fd, SYNCFB_ON)) + printf("video_out_syncfb: error. (on ioctl failed)\n"); + else + this->overlay_state = 1; + } + + /* + * clear unused output area + */ - if (ioctl(_mga_priv.fd,SYNCFB_GET_CONFIG,&_mga_priv.mga_vid_config)) - printf("Error in get_config ioctl\n"); + XSetForeground (this->display, this->gc, this->black.pixel); - _mga_priv.mga_vid_config.fb_screen_size = _display.width * _display.height * (_display.depth/8); // maybe wrong if depth = 15 (?) - _mga_priv.mga_vid_config.src_width = _mga_priv.image_width; - _mga_priv.mga_vid_config.src_height= _mga_priv.image_height; - _mga_priv.bespitch = (_mga_priv.image_width + 31) & ~31; + XFillRectangle(this->display, this->drawable, this->gc, + dest_x, dest_y, dest_width, this->output_yoffset - dest_y); - switch (_mga_priv.fourcc_format) { - case IMGFMT_YV12: - _mga_priv.mga_vid_config.src_palette = VIDEO_PALETTE_YUV420P3; - break; - case IMGFMT_YUY2: - _mga_priv.mga_vid_config.src_palette = VIDEO_PALETTE_YUYV; - break; - default: - _mga_priv.mga_vid_config.src_palette = VIDEO_PALETTE_YUV420P3; - break; - } - _mga_priv.mga_vid_config.image_width = _mga_priv.dest_width; - _mga_priv.mga_vid_config.image_height= _mga_priv.dest_height; -// _mga_priv.mga_vid_config.syncfb_mode = SYNCFB_FEATURE_BLOCK_REQUEST | SYNCFB_FEATURE_SCALE_H | SYNCFB_FEATURE_SCALE_V | SYNCFB_FEATURE_CROP ; /* | SYNCFB_FEATURE_DEINTERLACE; */ - _mga_priv.mga_vid_config.syncfb_mode = SYNCFB_FEATURE_SCALE_H | SYNCFB_FEATURE_SCALE_V | SYNCFB_FEATURE_CROP ; /* | SYNCFB_FEATURE_DEINTERLACE; */ - if (_mga_priv.interlaced) - _mga_priv.mga_vid_config.syncfb_mode |= SYNCFB_FEATURE_DEINTERLACE; - _mga_priv.mga_vid_config.image_xorg= _mga_priv.image_xoff; - _mga_priv.mga_vid_config.image_yorg= _mga_priv.image_yoff; - - _mga_priv.mga_vid_config.src_crop_top = 0; - _mga_priv.mga_vid_config.src_crop_bot = 0; - -#ifdef CINEMODE - _mga_priv.mga_vid_config.default_repeat = 3; -#else - _mga_priv.mga_vid_config.default_repeat = 2; -#endif + XFillRectangle(this->display, this->drawable, this->gc, + dest_x, dest_y, this->output_xoffset-dest_x, dest_height); - if (ioctl(_mga_priv.fd,SYNCFB_SET_CONFIG,&_mga_priv.mga_vid_config)) - xprintf(VERBOSE|VIDEO,"Error in set_config ioctl\n"); - if (_mga_priv.bLogoMode) { - if (ioctl(_mga_priv.fd,SYNCFB_OFF)) { - xprintf(VERBOSE|VIDEO,"Error in OFF ioctl\n"); - } - else - _mga_priv.overlay_state = 0; - } + XFillRectangle(this->display, this->drawable, this->gc, + dest_x, this->output_yoffset+this->output_height, + dest_width, + dest_height - this->output_yoffset - this->output_height); -// if (ioctl(_mga_priv.fd,SYNCFB_ON)) -// xprintf(VERBOSE|VIDEO,"Error in ON ioctl\n"); -#if 0 - // create a simple window without anything. Just make overlay clickable. :) - if (!_window.clasped_window) { - Atom prop; - MWMHints mwmhints; + XFillRectangle(this->display, this->drawable, this->gc, + this->output_xoffset+this->output_width, dest_y, + dest_width - this->output_xoffset - this->output_width, + dest_height); - _window.clasped_window = XCreateSimpleWindow(_mga_priv.lDisplay, RootWindow(_mga_priv.lDisplay, _display.default_screen), 0, 0, _mga_priv.dest_width, _mga_priv.dest_height, 0, 0, 0); -// gVideoWin = _window.clasped_window; - - // turn off all borders etc. (taken from the Xv plugin) - prop = XInternAtom(_mga_priv.lDisplay, "_MOTIF_WM_HINTS", False); - mwmhints.flags = MWM_HINTS_DECORATIONS; - mwmhints.decorations = 0; -// XChangeProperty(_mga_priv.lDisplay, gVideoWin, prop, prop, 32, -// PropModeReplace, (unsigned char *) &mwmhints, -// PROP_MWM_HINTS_ELEMENTS); -// XSetTransientForHint(_mga_priv.lDisplay, gVideoWin, None); - - XSelectInput(_mga_priv.gDisplay, _window.clasped_window, VisibilityChangeMask | KeyPressMask | ButtonPressMask | SubstructureNotifyMask | StructureNotifyMask); - XMapRaised(_mga_priv.lDisplay, _window.clasped_window); - XSync(_mga_priv.lDisplay,0); - } - - XSetStandardProperties(_mga_priv.lDisplay, _window.clasped_window, _window.title, _window.title, None, NULL, 0, NULL); - XMoveResizeWindow(_mga_priv.lDisplay, _window.clasped_window, (_mga_priv.bIsFullscreen) ? 0 : _mga_priv.image_xoff, (_mga_priv.bIsFullscreen) ? 0 : _mga_priv.image_yoff, (_mga_priv.bIsFullscreen) ? _display.width : _mga_priv.dest_width, (_mga_priv.bIsFullscreen) ? _display.height : _mga_priv.dest_height); - XMapRaised(_mga_priv.lDisplay, _window.clasped_window); - XSync(_mga_priv.lDisplay,0); -#endif + XUnlockDisplay (this->display); } +static void syncfb_calc_format(syncfb_driver_t* this, + int width, int height, int ratio_code) { + double image_ratio, desired_ratio; + double corr_factor; + int ideal_width, ideal_height; + int dest_x, dest_y, dest_width, dest_height; -/* setup internal variables and (re-)init window if necessary */ -static void mga_set_image_format (uint32_t width, uint32_t height, int ratio, int format) { - - - double res_h, res_v, display_ratio, aspect_ratio; - if ( (_mga_priv.image_width == width) - && (_mga_priv.image_height == height) - && (_mga_priv.ratio == ratio) - && (_mga_priv.fourcc_format == format) - && !_mga_priv.user_ratio_changed ) { - return ; - } - -printf("new frame format width %d height %d ratio %d format %x\n",width,height,ratio,format); - _mga_priv.image_width = width; - _mga_priv.image_height = height; - _mga_priv.ratio = ratio; - _mga_priv.fourcc_format = format; - _mga_priv.user_ratio_changed = 0; + this->delivered_width = width; + this->delivered_height = height; + this->delivered_ratio_code = ratio_code; + if((!width) || (!height)) + return; /* - * Mpeg-2: + * aspect ratio calculation */ - res_h = 1; // _display.width; - res_v = 1; // _display.height; - - display_ratio = res_h / res_v; + image_ratio = + (double) this->delivered_width / (double) this->delivered_height; - xprintf (VERBOSE | VIDEO, "display_ratio : %f\n",display_ratio); + xprintf (VERBOSE | VIDEO, "display_ratio : %f\n", this->display_ratio); + xprintf (VERBOSE | VIDEO, "stream aspect ratio : %f , code : %d\n", + image_ratio, ratio_code); - if (_mga_priv.user_ratio == ASPECT_AUTO) { - switch (_mga_priv.ratio) { - case 0: /* forbidden */ - fprintf (stderr, "invalid ratio\n"); - exit (1); - break; - case XINE_ASPECT_RATIO_4_3: - aspect_ratio = 4.0 / 3.0; + switch (this->props[VO_PROP_ASPECT_RATIO].value) { + case ASPECT_AUTO: + switch (ratio_code) { + case XINE_ASPECT_RATIO_ANAMORPHIC: /* anamorphic */ + desired_ratio = 16.0 /9.0; break; - case XINE_ASPECT_RATIO_ANAMORPHIC: - aspect_ratio = 16.0 / 9.0; + case XINE_ASPECT_RATIO_211_1: /* 2.11:1 */ + desired_ratio = 2.11/1.0; break; - case XINE_ASPECT_RATIO_211_1: - aspect_ratio = 2.11/1.0; + case XINE_ASPECT_RATIO_SQUARE: /* "square" source pels */ + case XINE_ASPECT_RATIO_DONT_TOUCH: /* probably non-mpeg stream => don't touch aspect ratio */ + desired_ratio = image_ratio; break; - case XINE_ASPECT_RATIO_DONT_TOUCH: /* some stupid stream => don't touch aspect ratio */ + case 0: /* forbidden */ + fprintf (stderr, "invalid ratio, using 4:3\n"); default: - xprintf (VIDEO, "unknown aspect ratio (%d) in stream. untouched.\n", _mga_priv.ratio); - case 1: /* "square" source pels */ - aspect_ratio = (double)_mga_priv.image_width / (double)_mga_priv.image_height; + xprintf (VIDEO, "unknown aspect ratio (%d) in stream => using 4:3\n", + ratio_code); + case XINE_ASPECT_RATIO_4_3: /* 4:3 */ + desired_ratio = 4.0 / 3.0; break; } - } else if (_mga_priv.user_ratio == ASPECT_ANAMORPHIC) { - aspect_ratio = 16.0 / 9.0; - } else if (_mga_priv.user_ratio == ASPECT_DVB) { - aspect_ratio = 2.0 / 1.0; - } else if (_mga_priv.user_ratio == ASPECT_SQUARE) { - aspect_ratio = (double)_mga_priv.image_width / (double)_mga_priv.image_height; - } else { - aspect_ratio = 4.0 / 3.0; - } - aspect_ratio *= display_ratio; - if (_mga_priv.image_height * aspect_ratio >= _mga_priv.image_width) { - _mga_priv.orig_width = rint((double)((double)_mga_priv.image_height * aspect_ratio)); - _mga_priv.orig_height = _mga_priv.image_height; - } - else { - _mga_priv.orig_width = _mga_priv.image_width; - _mga_priv.orig_height = rint((double)((double)_mga_priv.image_width / aspect_ratio)); + break; + case ASPECT_ANAMORPHIC: + desired_ratio = 16.0 / 9.0; + break; + case ASPECT_DVB: + desired_ratio = 2.0 / 1.0; + break; + case ASPECT_SQUARE: + desired_ratio = image_ratio; + break; + case ASPECT_FULL: + default: + desired_ratio = 4.0 / 3.0; } - - xprintf (VERBOSE|VIDEO, "picture size : %d x %d (Ratio: %d)\n", - width, height, ratio); - - setup_window_mga () ; -printf("behind setup window mga\n"); - return ; -} + this->ratio_factor = this->display_ratio * desired_ratio; -static void mga_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, - uint32_t width, uint32_t height, int ratio_code, - int format, int flags) { - - mga_frame_t *frame = (mga_frame_t *) frame_gen; - -// printf("MGA update frame format width %d height %d format %d\n",width,height,format); - - frame->ratio_code = ratio_code; - if (frame->width == width && frame->height == height && frame->format == format) - return; - - - if (frame->vo_frame.base[0]) { - shmdt(frame->vo_frame.base[0]); - shmctl(frame->id,IPC_RMID,NULL); - frame->vo_frame.base[0] = NULL; - } - - frame->width = width; - frame->height = height; - frame->format = format; + /* + * calc ideal output frame size + */ - // we only know how to do 4:2:0 planar yuv right now. - // we prepare for YUY2 sizes - frame->id = shmget(IPC_PRIVATE, - frame->width * frame->height * 2, - IPC_CREAT | 0777); + corr_factor = this->ratio_factor / image_ratio ; - if (frame->id < 0 ) { - perror("syncfb: shared memory error in shmget: "); - exit (1); + if (corr_factor >= 1.0) { + ideal_width = this->delivered_width * corr_factor; + ideal_height = this->delivered_height ; } - - frame->vo_frame.base[0] = shmat(frame->id, 0, 0); - - if (frame->vo_frame.base[0] == NULL) { - fprintf(stderr, "syncfb: shared memory error (address error NULL)\n"); - exit (1); + else { + ideal_width = this->delivered_width; + ideal_height = this->delivered_height / corr_factor; } - if (frame->vo_frame.base[0] == (void *) -1) { - fprintf(stderr, "syncfb: shared memory error (address error)\n"); - exit (1); + /* little hack to zoom mpeg1 / other small streams by default*/ + if(ideal_width<400) { + ideal_width *=2; + ideal_height *=2; } - shmctl(frame->id, IPC_RMID, 0); - frame->vo_frame.base[1] = frame->vo_frame.base[0] + width * height * 5 / 4; - frame->vo_frame.base[2] = frame->vo_frame.base[0] + width * height; + /* + * ask gui to adapt to this size + */ - return; -} + this->request_dest_size (this->user_data, + ideal_width, ideal_height, + &dest_x, &dest_y, &dest_width, &dest_height); -static void mga_frame_field (vo_frame_t *vo_img, int which_field) { - /* not needed for MGA */ + syncfb_adapt_to_output_area(this, dest_x, dest_y, dest_width, dest_height); } -static void mga_frame_dispose (vo_frame_t *vo_img) { - - mga_frame_t *frame = (mga_frame_t *) vo_img ; +static void syncfb_translate_gui2video(syncfb_driver_t* this, + int x, int y, + int* vid_x, int* vid_y) +{ + if (this->output_width > 0 && this->output_height > 0) { + /* + * 1. + * the xv driver may center a small output area inside a larger + * gui area. This is the case in fullscreen mode, where we often + * have black borders on the top/bottom/left/right side. + */ + x -= this->output_xoffset; + y -= this->output_yoffset; - if (frame->vo_frame.base[0]) { - shmdt(frame->vo_frame.base[0]); - shmctl(frame->id,IPC_RMID,NULL); - frame->vo_frame.base[0] = NULL; + /* + * 2. + * the xv driver scales the delivered area into an output area. + * translate output area coordianates into the delivered area + * coordiantes. + */ + x = x * this->delivered_width / this->output_width; + y = y * this->delivered_height / this->output_height; } - free (frame); + *vid_x = x; + *vid_y = y; } -static vo_frame_t *mga_alloc_frame (vo_driver_t *this_gen) { +// +// X error handler functions +// (even though the syncfb plugin doesn't check for gX11Fail yet, it is +// probably a good idea to leave this in place for future use) +// +int HandleXError(Display* display, XErrorEvent* xevent) { - mga_frame_t *frame ; + char str [1024]; - frame = (mga_frame_t *) malloc (sizeof (mga_frame_t)); - memset (frame, 0, sizeof(mga_frame_t)); + XGetErrorText (display, xevent->error_code, str, 1024); - if (frame==NULL) { - printf ("mga_alloc_frame: out of memory\n"); - } - - pthread_mutex_init (&frame->vo_frame.mutex, NULL); - - - /* - * supply required functions - */ + printf ("received X error event: %s\n", str); - frame->vo_frame.copy = NULL; - frame->vo_frame.field = mga_frame_field; - frame->vo_frame.dispose = mga_frame_dispose; + gX11Fail = 1; + return 0; +} +static void x11_InstallXErrorHandler(syncfb_driver_t* this) +{ + XSetErrorHandler (HandleXError); + XFlush (this->display); +} - return (vo_frame_t *) frame; +static void x11_DeInstallXErrorHandler(syncfb_driver_t* this) +{ + XSetErrorHandler (NULL); + XFlush (this->display); } -/* - * - */ -static void mga_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { -#if 0 - xv_frame_t *frame = (xv_frame_t *) frame_gen; +// +// video_out_syncfb functions available to the outside world :) +// +static uint32_t syncfb_get_capabilities(vo_driver_t* this_gen) { + // FIXME: VO_CAP_CONTRAST and VO_CAP_BRIGHTNESS unsupported at the moment, + // because they seem to be disabled in the syncfb module anyway. :( + return VO_CAP_YV12 | VO_CAP_YUY2; +} - /* Alpha Blend here - * As XV drivers improve to support Hardware overlay, we will change this function. - */ +static void syncfb_frame_field (vo_frame_t *vo_img, int which_field) { + /* not needed for Xv */ +} - if (overlay->data) { - blend_yuv( frame->image->data, overlay, frame->width, frame->height); +static void syncfb_frame_dispose(vo_frame_t* vo_img) +{ + syncfb_frame_t* frame = (syncfb_frame_t *) vo_img ; + + if(frame->vo_frame.base[0]) { + shmdt(frame->vo_frame.base[0]); + shmctl(frame->id,IPC_RMID,NULL); + frame->vo_frame.base[0] = NULL; } -#endif + + free (frame); } -static void mga_display_frame(vo_driver_t *this, vo_frame_t *frame_gen) { +static vo_frame_t* syncfb_alloc_frame(vo_driver_t* this_gen) +{ + syncfb_frame_t* frame; - mga_frame_t *frame = (mga_frame_t *) frame_gen; - - - if (frame->width != _mga_priv.image_width || - frame->height != _mga_priv.image_height || - frame->format != _mga_priv.fourcc_format || - frame->ratio_code != _mga_priv.ratio) { - mga_set_image_format(frame->width,frame->height,frame->ratio_code,frame->format); - } + frame = (syncfb_frame_t *) malloc(sizeof (syncfb_frame_t)); + memset(frame, 0, sizeof(syncfb_frame_t)); + if(frame == NULL) { + printf ("video_out_syncfb: error. (memory allocating of frame failed)\n"); + } - // only write frame if overlay is active (otherwise syncfb hangs) - if (_mga_priv.overlay_state == 1) { - ioctl(_mga_priv.fd,SYNCFB_REQUEST_BUFFER,&_mga_priv.bufinfo); - //printf("get buffer %d\n",_mga_priv.bufinfo.id); - if ( _mga_priv.bufinfo.id == -1 ) { - printf( "Got buffer #%d\n", _mga_priv.bufinfo.id ); - frame->vo_frame.displayed (&frame->vo_frame); - return; - } + pthread_mutex_init (&frame->vo_frame.mutex, NULL); - _mga_priv.vid_data = (uint_8 *)(_mga_priv.frame0 + _mga_priv.bufinfo.offset); + /* + * supply required functions + */ - _mga_write_frame_g400(&frame->vo_frame.base[0]); + frame->vo_frame.copy = NULL; + frame->vo_frame.field = syncfb_frame_field; + frame->vo_frame.dispose = syncfb_frame_dispose; - ioctl(_mga_priv.fd,SYNCFB_COMMIT_BUFFER,&_mga_priv.bufinfo); - } - /* Image is copied so release buffer */ - frame->vo_frame.displayed (&frame->vo_frame); + return (vo_frame_t *) frame; } -#if 0 -void draw_logo_xv () { - XClearWindow (gDisplay, gXv.window); - - XCopyArea (gDisplay, gXineLogo, gXv.window, gXv.gc, 0, 0, - gXineLogoWidth, gXineLogoHeight, - (gXv.dest_width - gXineLogoWidth)/2, - (gXv.dest_height - gXineLogoHeight)/2); - - XFlush(gDisplay); -} -#endif +static void syncfb_update_frame_format(vo_driver_t* this_gen, + vo_frame_t* frame_gen, + uint32_t width, uint32_t height, + int ratio_code, int format, int flags) +{ + syncfb_frame_t* frame = (syncfb_frame_t *) frame_gen; + + if((frame->width != width) + || (frame->height != height) + || (frame->format != format)) { + + if(frame->vo_frame.base[0]) { + shmdt(frame->vo_frame.base[0]); + shmctl(frame->id,IPC_RMID,NULL); + frame->vo_frame.base[0] = NULL; + } + + frame->width = width; + frame->height = height; + frame->format = format; + + // we only know how to do 4:2:0 planar yuv right now. + // we prepare for YUY2 sizes + frame->id = shmget(IPC_PRIVATE, frame->width * frame->height * 2, IPC_CREAT | 0777); + + if(frame->id < 0 ) { + printf("video_out_syncfb: aborted. (shared memory error in shmget)\n"); + exit(1); + } + + frame->vo_frame.base[0] = shmat(frame->id, 0, 0); + + if(frame->vo_frame.base[0] == NULL) { + printf("video_out_syncfb: failed. (shared memory error => address error NULL)\n"); + exit(1); + } + + if(frame->vo_frame.base[0] == (void *) -1) { + fprintf(stderr, "syncfb: shared memory error (address error)\n"); + exit (1); + } + + shmctl(frame->id, IPC_RMID, 0); + + frame->vo_frame.base[1] = frame->vo_frame.base[0] + width * height * 5 / 4; + frame->vo_frame.base[2] = frame->vo_frame.base[0] + width * height; + } -void handle_event_mga (XEvent *event) { - switch (event->type) { - case VisibilityNotify: - if (event->xany.window == _window.clasped_window) { - if (event->xvisibility.state == VisibilityFullyObscured) - { - _window.visibility = 0; - - if (_mga_priv.overlay_state == 1) { - if (ioctl(_mga_priv.fd,SYNCFB_OFF)) { - xprintf(VERBOSE|VIDEO,"Error in OFF ioctl\n"); - } - else - _mga_priv.overlay_state = 0; - } - } - else - { - _window.visibility = 1; - - if (_mga_priv.overlay_state == 0 && !_mga_priv.bLogoMode) { - if (ioctl(_mga_priv.fd,SYNCFB_GET_CONFIG,&_mga_priv.mga_vid_config)) - printf("Error in get_config ioctl\n"); - if (ioctl(_mga_priv.fd,SYNCFB_SET_CONFIG,&_mga_priv.mga_vid_config)) - printf("Error in get_config ioctl\n"); - if (ioctl(_mga_priv.fd,SYNCFB_ON)) { - xprintf(VERBOSE|VIDEO,"Error in ON ioctl\n"); - } - else - _mga_priv.overlay_state = 1; - } - } - } - break; - } + frame->ratio_code = ratio_code; } -void set_logo_mode_mga (int bLogoMode) { - if (_mga_priv.bLogoMode == bLogoMode) - return; - - _mga_priv.bLogoMode = bLogoMode; - - if (bLogoMode) { - if (ioctl(_mga_priv.fd,SYNCFB_OFF)) { - xprintf(VERBOSE|VIDEO,"Error in OFF ioctl\n"); - } - else - _mga_priv.overlay_state = 0; - } - else { - if (_window.visibility == 1) { - if (ioctl(_mga_priv.fd,SYNCFB_GET_CONFIG,&_mga_priv.mga_vid_config)) - printf("Error in get_config ioctl\n"); - if (ioctl(_mga_priv.fd,SYNCFB_SET_CONFIG,&_mga_priv.mga_vid_config)) - printf("Error in get_config ioctl\n"); - if (ioctl(_mga_priv.fd,SYNCFB_ON)) { - xprintf(VERBOSE|VIDEO,"Error in ON ioctl\n"); - } - else { - _mga_priv.overlay_state = 1; - } - } - } - -#if 0 - XLOCK - if (bLogoMode) - draw_logo_xv (); - else { /* FIXME : Bad hack to reinstall Xv overlay */ - XUnmapWindow(gDisplay, gXv.window); - XMapRaised(gDisplay, gXv.window); - - /* Spark - * move the window back to 0,0 in case the window manager moved it - * do this only is the window is fullscreen or - * we lose the top and left windowborders - */ - if (gXv.bIsFullscreen) { - XMoveWindow(gDisplay, gXv.window, 0, 0); - } +// FIXME: not yet implemented, being worked on! +/* +static void syncfb_overlay_blend(vo_driver_t* this_gen, vo_frame_t* frame_gen, vo_overlay_t* overlay) +{ + syncfb_frame_t* frame = (syncfb_frame_t *) frame_gen; + if(overlay->rle) { + blend_yuv(frame->XXX, overlay, frame->width, frame->height); } - XUNLOCK -#endif } +*/ +static void syncfb_display_frame(vo_driver_t* this_gen, vo_frame_t* frame_gen) +{ + syncfb_driver_t* this = (syncfb_driver_t *) this_gen; + syncfb_frame_t* frame = (syncfb_frame_t *) frame_gen; -void mga_exit (vo_driver_t *this) { -printf("exit mga\n"); - if (ioctl(_mga_priv.fd,SYNCFB_ON)) { - xprintf(VERBOSE|VIDEO,"Error in ON ioctl\n"); + if((frame->width != this->frame_width) || (frame->height != this->frame_height)) { + this->frame_height = frame->height; + this->frame_width = frame->width; } - if (ioctl(_mga_priv.fd,SYNCFB_OFF)) { - xprintf(VERBOSE|VIDEO,"Error in OFF ioctl\n"); + + if((frame->width != this->delivered_width) + || (frame->height != this->delivered_height) + || (frame->ratio_code != this->delivered_ratio_code) ) { + syncfb_calc_format(this, frame->width, frame->height, frame->ratio_code); } - close(_mga_priv.fd); - _mga_priv.fd = -1; -} + + // the rest is only successful and safe, if the overlay is really on + if(this->overlay_state) { + // FIXME: hardware deinterlacing is not yet activated. + if(this->deinterlace_enabled); + + if(this->bufinfo.id != -1) { + printf("video_out_syncfb: error. (invalid syncfb image buffer state)\n"); + return; + } + if(ioctl(this->fd, SYNCFB_REQUEST_BUFFER, &this->bufinfo)) + printf("video_out_syncfb: error. (request ioctl failed)\n"); + + if(this->bufinfo.id == -1) { + printf("video_out_syncfb: error. (syncfb module couldn't allocate image buffer)\n"); + frame->vo_frame.displayed(&frame->vo_frame); + + return; + } -static uint32_t mga_get_capabilities (vo_driver_t *this) { - return VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CONTRAST | VO_CAP_BRIGHTNESS; + write_frame_sfb(this, frame); + + if(ioctl(this->fd, SYNCFB_COMMIT_BUFFER, &this->bufinfo)) + printf("video_out_syncfb: error. (commit ioctl failed)\n"); + } + + frame->vo_frame.displayed(&frame->vo_frame); + this->bufinfo.id = -1; } -/* - * Properties - */ -static int mga_set_property(vo_driver_t *this, int property, int value) { -printf("set property %d value %d\n",property,value); - switch (property) { - case VO_PROP_CONTRAST: - _mga_priv.cont_current=value; - break; - case VO_PROP_BRIGHTNESS: - _mga_priv.bright_current=value; - break; - case VO_PROP_INTERLACED: - if (value != _mga_priv.interlaced) { - if (value > 1) - value = 0; - _mga_priv.interlaced = value; - _mga_priv.user_ratio_changed = 1; - mga_set_image_format (_mga_priv.image_width, _mga_priv.image_height, _mga_priv.ratio, _mga_priv.fourcc_format); - } - return value; - case VO_PROP_ASPECT_RATIO: - if (value >= NUM_ASPECT_RATIOS) - value = ASPECT_AUTO; - if (value != _mga_priv.user_ratio) { - _mga_priv.user_ratio = value; - _mga_priv.user_ratio_changed = 1; - mga_set_image_format (_mga_priv.image_width, _mga_priv.image_height, _mga_priv.ratio, _mga_priv.fourcc_format); - } - return value; - default: - return value; - } - - _mga_priv.param.contrast = _mga_priv.cont_current; - _mga_priv.param.brightness = _mga_priv.bright_current; - - if (ioctl(_mga_priv.fd,SYNCFB_SET_PARAMS,&_mga_priv.param) == 0) { - return value; - } - return 0; +static int syncfb_get_property(vo_driver_t* this_gen, int property) +{ + syncfb_driver_t* this = (syncfb_driver_t *) this_gen; + + return this->props[property].value; } - -static void mga_get_property_min_max (vo_driver_t *this, int property, int *min, int *max) { - +static int syncfb_set_property(vo_driver_t* this_gen, int property, int value) +{ + syncfb_driver_t* this = (syncfb_driver_t *) this_gen; + switch (property) { - case VO_PROP_CONTRAST: - *min = _mga_priv.cont_min; - *max = _mga_priv.cont_max; - break; - case VO_PROP_BRIGHTNESS: - *min = _mga_priv.bright_min; - *max = _mga_priv.bright_max; - break; - default: - break; - } -} + case VO_PROP_INTERLACED: + this->props[property].value = value; + printf("video_out_syncfb: VO_PROP_INTERLACED(%d)\n", + this->props[property].value); + this->deinterlace_enabled = value; + break; + case VO_PROP_ASPECT_RATIO: + if(value>=NUM_ASPECT_RATIOS) + value = ASPECT_AUTO; -static int mga_get_property (vo_driver_t *this, int property) { + this->props[property].value = value; + printf("video_out_syncfb: VO_PROP_ASPECT_RATIO(%d)\n", + this->props[property].value); - switch (property) { - case VO_PROP_CONTRAST: - return _mga_priv.cont_current; - case VO_PROP_BRIGHTNESS: - return _mga_priv.bright_current; - case VO_PROP_ASPECT_RATIO: - return _mga_priv.user_ratio; - case VO_PROP_INTERLACED: - return _mga_priv.interlaced; - default: - return 0; + syncfb_calc_format(this, this->delivered_width, this->delivered_height, + this->delivered_ratio_code); + break; } -} + return value; +} +static void syncfb_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) +{ + syncfb_driver_t *this = (syncfb_driver_t *) this_gen; -static int mga_gui_data_exchange (vo_driver_t *this, int data_type, void *data) { + *min = this->props[property].min; + *max = this->props[property].max; +} -// xv_driver_t *this = (xv_driver_t *) this_gen; - x11_rectangle_t *area; -printf("gui_data \n"); +static int syncfb_gui_data_exchange (vo_driver_t* this_gen, int data_type, void *data) +{ + syncfb_driver_t* this = (syncfb_driver_t *) this_gen; + x11_rectangle_t* area; switch (data_type) { - case GUI_DATA_EX_DEST_POS_SIZE_CHANGED: - - area = (x11_rectangle_t *) data; -printf("move to %d %d with %d %d\n",area->x,area->y,area->w,area->h); -// xv_adapt_to_output_area (this, area->x, area->y, area->w, area->h); - if (area->w == 1024) - _mga_priv.bFullscreen = 1; - else - _mga_priv.bFullscreen = 0; - if (_mga_priv.fourcc_format) - setup_window_mga(); - - - break; - case GUI_DATA_EX_COMPLETION_EVENT: + case GUI_DATA_EX_DEST_POS_SIZE_CHANGED: { + + area = (x11_rectangle_t *) data; + + syncfb_adapt_to_output_area(this, area->x, area->y, area->w, area->h); + } + break; - /* FIXME : implement */ + // FIXME: consider if this is of use for us... + case GUI_DATA_EX_EXPOSE_EVENT: + break; + case GUI_DATA_EX_DRAWABLE_CHANGED: + this->drawable = (Drawable) data; + this->gc = XCreateGC (this->display, this->drawable, 0, NULL); break; - /* FIXME: implement this - case GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO: - { - x11_rectangle_t *rect = data; - int x1, y1, x2, y2; - xv_translate_gui2video(this, rect->x, rect->y, - &x1, &y1); - xv_translate_gui2video(this, rect->x + rect->w, rect->y + rect->h, - &x2, &y2); - rect->x = x1; - rect->y = y1; - rect->w = x2-x1; - rect->h = y2-y1; - } + // FIXME: does this actually work - or do we have to modify it for SyncFB?! + case GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO: { + int x1, y1, x2, y2; + x11_rectangle_t *rect = data; + + syncfb_translate_gui2video(this, rect->x, rect->y, + &x1, &y1); + syncfb_translate_gui2video(this, rect->x + rect->w, rect->y + rect->h, + &x2, &y2); + rect->x = x1; + rect->y = y1; + rect->w = x2-x1; + rect->h = y2-y1; + } break; - */ default: return -1; @@ -856,129 +756,143 @@ printf("move to %d %d with %d %d\n",area->x,area->y,area->w,area->h); return 0; } +static void syncfb_exit (vo_driver_t* this_gen) +{ + syncfb_driver_t *this = (syncfb_driver_t *) this_gen; -static vo_driver_t vo_mga = { - mga_get_capabilities, - mga_alloc_frame, - mga_update_frame_format, - mga_display_frame, - mga_overlay_blend, - mga_get_property, - mga_set_property, - mga_get_property_min_max, - mga_gui_data_exchange, - mga_exit, -}; - - -/* - * connect to server, create and map window, - * allocate colors and (shared) memory - */ - -vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual) { - -#ifdef CONFIG_DEVFS_FS - char name[]= "/dev/fb/syncfb"; -#else - char name[]= "/dev/syncfb"; -#endif - - - if ((_mga_priv.fd = open ((char *) name, O_RDWR)) < 0) { - xprintf(VERBOSE|VIDEO, "Can't open %s\n", (char *) name); - return NULL; - } - - if (ioctl(_mga_priv.fd,SYNCFB_GET_CAPS,&_mga_priv.caps)) { - xprintf(VERBOSE|VIDEO,"Error in config ioctl"); - close(_mga_priv.fd); - return NULL; - } - - _mga_priv.vid_data = (char*)mmap(0,_mga_priv.caps.memory_size,PROT_WRITE,MAP_SHARED,_mga_priv.fd,0); - - //clear the buffer - // memset(_mga_priv.vid_data,0,1024*768*2); - + // get it off the screen - I wanna see my desktop again :-) + if (ioctl(this->fd, SYNCFB_OFF)) + printf("video_out_syncfb: error. (syncfb on ioctl failed)\n"); + + // don't know if it is necessary are even right, but anyway...?! + munmap(0, this->capabilities.memory_size); + + close(this->fd); +} - _mga_priv.frame0 = _mga_priv.vid_data; +vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) +{ + XWindowAttributes attr; + XColor dummy; + + syncfb_driver_t* this; + x11_visual_t* visual = (x11_visual_t *) visual_gen; + int i = 0; + char* device_name; + + device_name = config->lookup_str(config, "syncfb_device", "/dev/syncfb"); + xine_debug = config->lookup_int(config, "xine_debug", 0); + + if(!(this = malloc (sizeof (syncfb_driver_t)))) { + printf("video_out_syncfb: aborting. (malloc failed)\n"); + return NULL; + } + memset (this, 0, sizeof(syncfb_driver_t)); + + // check for syncfb device + if((this->fd = open(device_name, O_RDWR)) < 0) { + printf("video_out_syncfb: aborting. (unable to open device \"%s\")\n", device_name); + free(this); + return NULL; + } + + // get capabilities from the syncfb module + if(ioctl(this->fd, SYNCFB_GET_CAPS, &this->capabilities)) { + printf("video_out_syncfb: aborting. (syncfb_get_caps ioctl failed)\n"); + + close(this->fd); + free(this); + + return NULL; + } + // mmap whole video memory + this->video_mem = (char *) mmap(0, this->capabilities.memory_size, PROT_WRITE, MAP_SHARED, this->fd, 0); + + // check palette support + if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV420P3)) { + this->palette = VIDEO_PALETTE_YUV420P3; + printf("video_out_syncfb: using palette yuv420p3.\n"); + } else if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV420P2)) { + this->palette = VIDEO_PALETTE_YUV420P2; + printf("video_out_syncfb: using palette yuv420p2.\n"); + } else if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV422)) { + this->palette = VIDEO_PALETTE_YUV422; + printf("video_out_syncfb: using palette yuv422.\n"); + } else { + printf("video_out_syncfb: aborting. (no supported palette found)\n"); + + close(this->fd); + free(this); + + return NULL; + } + XGetWindowAttributes(visual->display, DefaultRootWindow(visual->display), &attr); + + this->bufinfo.id = -1; + this->config = config; + this->display = visual->display; + this->display_ratio = visual->display_ratio; + this->drawable = visual->d; + this->frame_height = 0; + this->frame_width = 0; + this->gc = XCreateGC (this->display, this->drawable, 0, NULL); + this->output_height = 0; + this->output_width = 0; + this->output_xoffset = 0; + this->output_yoffset = 0; + this->overlay = NULL; + this->overlay_state = 0; + this->request_dest_size = visual->request_dest_size; + this->screen = visual->screen; + this->screen_depth = attr.depth; + this->user_data = visual->user_data; + this->virtual_screen_height = attr.height; + this->virtual_screen_width = attr.width; + + XAllocNamedColor(this->display, + DefaultColormap(this->display, this->screen), + "black", &this->black, &dummy); + + this->vo_driver.get_capabilities = syncfb_get_capabilities; + this->vo_driver.alloc_frame = syncfb_alloc_frame; + this->vo_driver.update_frame_format = syncfb_update_frame_format; +// this->vo_driver.overlay_blend = syncfb_overlay_blend; + this->vo_driver.overlay_blend = NULL; // FIXME: support coming soon + this->vo_driver.display_frame = syncfb_display_frame; + this->vo_driver.get_property = syncfb_get_property; + this->vo_driver.set_property = syncfb_set_property; + this->vo_driver.get_property_min_max = syncfb_get_property_min_max; + this->vo_driver.gui_data_exchange = syncfb_gui_data_exchange; + this->vo_driver.exit = syncfb_exit; + + this->deinterlace_enabled = 0; + /* - * init global variables + * init properties */ - - strcpy(_window.title, "Xine syncfb overlay\0"); - _window.visibility = 1; - _mga_priv.lDisplay = XOpenDisplay(":0.0"); /* Xine may run on another Display but syncfb always goes to :0.0 */ -// lDisplay = gDisplay; - - xine_debug = config->lookup_int (config, "xine_debug", 0); - - _mga_priv.gDisplay = (Display *) visual; - _mga_priv.bFullscreen = 0; - _mga_priv.bIsFullscreen = 0; - _mga_priv.image_width = 0; - _mga_priv.image_height = 0; - _mga_priv.ratio = 0; - _mga_priv.bLogoMode = 0; -// _mga_priv.cur_image = NULL; - _mga_priv.user_ratio = ASPECT_AUTO; - _mga_priv.user_ratio_changed = 0 ; - _mga_priv.fourcc_format = 0; - _mga_priv.request_dest_size = ((x11_visual_t*) visual)->request_dest_size; - _mga_priv.user_data = ((x11_visual_t*) visual)->user_data; - - _window.clasped_window = 0; - _display.default_screen = DefaultScreen(_mga_priv.lDisplay); - _mga_priv.cont_min = 0; - _mga_priv.cont_max = 255; - _mga_priv.bright_max = 127; - _mga_priv.bright_min = -128; - - _mga_priv.overlay_state = 1; // 0 = off, 1 = on - - if (ioctl(_mga_priv.fd,SYNCFB_GET_PARAMS,&_mga_priv.param) == 0) { - _mga_priv.cont_current = _mga_priv.param.contrast; - _mga_priv.bright_current = _mga_priv.param.brightness; - } - else { - _mga_priv.cont_current = 0x80; - _mga_priv.bright_current = 0; - xprintf(VERBOSE|VIDEO,"syncfb:Brightness and Contrast control not available, please update your syncfb module"); - printf("syncfb:Brightness and Contrast control not available, please update your syncfb module\n"); - - } - - set_logo_mode_mga(0); - - return &vo_mga; + for(i = 0; i < VO_NUM_PROPERTIES; i++) { + this->props[i].value = 0; + this->props[i].min = 0; + this->props[i].max = 0; + this->props[i].key = NULL; + } + + return &this->vo_driver; } - -static vo_info_t vo_info_mga = { +static vo_info_t vo_info_syncfb = { 2, - "Syncfb", - "xine video output plugin using MGA Teletux (syncfb) video extension", + "SyncFB", + "xine video output plugin using the SyncFB module for Matrox G200/G400 cards", VISUAL_TYPE_X11, 10 }; -vo_info_t *get_video_out_plugin_info() { - return &vo_info_mga; +vo_info_t *get_video_out_plugin_info() +{ + return &vo_info_syncfb; } - - - - -/* #else *//* no MGA */ - -/* vo_functions_t *init_video_out_xv () { */ -/* fprintf (stderr, "Xvideo support not compiled in\n"); */ -/* return NULL; */ -/* } */ - -/* #endif */ /* HAVE_XV */ |