summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_out/Makefile.am2
-rw-r--r--src/video_out/video_out_syncfb.c1504
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 */