summaryrefslogtreecommitdiffstats
path: root/libvo/vo_tdfxfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvo/vo_tdfxfb.c')
-rw-r--r--libvo/vo_tdfxfb.c529
1 files changed, 0 insertions, 529 deletions
diff --git a/libvo/vo_tdfxfb.c b/libvo/vo_tdfxfb.c
deleted file mode 100644
index 6e14f600b7..0000000000
--- a/libvo/vo_tdfxfb.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * copyright (C) 2002 Mark Zealey <mark@zealos.org>
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * 30/03/02: An almost total rewrite, added DR support and support for modes
- * other than 16bpp. Fixed the crash when playing multiple files
- * 07/04/02: Fixed DR support, added YUY2 support, fixed OSD stuff.
- * 08/04/02: Fixed a wierd sound corruption problem caused by some optomizations
- * I made.
- * 09/04/02: Fixed a problem with changing the variables passed to draw_slice().
- * Fixed DR support for YV12 et al. Added BGR support. Removed lots of dud code.
- * 10/04/02: Changed the memcpy functions to mem2agpcpy.. should be a tad
- * faster.
- * 11/04/02: Added a compile option so you can watch the film with the console
- * as the background, or not.
- * 13/04/02: Fix rough OSD stuff by rendering it straight onto the output
- * buffer. Added double-buffering. Supports hardware zoom/reduce zoom modes.
- * 13/04/02: Misc cleanups of the code.
- * 22/10/02: Added geometry support to it
- *
- * Hints and tricks:
- * - Use -dr to get direct rendering
- * - Use -vf yuy2 to get yuy2 rendering, *MUCH* faster than yv12
- * - To get a black background and nice smooth OSD, use -double
- * - To get the console as a background, but with scaled OSD, use -nodouble
- * - The driver supports both scaling and shrinking the image using the -x and
- * -y options on the mplayer commandline. Also repositioning via the -geometry
- * option.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <linux/fb.h>
-
-#include "config.h"
-#include "mp_msg.h"
-#include "fastmemcpy.h"
-#include "video_out.h"
-#include "video_out_internal.h"
-#include "drivers/3dfx.h"
-#include "aspect.h"
-#include "sub/sub.h"
-
-static const vo_info_t info =
-{
- "3Dfx Banshee/Voodoo3/Voodoo5",
- "tdfxfb",
- "Mark Zealey <mark@zealos.org>",
- ""
-};
-
-const LIBVO_EXTERN(tdfxfb)
-
-/* Some registers on the card */
-#define S2S_STRECH_BLT 2 // BLT + Strech
-#define S2S_IMMED (1 << 8) // Do it immediatly
-#define S2S_ROP (0xCC << 24) // ???
-
-/* Stepping between the different YUV plane registers */
-#define YUV_STRIDE 1024
-struct YUV_plane {
- char Y[0x0100000];
- char U[0x0100000];
- char V[0x0100000];
-};
-
-static int fd = -1;
-static struct fb_fix_screeninfo fb_finfo;
-static struct fb_var_screeninfo fb_vinfo;
-static uint32_t in_width, in_height, in_format, in_depth, in_voodoo_format,
- screenwidth, screenheight, screendepth, vidwidth, vidheight, vidx, vidy,
- vid_voodoo_format, *vidpage, *hidpage, *inpage, vidpageoffset,
- hidpageoffset, inpageoffset, *memBase0 = NULL, *memBase1 = NULL, r_width, r_height;
-static volatile voodoo_io_reg *reg_IO;
-static volatile voodoo_2d_reg *reg_2d;
-static voodoo_yuv_reg *reg_YUV;
-static struct YUV_plane *YUV;
-static void (*alpha_func)(), (*alpha_func_double)();
-
-static int preinit(const char *arg)
-{
- char *name;
-
- if(arg)
- name = (char*)arg;
- else if(!(name = getenv("FRAMEBUFFER")))
- name = "/dev/fb0";
-
- if((fd = open(name, O_RDWR)) == -1) {
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] Can't open %s: %s.\n", name, strerror(errno));
- return -1;
- }
-
- if(ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] Problem with FBITGET_FSCREENINFO ioctl: %s.\n",
- strerror(errno));
- close(fd);
- fd = -1;
- return -1;
- }
-
- if(ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] Problem with FBITGET_VSCREENINFO ioctl: %s.\n",
- strerror(errno));
- close(fd);
- fd = -1;
- return -1;
- }
-
- /* BANSHEE means any of the series aparently */
- if (fb_finfo.accel != FB_ACCEL_3DFX_BANSHEE) {
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] This driver only supports the 3Dfx Banshee, Voodoo3 and Voodoo 5.\n");
- close(fd);
- fd = -1;
- return -1;
- }
-
- // Check the depth now as config() musn't fail
- switch(fb_vinfo.bits_per_pixel) {
- case 16:
- case 24:
- case 32:
- break; // Ok
- default:
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] %d bpp output is not supported.\n", fb_vinfo.bits_per_pixel);
- close(fd);
- fd = -1;
- return -1;
- }
-
- /* Open up a window to the hardware */
- memBase1 = mmap(0, fb_finfo.smem_len, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
- memBase0 = mmap(0, fb_finfo.mmio_len, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, fb_finfo.smem_len);
-
- if((long)memBase0 == -1 || (long)memBase1 == -1) {
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] Couldn't map memory areas: %s.\n", strerror(errno));
- if((long)memBase0 != -1)
- munmap(memBase0, fb_finfo.smem_len);
- if((long)memBase1 != -1)
- munmap(memBase1, fb_finfo.smem_len);
- memBase0 = memBase1 = NULL;
- return -1;
- }
-
- /* Set up global pointers to the voodoo's regs */
- reg_IO = (void *)memBase0 + VOODOO_IO_REG_OFFSET;
- reg_2d = (void *)memBase0 + VOODOO_2D_REG_OFFSET;
- reg_YUV = (void *)memBase0 + VOODOO_YUV_REG_OFFSET;
- YUV = (void *)memBase0 + VOODOO_YUV_PLANE_OFFSET;
-
- return 0;
-}
-
-static void uninit(void)
-{
- if(reg_IO) {
- /* Restore the screen (Linux lives at 0) */
- reg_IO->vidDesktopStartAddr = 0;
- reg_IO = NULL;
- }
-
- /* And close our mess */
- if(memBase1) {
- munmap(memBase1, fb_finfo.smem_len);
- memBase1 = NULL;
- }
-
- if(memBase0) {
- munmap(memBase0, fb_finfo.mmio_len);
- memBase0 = NULL;
- }
-
- if(fd != -1) {
- close(fd);
- fd = -1;
- }
-}
-
-static void clear_screen(void)
-{
- /* There needs to be some sort of delay here or else things seriously
- * screw up. Causes the image to not be the right size on screen if
- * this isn't like this. A printf before the memset call also seems to
- * work, but this made more sense since it actually checks the status of
- * the card.
- */
- if(vo_doublebuffering) {
- /* first wait for the card to be ready, do not try to write
- * every time - alex */
- do {} while((reg_IO->status & 0x1f) < 1);
- memset(vidpage, 0, screenwidth * screenheight * screendepth);
- memset(hidpage, 0, screenwidth * screenheight * screendepth);
- }
-}
-
-/* Setup output screen dimensions etc */
-static void setup_screen(uint32_t full)
-{
- aspect(&vidwidth, &vidheight, full ? A_ZOOM : A_NOZOOM);
-
- geometry(&vidx, &vidy, &vidwidth, &vidheight, screenwidth, screenheight);
- vo_fs = full;
- clear_screen();
-}
-
-static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height,
- uint32_t flags, char *title, uint32_t format)
-{
- screenwidth = fb_vinfo.xres;
- screenheight = fb_vinfo.yres;
- aspect_save_screenres(fb_vinfo.xres,fb_vinfo.yres);
-
- in_width = width;
- in_height = height;
- in_format = format;
- aspect_save_orig(width,height);
-
- r_width = d_width;
- r_height = d_height;
- aspect_save_prescale(d_width,d_height);
-
- /* Setup the screen for rendering to */
- switch(fb_vinfo.bits_per_pixel) {
- case 16:
- screendepth = 2;
- vid_voodoo_format = VOODOO_BLT_FORMAT_16;
- alpha_func_double = vo_draw_alpha_rgb16;
- break;
-
- case 24:
- screendepth = 3;
- vid_voodoo_format = VOODOO_BLT_FORMAT_24;
- alpha_func_double = vo_draw_alpha_rgb24;
- break;
-
- case 32:
- screendepth = 4;
- vid_voodoo_format = VOODOO_BLT_FORMAT_32;
- alpha_func_double = vo_draw_alpha_rgb32;
- break;
-
- default:
- mp_tmsg(MSGT_VO, MSGL_ERR, "[VO_TDFXFB] %d bpp output is not supported (This should never have happened).\n", fb_vinfo.bits_per_pixel);
- return -1;
- }
-
- vid_voodoo_format |= screenwidth * screendepth;
-
- /* Some defaults here */
- in_voodoo_format = VOODOO_BLT_FORMAT_YUYV;
- in_depth = 2;
- alpha_func = vo_draw_alpha_yuy2;
-
- switch(in_format) {
- case IMGFMT_YV12:
- case IMGFMT_I420:
- case IMGFMT_IYUV:
- case IMGFMT_YUY2:
- break;
- case IMGFMT_UYVY:
- in_voodoo_format = VOODOO_BLT_FORMAT_UYVY;
- break;
- case IMGFMT_BGR16:
- in_voodoo_format = VOODOO_BLT_FORMAT_16;
- alpha_func = vo_draw_alpha_rgb16;
- break;
-
- case IMGFMT_BGR24:
- in_depth = 3;
- in_voodoo_format = VOODOO_BLT_FORMAT_24;
- alpha_func = vo_draw_alpha_rgb24;
- break;
-
- case IMGFMT_BGR32:
- in_depth = 4;
- in_voodoo_format = VOODOO_BLT_FORMAT_32;
- alpha_func = vo_draw_alpha_rgb32;
- break;
-
- default:
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] Eik! Something's wrong with control().\n");
- return -1;
- }
-
- in_voodoo_format |= in_width * in_depth;
-
- /* Linux lives in the first frame */
- if(vo_doublebuffering) {
- vidpageoffset = screenwidth * screenheight * screendepth;
- hidpageoffset = vidpageoffset + screenwidth * screenheight * screendepth;
- } else
- vidpageoffset = hidpageoffset = 0; /* Console background */
-
-
- inpageoffset = hidpageoffset + screenwidth * screenheight * screendepth;
-
- if(inpageoffset + in_width * in_depth * in_height > fb_finfo.smem_len) {
- mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_TDFXFB] Not enough video memory to play this movie. Try at a lower resolution.\n");
- return -1;
- }
-
- vidpage = (void *)memBase1 + (unsigned long)vidpageoffset;
- hidpage = (void *)memBase1 + (unsigned long)hidpageoffset;
- inpage = (void *)memBase1 + (unsigned long)inpageoffset;
-
- setup_screen(flags & VOFLAG_FULLSCREEN);
-
- memset(inpage, 0, in_width * in_height * in_depth);
-
- mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_TDFXFB] Screen is %dx%d at %d bpp, in is %dx%d at %d bpp, norm is %dx%d.\n",
- screenwidth, screenheight, screendepth * 8,
- in_width, in_height, in_depth * 8,
- d_width, d_height);
-
- return 0;
-}
-
-/* Double-buffering draw_alpha */
-static void draw_alpha_double(int x, int y, int w, int h, unsigned char *src,
- unsigned char *srca, int stride)
-{
- char *dst = (char *)vidpage + ((y + vidy) * screenwidth + x + vidx) * screendepth;
- alpha_func_double(w, h, src, srca, stride, dst, screenwidth * screendepth);
-}
-
-/* Single-buffering draw_alpha */
-static void draw_alpha(int x, int y, int w, int h, unsigned char *src,
- unsigned char *srca, int stride)
-{
- char *dst = (char *)inpage + (y * in_width + x) * in_depth;
- alpha_func(w, h, src, srca, stride, dst, in_width * in_depth);
-}
-
-static void draw_osd(void)
-{
- if(!vo_doublebuffering)
- vo_draw_text(in_width, in_height, draw_alpha);
-}
-
-/* Render onto the screen */
-static void flip_page(void)
-{
- voodoo_2d_reg regs = *reg_2d; /* Copy the regs */
- int i = 0;
-
- if(vo_doublebuffering) {
- /* Flip to an offscreen buffer for rendering */
- uint32_t t = vidpageoffset;
- void *j = vidpage;
-
- vidpage = hidpage;
- hidpage = j;
- vidpageoffset = hidpageoffset;
- hidpageoffset = t;
- }
-
- reg_2d->commandExtra = 0;
- reg_2d->clip0Min = 0;
- reg_2d->clip0Max = 0xffffffff;
-
- reg_2d->srcBaseAddr = inpageoffset;
- reg_2d->srcXY = 0;
- reg_2d->srcFormat = in_voodoo_format;
- reg_2d->srcSize = XYREG(in_width, in_height);
-
- reg_2d->dstBaseAddr = vidpageoffset;
- reg_2d->dstXY = XYREG(vidx, vidy);
- reg_2d->dstFormat = vid_voodoo_format;
- reg_2d->dstSize = XYREG(vidwidth, vidheight);
- reg_2d->command = S2S_STRECH_BLT | S2S_IMMED | S2S_ROP;
-
- /* Wait for the command to finish (If we don't do this, we get wierd
- * sound corruption... */
- while((reg_IO->status & 0x1f) < 1)
- /* Wait */;
-
- *((volatile uint32_t *)((uint32_t *)reg_IO + COMMAND_3D)) = COMMAND_3D_NOP;
-
- while(i < 3)
- if(!(reg_IO->status & STATUS_BUSY))
- i++;
-
- /* Restore the old regs now */
- reg_2d->commandExtra = regs.commandExtra;
- reg_2d->clip0Min = regs.clip0Min;
- reg_2d->clip0Max = regs.clip0Max;
-
- reg_2d->srcBaseAddr = regs.srcBaseAddr;
- reg_2d->srcXY = regs.srcXY;
- reg_2d->srcFormat = regs.srcFormat;
- reg_2d->srcSize = regs.srcSize;
-
- reg_2d->dstBaseAddr = regs.dstBaseAddr;
- reg_2d->dstXY = regs.dstXY;
- reg_2d->dstFormat = regs.dstFormat;
- reg_2d->dstSize = regs.dstSize;
-
- reg_2d->command = 0;
-
- /* Render any text onto this buffer */
- if(vo_doublebuffering)
- vo_draw_text(vidwidth, vidheight, draw_alpha_double);
-
- /* And flip to the new buffer! */
- reg_IO->vidDesktopStartAddr = vidpageoffset;
-}
-
-static int draw_frame(uint8_t *src[])
-{
- mem2agpcpy(inpage, src[0], in_width * in_depth * in_height);
- return 0;
-}
-
-static int draw_slice(uint8_t *i[], int s[], int w, int h, int x, int y)
-{
- /* We want to render to the YUV to the input page + the location
- * of the stripes we're doing */
- reg_YUV->yuvBaseAddr = inpageoffset + in_width * in_depth * y + x;
- reg_YUV->yuvStride = in_width * in_depth;
-
- /* Put the YUV channels into the voodoos internal combiner unit
- * thingie */
- mem2agpcpy_pic(YUV->Y, i[0], s[0], h , YUV_STRIDE, s[0]);
- mem2agpcpy_pic(YUV->U, i[1], s[1], h / 2, YUV_STRIDE, s[1]);
- mem2agpcpy_pic(YUV->V, i[2], s[2], h / 2, YUV_STRIDE, s[2]);
- return 0;
-}
-
-/* Attempt to start doing DR */
-static uint32_t get_image(mp_image_t *mpi)
-{
-
- if(mpi->flags & MP_IMGFLAG_READABLE)
- return VO_FALSE;
- if(mpi->type == MP_IMGTYPE_STATIC && vo_doublebuffering)
- return VO_FALSE;
- if(mpi->type > MP_IMGTYPE_TEMP)
- return VO_FALSE; // TODO ??
-
- switch(in_format) {
- case IMGFMT_YUY2:
- case IMGFMT_BGR16:
- case IMGFMT_BGR24:
- case IMGFMT_BGR32:
- case IMGFMT_UYVY:
- mpi->planes[0] = (char *)inpage;
- mpi->stride[0] = in_width * in_depth;
- break;
-
- case IMGFMT_YV12:
- case IMGFMT_I420:
- case IMGFMT_IYUV:
- if(!(mpi->flags & MP_IMGFLAG_ACCEPT_STRIDE) && mpi->w != YUV_STRIDE)
- return VO_FALSE;
- mpi->planes[0] = YUV->Y;
- mpi->planes[1] = YUV->U;
- mpi->planes[2] = YUV->V;
- mpi->stride[0] = mpi->stride[1] = mpi->stride[2] = YUV_STRIDE;
- reg_YUV->yuvBaseAddr = inpageoffset;
- reg_YUV->yuvStride = in_width * in_depth;
- break;
-
- default:
- return VO_FALSE;
- }
-
- mpi->width = in_width;
- mpi->flags |= MP_IMGFLAG_DIRECT;
-
- return VO_TRUE;
-}
-
-static int control(uint32_t request, void *data)
-{
- switch(request) {
- case VOCTRL_GET_IMAGE:
- return get_image(data);
-
- case VOCTRL_QUERY_FORMAT:
- switch(*((uint32_t*)data)) {
- case IMGFMT_YV12:
- case IMGFMT_I420:
- case IMGFMT_IYUV:
- case IMGFMT_YUY2:
- case IMGFMT_UYVY:
- case IMGFMT_BGR16:
- case IMGFMT_BGR24:
- case IMGFMT_BGR32:
- return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
- VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
- }
-
- return 0; /* Not supported */
-
- case VOCTRL_FULLSCREEN:
- setup_screen(!vo_fs);
- return 0;
- }
-
- return VO_NOTIMPL;
-}
-
-/* Dummy funcs */
-static void check_events(void) {}