# HG changeset patch # User albeu # Date 1047062702 0 # Node ID 8feb4bb5b334a10bd21b49e17fc8128643a99cf8 # Parent d1bbeae9f46a50c167fbf1c5ea57e5c685f2306b vo tdfx vid, even faster than tdfxfb and that's just the beginning ;) diff -r d1bbeae9f46a -r 8feb4bb5b334 configure --- a/configure Fri Mar 07 18:42:08 2003 +0000 +++ b/configure Fri Mar 07 18:45:02 2003 +0000 @@ -218,6 +218,7 @@ --enable-directfb build with DirectFB support [autodetect] --enable-zr build with ZR360[56]7/ZR36060 support [autodetect] --enable-bl build with Blinkenlights support [disable] + --enable-tdfxvid build with tdfx vid support [disable] Audio output: --disable-ossaudio disable OSS sound support [autodetect] @@ -1044,6 +1045,7 @@ _termios=auto _3dfx=no _tdfxfb=no +_tdfxvid=no _directfb=auto _zr=auto _bl=no @@ -1223,6 +1225,8 @@ --enable-3dfx) _3dfx=yes ;; --disable-3dfx) _3dfx=no ;; --enable-tdfxfb) _tdfxfb=yes ;; + --disable-tdfxvid) _tdfxvid=no ;; + --enable-tdfxvid) _tdfxvid=yes ;; --disable-tdfxfb) _tdfxfb=no ;; --enable-directfb) _directfb=yes ;; --disable-directfb) _directfb=no ;; @@ -2343,6 +2347,16 @@ fi echores "$_tdfxfb" +echocheck "tdfxvid" +if test "$_tdfxvid" = yes ; then + _def_tdfxvid='#define HAVE_TDFX_VID 1' + _vosrc="$_vosrc vo_tdfx_vid.c" + _vomodules="tdfx_vid $_vomodules" +else + _def_tdfxvid='#undef HAVE_TDFX_VID' + _novomodules="tdfx_vid $_novomodules" +fi +echores "$_tdfxfb" echocheck "DirectFB headers presence" if test -z "$_inc_directfb" ; then @@ -5471,6 +5485,7 @@ $_def_ggi $_def_3dfx $_def_tdfxfb +$_def_tdfxvid $_def_directfb $_def_directfb_version $_def_zr diff -r d1bbeae9f46a -r 8feb4bb5b334 libvo/video_out.c --- a/libvo/video_out.c Fri Mar 07 18:42:08 2003 +0000 +++ b/libvo/video_out.c Fri Mar 07 18:45:02 2003 +0000 @@ -99,9 +99,15 @@ #ifdef CONFIG_VIDIX extern vo_functions_t video_out_xvidix; #endif +#ifdef HAVE_TDFX_VID +extern vo_functions_t video_out_tdfx_vid; +#endif vo_functions_t* video_out_drivers[] = { +#ifdef HAVE_TDFX_VID + &video_out_tdfx_vid, +#endif #ifdef HAVE_DIRECTX &video_out_directx, #endif diff -r d1bbeae9f46a -r 8feb4bb5b334 libvo/vo_tdfx_vid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libvo/vo_tdfx_vid.c Fri Mar 07 18:45:02 2003 +0000 @@ -0,0 +1,482 @@ +/* + * video_out_null.c + * + * Copyright (C) Aaron Holtzman - June 2000 + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * + * mpeg2dec 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, or (at your option) + * any later version. + * + * mpeg2dec 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "video_out.h" +#include "video_out_internal.h" +#include "aspect.h" + +#include "fastmemcpy.h" +#include "drivers/tdfx_vid.h" + + +static vo_info_t info = +{ + "tdfx_vid video output", + "tdfx_vid", + "Albeu", + "" +}; + +LIBVO_EXTERN(tdfx_vid) + +static tdfx_vid_config_t tdfx_cfg; + +static unsigned char* agp_mem = NULL; +static int tdfx_fd = -1; + +static uint32_t img_fmt; // The real input format +static uint32_t src_width, src_height, src_fmt, src_bpp, src_stride; +static uint32_t dst_width, dst_height, dst_fmt, dst_bpp, dst_stride; + +static uint32_t tdfx_page; +static uint32_t front_buffer; +static uint32_t back_buffer; + + +static uint32_t draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y) +{ + tdfx_vid_agp_move_t mov; + tdfx_vid_yuv_t yuv; + int p; + uint8_t* ptr[3]; + + switch(img_fmt) { + case IMGFMT_YUY2: + case IMGFMT_UYVY: + case IMGFMT_BGR8: + case IMGFMT_BGR16: + case IMGFMT_BGR24: + case IMGFMT_BGR32: + // copy :( to agp_mem + // still faster than tdfxfb wich directly copy to the video mem :) + memcpy_pic(agp_mem,image[0],src_bpp*w,h,stride[0],stride[0]); + + mov.move2 = TDFX_VID_MOVE_2_PACKED; + mov.width = w*src_bpp; + mov.height = h; + mov.src = 0; + mov.src_stride = stride[0]; + + mov.dst = back_buffer + y*src_stride + x * src_bpp; + mov.dst_stride = src_stride; + + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed\n"); + return 1; + } + break; + case IMGFMT_YV12: + case IMGFMT_I420: + // Copy to agp mem + ptr[0] = agp_mem; + memcpy_pic(ptr[0],image[0],w,h,stride[0],stride[0]); + ptr[1] = ptr[0] + (h*stride[0]); + memcpy_pic(ptr[1],image[1],w/2,h/2,stride[1],stride[1]); + ptr[2] = ptr[1] + (h/2*stride[1]); + memcpy_pic(ptr[2],image[2],w/2,h/2,stride[2],stride[2]); + + // Setup the yuv thing + yuv.base = back_buffer + y*src_stride + x * src_bpp; + yuv.stride = src_stride; + if(ioctl(tdfx_fd,TDFX_VID_SET_YUV,&yuv)) { + printf("tdfx_vid: Set yuv failed\n"); + return 1; + } + + // Now agp move that + // Y + mov.move2 = TDFX_VID_MOVE_2_YUV; + mov.width = w; + mov.height = h; + mov.src = ptr[0] - agp_mem; + mov.src_stride = stride[0]; + mov.dst = 0x0; + mov.dst_stride = TDFX_VID_YUV_STRIDE; + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed on Y plane\n"); + return 1; + } + //return 0; + // U + p = img_fmt == IMGFMT_YV12 ? 1 : 2; + mov.width = w/2; + mov.height = h/2; + mov.src = ptr[p] - agp_mem; + mov.src_stride = stride[p]; + mov.dst += TDFX_VID_YUV_PLANE_SIZE; + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed on U plane\n"); + return 1; + } + // V + p = img_fmt == IMGFMT_YV12 ? 2 : 1; + mov.src = ptr[p] - agp_mem; + mov.src_stride = stride[p]; + mov.dst += TDFX_VID_YUV_PLANE_SIZE; + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed on U plane\n"); + return 1; + } + } + + return 0; +} + +static void draw_osd(void) +{ +} + +static void +flip_page(void) +{ + tdfx_vid_blit_t blit; + //return; + // Scale convert + blit.src = back_buffer; + blit.src_stride = src_stride; + blit.src_x = 0; + blit.src_y = 0; + blit.src_w = src_width; + blit.src_h = src_height; + blit.src_format = src_fmt; + + blit.dst = front_buffer; + blit.dst_stride = dst_stride; + blit.dst_x = 0; + blit.dst_y = 0; + blit.dst_w = dst_width; + blit.dst_h = dst_height; + blit.dst_format = dst_fmt; + + if(ioctl(tdfx_fd,TDFX_VID_BLIT,&blit)) + printf("tdfx_vid: Blit failed\n"); +} + +static uint32_t +draw_frame(uint8_t *src[]) +{ + int stride[] = { src_stride, 0, 0}; + return draw_slice(src,stride,src_width, src_height,0,0); +} + +static uint32_t +query_format(uint32_t format) +{ + switch(format) { + case IMGFMT_YUY2: + case IMGFMT_UYVY: + case IMGFMT_BGR8: + case IMGFMT_BGR16: + case IMGFMT_BGR24: + case IMGFMT_BGR32: + case IMGFMT_YV12: + case IMGFMT_I420: + return 3 | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE; + } + return 0; +} + +static uint32_t +config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) +{ + + if(tdfx_fd < 0) + return 1; + + if(!vo_screenwidth) + vo_screenwidth = tdfx_cfg.screen_width; + if(!vo_screenheight) + vo_screenheight = tdfx_cfg.screen_height; + + aspect_save_orig(width,height); + aspect_save_prescale(d_width,d_height); + aspect_save_screenres(vo_screenwidth,vo_screenheight); + + if(fullscreen&0x01) { /* -fs */ + aspect(&d_width,&d_height,A_ZOOM); + vo_fs = VO_TRUE; + } else { + aspect(&d_width,&d_height,A_NOZOOM); + vo_fs = VO_FALSE; + } + + src_width = width; + src_height = height; + switch(format) { + case IMGFMT_BGR8: + case IMGFMT_BGR16: + case IMGFMT_BGR24: + case IMGFMT_BGR32: + src_fmt = format; + src_bpp = ((format & 0x3F)+7)/8; + break; + case IMGFMT_YUY2: + case IMGFMT_YV12: + case IMGFMT_I420: + src_fmt = TDFX_VID_FORMAT_YUY2; + src_bpp = 2; + break; + default: + printf("Unsupported input format 0x%x\n",format); + return 1; + } + + img_fmt = format; + src_stride = src_width*src_bpp; + + dst_fmt = tdfx_cfg.screen_format; + dst_bpp = ((dst_fmt & 0x3F)+7)/8; + dst_width = d_width; + dst_height = d_height; + dst_stride = tdfx_cfg.screen_stride; + + tdfx_page = tdfx_cfg.screen_stride*tdfx_cfg.screen_height; + front_buffer = tdfx_cfg.screen_start; + back_buffer = front_buffer + tdfx_page; + + printf("tdfxvid setup : %d(%d) x %d @ %d => %d(%d) x %d @ %d\n", + src_width,src_stride,src_height,src_bpp, + dst_width,dst_stride,dst_height,dst_bpp); + + return 0; +} + +static void +uninit(void) +{ + close(tdfx_fd); + tdfx_fd = -1; +} + + +static void check_events(void) +{ +} + +static uint32_t preinit(const char *arg) +{ + + tdfx_fd = open(arg ? arg : "/dev/tdfx_vid", O_RDWR); + if(tdfx_fd < 0) { + printf("tdfx_vid: Can't open %s: %s\n",arg ? arg : "/dev/tdfx_vid", + strerror(errno)); + return 1; + } + + if(ioctl(tdfx_fd,TDFX_VID_GET_CONFIG,&tdfx_cfg)) { + printf("tdfx_vid: Can't get current cfg: %s\n",strerror(errno)); + return 1; + } + + printf("tdfx_vid version %d\n" + " Ram: %d\n" + " Screen: %d x %d\n" + " Format: %c%c%c%d\n", + tdfx_cfg.version, + tdfx_cfg.ram_size, + tdfx_cfg.screen_width, tdfx_cfg.screen_height, + tdfx_cfg.screen_format>>24,(tdfx_cfg.screen_format>>16)&0xFF, + (tdfx_cfg.screen_format>>8)&0xFF,tdfx_cfg.screen_format&0xFF); + + // For now just allocate more than i ever need + agp_mem = mmap( NULL, 1024*768*4, PROT_READ | PROT_WRITE, MAP_SHARED, + tdfx_fd, 0); + + if(agp_mem == MAP_FAILED) { + printf("tdfx_vid: Memmap failed !!!!!\n"); + return 1; + } + + memset(agp_mem,0,1024*768*4); + + return 0; +} + +static uint32_t get_image(mp_image_t *mpi) { + + if(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) + mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK; + + if(mpi->type > MP_IMGTYPE_TEMP) + return VO_FALSE; // TODO ?? + + switch(mpi->imgfmt) { + case IMGFMT_YUY2: + case IMGFMT_UYVY: + // case IMGFMT_BGR8: + case IMGFMT_BGR16: + case IMGFMT_BGR24: + case IMGFMT_BGR32: + mpi->planes[0] = agp_mem; + mpi->stride[0] = src_stride; + break; + case IMGFMT_YV12: + mpi->planes[0] = agp_mem; + mpi->stride[0] = mpi->width; + mpi->planes[1] = mpi->planes[0] + mpi->stride[0]*mpi->height; + mpi->stride[1] = mpi->chroma_width; + mpi->planes[2] = mpi->planes[1] + mpi->stride[1]*mpi->chroma_height; + mpi->stride[2] = mpi->chroma_width; + break; + default: + printf("Get image todo\n"); + return VO_FALSE; + } + mpi->flags |= MP_IMGFLAG_DIRECT; + + return VO_TRUE; +} + +static uint32_t draw_image(mp_image_t *mpi){ + tdfx_vid_agp_move_t mov; + tdfx_vid_yuv_t yuv; + int p; + uint8_t* planes[3]; + int stride[3]; + + //printf("Draw image !!!!\n"); + if(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) + return VO_TRUE; + + switch(mpi->imgfmt) { + case IMGFMT_YUY2: + case IMGFMT_UYVY: + case IMGFMT_BGR8: + case IMGFMT_BGR16: + case IMGFMT_BGR24: + case IMGFMT_BGR32: + if(!(mpi->flags&MP_IMGFLAG_DIRECT)) { + // copy :( to agp_mem + // still faster than tdfxfb wich directly copy to the video mem :) + planes[0] = agp_mem; + memcpy_pic(agp_mem,mpi->planes[0],src_bpp*mpi->width,mpi->height, + mpi->stride[0],mpi->stride[0]); + } else + planes[0] = mpi->planes[0]; + + mov.move2 = TDFX_VID_MOVE_2_PACKED; + mov.width = mpi->width*((mpi->bpp+7)/8); + mov.height = mpi->height; + mov.src = planes[0] - agp_mem; + mov.src_stride = mpi->stride[0]; + + mov.dst = back_buffer; + mov.dst_stride = src_stride; + + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) + printf("tdfx_vid: AGP move failed\n"); + break; + + case IMGFMT_YV12: + case IMGFMT_I420: + if(!(mpi->flags&MP_IMGFLAG_DIRECT)) { + // Copy to agp mem + planes[0] = agp_mem; + memcpy_pic(planes[0],mpi->planes[0],mpi->width,mpi->height, + mpi->stride[0],mpi->stride[0]); + planes[1] = planes[0] + (mpi->height*mpi->stride[0]); + memcpy_pic(planes[1],mpi->planes[1],mpi->chroma_width,mpi->chroma_height, + mpi->stride[1],mpi->stride[1]); + planes[2] = planes[1] + (mpi->chroma_height*mpi->stride[1]); + memcpy_pic(planes[2],mpi->planes[2],mpi->chroma_width,mpi->chroma_height, + mpi->stride[2],mpi->stride[2]); + } else + memcpy(planes,mpi->planes,3*sizeof(uint8_t*)); + + // Setup the yuv thing + yuv.base = back_buffer; + yuv.stride = src_stride; + if(ioctl(tdfx_fd,TDFX_VID_SET_YUV,&yuv)) { + printf("tdfx_vid: Set yuv failed\n"); + break; + } + //return VO_FALSE; + // Now agp move that + // Y + mov.move2 = TDFX_VID_MOVE_2_YUV; + mov.width = mpi->width; + mov.height = mpi->height; + mov.src = planes[0] - agp_mem; + mov.src_stride = mpi->stride[0]; + mov.dst = 0x0; + mov.dst_stride = TDFX_VID_YUV_STRIDE; + + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed on Y plane\n"); + break; + } + //return 0; + // U + p = mpi->imgfmt == IMGFMT_YV12 ? 1 : 2; + mov.width = mpi->chroma_width; + mov.height = mpi->chroma_height; + mov.src = planes[p] - agp_mem; + mov.src_stride = mpi->stride[p]; + mov.dst += TDFX_VID_YUV_PLANE_SIZE; + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed on U plane\n"); + break; + } + // V + p = mpi->imgfmt == IMGFMT_YV12 ? 2 : 1; + mov.src = planes[p] - agp_mem; + mov.src_stride = mpi->stride[p]; + mov.dst += TDFX_VID_YUV_PLANE_SIZE; + if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) { + printf("tdfx_vid: AGP move failed on U plane\n"); + break; + } + break; + default: + printf("What's that for a format 0x%x\n",mpi->imgfmt); + return VO_TRUE; + } + printf("Draw image true !!!!!\n"); + return VO_TRUE; +} + + +static uint32_t control(uint32_t request, void *data, ...) +{ + switch (request) { + case VOCTRL_QUERY_FORMAT: + return query_format(*((uint32_t*)data)); + case VOCTRL_GET_IMAGE: + return get_image(data); + case VOCTRL_DRAW_IMAGE: + return draw_image(data); + } + return VO_NOTIMPL; +} +