summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--acconfig.h5
-rw-r--r--configure.in24
-rw-r--r--src/video_out/Makefile.am10
-rw-r--r--src/video_out/video_out_pgx64.c731
4 files changed, 768 insertions, 2 deletions
diff --git a/acconfig.h b/acconfig.h
index f9e7d654a..815993ca4 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -21,9 +21,12 @@
/* Define this if you're running PowerPC architecture */
#undef ARCH_PPC
-/* Define this if you have the Motorola 74xx CPU */
+/* Define this if you have a Motorola 74xx CPU */
#undef ENABLE_ALTIVEC
+/* Define this if you have Sun UltraSPARC CPU */
+#undef ENABLE_VIS
+
/* Define this if you're running Sparc architecture */
#undef __sparc__
diff --git a/configure.in b/configure.in
index 1f7d64d5e..2174a5e6c 100644
--- a/configure.in
+++ b/configure.in
@@ -207,6 +207,9 @@ LIBFFMPEG_CFLAGS="-DSIMPLE_IDCT -DHAVE_AV_CONFIG_H"
AC_ARG_ENABLE(altivec, [ --disable-altivec use assembly codes for Motorola 74xx CPUs],
enable_altivec=no, enable_altivec=yes)
+AC_ARG_ENABLE(vis, [ --enable-vis use assembly codes for Sun UltraSPARC cpus],
+ enable_vis=yes, enable_vis=no)
+
if test x$enable_mlib = x; then
AC_ARG_ENABLE(mlib,
[ --disable-mlib make a version not using mediaLib],
@@ -392,6 +395,12 @@ AM_PATH_AALIB(1.2,, AC_MSG_RESULT([*** All of AALIB dependent parts will be disa
AM_CONDITIONAL(HAVE_AA, test x$no_aalib != "xyes")
dnl
+dnl Check solaris framebuffer device support
+dnl
+AC_CHECK_HEADER(sys/fbio.h, ac_have_sunfb=yes,)
+AM_CONDITIONAL(HAVE_SUNFB, [test x"$ac_have_sunfb" = "xyes"])
+
+dnl
dnl Check linux framebuffer device support
dnl
AC_CHECK_HEADER(linux/fb.h, have_fb=yes,)
@@ -809,6 +818,12 @@ case "$host_or_hostalias" in
sparc-*) cpu_cflags="-mcpu=supersparc -mtune=supersparc" ;;
sparc64-*) cpu_cflags="-mcpu=supersparc -mtune=ultrasparc" ;;
esac
+
+ if test x$enable_vis = xyes; then
+ AC_DEFINE(ENABLE_VIS)
+ cpu_cflags="-mcpu=ultrasparc"
+ fi
+
CFLAGS="$CFLAGS -O3 $cpu_cflags -funroll-loops -funroll-all-loops -finline-functions"
DEBUG_CFLAGS="$DEBUG_CFLAGS -O $cpu_cflags -funroll-loops -funroll-all-loops -finline-functions"
@@ -823,6 +838,12 @@ case "$host_or_hostalias" in
sun4u) cpu_cflags="-mcpu=supersparc -mtune=ultrasparc" ;;
*) cpu_cflags= ;;
esac
+
+ if test x$enable_vis = xyes; then
+ AC_DEFINE(ENABLE_VIS)
+ cpu_cflags="-mcpu=ultrasparc"
+ fi
+
cc_optimize_cflags="-O3 $cpu_cflags -funroll-loops -funroll-all-loops -finline-functions"
cc_debug_cflags="-O $cpu_cflags -funroll-loops -funroll-all-loops -finline-functions"
AC_DEFINE(FPM_SPARC) dnl uses gnu c asm extensions
@@ -1197,6 +1218,9 @@ if test x"$no_x" != "xyes"; then
x$ac_have_opengl = "xyes" -a x$ac_have_glu="xyes"; then
echo " - OpenGL"
fi
+ if test x$ac_have_sunfb = "xyes"; then
+ echo " - PGX64 (for Sun PGX64/PGX24 cards)"
+ fi
fi
if test x$no_aalib != "xyes"; then
echo " - aa (Ascii ART)"
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am
index 4066bf549..b11d808c8 100644
--- a/src/video_out/Makefile.am
+++ b/src/video_out/Makefile.am
@@ -21,6 +21,9 @@ endif
if HAVE_OPENGL
opengl_module = xineplug_vo_out_opengl.la
endif
+if HAVE_SUNFB
+pgx64_module = xineplug_vo_out_pgx64.la
+endif
endif
if HAVE_AA
@@ -47,7 +50,8 @@ endif
# "xineplug_vo_out_*"
lib_LTLIBRARIES = $(xshm_module) $(xv_module) $(directfb_module) $(aa_module) \
- $(syncfb_module) $(fb_module) $(opengl_module) $(sdl_module) $(vidix_module)
+ $(syncfb_module) $(fb_module) $(opengl_module) \
+ $(sdl_module) $(vidix_module) $(pgx64_module)
xineplug_vo_out_xv_la_SOURCES = deinterlace.c alphablend.c video_out_xv.c
xineplug_vo_out_xv_la_LIBADD = $(XV_LIB) $(X_LIBS) -lXext \
@@ -91,6 +95,10 @@ xineplug_vo_out_vidix_la_SOURCES = alphablend.c video_out_vidix.c
xineplug_vo_out_vidix_la_LIBADD = $(X_LIBS) $(top_builddir)/src/video_out/vidix/libvidix.la
xineplug_vo_out_vidix_la_LDFLAGS = -avoid-version -module
+xineplug_vo_out_pgx64_la_SOURCES = video_out_pgx64.c
+xineplug_vo_out_pgx64_la_LIBADD = $(X_LIBS)
+xineplug_vo_out_pgx64_la_LDFLAGS = -avoid-version -module
+
noinst_HEADERS = yuv2rgb.h video_out_syncfb.h alphablend.h deinterlace.h
include_HEADERS = video_out_x11.h
diff --git a/src/video_out/video_out_pgx64.c b/src/video_out/video_out_pgx64.c
new file mode 100644
index 000000000..a8e2aa600
--- /dev/null
+++ b/src/video_out/video_out_pgx64.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) 2000-2002 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
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * 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_pgx64.c,v 1.1 2002/08/16 14:56:42 komadori Exp $
+ *
+ * video_out_pgx64.c, Sun PGX64/PGX24 output plugin for xine
+ *
+ * written and currently maintained by Robin Kay <komadori@myrealbox.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/fbio.h>
+#include <sys/mman.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "video_out.h"
+#include "video_out_x11.h"
+#include "xine_internal.h"
+#include "xineutils.h"
+
+#define ADDRSPACE 8388608
+#define REGBASE 8386560
+
+#define BUS_CNTL 0x128
+#define BUS_EXT_REG_EN 0x08000000
+#define FIFO_STAT 0x1C4
+
+#define OVERLAY_SCALE_INC 0x008
+#define SCALER_HEIGHT_WIDTH 0x00A
+#define OVERLAY_GRAPHICS_KEY_CLR 0x004
+#define OVERLAY_GRAPHICS_KEY_MSK 0x005
+#define OVERLAY_KEY_CNTL 0x006
+#define SCALER_COLOUR_CNTL 0x054
+
+#define SCALER_H_COEFF0 0x055
+#define SCALER_H_COEFF0_DEFAULT 0x00002000
+#define SCALER_H_COEFF1 0x056
+#define SCALER_H_COEFF1_DEFAULT 0x0D06200D
+#define SCALER_H_COEFF2 0x057
+#define SCALER_H_COEFF2_DEFAULT 0x0D0A1C0D
+#define SCALER_H_COEFF3 0x058
+#define SCALER_H_COEFF3_DEFAULT 0x0C0E1A0C
+#define SCALER_H_COEFF4 0x059
+#define SCALER_H_COEFF4_DEFAULT 0x0C14140C
+
+#define SCALER_BUF0_OFFSET 0x00D
+#define SCALER_BUF0_OFFSET_U 0x075
+#define SCALER_BUF0_OFFSET_V 0x076
+#define SCALER_BUF_PITCH 0x00F
+#define VIDEO_FORMAT 0x012
+#define VIDEO_FORMAT_YUV12 0x000A0000
+#define VIDEO_FORMAT_YUY2 0x000B0000
+#define CAPTURE_CONFIG 0x014
+
+#define OVERLAY_X_Y_START 0x000
+#define OVERLAY_X_Y_END 0x001
+#define OVERLAY_X_Y_LOCK 0x80000000
+#define OVERLAY_SCALE_CNTL 0x009
+#define OVERLAY_EN 0xC0000000
+
+#define DEINTERLACE_ONEFIELD 0
+#define DEINTERLACE_LINEARBLEND 1
+#define DEINTERLACE_LINEARBLEND_VIS 2
+
+static char *deinterlace_methods[] = {"one field",
+ "linear blend",
+#ifdef ENABLE_VIS
+ "linear blend (VIS)",
+#endif
+ NULL};
+
+typedef struct {
+ vo_driver_t vo_driver;
+ config_values_t *config;
+ Display *display;
+ int screen;
+ Window root;
+ Drawable drawable;
+ GC gc;
+ void *user_data;
+ void (*frame_output_cb) (void *user_data, int video_width, int video_height, int *dest_x, int *dest_y, int *dest_width, int *dest_height, int *win_x, int *win_y);
+
+ int fbfd;
+ void *fbbase;
+ volatile uint32_t *fbregs;
+ uint32_t top, buf_y, buf_u, buf_v;
+
+ int colour_key, brightness, saturation, ratio_property;
+ int force_update, deinterlace, deinterlace_method;
+ double frame_ratio, image_ratio, unscale_x, unscale_y;
+ int dest_x, dest_y, old_dest_x, old_dest_y;
+ int dest_width, dest_height, old_dest_width, old_dest_height;
+ int win_x, win_y, old_win_x, old_win_y;
+ int display_width, display_height, display_xoffset, display_yoffset;
+ int correct_width, correct_height;
+} pgx64_driver_t;
+
+typedef struct {
+ vo_frame_t vo_frame;
+
+ int lengths[3];
+ int width, height, ratio_code, format;
+} pgx64_frame_t;
+
+/*
+ * Dispose of any allocated image data within a pgx64_frame_t
+ */
+
+static void dispose_frame_internals(pgx64_frame_t *frame)
+{
+ if (frame->vo_frame.base[0]) {
+ free(frame->vo_frame.base[0]);
+ frame->vo_frame.base[0] = NULL;
+ }
+ if (frame->vo_frame.base[1]) {
+ free(frame->vo_frame.base[1]);
+ frame->vo_frame.base[1] = NULL;
+ }
+ if (frame->vo_frame.base[2]) {
+ free(frame->vo_frame.base[2]);
+ frame->vo_frame.base[2] = NULL;
+ }
+}
+
+/*
+ * Swap the byte order of a 32 bit word
+ */
+
+static inline uint32_t swap_uint32(uint32_t value)
+{
+#ifdef WORDS_BIGENDIAN
+ return ((((value) & 0xff000000) >> 24) |
+ (((value) & 0x00ff0000) >> 8) |
+ (((value) & 0x0000ff00) << 8) |
+ (((value) & 0x000000ff) << 24));
+#else
+ return value;
+#endif
+}
+
+/*
+ * Read and write to the little endian framebuffer registers
+ */
+
+static inline uint32_t read_reg(pgx64_driver_t *this, int reg)
+{
+ return swap_uint32(this->fbregs[reg]);
+}
+
+static inline void write_reg(pgx64_driver_t *this, int reg, uint32_t value)
+{
+ this->fbregs[reg] = swap_uint32(value);
+}
+
+static inline void set_reg_bits(pgx64_driver_t *this, int reg, uint32_t mask)
+{
+ this->fbregs[reg] |= swap_uint32(mask);
+}
+
+static inline void clear_reg_bits(pgx64_driver_t *this, int reg, uint32_t mask)
+{
+ this->fbregs[reg] &= swap_uint32(~mask);
+}
+
+/*
+ * Read and write to the graphics status register of VIS(TM) capable processors
+ */
+
+#ifdef ENABLE_VIS
+static inline uint32_t read_gsr()
+{
+ uint32_t gsr;
+ asm ("rd %%gsr, %0" : "=r" (gsr));
+ return gsr;
+}
+
+static inline void write_gsr(uint32_t gsr)
+{
+ asm ("wr %0, %%g0, %%gsr" : : "r" (gsr));
+}
+#endif
+
+/*
+ * !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT!
+ * All the following functions are defined by the xine video_out API
+ * !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT! !IMPORTANT!
+ */
+
+static void pgx64_config_changed(pgx64_driver_t *this, cfg_entry_t *entry)
+{
+ if (strcmp(entry->key, "video.pgx64_colour_key") == 0) {
+ this->colour_key = entry->num_value;
+ this->force_update = -1;
+ } else if (strcmp(entry->key, "video.pgx64_brightness") == 0) {
+ this->brightness = entry->num_value;
+ write_reg(this, SCALER_COLOUR_CNTL, (this->saturation<<16) | (this->saturation<<8) | (this->brightness&0x7F));
+ } else if (strcmp(entry->key, "video.pgx64_saturation") == 0) {
+ this->saturation = entry->num_value;
+ write_reg(this, SCALER_COLOUR_CNTL, (this->saturation<<16) | (this->saturation<<8) | (this->brightness&0x7F));
+ } else if (strcmp(entry->key, "video.pgx64_deinterlace_method") == 0) {
+ this->deinterlace_method = entry->num_value;
+ this->force_update = -1;
+ }
+}
+
+static void pgx64_frame_field(pgx64_frame_t *frame, int which_field)
+{
+}
+
+static void pgx64_frame_dispose(pgx64_frame_t *frame)
+{
+ dispose_frame_internals(frame);
+ free(frame);
+}
+
+static uint32_t pgx64_get_capabilities(pgx64_driver_t *this)
+{
+ return VO_CAP_YV12 |
+ VO_CAP_YUY2 |
+ VO_CAP_COLORKEY |
+ VO_CAP_SATURATION |
+ VO_CAP_BRIGHTNESS;
+}
+
+static pgx64_frame_t* pgx64_alloc_frame(pgx64_driver_t *this)
+{
+ pgx64_frame_t *frame;
+
+ frame = (pgx64_frame_t*)malloc(sizeof(pgx64_frame_t));
+ if (!frame) {
+ printf("video_out_pgx64: frame malloc failed\n");
+ return NULL;
+ }
+ memset(frame, 0, sizeof(pgx64_frame_t));
+
+ pthread_mutex_init(&frame->vo_frame.mutex, NULL);
+
+ frame->vo_frame.field = (void*)pgx64_frame_field;
+ frame->vo_frame.dispose = (void*)pgx64_frame_dispose;
+
+ return frame;
+}
+
+static void pgx64_update_frame_format(pgx64_driver_t *this, pgx64_frame_t *frame, uint32_t width, uint32_t height, int ratio_code, int format, int flags)
+{
+ if ((width != frame->width) ||
+ (height != frame->height) ||
+ (ratio_code != frame->ratio_code) ||
+ (format != frame->format)) {
+ dispose_frame_internals(frame);
+
+ switch (format) {
+ case IMGFMT_YUY2:
+ frame->vo_frame.pitches[0] = width * 2;
+ frame->lengths[0] = frame->vo_frame.pitches[0] * height;
+ frame->vo_frame.base[0] = (void*)memalign(8, frame->lengths[0]);
+ this->buf_y = (this->top - frame->lengths[0]) & ~0x07;
+ break;
+
+ case IMGFMT_YV12:
+ frame->vo_frame.pitches[0] = width;
+ frame->vo_frame.pitches[1] = width / 2;
+ frame->vo_frame.pitches[2] = width / 2;
+ frame->lengths[0] = frame->vo_frame.pitches[0] * height;
+ frame->lengths[1] = frame->vo_frame.pitches[1] * height;
+ frame->lengths[2] = frame->vo_frame.pitches[2] * height;
+ frame->vo_frame.base[0] = (void*)memalign(8, frame->lengths[0]);
+ frame->vo_frame.base[1] = (void*)memalign(8, frame->lengths[1]);
+ frame->vo_frame.base[2] = (void*)memalign(8, frame->lengths[2]);
+ this->buf_y = (this->top - frame->lengths[0]) & ~0x07;
+ this->buf_u = (this->buf_y - frame->lengths[1]) & ~0x07;
+ this->buf_v = (this->buf_u - frame->lengths[2]) & ~0x07;
+ break;
+ }
+
+ this->image_ratio = (double)width / (double)height;
+ switch (ratio_code) {
+ default:
+ case XINE_ASPECT_RATIO_DONT_TOUCH:
+ case XINE_ASPECT_RATIO_SQUARE:
+ this->frame_ratio = this->image_ratio;
+ break;
+ case XINE_ASPECT_RATIO_4_3:
+ this->frame_ratio = 4.0 / 3.0;
+ break;
+ case XINE_ASPECT_RATIO_ANAMORPHIC:
+ this->frame_ratio = 16.0 / 9.0;
+ break;
+ case XINE_ASPECT_RATIO_211_1:
+ this->frame_ratio = 2.11;
+ break;
+ }
+
+ frame->width = width;
+ frame->height = height;
+ frame->ratio_code = ratio_code;
+ frame->format = format;
+ this->force_update = -1;
+ }
+}
+
+static void pgx64_display_frame(pgx64_driver_t *this, pgx64_frame_t *frame)
+{
+ if (this->force_update) {
+ double ratio;
+
+ switch (this->ratio_property) {
+ default:
+ case ASPECT_AUTO:
+ ratio = this->frame_ratio;
+ break;
+ case ASPECT_ANAMORPHIC:
+ ratio = 16.0 / 9.0;
+ break;
+ case ASPECT_FULL:
+ ratio = 4.0 / 3.0;
+ break;
+ case ASPECT_DVB:
+ ratio = 2.0;
+ break;
+ case ASPECT_SQUARE:
+ ratio = this->image_ratio;
+ break;
+ }
+
+ ratio /= this->image_ratio;
+ if (ratio >= 1.0) {
+ this->correct_width = frame->width * ratio;
+ this->correct_height = frame->height;
+ }
+ else {
+ this->correct_width = frame->width;
+ this->correct_height = frame->height / ratio;
+ }
+ }
+
+ this->frame_output_cb(this->user_data, this->correct_width, this->correct_height, &this->dest_x, &this->dest_y, &this->dest_width, &this->dest_height, &this->win_x, &this->win_y);
+
+ if ((this->win_x == 0) ||
+ (this->win_y == 0)) {
+ Window temp_window;
+
+ XLockDisplay(this->display);
+ XTranslateCoordinates(this->display, this->drawable, this->root, 0, 0, &this->win_x, &this->win_y, &temp_window);
+ XUnlockDisplay(this->display);
+ }
+
+ if ((this->force_update) ||
+ (this->old_dest_x != this->dest_x) ||
+ (this->old_dest_y != this->dest_y) ||
+ (this->old_dest_width != this->dest_width) ||
+ (this->old_dest_height != this->dest_height) ||
+ (this->old_win_x != this->win_x) ||
+ (this->old_win_y != this->win_y)) {
+ double scale_fitw, scale_fith;
+
+ this->display_width = this->correct_width;
+ this->display_height = this->correct_height;
+ scale_fitw = (double)this->dest_width / (double)this->display_width;
+ scale_fith = (double)this->dest_height / (double)this->display_height;
+ if (scale_fitw < scale_fith) {
+ this->display_width *= scale_fitw;
+ this->display_height *= scale_fitw;
+ }
+ else {
+ this->display_width *= scale_fith;
+ this->display_height *= scale_fith;
+ }
+ this->display_xoffset = (this->dest_width - this->display_width) / 2 + this->dest_x;
+ this->display_yoffset = (this->dest_height - this->display_height) / 2 + this->dest_y;
+
+ XLockDisplay(this->display);
+ XSetForeground(this->display, this->gc, BlackPixel(this->display, this->screen));
+ XFillRectangle(this->display, this->drawable, this->gc, this->dest_x, this->dest_y, this->display_width, this->display_yoffset - this->dest_y);
+ XFillRectangle(this->display, this->drawable, this->gc, this->dest_x, this->display_yoffset + this->display_height, this->dest_width, this->dest_height - (this->display_yoffset + this->display_height));
+ XFillRectangle(this->display, this->drawable, this->gc, this->dest_x, this->dest_y, this->display_xoffset - this->dest_y, this->display_height);
+ XFillRectangle(this->display, this->drawable, this->gc, this->display_xoffset + this->display_width, this->dest_y, this->dest_width - (this->display_xoffset + this->display_width), this->dest_height);
+ XSetForeground(this->display, this->gc, this->colour_key);
+ XFillRectangle(this->display, this->drawable, this->gc, this->display_xoffset, this->display_yoffset, this->display_width, this->display_height);
+ XFlush(this->display);
+ XUnlockDisplay(this->display);
+
+ write_reg(this, VIDEO_FORMAT, (frame->format == IMGFMT_YUY2) ? VIDEO_FORMAT_YUY2 : VIDEO_FORMAT_YUV12);
+ write_reg(this, SCALER_BUF0_OFFSET, this->buf_y);
+ write_reg(this, SCALER_BUF0_OFFSET_U, this->buf_u);
+ write_reg(this, SCALER_BUF0_OFFSET_V, this->buf_v);
+ write_reg(this, SCALER_BUF_PITCH, this->deinterlace && (this->deinterlace_method == DEINTERLACE_ONEFIELD) ? frame->width*2 : frame->width);
+ write_reg(this, OVERLAY_X_Y_START, ((this->win_x + this->display_xoffset) << 16) | (this->win_y + this->display_yoffset) | OVERLAY_X_Y_LOCK);
+ write_reg(this, OVERLAY_X_Y_END, ((this->win_x + this->display_xoffset + this->display_width) << 16) | (this->win_y + this->display_yoffset + this->display_height));
+ write_reg(this, OVERLAY_GRAPHICS_KEY_CLR, this->colour_key);
+ write_reg(this, OVERLAY_SCALE_INC, (((frame->width << 12) / this->display_width) << 16) | (((this->deinterlace && (this->deinterlace_method == DEINTERLACE_ONEFIELD) ? frame->height/2 : frame->height) << 12) / this->display_height));
+ write_reg(this, SCALER_HEIGHT_WIDTH, (frame->width << 16) | (this->deinterlace && (this->deinterlace_method == DEINTERLACE_ONEFIELD) ? frame->height/2 : frame->height));
+ set_reg_bits(this, OVERLAY_SCALE_CNTL, OVERLAY_EN);
+
+ this->unscale_x = (double)frame->width / (double)this->display_width;
+ this->unscale_y = (double)frame->height / (double)this->display_height;
+
+ this->force_update = 0;
+ this->old_dest_x = this->dest_x;
+ this->old_dest_y = this->dest_y;
+ this->old_dest_width = this->dest_width;
+ this->old_dest_height = this->dest_height;
+ this->old_win_x = this->win_x;
+ this->old_win_y = this->win_y;
+ }
+
+ if (this->deinterlace && (frame->format == IMGFMT_YV12)) {
+ switch (this->deinterlace_method) {
+ case DEINTERLACE_LINEARBLEND: {
+ register uint8_t *p = frame->vo_frame.base[0];
+ register uint8_t *endp = p+(frame->width*(frame->height-2));
+
+ for (;p != endp;p++) {
+ p[0] = (p[0] + p[frame->width]*2 + p[2*frame->width]) >> 2;
+ }
+
+ break;
+ }
+
+#ifdef ENABLE_VIS
+ case DEINTERLACE_LINEARBLEND_VIS: {
+ register uint32_t *p = (uint32_t*)frame->vo_frame.base[0];
+ register uint32_t *endp = p+((frame->width>>2)*(frame->height-2));
+ register uint32_t width = frame->width;
+
+ write_gsr((read_gsr() & 0xffffff07) | 0x000000008);
+
+ for (;p != endp;p++) {
+ asm volatile("ld [%0], %%f0\n\t"
+ "add %0, %1, %%l0\n\t"
+ "fexpand %%f0, %%f6\n\t"
+ "ld [%%l0], %%f2\n\t"
+ "add %%l0, %1, %%l1\n\t"
+ "fexpand %%f2, %%f8\n\t"
+ "ld [%%l1], %%f4\n\t"
+ "fpadd16 %%f6, %%f8, %%f0\n\t"
+ "fexpand %%f4, %%f10\n\t"
+ "fpadd16 %%f0, %%f8, %%f2\n\t"
+ "fpadd16 %%f2, %%f10, %%f4\n\t"
+ "fpack16 %%f4, %%f0\n\t"
+ "st %%f0, [%0]"
+ : : "r" (p), "r" (width)
+ : "%f0", "%f1", "%f2", "%f3", "%f4", "%f5",
+ "%f6", "%f7", "%f8", "%f9", "%f10", "%f11",
+ "%l0", "%l1");
+ }
+
+ break;
+ }
+#endif
+
+ }
+ }
+
+ memcpy(this->fbbase+this->buf_y, frame->vo_frame.base[0], frame->lengths[0]);
+ if (frame->format == IMGFMT_YV12) {
+ memcpy(this->fbbase+this->buf_u, frame->vo_frame.base[1], frame->lengths[1]);
+ memcpy(this->fbbase+this->buf_v, frame->vo_frame.base[2], frame->lengths[2]);
+ }
+
+ frame->vo_frame.displayed(&frame->vo_frame);
+}
+
+static void pgx64_overlay_blend(pgx64_driver_t *this, pgx64_frame_t *frame, vo_overlay_t *overlay)
+{
+}
+
+static int pgx64_get_property(pgx64_driver_t *this, int property)
+{
+ switch (property) {
+ case VO_PROP_INTERLACED:
+ return this->deinterlace;
+ break;
+
+ case VO_PROP_ASPECT_RATIO:
+ return this->ratio_property;
+ break;
+
+ case VO_PROP_SATURATION:
+ return this->saturation;
+ break;
+
+ case VO_PROP_BRIGHTNESS:
+ return this->brightness;
+ break;
+
+ case VO_PROP_COLORKEY:
+ return this->colour_key;
+ break;
+
+ default:
+ return 0;
+ break;
+ }
+}
+
+static int pgx64_set_property(pgx64_driver_t *this, int property, int value)
+{
+ printf("video_out_pgx64: Propery %d was set to 0x%08x\n", property, value);
+
+ switch (property) {
+ case VO_PROP_INTERLACED: {
+ this->deinterlace = value;
+ this->force_update = -1;
+ }
+ break;
+
+ case VO_PROP_ASPECT_RATIO: {
+ if (value >= NUM_ASPECT_RATIOS) {
+ value = ASPECT_AUTO;
+ }
+ this->ratio_property = value;
+ this->force_update = -1; }
+ break;
+
+ case VO_PROP_SATURATION: {
+ this->saturation = value;
+ write_reg(this, SCALER_COLOUR_CNTL, (this->saturation<<16) | (this->saturation<<8) | (this->brightness&0x7F));
+ }
+ break;
+
+ case VO_PROP_BRIGHTNESS: {
+ this->brightness = value;
+ write_reg(this, SCALER_COLOUR_CNTL, (this->saturation<<16) | (this->saturation<<8) | (this->brightness&0x7F));
+ }
+ break;
+
+ case VO_PROP_COLORKEY: {
+ this->colour_key = value;
+ this->force_update = -1;
+ }
+ break;
+ }
+ return value;
+}
+
+static void pgx64_get_property_min_max(pgx64_driver_t *this, int property, int *min, int *max)
+{
+ switch (property) {
+ case VO_PROP_SATURATION: {
+ *min = 0;
+ *max = 31;
+ }
+ break;
+
+ case VO_PROP_BRIGHTNESS: {
+ *min = -64;
+ *max = 63;
+ }
+ break;
+
+ default:
+ *min = 0;
+ *max = 0;
+ break;
+ }
+}
+
+static int pgx64_gui_data_exchange(pgx64_driver_t *this, int data_type, void *data)
+{
+ switch (data_type) {
+ case GUI_DATA_EX_DRAWABLE_CHANGED: {
+ this->drawable = (Drawable)data;
+ XLockDisplay(this->display);
+ this->gc = XCreateGC(this->display, this->drawable, 0, NULL);
+ XUnlockDisplay(this->display);
+ }
+ break;
+
+ case GUI_DATA_EX_EXPOSE_EVENT: {
+ this->force_update = -1;
+ }
+ break;
+
+ case GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO: {
+ x11_rectangle_t *rect = data;
+
+ rect->x = (rect->x - this->display_xoffset) * this->unscale_x;
+ rect->y = (rect->y - this->display_yoffset) * this->unscale_x;
+ rect->w = (rect->w - this->display_xoffset) * this->unscale_y;
+ rect->h = (rect->h - this->display_yoffset) * this->unscale_y;
+ }
+ break;
+
+ case GUI_DATA_EX_VIDEOWIN_VISIBLE: {
+ if (!((int *)data)) {
+ clear_reg_bits(this, OVERLAY_SCALE_CNTL, OVERLAY_EN);
+ }
+ else {
+ set_reg_bits(this, OVERLAY_SCALE_CNTL, OVERLAY_EN);
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int pgx64_redraw_needed(pgx64_driver_t *this)
+{
+ return -1;
+}
+
+static void pgx64_exit(pgx64_driver_t *this)
+{
+ write_reg(this, OVERLAY_SCALE_CNTL, 0);
+ clear_reg_bits(this, BUS_CNTL, BUS_EXT_REG_EN);
+ munmap(this->fbbase, ADDRSPACE);
+ close(this->fbfd);
+}
+
+pgx64_driver_t* init_video_out_plugin(config_values_t *config, void *visual_gen) {
+ pgx64_driver_t *this;
+ char *devname;
+ int fbfd;
+ void *baseaddr;
+ struct fbgattr attr;
+
+ printf("video_out_pgx64: PGX64 video output plugin - By Robin Kay\n");
+
+ devname = config->register_string (config, "video.pgx64_device", "/dev/m640", "name of pgx64 device", NULL, NULL, NULL);
+ if ((fbfd = open(devname, O_RDWR)) < 0) {
+ printf("video_out_pgx64: can't open framebuffer device (%s)\n", devname);
+ return NULL;
+ }
+
+ if (ioctl(fbfd, FBIOGATTR, &attr) < 0) {
+ printf("video_out_pgx64: unable to determine amount of available video memory\n");
+ close(fbfd);
+ return NULL;
+ }
+
+ if ((baseaddr = mmap(baseaddr, ADDRSPACE, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0)) == MAP_FAILED) {
+ printf("video_out_pgx64: unable to memory map framebuffer\n");
+ close(fbfd);
+ return NULL;
+ }
+
+ this = (pgx64_driver_t*)malloc(sizeof(pgx64_driver_t));
+ if (!this) {
+ printf("video_out_pgx64: driver malloc failed\n");
+ return NULL;
+ }
+ memset(this, 0, sizeof(pgx64_driver_t));
+
+ this->vo_driver.get_capabilities = (void*)pgx64_get_capabilities;
+ this->vo_driver.alloc_frame = (void*)pgx64_alloc_frame;
+ this->vo_driver.update_frame_format = (void*)pgx64_update_frame_format;
+ this->vo_driver.overlay_blend = (void*)pgx64_overlay_blend;
+ this->vo_driver.display_frame = (void*)pgx64_display_frame;
+ this->vo_driver.get_property = (void*)pgx64_get_property;
+ this->vo_driver.set_property = (void*)pgx64_set_property;
+ this->vo_driver.get_property_min_max = (void*)pgx64_get_property_min_max;
+ this->vo_driver.gui_data_exchange = (void*)pgx64_gui_data_exchange;
+ this->vo_driver.redraw_needed = (void*)pgx64_redraw_needed;
+ this->vo_driver.exit = (void*)pgx64_exit;
+
+ this->config = config;
+
+ this->display = ((x11_visual_t*)visual_gen)->display;
+ this->screen = ((x11_visual_t*)visual_gen)->screen;
+ this->root = RootWindow(this->display, this->screen);
+ this->drawable = ((x11_visual_t*)visual_gen)->d;
+ this->gc = XCreateGC(this->display, this->drawable, 0, NULL);
+ this->user_data = ((x11_visual_t*)visual_gen)->user_data;
+ this->frame_output_cb = ((x11_visual_t*)visual_gen)->frame_output_cb;
+
+ this->colour_key = config->register_num(config, "video.pgx64_colour_key", 1, "video overlay colour key", NULL, (void*)pgx64_config_changed, this);
+ this->brightness = config->register_range(config, "video.pgx64_brightness", 0, -64, 63, "video overlay brightness", NULL, (void*)pgx64_config_changed, this);
+ this->saturation = config->register_range(config, "video.pgx64_saturation", 16, 0, 31, "video overlay saturation", NULL, (void*)pgx64_config_changed, this);
+ this->deinterlace_method = config->register_enum(config, "video.pgx64_deinterlace_method", 0, deinterlace_methods, "video deinterlacing method", NULL, (void*)pgx64_config_changed, this);
+
+ this->fbfd = fbfd;
+ this->top = attr.sattr.dev_specific[0];
+ this->fbbase = baseaddr;
+ this->fbregs = baseaddr + REGBASE;
+
+ set_reg_bits(this, BUS_CNTL, BUS_EXT_REG_EN);
+ write_reg(this, OVERLAY_SCALE_CNTL, 0x04000000);
+ write_reg(this, SCALER_H_COEFF0, SCALER_H_COEFF0_DEFAULT);
+ write_reg(this, SCALER_H_COEFF1, SCALER_H_COEFF1_DEFAULT);
+ write_reg(this, SCALER_H_COEFF2, SCALER_H_COEFF2_DEFAULT);
+ write_reg(this, SCALER_H_COEFF3, SCALER_H_COEFF3_DEFAULT);
+ write_reg(this, SCALER_H_COEFF4, SCALER_H_COEFF4_DEFAULT);
+ write_reg(this, CAPTURE_CONFIG, 0x00000000);
+ write_reg(this, SCALER_COLOUR_CNTL, (this->saturation<<16) | (this->saturation<<8) | (this->brightness&0x7F));
+ write_reg(this, OVERLAY_KEY_CNTL, 0x00000050);
+ write_reg(this, OVERLAY_GRAPHICS_KEY_MSK, (1 << DefaultDepth(this->display, this->screen)) - 1);
+
+ return this;
+}
+
+static vo_info_t vo_info_pgx64 = {
+ 6,
+ "PGX64",
+ "xine video output plugin for Sun PGX6/PGX24 framebuffers",
+ VISUAL_TYPE_X11,
+ 10
+};
+
+vo_info_t* get_video_out_plugin_info()
+{
+ return &vo_info_pgx64;
+}