Re: [PATCH] vo_tdfx_vid.c and vo_xover.c
Alban Bedel <[email protected]>
| Newsgroups | gmane.comp.video.mplayer.g2.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Arpi, on Thu, 17 Jul 2003 20:27:14 +0200 you wrote: New version. Albeu -- Everything is controlled by a small evil group to which, unfortunately, no one we know belongs. _______________________________________________ MPlayer-G2-dev mailing list [email protected] http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev
g2.diff
(application/octet-stream, 73.3 KB)
--- /home/alban/MP/g2/cfg-l1.c Sat Jul 5 22:27:02 2003
+++ /home/alban/MP/g2.dev/cfg-l1.c Fri Jul 18 13:38:59 2003
@@ -12,6 +12,34 @@
#define CFG_STRING_LIST_SEPARATOR ','
+static char* esc_strchr(char* str,char c) {
+ int esc;
+
+ if(!str) return NULL;
+
+ for(esc = 0 ; str[0] ; str++) {
+ if(str[0] == '(') esc++;
+ else if(str[0] == ')') esc--;
+ else if(esc > 0) continue;
+ else if(str[0] == c) break;
+ }
+
+ return str[0] == c ? str : NULL;
+}
+
+static char* esc_strdup(char* str) {
+ int l;
+ if(!str) return NULL;
+ l = strlen(str);
+ if(l < 2) return strdup(str);
+ if(str[0] == '(' && str[l-1] == ')') {
+ char* r = strdup(str+1);
+ r[l-2] = '\0';
+ return r;
+ }
+ return strdup(str);
+}
+
int mpconfig_parse_param(module_info_t* mod, config_t* cd, config_data_t* cfg, char* param){
// int i;
long tmp_int;
@@ -173,10 +201,11 @@
while(m){
module_info_t* mymod=NULL;
config_modinfo_t mi_func=cd->priv;
- char* q=strchr(m,',');
+ char* q=esc_strchr(m,',');
char* r;
if(q){ *q=0; ++q; }
r=strchr(m,'=');
+ if(q && r > q) r = NULL;
if(r){ *r=0; ++r; }
mymod=mi_func(m); // find module
if(!mymod){
@@ -304,9 +333,9 @@
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "[%s] this module have no config options\n",mod->name);
return CFG_ERR_INVALID;
}
- p=subconfig=strdup(subconfig);
+ p=subconfig=esc_strdup(subconfig);
while(p && *p){
- q=strchr(p,':');
+ q=esc_strchr(p,':');
if(q){ *q=0; ++q; };
r=strchr(p,'=');
if(r){
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/drivers/tdfx_vid.c Thu Jul 17 15:40:45 2003
@@ -0,0 +1,1427 @@
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/agp_backend.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "tdfx_vid.h"
+#include "3dfx.h"
+
+
+#define TDFX_VID_MAJOR 178
+
+MODULE_AUTHOR("Albeu");
+MODULE_DESCRIPTION("A driver for Banshee targeted for video app");
+
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+#ifndef min
+#define min(x,y) (((x)<(y))?(x):(y))
+#endif
+
+static struct pci_dev *pci_dev;
+
+static uint8_t *tdfx_mmio_base = 0;
+static uint32_t tdfx_mem_base = 0;
+static uint32_t tdfx_io_base = 0;
+
+static int tdfx_ram_size = 0;
+
+static int tdfx_vid_in_use = 0;
+
+static drm_agp_t *drm_agp = NULL;
+static agp_kern_info agp_info;
+static agp_memory *agp_mem = NULL;
+
+static __initdata int tdfx_map_io = 1;
+static __initdata unsigned long map_start = 0; //0x7300000;
+static __initdata unsigned long map_max = (10*1024*1024);
+static unsigned long map_base = 0;
+
+static __initdata int use_fifo = 0;
+static uint32_t fifo_offset = 0;
+static uint32_t *fifo = NULL;
+static uint32_t fifo_write_pos = 0;
+static uint32_t fifo_n = FIFO0;
+
+#define FIFO_PAGE_SIZE (TDFX_VID_FIFO_PAGE_SIZE)
+#define FIFO_PAGES 1
+#define FIFO_SIZE (FIFO_PAGE_SIZE*FIFO_PAGES)
+
+MODULE_PARM(tdfx_map_io,"i");
+MODULE_PARM_DESC(tdfx_map_io, "Set to 0 to use the page fault handler (you need to patch agpgart_be.c to allow the mapping in user space)\n");
+MODULE_PARM(map_start,"l");
+MODULE_PARM_DESC(map_start,"Use a block of physical mem instead of the agp arerture.\n");
+MODULE_PARM(map_max,"l");
+MODULE_PARM_DESC(map_max, "Maximum amout of physical memory (in bytes) that can be used\n");
+MODULE_PARM(use_fifo,"i");
+MODULE_PARM_DESC(use_fifo, "Set to one to use AGP fifo instead of PCI access whenever possible\n");
+
+
+static inline u32 tdfx_inl(unsigned int reg) {
+ return readl(tdfx_mmio_base + reg);
+}
+
+static inline void tdfx_outl(unsigned int reg, u32 val) {
+ writel(val,tdfx_mmio_base + reg);
+}
+
+static inline void banshee_make_room(int size) {
+ while((tdfx_inl(STATUS) & 0x1f) < size);
+}
+
+static inline void banshee_wait_idle(void) {
+ int i = 0;
+
+ banshee_make_room(1);
+ tdfx_outl(COMMAND_3D, COMMAND_3D_NOP);
+
+ while(1) {
+ i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1;
+ if(i == 3) break;
+ }
+}
+
+static unsigned long get_lfb_size(void) {
+ u32 draminit0 = 0;
+ u32 draminit1 = 0;
+ // u32 miscinit1 = 0;
+ u32 lfbsize = 0;
+ int sgram_p = 0;
+
+ draminit0 = tdfx_inl(DRAMINIT0);
+ draminit1 = tdfx_inl(DRAMINIT1);
+
+ if ((pci_dev->device == PCI_DEVICE_ID_3DFX_BANSHEE) ||
+ (pci_dev->device == PCI_DEVICE_ID_3DFX_VOODOO3)) {
+ sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1;
+
+ lfbsize = sgram_p ?
+ (((draminit0 & DRAMINIT0_SGRAM_NUM) ? 2 : 1) *
+ ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) :
+ 16 * 1024 * 1024;
+ } else {
+ /* Voodoo4/5 */
+ u32 chips, psize, banks;
+
+ chips = ((draminit0 & (1 << 26)) == 0) ? 4 : 8;
+ psize = 1 << ((draminit0 & 0x38000000) >> 28);
+ banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4;
+ lfbsize = chips * psize * banks;
+ lfbsize <<= 20;
+ }
+
+#if 0
+ /* disable block writes for SDRAM (why?) */
+ miscinit1 = tdfx_inl(MISCINIT1);
+ miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS;
+ miscinit1 |= MISCINIT1_CLUT_INV;
+
+ banshee_make_room(1);
+ tdfx_outl(MISCINIT1, miscinit1);
+#endif
+
+ return lfbsize;
+}
+
+static int tdfx_vid_find_card(void)
+{
+ struct pci_dev *dev = NULL;
+ // unsigned int card_option;
+
+ if((dev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE, NULL)))
+ printk(KERN_INFO "tdfx_vid: Found VOODOO BANSHEE\n");
+ else if((dev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3, NULL)))
+ printk(KERN_INFO "tdfx_vid: Found VOODOO 3 \n");
+ else
+ return 0;
+
+
+ pci_dev = dev;
+
+#if LINUX_VERSION_CODE >= 0x020300
+ tdfx_mmio_base = ioremap_nocache(dev->resource[0].start,1 << 24);
+ tdfx_mem_base = dev->resource[1].start;
+ tdfx_io_base = dev->resource[2].start;
+#else
+ tdfx_mmio_base = ioremap_nocache(dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK,0x4000);
+ tdfx_mem_base = dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK;
+ tdfx_io_base = dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK;
+#endif
+ printk(KERN_INFO "tdfx_vid: MMIO at 0x%p\n", tdfx_mmio_base);
+ tdfx_ram_size = get_lfb_size();
+
+ printk(KERN_INFO "tdfx_vid: Found %d MB (%d bytes) of memory\n",
+ tdfx_ram_size / 1024 / 1024,tdfx_ram_size);
+
+
+#if 0
+ {
+ int temp;
+ printk("List resources -----------\n");
+ for(temp=0;temp<DEVICE_COUNT_RESOURCE;temp++){
+ struct resource *res=&pci_dev->resource[temp];
+ if(res->flags){
+ int size=(1+res->end-res->start)>>20;
+ printk(KERN_DEBUG "res %d: start: 0x%X end: 0x%X (%d MB) flags=0x%X\n",temp,res->start,res->end,size,res->flags);
+ if(res->flags&(IORESOURCE_MEM|IORESOURCE_PREFETCH)){
+ if(size>tdfx_ram_size && size<=64) tdfx_ram_size=size;
+ }
+ }
+ }
+ }
+#endif
+
+
+ return 1;
+}
+
+static int agp_init(void) {
+
+ drm_agp = (drm_agp_t*)inter_module_get("drm_agp");
+
+ if(!drm_agp) {
+ printk(KERN_ERR "tdfx_vid: Unable to get drm_agp pointer\n");
+ return 0;
+ }
+
+ if(drm_agp->acquire()) {
+ printk(KERN_ERR "tdfx_vid: Unable to acquire the agp backend\n");
+ drm_agp = NULL;
+ return 0;
+ }
+
+ drm_agp->copy_info(&agp_info);
+#if 0
+ printk(KERN_DEBUG "AGP Version : %d %d\n"
+ "AGP Mode: %#X\nAperture Base: %p\nAperture Size: %d\n"
+ "Max memory = %d\nCurrent mem = %d\nCan use perture : %s\n"
+ "Page mask = %#X\n",
+ agp_info.version.major,agp_info.version.minor,
+ agp_info.mode,agp_info.aper_base,agp_info.aper_size,
+ agp_info.max_memory,agp_info.current_memory,
+ agp_info.cant_use_aperture ? "no" : "yes",
+ agp_info.page_mask);
+#endif
+ drm_agp->enable(agp_info.mode);
+
+
+ printk(KERN_INFO "AGP Enabled\n");
+
+ return 1;
+}
+
+static void agp_close(void) {
+
+ if(!drm_agp) return;
+
+ if(agp_mem) {
+ drm_agp->unbind_memory(agp_mem);
+ drm_agp->free_memory(agp_mem);
+ agp_mem = NULL;
+ }
+
+
+ drm_agp->release();
+ inter_module_put("drm_agp");
+}
+
+static int write_fifo(void* data,u32 size);
+
+static int agp_move(tdfx_vid_agp_move_t* m) {
+ u32 src = 0;
+ u32 src_h,src_l;
+
+ if(!(agp_mem||map_start))
+ return (-EAGAIN);
+
+ if(m->move2 > 3) {
+ printk(KERN_DEBUG "tdfx_vid: AGP move invalid destination %d\n",
+ m->move2);
+ return (-EAGAIN);
+ }
+
+ if(map_start)
+ src = map_start + m->src;
+ else
+ src = agp_info.aper_base + m->src;
+
+ src_l = (u32)src;
+ src_h = (m->width | (m->src_stride << 14)) & 0x0FFFFFFF;
+
+ if(use_fifo && fifo) {
+ u32 cmd[5] = {
+ // transfert size on 20bits dst type cmd
+ ((m->src_stride*m->height) & 0xFFFFF) << 5 | (m->move2 << 3) | 0x6,
+ src_l,
+ src_h,
+ m->dst & 0x3FFFFFF, // 26 bits
+ m->dst_stride & 0x7FFF // 15 bits
+ };
+ return write_fifo(cmd,5*4);
+ }
+
+
+ // banshee_wait_idle();
+ banshee_make_room(6);
+ tdfx_outl(AGPHOSTADDRESSHIGH,src_h);
+ tdfx_outl(AGPHOSTADDRESSLOW,src_l);
+
+ tdfx_outl(AGPGRAPHICSADDRESS, m->dst);
+ tdfx_outl(AGPGRAPHICSSTRIDE, m->dst_stride);
+ tdfx_outl(AGPREQSIZE,m->src_stride*m->height);
+
+ tdfx_outl(AGPMOVECMD,m->move2 << 3);
+ banshee_wait_idle();
+
+ return 0;
+}
+
+static int open_fifo(u32 offset,ssize_t pages) {
+ u32 addr = offset; //agp_info.aper_base + offset;
+ u32 size;
+
+ size = tdfx_inl(CMDBASESIZE0 + fifo_n);
+ if(size & 0x100) {
+ printk(KERN_INFO "tdfx_vid: fifo alredy in use\n");
+ return 0;
+ }
+
+ if((addr >> 12)<<12 != addr) {
+ printk(KERN_INFO "tdfx_vid: unaligned fifo start\n");
+ return 0;
+ }
+
+ size = ((pages-1) & 0xFF) | 0x700; // fifo on, in agp mem, disable hole cnt
+
+ banshee_wait_idle();
+ banshee_make_room(9);
+ // The adresse is in 4KB pages (2^12 bits)
+ // AGP adress are 36 bits and this one is 24 bits => 36-24=12
+ // So it probably need the upper 20 bits of our 32 bits address
+ tdfx_outl(CMDBASEADDR0 + fifo_n,addr >> 12);
+ tdfx_outl(CMDBUMP0+fifo_n,0);
+ // But these need the lower 32 bits of the AGP address
+ tdfx_outl(CMDRDPTRL0 + fifo_n, addr);
+ // And here the upper 4 bit of the AGP adresse
+ // For it's then 0
+ tdfx_outl(CMDRDPTRH0 + fifo_n, 0);
+ // A 25 bits adresse
+ // It need the -4
+ tdfx_outl(CMDAMIN0 + fifo_n, (addr - 4) & 0x1FFFFFF);
+ tdfx_outl(CMDAMAX0 + fifo_n, (addr - 4) & 0x1FFFFFF);
+ tdfx_outl(CMDFIFODEPTH0 + fifo_n, 0);
+ tdfx_outl(CMDHOLECNT0 + fifo_n, 0);
+ tdfx_outl(CMDBASESIZE0 + fifo_n,size);
+
+ banshee_wait_idle();
+
+ return 1;
+}
+
+static int write_fifo(void* data,u32 size) {
+ u32 read_pos;
+ u32 max_size = 0;
+
+ if(size > FIFO_SIZE) {
+ printk(KERN_INFO "tdfx_vid: Too big command for the fifo\n");
+ return 0;
+ }
+
+ if((size/4)*4 != size) {
+ printk(KERN_INFO "tdfx_vid: Got command with unaligned size !!!\n");
+ return 0;
+ }
+
+ // Wait until we got enough space
+ while(max_size < size) {
+ read_pos = tdfx_inl(CMDRDPTRL0+fifo_n) - agp_info.aper_base - fifo_offset;
+ if(read_pos <= fifo_write_pos)
+ max_size = FIFO_SIZE - (fifo_write_pos - read_pos);
+ else
+ max_size = FIFO_SIZE - (read_pos - fifo_write_pos);
+ }
+
+ if(fifo_write_pos + size > FIFO_SIZE) {
+ memcpy_toio(fifo + fifo_write_pos, data,FIFO_SIZE - fifo_write_pos);
+ memcpy_toio(fifo, data + (FIFO_SIZE - fifo_write_pos),
+ size - (FIFO_SIZE - fifo_write_pos));
+ fifo_write_pos = size - (FIFO_SIZE - fifo_write_pos);
+ } else {
+ memcpy_toio(fifo + fifo_write_pos, data,size);
+ fifo_write_pos += size % FIFO_SIZE;
+ }
+
+ banshee_make_room(1);
+ tdfx_outl(CMDBUMP0+fifo_n ,size/4);
+ return 1;
+}
+
+static void close_fifo(void) {
+ u32 size = tdfx_inl(CMDBASESIZE0+fifo_n);
+
+ size &= ~0x100;
+ banshee_wait_idle();
+ tdfx_outl(CMDBASESIZE0+fifo_n,size);
+ banshee_wait_idle();
+}
+
+
+static void tdfx_vid_get_config(tdfx_vid_config_t* cfg) {
+ u32 in;
+
+ cfg->version = TDFX_VID_VERSION;
+ cfg->ram_size = tdfx_ram_size;
+
+ in = tdfx_inl(VIDSCREENSIZE);
+ cfg->screen_width = in & 0xFFF;
+ cfg->screen_height = (in >> 12) & 0xFFF;
+ in = (tdfx_inl(VIDPROCCFG)>> 18)& 0x7;
+ switch(in) {
+ case 0:
+ cfg->screen_format = TDFX_VID_FORMAT_BGR8;
+ break;
+ case 1:
+ cfg->screen_format = TDFX_VID_FORMAT_BGR16;
+ break;
+ case 2:
+ cfg->screen_format = TDFX_VID_FORMAT_BGR24;
+ break;
+ case 3:
+ cfg->screen_format = TDFX_VID_FORMAT_BGR32;
+ break;
+ default:
+ printk(KERN_INFO "tdfx_vid: unknown screen format %d\n",in);
+ cfg->screen_format = 0;
+ break;
+ }
+ cfg->screen_stride = tdfx_inl(VIDDESKSTRIDE) & 0x7FFF;
+ cfg->screen_start = tdfx_inl(VIDDESKSTART);
+ cfg->triple_buffering = (tdfx_inl(DRAMINIT1) & (1<<11))>>11;
+}
+
+inline static u32 tdfx_vid_make_format(int src,u16 stride,u32 fmt) {
+ u32 r = stride & 0xFFF3;
+ u32 tdfx_fmt = 0;
+
+ // src and dest formats
+ switch(fmt) {
+ case TDFX_VID_FORMAT_BGR8:
+ tdfx_fmt = 1;
+ break;
+ case TDFX_VID_FORMAT_BGR16:
+ tdfx_fmt = 3;
+ break;
+ case TDFX_VID_FORMAT_BGR24:
+ tdfx_fmt = 4;
+ break;
+ case TDFX_VID_FORMAT_BGR32:
+ tdfx_fmt = 5;
+ break;
+ }
+
+ if(!src && !tdfx_fmt) {
+ printk(KERN_INFO "tdfx_vid: Invalid destination format %#X\n",fmt);
+ return 0;
+ }
+
+ if(src && !tdfx_fmt) {
+ // src only format
+ switch(fmt){
+ case TDFX_VID_FORMAT_BGR1:
+ tdfx_fmt = 0;
+ break;
+ case TDFX_VID_FORMAT_BGR15: // To check
+ tdfx_fmt = 2;
+ break;
+ case TDFX_VID_FORMAT_YUY2:
+ tdfx_fmt = 8;
+ break;
+ case TDFX_VID_FORMAT_UYVY:
+ tdfx_fmt = 9;
+ break;
+ default:
+ printk(KERN_INFO "tdfx_vid: Invalid source format %#X\n",fmt);
+ return 0;
+ }
+ }
+
+ r |= tdfx_fmt << 16;
+
+ return r;
+}
+
+static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
+ u32 src_fmt,dst_fmt,cmd = 2;
+ u32 cmin,cmax,srcbase,srcxy,srcfmt,srcsize;
+ u32 dstbase,dstxy,dstfmt,dstsize = 0;
+ u32 cmd_extra = 0,src_ck[2],dst_ck[2],rop123=0;
+
+ //printk(KERN_INFO "tdfx_vid: Make src fmt 0x%x\n",blit->src_format);
+ src_fmt = tdfx_vid_make_format(1,blit->src_stride,blit->src_format);
+ if(!src_fmt)
+ return 0;
+ //printk(KERN_INFO "tdfx_vid: Make dst fmt 0x%x\n", blit->dst_format);
+ dst_fmt = tdfx_vid_make_format(0,blit->dst_stride,blit->dst_format);
+ if(!dst_fmt)
+ return 0;
+ blit->colorkey &= 0x3;
+ // Be nice if user just want a simple blit
+ if((!blit->colorkey) && (!blit->rop[0]))
+ blit->rop[0] = TDFX_VID_ROP_COPY;
+ // No stretch : fix me the cmd should be 1 but it
+ // doesn't work. Maybe some other regs need to be set
+ // as non-stretch blit have more options
+ if(((!blit->dst_w) && (!blit->dst_h)) ||
+ ((blit->dst_w == blit->src_w) && (blit->dst_h == blit->src_h)))
+ cmd = 2;
+
+ // Save the regs otherwise fb get crazy
+ // we can perhaps avoid some ...
+ banshee_wait_idle();
+ cmin = tdfx_inl(CLIP0MIN);
+ cmax = tdfx_inl(CLIP0MAX);
+ srcbase = tdfx_inl(SRCBASE);
+ srcxy = tdfx_inl(SRCXY);
+ srcfmt = tdfx_inl(SRCFORMAT);
+ srcsize = tdfx_inl(SRCSIZE);
+ dstbase = tdfx_inl(DSTBASE);
+ dstxy = tdfx_inl(DSTXY);
+ dstfmt = tdfx_inl(DSTFORMAT);
+ if(cmd == 2)
+ dstsize = tdfx_inl(DSTSIZE);
+ if(blit->colorkey & TDFX_VID_SRC_COLORKEY) {
+ src_ck[0] = tdfx_inl(SRCCOLORKEYMIN);
+ src_ck[1] = tdfx_inl(SRCCOLORKEYMAX);
+ tdfx_outl(SRCCOLORKEYMIN,blit->src_colorkey[0]);
+ tdfx_outl(SRCCOLORKEYMAX,blit->src_colorkey[1]);
+ }
+ if(blit->colorkey & TDFX_VID_DST_COLORKEY) {
+ dst_ck[0] = tdfx_inl(DSTCOLORKEYMIN);
+ dst_ck[1] = tdfx_inl(DSTCOLORKEYMAX);
+ tdfx_outl(SRCCOLORKEYMIN,blit->dst_colorkey[0]);
+ tdfx_outl(SRCCOLORKEYMAX,blit->dst_colorkey[1]);
+ }
+ if(blit->colorkey) {
+ cmd_extra = tdfx_inl(COMMANDEXTRA_2D);
+ rop123 = tdfx_inl(ROP123);
+ tdfx_outl(COMMANDEXTRA_2D, blit->colorkey);
+ tdfx_outl(ROP123,(blit->rop[1] | (blit->rop[2] << 8) | blit->rop[3] << 16));
+
+ }
+ // Get rid of the clipping at the moment
+ tdfx_outl(CLIP0MIN,0);
+ tdfx_outl(CLIP0MAX,0x0fff0fff);
+
+ // Setup the src
+ tdfx_outl(SRCBASE,blit->src & 0x00FFFFFF);
+ tdfx_outl(SRCXY,XYREG(blit->src_x,blit->src_y));
+ tdfx_outl(SRCFORMAT,src_fmt);
+ tdfx_outl(SRCSIZE,XYREG(blit->src_w,blit->src_h));
+
+ // Setup the dst
+ tdfx_outl(DSTBASE,blit->dst & 0x00FFFFFF);
+ tdfx_outl(DSTXY,XYREG(blit->dst_x,blit->dst_y));
+ tdfx_outl(DSTFORMAT,dst_fmt);
+ if(cmd == 2)
+ tdfx_outl(DSTSIZE,XYREG(blit->dst_w,blit->dst_h));
+
+ // Send the command
+ tdfx_outl(COMMAND_2D,cmd | 0x100 | (blit->rop[0] << 24));
+ banshee_wait_idle();
+
+ // Now restore the regs to make fb happy
+ tdfx_outl(CLIP0MIN, cmin);
+ tdfx_outl(CLIP0MAX, cmax);
+ tdfx_outl(SRCBASE, srcbase);
+ tdfx_outl(SRCXY, srcxy);
+ tdfx_outl(SRCFORMAT, srcfmt);
+ tdfx_outl(SRCSIZE, srcsize);
+ tdfx_outl(DSTBASE, dstbase);
+ tdfx_outl(DSTXY, dstxy);
+ tdfx_outl(DSTFORMAT, dstfmt);
+ if(cmd == 2)
+ tdfx_outl(DSTSIZE, dstsize);
+ if(blit->colorkey & TDFX_VID_SRC_COLORKEY) {
+ tdfx_outl(SRCCOLORKEYMIN,src_ck[0]);
+ tdfx_outl(SRCCOLORKEYMAX,src_ck[1]);
+ }
+ if(blit->colorkey & TDFX_VID_DST_COLORKEY) {
+ tdfx_outl(SRCCOLORKEYMIN,dst_ck[0]);
+ tdfx_outl(SRCCOLORKEYMAX,dst_ck[1]);
+ }
+ if(blit->colorkey) {
+ tdfx_outl(COMMANDEXTRA_2D,cmd_extra);
+ tdfx_outl(ROP123,rop123);
+ }
+ return 1;
+}
+
+static int tdfx_vid_set_yuv(unsigned long arg) {
+ tdfx_vid_yuv_t yuv;
+
+ if(copy_from_user(&yuv,(tdfx_vid_yuv_t*)arg,sizeof(tdfx_vid_yuv_t))) {
+ printk(KERN_DEBUG "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+ banshee_make_room(2);
+ tdfx_outl(YUVBASEADDRESS,yuv.base & 0x01FFFFFF);
+ tdfx_outl(YUVSTRIDE, yuv.stride & 0x3FFF);
+
+ banshee_wait_idle();
+
+ return 0;
+}
+
+static int tdfx_vid_get_yuv(unsigned long arg) {
+ tdfx_vid_yuv_t yuv;
+
+ yuv.base = tdfx_inl(YUVBASEADDRESS) & 0x01FFFFFF;
+ yuv.stride = tdfx_inl(YUVSTRIDE) & 0x3FFF;
+
+ if(copy_to_user((tdfx_vid_yuv_t*)arg,&yuv,sizeof(tdfx_vid_yuv_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
+ return(-EFAULT);
+ }
+
+ return 0;
+}
+
+static int tdfx_vid_set_overlay(unsigned long arg) {
+ tdfx_vid_overlay_t ov;
+ uint32_t screen_w,screen_h;
+ uint32_t vidcfg,stride,vidbuf;
+ int disp_w,disp_h;
+
+ if(copy_from_user(&ov,(tdfx_vid_overlay_t*)arg,sizeof(tdfx_vid_overlay_t))) {
+ printk(KERN_DEBUG "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+
+ if(ov.dst_y < 0) {
+ int shift;
+ if(-ov.dst_y >= ov.src_height) {
+ printk(KERN_DEBUG "tdfx_vid: Overlay outside of the screen ????\n");
+ return(-EFAULT);
+ }
+ shift = (-ov.dst_y)/(double)ov.dst_height*ov.src_height;
+ ov.src[0] += shift*ov.src_stride;
+ ov.src_height -= shift;
+ ov.dst_height += ov.dst_y;
+ ov.dst_y = 0;
+ }
+
+ if(ov.dst_x < 0) {
+ int shift;
+ if(-ov.dst_x >= ov.src_width) {
+ printk(KERN_DEBUG "tdfx_vid: Overlay outside of the screen ????\n");
+ return(-EFAULT);
+ }
+ shift = (-ov.dst_x)/(double)ov.dst_width*ov.src_width;
+ shift = ((shift+3)/2)*2;
+ ov.src[0] += shift*2;
+ ov.src_width -= shift;
+ ov.dst_width += ov.dst_x;
+ ov.dst_x = 0;
+ }
+
+ vidcfg = tdfx_inl(VIDPROCCFG);
+ // clear the overlay fmt
+ vidcfg &= ~(7 << 21);
+ switch(ov.format) {
+ case TDFX_VID_FORMAT_BGR15:
+ vidcfg |= (1 << 21);
+ break;
+ case TDFX_VID_FORMAT_BGR16:
+ vidcfg |= (7 << 21);
+ break;
+ case TDFX_VID_FORMAT_YUY2:
+ vidcfg |= (5 << 21);
+ break;
+ case TDFX_VID_FORMAT_UYVY:
+ vidcfg |= (6 << 21);
+ break;
+ default:
+ printk(KERN_DEBUG "tdfx_vid: Invalid overlay fmt 0x%x\n",ov.format);
+ return (-EFAULT);
+ }
+
+ // YUV422 need 4 bytes aligned stride and address
+ if((ov.format == TDFX_VID_FORMAT_YUY2 ||
+ ov.format == TDFX_VID_FORMAT_UYVY)) {
+ if((ov.src_stride & ~0x3) != ov.src_stride) {
+ printk(KERN_DEBUG "tdfx_vid: YUV need a 4 bytes aligned stride %d\n",ov.src_stride);
+ return(-EFAULT);
+ }
+ if((ov.src[0] & ~0x3) != ov.src[0] || (ov.src[1] & ~0x3) != ov.src[1]){
+ printk(KERN_DEBUG "tdfx_vid: YUV need a 4 bytes aligned address 0x%x 0x%x\n",ov.src[0],ov.src[1]);
+ return(-EFAULT);
+ }
+ }
+
+ // Now we have a good input format
+ // but first get the screen size to check a bit
+ // if the size/position is valid
+ screen_w = tdfx_inl(VIDSCREENSIZE);
+ screen_h = (screen_w >> 12) & 0xFFF;
+ screen_w &= 0xFFF;
+ disp_w = ov.dst_x + ov.dst_width >= screen_w ?
+ screen_w - ov.dst_x : ov.dst_width;
+ disp_h = ov.dst_y + ov.dst_height >= screen_h ?
+ screen_h - ov.dst_y : ov.dst_height;
+
+ if(ov.dst_x >= screen_w || ov.dst_y >= screen_h ||
+ disp_h <= 0 || disp_h > screen_h || disp_w <= 0 || disp_w > screen_w) {
+ printk(KERN_DEBUG "tdfx_vid: Invalid overlay dimension and/or position\n");
+ return (-EFAULT);
+ }
+ // Setup the vidproc
+ // H scaling
+ if(ov.src_width < ov.dst_width)
+ vidcfg |= (1<<14);
+ else
+ vidcfg &= ~(1<<14);
+ // V scaling
+ if(ov.src_height < ov.dst_height)
+ vidcfg |= (1<<15);
+ else
+ vidcfg &= ~(1<<15);
+ // Filtering can only be used in 1x mode
+ if(!(vidcfg | (1<<26)))
+ vidcfg |= (3<<16);
+ else
+ vidcfg &= ~(3<<16);
+ // disable overlay stereo mode
+ vidcfg &= ~(1<<2);
+ // Colorkey on/off
+ if(ov.use_colorkey) {
+ // Colorkey inversion
+ if(ov.invert_colorkey)
+ vidcfg |= (1<<6);
+ else
+ vidcfg &= ~(1<<6);
+ vidcfg |= (1<<5);
+ } else
+ vidcfg &= ~(1<<5);
+ // Overlay isn't VidIn
+ vidcfg &= ~(1<<9);
+ // vidcfg |= (1<<8);
+ tdfx_outl(VIDPROCCFG,vidcfg);
+
+ // Start coord
+ //printk(KERN_DEBUG "tdfx_vid: start %dx%d\n",ov.dst_x & 0xFFF,ov.dst_y & 0xFFF);
+ tdfx_outl(VIDOVRSTARTCRD,(ov.dst_x & 0xFFF)|((ov.dst_y & 0xFFF)<<12));
+ // End coord
+ tdfx_outl(VIDOVRENDCRD, ((ov.dst_x + disp_w-1) & 0xFFF)|
+ (((ov.dst_y + disp_h-1) & 0xFFF)<<12));
+ // H Scaling
+ tdfx_outl(VIDOVRDUDX,( ((u32)ov.src_width) << 20) / ov.dst_width);
+ // Src offset and width (in bytes)
+ tdfx_outl(VIDOVRDUDXOFF,((ov.src_width<<1) & 0xFFF) << 19);
+ // V Scaling
+ tdfx_outl(VIDOVRDVDY, ( ((u32)ov.src_height) << 20) / ov.dst_height);
+ //else
+ // tdfx_outl(VIDOVRDVDY,0);
+ // V Offset
+ tdfx_outl(VIDOVRDVDYOFF,0);
+ // Overlay stride
+ stride = tdfx_inl(VIDDESKSTRIDE) & 0xFFFF;
+ tdfx_outl(VIDDESKSTRIDE,stride | (((u32)ov.src_stride) << 16));
+ // Buffers address
+ tdfx_outl(LEFTOVBUF, ov.src[0]);
+ //tdfx_outl(RIGHTOVBUF, ov.src[1]);
+
+ // Send a swap buffer cmd if we are not on one of the 2 buffers
+ // vidbuf = tdfx_inl(VIDCUROVRSTART);
+ //if(vidbuf != ov.src[0] && vidbuf != ov.src[1]) {
+ tdfx_outl(SWAPPENDING,1);
+ tdfx_outl(SWAPBUFCMD, 0);
+ //}
+ //printk(KERN_DEBUG "tdfx_vid: Buf0=0x%x Buf1=0x%x Current=0x%x\n",
+ // ov.src[0],ov.src[1],tdfx_inl(VIDCUROVRSTART));
+ // Colorkey
+ if(ov.use_colorkey) {
+ tdfx_outl(VIDCHRMIN,ov.colorkey[0]);
+ tdfx_outl(VIDCHRMAX,ov.colorkey[1]);
+ }
+
+ return 0;
+}
+
+static int tdfx_vid_overlay_swap(unsigned long arg) {
+ tdfx_vid_swap_t swap;
+ int s = 0;
+
+ if(copy_from_user(&swap,(tdfx_vid_swap_t*)arg,sizeof(tdfx_vid_swap_t))) {
+ printk(KERN_DEBUG "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+
+ if(swap.sync) {
+ s = 1;
+ s |= (swap.sync-1)<<1;
+ }
+
+ banshee_make_room(3);
+ tdfx_outl(LEFTOVBUF, swap.buffer);
+ tdfx_outl(SWAPPENDING,1);
+ tdfx_outl(SWAPBUFCMD, s);
+ //banshee_wait_idle();
+
+ return 0;
+}
+
+
+static int tdfx_vid_overlay_on(void) {
+ uint32_t vidcfg = tdfx_inl(VIDPROCCFG);
+ //return 0;
+ if(vidcfg & (1<<8)) { // Overlay is alredy on
+ //printk(KERN_DEBUG "tdfx_vid: Overlay is alredy on\n");
+ return (-EFAULT);
+ }
+ vidcfg |= (1<<8);
+ tdfx_outl(VIDPROCCFG,vidcfg);
+ return 0;
+}
+
+static int tdfx_vid_overlay_off(void) {
+ uint32_t vidcfg = tdfx_inl(VIDPROCCFG);
+
+ if(vidcfg & (1<<8)) {
+ vidcfg &= ~(1<<8);
+ tdfx_outl(VIDPROCCFG,vidcfg);
+ return 0;
+ }
+
+ printk(KERN_DEBUG "tdfx_vid: Overlay is alredy off\n");
+ return (-EFAULT);
+}
+
+static int tdfx_vid_get_3d_lfb(unsigned long arg) {
+ tdfx_vid_3d_lfb_t lfb;
+ u32 mode = tdfx_inl(LFBMODE);
+
+ // Parse the write format
+ lfb.format = 0;
+ switch(mode & 0xF) {
+ case 0: // RGB 16
+ switch((mode & 0x600) >> 10) {
+ case 0:
+ case 2:
+ lfb.format = TDFX_VID_FORMAT_BGR16;
+ break;
+ case 1:
+ case 3:
+ lfb.format = TDFX_VID_FORMAT_RGB16;
+ break;
+ }
+ break;
+ case 1: // RGB 15
+ switch((mode & 0x600) >> 10) {
+ case 0:
+ lfb.format = TDFX_VID_FORMAT_BGR15;
+ break;
+ case 1:
+ lfb.format = TDFX_VID_FORMAT_RGB15;
+ break;
+ case 2:
+ lfb.format = TDFX_VID_FORMAT_15BGR;
+ break;
+ case 3:
+ lfb.format = TDFX_VID_FORMAT_15RGB;
+ break;
+ }
+ break;
+ case 2: // ARGB 16
+ switch((mode & 0x600) >> 10) {
+ case 0:
+ lfb.format = TDFX_VID_FORMAT_BGRA16;
+ break;
+ case 1:
+ lfb.format = TDFX_VID_FORMAT_RGBA16;
+ break;
+ case 2:
+ lfb.format = TDFX_VID_FORMAT_ABGR16;
+ break;
+ case 3:
+ lfb.format = TDFX_VID_FORMAT_ARGB16;
+ break;
+ }
+ break;
+ case 4: // RGB 24
+ switch((mode & 0x600) >> 10) {
+ case 0:
+ lfb.format = TDFX_VID_FORMAT_BGR24;
+ break;
+ case 1:
+ lfb.format = TDFX_VID_FORMAT_RGB24;
+ break;
+ case 2:
+ lfb.format = TDFX_VID_FORMAT_24BGR;
+ break;
+ case 3:
+ lfb.format = TDFX_VID_FORMAT_24RGB;
+ break;
+ }
+ break;
+ case 5: // ARGB 32
+ switch((mode & 0x600) >> 10) {
+ case 0:
+ lfb.format = TDFX_VID_FORMAT_BGRA32;
+ break;
+ case 1:
+ lfb.format = TDFX_VID_FORMAT_RGBA32;
+ break;
+ case 2:
+ lfb.format = TDFX_VID_FORMAT_ABGR32;
+ break;
+ case 3:
+ lfb.format = TDFX_VID_FORMAT_ARGB32;
+ break;
+ }
+ break;
+ // TODO add the depth stuff
+ }
+
+ lfb.color_buf = tdfx_inl(COLBUFFERADDR);
+ lfb.color_stride = tdfx_inl(COLBUFFERSTRIDE);
+
+ lfb.aux_buf = tdfx_inl(AUXBUFFERADDR);
+ lfb.aux_stride = tdfx_inl(AUXBUFFERSTRIDE);
+ lfb.flags = mode & 0xF900;
+
+ lfb.mode = tdfx_inl(FBZMODE);
+
+ if(copy_to_user((tdfx_vid_3d_lfb_t*)arg,&lfb,sizeof(tdfx_vid_3d_lfb_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
+ return(-EFAULT);
+ }
+ return 0;
+}
+static int tdfx_vid_set_3d_lfb(unsigned long arg) {
+ tdfx_vid_3d_lfb_t lfb;
+ u32 mode = 0;
+
+ if(copy_from_user(&lfb,(tdfx_vid_3d_lfb_t*)arg,sizeof(tdfx_vid_3d_lfb_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+
+ if((lfb.color_buf & ~0xF) != lfb.color_buf) {
+ printk(KERN_DEBUG "tdfx_vid: color buffer address must be 16-bytes aligned\n");
+ return(-EFAULT);
+ }
+ if((lfb.color_stride & ~0xF) != lfb.color_stride) {
+ printk(KERN_DEBUG "tdfx_vid: color buffer stride must be 16-bytes aligned\n");
+ return(-EFAULT);
+ }
+ if((lfb.aux_buf & ~0xF) != lfb.aux_buf) {
+ printk(KERN_DEBUG "tdfx_vid: aux buffer address must be 16-bytes aligned\n");
+ return(-EFAULT);
+ }
+ if((lfb.aux_stride & ~0xF) != lfb.aux_stride) {
+ printk(KERN_DEBUG "tdfx_vid: aux buffer stride must be 16-bytes aligned\n");
+ return(-EFAULT);
+ }
+
+ switch(lfb.format) {
+ case TDFX_VID_FORMAT_BGR16:
+ break;
+ case TDFX_VID_FORMAT_RGB16:
+ mode = 1 << 9;
+ break;
+ case TDFX_VID_FORMAT_BGRA32:
+ case TDFX_VID_FORMAT_ABGR32:
+ case TDFX_VID_FORMAT_RGBA32:
+ case TDFX_VID_FORMAT_ARGB32:
+ mode = 5;
+ if(lfb.format >> 24 == 'R')
+ mode |= (1 << 9);
+ else if((lfb.format >> 24) == 'A' && ((lfb.format>>8) & 0xFF) == 'R')
+ mode |= (2 << 9);
+ else if((lfb.format >> 24) == 'A' && ((lfb.format>>8) & 0xFF) == 'B')
+ mode |= (3 << 9);
+ break;
+ default:
+ printk(KERN_DEBUG "tdfx_vid: Unsupported format (atm)\n");
+ return(-EFAULT);
+ }
+
+ mode |= (lfb.flags & 0xF900);
+ tdfx_outl(LFBMODE,mode);
+ mode = tdfx_inl(FBZCOLORPATH);
+ mode &= ~0xF;
+ tdfx_outl(FBZCOLORPATH,mode);
+
+ tdfx_outl(COLBUFFERADDR,lfb.color_buf);
+ // bit 15 can be used to enable titled
+ tdfx_outl(COLBUFFERSTRIDE,lfb.color_stride & 0x3FFF);
+ tdfx_outl(AUXBUFFERADDR,lfb.aux_buf);
+ // bit 15 can be used to enable titled
+ tdfx_outl(AUXBUFFERSTRIDE,lfb.aux_stride & 0x3FFF);
+ tdfx_outl(FBZMODE,lfb.mode);
+
+
+ return 0;
+}
+
+
+static int tdfx_vid_get_alpha(unsigned long arg) {
+ tdfx_vid_alpha_t alpha;
+ u32 reg = tdfx_inl(ALPHAMODE);
+
+ alpha.enable_func = reg & 1;
+ alpha.func = (reg >> 1) & 0x7;
+ alpha.enable_blend = (reg >> 4) & 1;
+ alpha.rgb_src = (reg >> 8) & 0xf;
+ alpha.rgb_dst = (reg >> 12) & 0xf;
+ alpha.alpha_src = (reg >> 16) & 0xf;
+ alpha.alpha_dst = (reg >> 20) & 0xf;
+ alpha.ref = reg >> 24;
+
+ if(copy_to_user((tdfx_vid_alpha_t*)arg,&alpha,sizeof(tdfx_vid_alpha_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
+ return(-EFAULT);
+ }
+ return 0;
+
+}
+
+static int tdfx_vid_set_alpha(unsigned long arg) {
+ tdfx_vid_alpha_t alpha;
+ u32 reg = tdfx_inl(ALPHAMODE);
+
+ if(copy_from_user(&alpha,(tdfx_vid_alpha_t*)arg,sizeof(tdfx_vid_alpha_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+
+ if(alpha.enable_func) {
+ reg &= ~0xE;
+ reg |= 1 | (alpha.func << 1);
+ } else
+ reg &= ~1;
+
+ if(alpha.enable_blend) {
+ reg &= ~0xFFFF00;
+ reg |= (1 << 4) | (alpha.rgb_src >> 8) | (alpha.rgb_dst >> 12) |
+ (alpha.alpha_src >> 16) | (alpha.alpha_dst >> 20);
+ } else
+ reg &= ~0x100;
+
+ reg &= 0xFFFFFF;
+ reg |= alpha.ref << 24;
+
+ tdfx_outl(ALPHAMODE,reg);
+
+ return 0;
+}
+
+
+static int tdfx_vid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ tdfx_vid_agp_move_t move;
+ tdfx_vid_config_t cfg;
+ tdfx_vid_blit_t blit;
+ u32 int32;
+
+ switch(cmd) {
+ case TDFX_VID_AGP_MOVE:
+ if(copy_from_user(&move,(tdfx_vid_agp_move_t*)arg,sizeof(tdfx_vid_agp_move_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+ return agp_move(&move);
+#if 0
+ case TDFX_VID_BUMP0:
+ if(copy_from_user(&int16,(u16*)arg,sizeof(u16))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+ return bump_fifo(int16);
+#endif
+ case TDFX_VID_BLIT:
+ if(copy_from_user(&blit,(tdfx_vid_blit_t*)arg,sizeof(tdfx_vid_blit_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+ if(!tdfx_vid_blit(&blit)) {
+ printk(KERN_INFO "tdfx_vid: Blit failed\n");
+ return(-EFAULT);
+ }
+ return 0;
+ case TDFX_VID_GET_CONFIG:
+ if(copy_from_user(&cfg,(tdfx_vid_config_t*)arg,sizeof(tdfx_vid_config_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+ tdfx_vid_get_config(&cfg);
+ if(copy_to_user((tdfx_vid_config_t*)arg,&cfg,sizeof(tdfx_vid_config_t))) {
+ printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
+ return(-EFAULT);
+ }
+ return 0;
+ case TDFX_VID_SET_YUV:
+ return tdfx_vid_set_yuv(arg);
+ case TDFX_VID_GET_YUV:
+ return tdfx_vid_get_yuv(arg);
+ case TDFX_VID_SET_OVERLAY:
+ return tdfx_vid_set_overlay(arg);
+ case TDFX_VID_OVERLAY_SWAP:
+ return tdfx_vid_overlay_swap(arg);
+ case TDFX_VID_OVERLAY_ON:
+ return tdfx_vid_overlay_on();
+ case TDFX_VID_OVERLAY_OFF:
+ return tdfx_vid_overlay_off();
+ case TDFX_VID_DUMP_REG:
+ if(copy_from_user(&int32,(u32*)arg,sizeof(u32))) {
+ printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
+ return(-EFAULT);
+ }
+ int32 = tdfx_inl(int32);
+ if(copy_to_user((u32*)arg,&int32,sizeof(u32))) {
+ printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
+ return(-EFAULT);
+ }
+ return 0;
+ case TDFX_VID_GET_3D_LFB:
+ return tdfx_vid_get_3d_lfb(arg);
+ case TDFX_VID_SET_3D_LFB:
+ return tdfx_vid_set_3d_lfb(arg);
+ case TDFX_VID_GET_ALPHA:
+ return tdfx_vid_get_alpha(arg);
+ case TDFX_VID_SET_ALPHA:
+ return tdfx_vid_set_alpha(arg);
+ default:
+ printk(KERN_ERR "tdfx_vid: Invalid ioctl %d\n",cmd);
+ return (-EINVAL);
+ }
+ return 0;
+}
+
+
+
+static ssize_t tdfx_vid_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ return 0;
+}
+
+static ssize_t tdfx_vid_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+
+ return 0;
+}
+
+static void tdfx_vid_mopen(struct vm_area_struct *vma) {
+ int i;
+ struct page *page;
+ unsigned long phys;
+
+ printk(KERN_DEBUG "tdfx_vid: mopen\n");
+
+ for(i = 0 ; i < agp_mem->page_count ; i++) {
+ phys = agp_mem->memory[i] & ~(0x00000fff);
+ page = virt_to_page(phys_to_virt(phys));
+ if(!page) {
+ printk(KERN_DEBUG "tdfx_vid: Can't get the page %d\%d\n",i,agp_mem->page_count);
+ return;
+ }
+ get_page(page);
+ }
+ MOD_INC_USE_COUNT;
+}
+
+static void tdfx_vid_mclose(struct vm_area_struct *vma) {
+ int i;
+ struct page *page;
+ unsigned long phys;
+
+ printk(KERN_DEBUG "tdfx_vid: mclose\n");
+
+ for(i = 0 ; i < agp_mem->page_count ; i++) {
+ phys = agp_mem->memory[i] & ~(0x00000fff);
+ page = virt_to_page(phys_to_virt(phys));
+ if(!page) {
+ printk(KERN_DEBUG "tdfx_vid: Can't get the page %d\%d\n",i,agp_mem->page_count);
+ return;
+ }
+ put_page(page);
+ }
+
+ MOD_DEC_USE_COUNT;
+}
+
+static struct page *tdfx_vid_nopage(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access) {
+ unsigned long off;
+ uint32_t n;
+ struct page *page;
+ unsigned long phys;
+
+ off = address - vma->vm_start + (vma->vm_pgoff<<PAGE_SHIFT);
+ n = off / PAGE_SIZE;
+
+ if(n >= agp_mem->page_count) {
+ printk(KERN_DEBUG "tdfx_vid: Too far away\n");
+ return ((struct page *)0UL);
+ }
+ phys = agp_mem->memory[n] & ~(0x00000fff);
+ page = virt_to_page(phys_to_virt(phys));
+ if(!page) {
+ printk(KERN_DEBUG "tdfx_vid: Can't get the page\n");
+ return ((struct page *)0UL);
+ }
+ return page;
+}
+
+/* memory handler functions */
+static struct vm_operations_struct tdfx_vid_vm_ops = {
+ open: tdfx_vid_mopen, /* mmap-open */
+ close: tdfx_vid_mclose,/* mmap-close */
+ nopage: tdfx_vid_nopage, /* no-page fault handler */
+};
+
+
+static int tdfx_vid_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ size_t size;
+#ifdef MP_DEBUG
+ printk(KERN_DEBUG "tdfx_vid: mapping agp memory into userspace\n");
+#endif
+
+ size = (vma->vm_end-vma->vm_start + PAGE_SIZE - 1) / PAGE_SIZE;
+
+ if(use_fifo) {
+ u32 s = tdfx_inl(CMDBASESIZE0);
+ fifo_n = FIFO0;
+ if(s & 0x100) {
+ printk(KERN_INFO "tdfx_vid: fifo0 alredy in use ... trying fifo1\n");
+ s = tdfx_inl(CMDBASESIZE1);
+ if(s & 0x100) {
+ printk(KERN_INFO "tdfx_vid: fifo1 also in use: no fifo\n");
+ use_fifo = 0;
+ } else
+ fifo_n = FIFO1;
+ }
+ }
+
+ if(use_fifo) {
+ printk(KERN_INFO "tdfx_vid: fifo avaible\n");
+ // Fix me if PAGE_SIZE != FIFO_PAGE_SIZE
+#if (PAGE_SIZE == FIFO_PAGE_SIZE)
+ fifo_offset = size*PAGE_SIZE;
+ size += FIFO_PAGES;
+#else
+#error Fix me
+#endif
+ }
+
+ if(map_start) { // Ok we map directly in the physcal ram
+ if(size*PAGE_SIZE > map_max) {
+ printk(KERN_ERR "tdfx_vid: Not enouth mem\n");
+ return(-EAGAIN);
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
+ if(remap_page_range(vma, vma->vm_start,map_start,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+#else
+ if(remap_page_range(vma->vm_start, (unsigned long)map_start,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+#endif
+ {
+ printk(KERN_ERR "tdfx_vid: error mapping video memory\n");
+ return(-EAGAIN);
+ }
+ printk(KERN_INFO "Physical mem 0x%lx mapped in userspace\n",map_start);
+ return 0;
+ }
+
+ if(agp_mem)
+ return(-EAGAIN);
+
+ agp_mem = drm_agp->allocate_memory(size,AGP_NORMAL_MEMORY);
+ if(!agp_mem) {
+ printk(KERN_ERR "Failed to allocate AGP memory\n");
+ return(-ENOMEM);
+ }
+
+ if(drm_agp->bind_memory(agp_mem,0)) {
+ printk(KERN_ERR "Failed to bind the AGP memory\n");
+ drm_agp->free_memory(agp_mem);
+ agp_mem = NULL;
+ return(-ENOMEM);
+ }
+
+ printk(KERN_INFO "%d pages of AGP mem allocated (%ld/%ld bytes) :)))\n",
+ size,vma->vm_end-vma->vm_start,size*PAGE_SIZE);
+
+
+ if(tdfx_map_io) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
+ if(remap_page_range(vma, vma->vm_start,agp_info.aper_base,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+#else
+ if(remap_page_range(vma->vm_start, (unsigned long)agp_info.aper_base,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+#endif
+ {
+ printk(KERN_ERR "tdfx_vid: error mapping video memory\n");
+ return(-EAGAIN);
+ }
+ } else {
+ // Never swap it out
+ vma->vm_flags |= VM_LOCKED | VM_IO;
+ vma->vm_ops = &tdfx_vid_vm_ops;
+ vma->vm_ops->open(vma);
+ printk(KERN_INFO "Page fault handler ready !!!!!\n");
+ }
+
+ if(use_fifo) {
+ use_fifo = open_fifo(fifo_offset,FIFO_PAGES);
+ if(use_fifo) {
+ fifo = ioremap_nocache(agp_info.aper_base + fifo_offset,FIFO_SIZE);
+ printk(KERN_INFO "Fifo at 0x%p\n", fifo);
+ }
+ }
+
+ return 0;
+}
+
+
+static int tdfx_vid_release(struct inode *inode, struct file *file)
+{
+#ifdef MP_DEBUG
+ printk(KERN_DEBUG "tdfx_vid: Video OFF (release)\n");
+#endif
+
+ if(use_fifo) {
+ close_fifo();
+ if(fifo)
+ iounmap(fifo);
+ fifo = NULL;
+ }
+
+ // Release the agp mem
+ if(agp_mem) {
+ drm_agp->unbind_memory(agp_mem);
+ drm_agp->free_memory(agp_mem);
+ agp_mem = NULL;
+ }
+
+ tdfx_vid_in_use = 0;
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static long long tdfx_vid_lseek(struct file *file, long long offset, int origin)
+{
+ return -ESPIPE;
+}
+
+static int tdfx_vid_open(struct inode *inode, struct file *file)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)
+ int minor = MINOR(inode->i_rdev.value);
+#else
+ int minor = MINOR(inode->i_rdev);
+#endif
+
+ if(minor != 0)
+ return(-ENXIO);
+
+ if(tdfx_vid_in_use == 1)
+ return(-EBUSY);
+
+ tdfx_vid_in_use = 1;
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+#if LINUX_VERSION_CODE >= 0x020400
+static struct file_operations tdfx_vid_fops =
+{
+ llseek: tdfx_vid_lseek,
+ read: tdfx_vid_read,
+ write: tdfx_vid_write,
+ ioctl: tdfx_vid_ioctl,
+ mmap: tdfx_vid_mmap,
+ open: tdfx_vid_open,
+ release: tdfx_vid_release
+};
+#else
+static struct file_operations tdfx_vid_fops =
+{
+ tdfx_vid_lseek,
+ tdfx_vid_read,
+ tdfx_vid_write,
+ NULL,
+ NULL,
+ tdfx_vid_ioctl,
+ tdfx_vid_mmap,
+ tdfx_vid_open,
+ NULL,
+ tdfx_vid_release
+};
+#endif
+
+
+int init_module(void)
+{
+ tdfx_vid_in_use = 0;
+
+ if(register_chrdev(TDFX_VID_MAJOR, "tdfx_vid", &tdfx_vid_fops)) {
+ printk(KERN_ERR "tdfx_vid: unable to get major: %d\n", TDFX_VID_MAJOR);
+ return -EIO;
+ }
+
+ if(!agp_init()) {
+ printk(KERN_ERR "tdfx_vid: AGP init failed\n");
+ unregister_chrdev(TDFX_VID_MAJOR, "tdfx_vid");
+ return -EINVAL;
+ }
+
+ if (!tdfx_vid_find_card()) {
+ printk(KERN_ERR "tdfx_vid: no supported devices found\n");
+ agp_close();
+ unregister_chrdev(TDFX_VID_MAJOR, "tdfx_vid");
+ return -EINVAL;
+ }
+
+
+
+ return (0);
+
+}
+
+void cleanup_module(void)
+{
+ if(tdfx_mmio_base)
+ iounmap(tdfx_mmio_base);
+ agp_close();
+ printk(KERN_INFO "tdfx_vid: Cleaning up module\n");
+ unregister_chrdev(TDFX_VID_MAJOR, "tdfx_vid");
+}
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/drivers/tdfx_vid.h Wed Jul 16 23:27:37 2003
@@ -0,0 +1,225 @@
+
+
+#define TDFX_VID_VERSION 1
+
+#define TDFX_VID_MOVE_2_PACKED 0
+#define TDFX_VID_MOVE_2_YUV 1
+#define TDFX_VID_MOVE_2_3D 2
+#define TDFX_VID_MOVE_2_TEXTURE 3
+
+#define TDFX_VID_SRC_COLORKEY 0x1
+#define TDFX_VID_DST_COLORKEY 0x2
+
+#define TDFX_VID_ROP_NOP 0xaa // dst ?
+#define TDFX_VID_ROP_COPY 0xcc // src
+#define TDFX_VID_ROP_INVERT 0x55 // NOT dst
+#define TDFX_VID_ROP_XOR 0x66 // src XOR dst
+#define TDFX_VID_ROP_OR 0xee // src OR dst
+
+#define TDFX_VID_FORMAT_BGR1 (('B'<<24)|('G'<<16)|('R'<<8)|1)
+#define TDFX_VID_FORMAT_BGR8 (('B'<<24)|('G'<<16)|('R'<<8)|8)
+// x-5-5-5
+#define TDFX_VID_FORMAT_BGR15 (('B'<<24)|('G'<<16)|('R'<<8)|15)
+#define TDFX_VID_FORMAT_RGB15 (('R'<<24)|('G'<<16)|('B'<<8)|15)
+// 5-5-5-x
+#define TDFX_VID_FORMAT_15BGR ((15<<24)|('B'<<16)|('G'<<8)|'R')
+#define TDFX_VID_FORMAT_15RGB ((15<<24)|('R'<<16)|('G'<<8)|'B')
+// 5-6-5
+#define TDFX_VID_FORMAT_BGR16 (('B'<<24)|('G'<<16)|('R'<<8)|16)
+#define TDFX_VID_FORMAT_RGB16 (('R'<<24)|('G'<<16)|('B'<<8)|16)
+// x-8-8-8
+#define TDFX_VID_FORMAT_BGR24 (('B'<<24)|('G'<<16)|('R'<<8)|24)
+#define TDFX_VID_FORMAT_RGB24 (('R'<<24)|('G'<<16)|('B'<<8)|24)
+// 8-8-8-x
+#define TDFX_VID_FORMAT_24BGR ((24<<24)|('B'<<16)|('G'<<8)|'R')
+#define TDFX_VID_FORMAT_24RGB ((24<<24)|('R'<<16)|('G'<<8)|'B')
+
+#define TDFX_VID_FORMAT_BGR32 (('B'<<24)|('G'<<16)|('R'<<8)|32)
+
+#define TDFX_VID_FORMAT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y')
+#define TDFX_VID_FORMAT_UYVY (('Y'<<24)|('V'<<16)|('Y'<<8)|'U')
+
+#define TDFX_VID_FORMAT_YV12 0x32315659
+#define TDFX_VID_FORMAT_IYUV (('I'<<24)|('Y'<<16)|('U'<<8)|'V')
+#define TDFX_VID_FORMAT_I420 (('I'<<24)|('4'<<16)|('2'<<8)|'0')
+
+// 1-5-5-5
+#define TDFX_VID_FORMAT_BGRA16 (('B'<<24)|('G'<<16)|('A'<<8)|16)
+// 8-8-8-8
+#define TDFX_VID_FORMAT_BGRA32 (('B'<<24)|('G'<<16)|('A'<<8)|32)
+#define TDFX_VID_FORMAT_ABGR16 (('A'<<24)|('G'<<16)|('R'<<8)|16)
+#define TDFX_VID_FORMAT_ABGR32 (('A'<<24)|('G'<<16)|('R'<<8)|32)
+
+// 5-5-5-1
+#define TDFX_VID_FORMAT_RGBA16 (('R'<<24)|('G'<<16)|('A'<<8)|16)
+#define TDFX_VID_FORMAT_RGBA32 (('R'<<24)|('G'<<16)|('A'<<8)|32)
+#define TDFX_VID_FORMAT_ARGB16 (('A'<<24)|('G'<<16)|('B'<<8)|16)
+#define TDFX_VID_FORMAT_ARGB32 (('A'<<24)|('G'<<16)|('B'<<8)|32)
+
+#define TDFX_VID_YUV_STRIDE (1024)
+#define TDFX_VID_YUV_PLANE_SIZE (0x0100000)
+
+
+#define TDFX_VID_FIFO_PAGE_SIZE 4096
+
+typedef struct tdfx_vid_blit_s {
+ uint32_t src;
+ uint32_t src_stride;
+ uint16_t src_x,src_y;
+ uint16_t src_w,src_h;
+ uint32_t src_format;
+
+ uint32_t dst;
+ uint32_t dst_stride;
+ uint16_t dst_x,dst_y;
+ uint16_t dst_w,dst_h;
+ uint32_t dst_format;
+
+ // Min/max colorkeys
+ uint32_t src_colorkey[2];
+ uint32_t dst_colorkey[2];
+
+ // Enable the src and/or dst colorkey
+ uint8_t colorkey;
+ /* rop define the action to execute on each pixel depending
+ * on the src and dst colorkey matching.
+ * a pixel match the colorkey if :
+ * pixel >= colorkey[0] && pixel <= colorkey[1] && colorkey & MASK
+ * So if the colorkey is not enabled it always fail.
+ * If colorkey == 0 && rop[0] == 0 the driver do a simple copy
+ * ie. rop[0] = TDFX_VID_ROP_COPY
+ *
+ * | src f | src m |
+ * -------+-------+-------+
+ * dst f | 0 | 2 |
+ * -------+-------+-------+
+ * dst m | 1 | 3 |
+ * -------+-------+-------+
+ */
+ uint8_t rop[4];
+} tdfx_vid_blit_t;
+
+typedef struct tdfx_vid_config_s {
+ uint16_t version;
+ uint16_t card_type;
+ uint32_t ram_size;
+ uint16_t screen_width;
+ uint16_t screen_height;
+ uint16_t screen_stride;
+ uint32_t screen_format;
+ uint32_t screen_start;
+ uint8_t triple_buffering;
+} tdfx_vid_config_t;
+
+typedef struct tdfx_vid_agp_move_s {
+ uint16_t move2;
+ uint16_t width,height;
+
+ uint32_t src;
+ uint32_t src_stride;
+
+ uint32_t dst;
+ uint32_t dst_stride;
+} tdfx_vid_agp_move_t;
+
+typedef struct tdfx_vid_yuv_s {
+ uint32_t base;
+ uint16_t stride;
+} tdfx_vid_yuv_t;
+
+typedef struct tdfx_vid_overlay_s {
+ uint32_t src[2]; // left and right buffer (2 buffer may be NULL)
+ uint16_t src_width,src_height;
+ uint16_t src_stride;
+ uint32_t format;
+
+ uint16_t dst_width,dst_height;
+ int16_t dst_x,dst_y;
+
+ uint8_t use_colorkey;
+ uint32_t colorkey[2]; // min/max
+ uint8_t invert_colorkey;
+} tdfx_vid_overlay_t;
+
+// flags
+// enable the graphic pipeline (ie do depth buffering, fog, alpha, etc)
+#define TDFX_VID_PIPELINE (1<<8)
+// swap incoming words
+#define TDFX_VID_WORD_SWAP (1<<11)
+// swap incoming bytes
+#define TDFX_VID_BYTE_SWAP (1<<12)
+
+typedef struct tdfx_vid_3d_lfb_s {
+ uint32_t color_buf; // ie the buffer where RGB data are wrote
+ uint16_t color_stride;
+ uint32_t format; // Write format
+ uint32_t flags; // enable/disable graphic pipeline, etc
+ uint32_t aux_buf;
+ uint16_t aux_stride; // For alpha or depth buffer
+
+ uint32_t mode; // enable/disable clipping, depth buffer, etc
+} tdfx_vid_3d_lfb_t;
+
+
+// Alpha func: colorkey on the alpha channel
+// The pixel is drawn only if (AlphaSrc AlphaFunc AlphaRef) is true
+#define TDFX_VID_AF_NEVER 0
+// less than
+#define TDFX_VID_AF_LT 1
+// equal
+#define TDFX_VID_AF_EQ 2
+// less or equal
+#define TDFX_VID_AF_LEQ 3
+// greater than
+#define TDFX_VID_AF_GT 4
+
+// Alpha blending
+// The blending is done by the following equation :
+// dst = (src * xxx_src) + (dst * xxx_dst)
+// where xxx is either rgb or alpha
+#define TDFX_VID_AB_ZERO 0x0
+#define TDFX_VID_AB_SRC 0x1
+#define TDFX_VID_AB_COLOR 0x2
+#define TDFX_VID_AB_DST 0x3
+#define TDFX_VID_AB_ONE 0x4
+#define TDFX_VID_AB_OM_SRC 0x5
+#define TDFX_VID_AB_OM_COLOR 0x6
+#define TDFX_VID_AB_OM_DST 0x7
+#define TDFX_VID_AB_SATURATE 0xf
+#define TDFX_VID_AB_COLORBEFOREFOG 0xf
+
+
+typedef struct tdfx_vid_alpha_s {
+ uint8_t enable_func;
+ uint8_t func;
+ uint8_t ref;
+
+ uint8_t enable_blend;
+ uint8_t rgb_src;
+ uint8_t rgb_dst;
+ uint8_t alpha_src;
+ uint8_t alpha_dst;
+} tdfx_vid_alpha_t;
+
+typedef struct tdfx_vid_swap_s {
+ uint32_t buffer;
+ uint8_t sync; // Sync V-Sync
+} tdfx_vid_swap_t;
+
+
+#define TDFX_VID_GET_CONFIG _IOR('J', 1, tdfx_vid_config_t)
+#define TDFX_VID_AGP_MOVE _IOW('J', 2, tdfx_vid_agp_move_t)
+#define TDFX_VID_BLIT _IOW('J', 3, tdfx_vid_blit_t)
+#define TDFX_VID_SET_YUV _IOW('J', 4, tdfx_vid_blit_t)
+#define TDFX_VID_GET_YUV _IOR('J', 5, tdfx_vid_blit_t)
+#define TDFX_VID_BUMP0 _IOW('J', 6, u16)
+#define TDFX_VID_SET_OVERLAY _IOW('J', 7, tdfx_vid_overlay_t)
+#define TDFX_VID_OVERLAY_ON _IO ('J', 8)
+#define TDFX_VID_OVERLAY_OFF _IO ('J', 9)
+#define TDFX_VID_OVERLAY_SWAP _IOW('J', 10, tdfx_vid_swap_t)
+#define TDFX_VID_DUMP_REG _IOR('J', 11, uint32_t)
+#define TDFX_VID_GET_3D_LFB _IOR('J', 12, tdfx_vid_3d_lfb_t)
+#define TDFX_VID_SET_3D_LFB _IOW('J', 13, tdfx_vid_3d_lfb_t)
+#define TDFX_VID_GET_ALPHA _IOR('J', 14, tdfx_vid_alpha_t)
+#define TDFX_VID_SET_ALPHA _IOW('J', 15, tdfx_vid_alpha_t)
+
--- /home/alban/MP/g2/libvo2/Makefile Sun Jul 13 18:20:25 2003
+++ /home/alban/MP/g2.dev/libvo2/Makefile Thu Jul 17 02:38:04 2003
@@ -3,7 +3,7 @@
LIBNAME = libvo2.a
-SRCS=vo_null.c vo_x11.c vo_xv.c vo_mga.c video_out.c event.c x11_helper.c # vo_pgm.c vo_md5.c
+SRCS=vo_null.c vo_x11.c vo_xv.c vo_mga.c vo_tdfx_vid.c vo_xover.c video_out.c event.c x11_helper.c # vo_pgm.c vo_md5.c
OBJS=$(SRCS:.c=.o)
ifeq ($(VIDIX),yes)
--- /home/alban/MP/g2/libvo2/video_out.c Sun Jul 13 18:33:42 2003
+++ /home/alban/MP/g2.dev/libvo2/video_out.c Thu Jul 17 02:44:34 2003
@@ -17,11 +17,15 @@
extern vo_info_t vo_driver_x11;
extern vo_info_t vo_driver_xv;
extern vo_info_t vo_driver_null;
+extern vo_info_t vo_driver_tdfx_vid;
+extern vo_info_t vo_driver_xover;
vo_info_t* video_out_drivers[] = {
&vo_driver_mga,
+ &vo_driver_tdfx_vid,
&vo_driver_x11,
&vo_driver_xv,
+ &vo_driver_xover,
&vo_driver_null,
NULL
};
--- /home/alban/MP/g2/libvo2/video_out.h Sun Jul 13 23:02:22 2003
+++ /home/alban/MP/g2.dev/libvo2/video_out.h Thu Jul 17 14:39:24 2003
@@ -22,6 +22,8 @@
#define VOCTRL_RESIZE_SRC 2
// tells driver the x11 (or win32) window id:
#define VOCTRL_SET_WINDOW 3
+/* set the colorkay to use for a child display */
+#define VOCTRL_SET_COLORKEY 10
/* signal a device pause */
#define VOCTRL_PAUSE 7
/* start/resume playback */
@@ -54,6 +56,8 @@
// show-frame() can display the frame at any time position (pts), using
// hardware timer (for example dxr3/dvb mpeg-pes) [replaces format flag 0x100]
#define VO_BUFFER_FLAG_TIMER 8
+// show-frame() can display the frame at any relative time position
+#define VO_BUFFER_FLAG_SLEEP 16
//****** vo2 specific module_info_t flags: ********
// module can work as parent for other sub-vo module (xover, vesa, fbdev...)
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/libvo2/vo_tdfx_vid.c Thu Jul 17 18:32:18 2003
@@ -0,0 +1,497 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "mp_msg.h"
+#include "video_out.h"
+#include "video/vfcap.h"
+#include "video/img_format.h"
+
+#include "drivers/tdfx_vid.h"
+
+/*
+ * We have two memory area. The AGP memory, wich is located
+ * in RAM (but sadly read are slow) and the video memory on the
+ * card.
+ * So we are exporting the AGP buffer. Stride doesn't matter as
+ * we can change it during the AGP move.
+ * On the card we use 4 buffers. The first 3 are used for the overlay
+ * and the last one is used to do colorspace conversion and/or
+ * scaling.
+ * The overlay can only accept 3 colorspace YUY2, UYVY and BGR16 and
+ * doesn't do downscaling.
+ * However the card have a chip to convert planar YUV (YV12 and I420)
+ * to YUY2 and we can do blit with colorspace conversion and/or scaling.
+ *
+ * The colorspace are handled as follow:
+ *
+ * YV12, I420 :
+ * - Upscaling : -> YUV -> Overlay buffer YUY2
+ * - Downscaling : -> YUV -> Conv Buffer YUY2 -> Overlay buffer BGR16
+ *
+ * YUY2, UYVY :
+ * - Upscaling : -> Overlay buffer YUY2 or UYVY
+ * - Downscaling : -> Conv Buffer YUY2 or UYVY -> Overlay buffer BGR16
+ *
+ * BGR16 :
+ * - Upscaling : -> Overlay buffer BGR16
+ * - Downscaling : -> Conv Buffer BGR16 -> Overlay buffer BGR16
+ *
+ * BGR24, BGR32 :
+ * - Upscaling : -> Conv Buffer BGR24 or BGR32 -> Overlay buffer BGR16
+ * - Downscaling : -> Conv Buffer BGR24 or BGR32 -> Overlay buffer BGR16
+ *
+ *
+ * The vrate option enable the VO_BUFFER_FLAG_SLEEP. You must give it
+ * the vertical refresh rate (in Hz) of your current video mode.
+ * In normal conditions mplayer uselly have to sleep before calling
+ * show_frame to ensure A/V sync. But when VO_BUFFER_FLAG_SLEEP is enabled
+ * mplayer won't sleep and will call show_frame with the wait delay in the
+ * pts argument.
+ * Now knowing the refresh rate we instruct the banshee to do flip at the
+ * right moment and return. This way mplayer doesn't need to sleep and the
+ * A/V sync is right :)
+ * On my box (K6-2 333) a clip wich normally use ~80% of CPU go down
+ * to ~55% according to top. So it seems to help :)
+ *
+ */
+
+
+#define ALIGN(p,n) ((((p)+(n-1))/n)*n)
+
+static struct config_data_s {
+ char* dev;
+ float v_rate;
+} options_def = {
+ "/dev/tdfx_vid",
+ 0
+};
+
+static config_t options[] = {
+ { "dev", &options_def.dev, CONF_TYPE_STRING, 0, 0, 0, 0, "Device to use" },
+ { "vrate", &options_def.v_rate, CONF_TYPE_FLOAT, CONF_MIN, 0, 0, 0, "Vertical refresh rate (enable 'sleeping vo')" },
+ { NULL, NULL, 0, 0, 0, 0, 0, NULL }
+};
+
+struct vo_priv_s {
+ int fd;
+ unsigned char* agp_mem;
+ tdfx_vid_config_t cfg;
+ tdfx_vid_overlay_t ov;
+ // Our 3 buffers used by the overlay in video mem
+ uint32_t ov_buf[3];
+ unsigned int ov_fmt; // To save the normal overlay format
+ // The conversion buffer (used for BGR24 or downscaling)
+ unsigned int cv_fmt;
+ int cv_stride;
+ int cv_bpp;
+ uint32_t cv_buf;
+ float v_rate; // V-Sync per second
+};
+
+static int control(struct vo_instance_s* vo,
+ int request, void *data, ...){
+ switch(request) {
+ case VOCTRL_RESIZE_DEST: {
+ int *a = data;
+
+ vo->priv->ov.src_width = vo->buffer_w;
+ vo->priv->ov.src_height = vo->buffer_h;
+ vo->priv->ov.format = vo->priv->ov_fmt;
+
+ if(a[0] >= 0) vo->priv->ov.dst_x = a[0];
+ if(a[1] >= 0) vo->priv->ov.dst_y = a[1];
+ if(a[2] > 0) vo->priv->ov.dst_width = a[2];
+ if(a[3] > 0) vo->priv->ov.dst_height = a[3];
+
+ // We can't downscale so we'll convert
+ if(vo->priv->ov.dst_width < vo->buffer_w) {
+ vo->priv->ov.src_width = vo->priv->ov.dst_width;
+ vo->priv->ov.format = IMGFMT_BGR16;
+ }
+ if(vo->priv->ov.dst_height < vo->buffer_h) {
+ vo->priv->ov.src_height = vo->priv->ov.dst_height;
+ vo->priv->ov.format = IMGFMT_BGR16;
+ }
+ if(ioctl(vo->priv->fd,TDFX_VID_SET_OVERLAY,&vo->priv->ov)) {
+ mp_msg(MSGT_VO, MSGL_ERR, "tdfx_vid: set_overlay failed\n");
+ return VO_FALSE;
+ }
+ return VO_TRUE;
+ } break;
+ case VOCTRL_SET_COLORKEY:
+ vo->priv->ov.use_colorkey = 1;
+ vo->priv->ov.colorkey[0] = vo->priv->ov.colorkey[1] = *((int*)data);
+ if(vo->config_count) {
+ if(ioctl(vo->priv->fd,TDFX_VID_SET_OVERLAY,&vo->priv->ov)) {
+ mp_msg(MSGT_VO, MSGL_ERR, "tdfx_vid: set_overlay failed\n");
+ return VO_FALSE;
+ }
+ }
+ return VO_TRUE;
+ default:
+ return VO_NOTIMPL;
+ };
+}
+
+static unsigned int query_format(struct vo_instance_s* vo,
+ unsigned int format, int width, int height){
+ unsigned int ret = VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_HWSCALE_UP|VFCAP_HWSCALE_DOWN|VFCAP_ACCEPT_STRIDE;
+
+ // TODO find the limits (both ov and planar thing) and check width, height
+
+ switch(format) {
+ case IMGFMT_YUY2:
+ case IMGFMT_UYVY:
+ // case IMGFMT_BGR15:
+ case IMGFMT_BGR16:
+ case IMGFMT_BGR24:
+ case IMGFMT_BGR32:
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ if(vo->priv->cfg.screen_format == TDFX_VID_FORMAT_BGR8)
+ return 0;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int config(struct vo_instance_s* vo,
+ int width, int height, int d_width, int d_height,
+ unsigned int format){
+ int buf_size;
+ int buf_stride;
+ uint32_t last_buf = (uint32_t)vo->priv->agp_mem;
+ int i,planar=0;;
+
+ vo->num_buffers=3;
+ if(vo->buffers) free(vo->buffers);
+ vo->buffers=calloc(sizeof(vo_buffer_t),vo->num_buffers);
+ vo->buffer_w=width; vo->buffer_h=height;
+ vo->format=format;
+ vo->buffer_flags=VO_BUFFER_FLAG_VIDEORAM; // AGP mem read are slow :(((
+ // We have the vertical refresh rate: enable 'sleeping vo'
+ if(vo->priv->v_rate > 0)
+ vo->buffer_flags|=VO_BUFFER_FLAG_SLEEP;
+ vo->w=d_width; vo->h=d_height;
+
+ switch(format) {
+ // Planar format
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ vo->priv->ov.format = IMGFMT_YUY2;
+ vo->priv->cv_fmt = vo->priv->ov.format;
+ buf_stride = ALIGN(width,2);
+ buf_size = buf_stride * height * 3 / 2;
+ planar = 1;
+ break;
+ // Native packed format
+ case IMGFMT_YUY2:
+ case IMGFMT_UYVY:
+ case IMGFMT_BGR16:
+ vo->priv->ov.format = format;
+ vo->priv->cv_fmt = format;
+ buf_stride = width * 2;
+ buf_size = buf_stride * height;
+ break;
+ // Converted packed
+ case IMGFMT_BGR24:
+ case IMGFMT_BGR32:
+ vo->priv->ov.format = IMGFMT_BGR16;
+ vo->priv->cv_fmt = format;
+ buf_stride = width * (IMGFMT_BGR_DEPTH(format)/8);
+ buf_size = buf_stride * height;
+ break;
+ default:
+ printf("Wrong format: %s (0x%x)\n",vo_format_name(format),format);
+ return VO_FALSE;
+ }
+
+ // Make the buffer list
+ //
+ for(i = 0 ; i < vo->num_buffers ; i++) {
+ vo->buffers[i].planes[0] = (unsigned char*)last_buf;
+ if(planar) {
+ vo->buffers[i].planes[1] = (unsigned char*)last_buf + (buf_stride*height);
+ vo->buffers[i].planes[2] = (unsigned char*)last_buf + (buf_stride*height)*5/4;
+ }
+ vo->buffers[i].stride[0] = buf_stride;
+ if(planar)
+ vo->buffers[i].stride[1] = vo->buffers[i].stride[2] = buf_stride/2;
+ vo->buffers[i].priv = (void*)i;
+ last_buf += buf_size;
+ }
+
+ // Setup the overlay stuff
+ // Note that the overlay bytes per pixel is always 2
+ // Overlay need a 4 bytes aligned stride and 16 bytes aligned buffers
+ vo->priv->ov.src_stride = ALIGN(2*width,4);
+
+ vo->priv->ov_buf[0] = ALIGN(vo->priv->cfg.screen_start + (vo->priv->cfg.screen_stride*vo->priv->cfg.screen_height),16);
+ vo->priv->ov_buf[1] = ALIGN(vo->priv->ov_buf[0] + (vo->priv->ov.src_stride * height),16);
+ vo->priv->ov_buf[2] = ALIGN(vo->priv->ov_buf[1] + (vo->priv->ov.src_stride * height),16);
+
+ vo->priv->ov.src_width = width;
+ vo->priv->ov.src_height = height;
+ vo->priv->ov.src[0] = vo->priv->ov_buf[0];
+ vo->priv->ov.dst_width = d_width;
+ vo->priv->ov.dst_height = d_height;
+
+ if(ioctl(vo->priv->fd,TDFX_VID_SET_OVERLAY,&vo->priv->ov)) {
+ mp_msg(MSGT_VO, MSGL_ERR, "tdfx_vid: set_overlay failed\n");
+ return VO_FALSE;
+ }
+
+ // Enable the overlay
+ if(ioctl(vo->priv->fd,TDFX_VID_OVERLAY_ON)) {
+ printf("tdfx_vid: Overlay on failed\n");
+ return VO_FALSE;
+ }
+
+ // The conversion buffer
+ vo->priv->cv_buf = vo->priv->ov_buf[2] + vo->priv->ov.src_stride * height;
+ switch(vo->priv->cv_fmt){
+ case IMGFMT_BGR24:
+ case IMGFMT_BGR32:
+ vo->priv->cv_bpp = (IMGFMT_BGR_DEPTH(format)/8);
+ break;
+ // YUY2, UYVY, BGR16
+ default:
+ vo->priv->cv_bpp = 2;
+ break;
+ }
+
+ vo->priv->cv_stride = width*vo->priv->cv_bpp;
+ vo->priv->ov_fmt = vo->priv->ov.format;
+
+ return VO_TRUE;
+}
+
+
+
+static int frame_done(struct vo_instance_s* vo, vo_buffer_t* buffer) {
+ tdfx_vid_agp_move_t mov;
+ tdfx_vid_blit_t blit;
+ int buf = (int)buffer->priv;
+ uint32_t dst;
+ uint32_t dst_stride;
+ uint32_t dst_bpp;
+
+ if(vo->priv->ov.format == vo->priv->cv_fmt &&
+ vo->priv->ov.src_width == vo->buffer_w &&
+ vo->priv->ov.src_height == vo->buffer_h) {
+ dst = vo->priv->ov_buf[buf];
+ dst_stride = vo->priv->ov.src_stride;
+ dst_bpp = 2;
+ } else {
+ dst = vo->priv->cv_buf;
+ dst_stride = vo->priv->cv_stride;
+ dst_bpp = vo->priv->cv_bpp;
+ }
+
+ // Planar format
+ if(vo->format == IMGFMT_YV12 || vo->format == IMGFMT_I420) {
+ tdfx_vid_yuv_t yuv;
+
+ // Setup the yuv thing
+ yuv.base = dst;
+ yuv.stride = dst_stride;
+ if(ioctl(vo->priv->fd,TDFX_VID_SET_YUV,&yuv)) {
+ printf("tdfx_vid: Set yuv failed\n");
+ return VO_FALSE;
+ }
+
+ // Now agp move that
+ // Y
+ mov.move2 = TDFX_VID_MOVE_2_YUV;
+ mov.width = vo->buffer_w;
+ mov.height = vo->buffer_h;
+ mov.src = buffer->planes[0] - vo->priv->agp_mem;
+ mov.src_stride = buffer->stride[0];
+ mov.dst = 0x0;
+ mov.dst_stride = TDFX_VID_YUV_STRIDE;
+
+ if(ioctl(vo->priv->fd,TDFX_VID_AGP_MOVE,&mov)) {
+ printf("tdfx_vid: AGP move failed on Y plane\n");
+ return VO_FALSE;
+ }
+ //return 0;
+ // U
+ mov.width = vo->buffer_w/2;
+ mov.height = vo->buffer_h/2;
+ mov.src = buffer->planes[2] - vo->priv->agp_mem;
+ mov.src_stride = buffer->stride[2];
+ mov.dst += TDFX_VID_YUV_PLANE_SIZE;
+ if(ioctl(vo->priv->fd,TDFX_VID_AGP_MOVE,&mov)) {
+ printf("tdfx_vid: AGP move failed on U plane\n");
+ return VO_FALSE;
+ }
+ // V
+ mov.src = buffer->planes[1] - vo->priv->agp_mem;
+ mov.src_stride = buffer->stride[1];
+ mov.dst += TDFX_VID_YUV_PLANE_SIZE;
+ if(ioctl(vo->priv->fd,TDFX_VID_AGP_MOVE,&mov)) {
+ printf("tdfx_vid: AGP move failed on U plane\n");
+ return VO_FALSE;
+ }
+
+ } else { // Packed format
+ mov.move2 = TDFX_VID_MOVE_2_PACKED;
+ mov.width = vo->buffer_w*dst_bpp;
+ mov.height = vo->buffer_h;
+ mov.src = buffer->planes[0] - vo->priv->agp_mem;
+ mov.src_stride = buffer->stride[0];
+
+ mov.dst = dst;
+ mov.dst_stride = dst_stride;
+
+ if(ioctl(vo->priv->fd,TDFX_VID_AGP_MOVE,&mov)) {
+ printf("tdfx_vid: AGP move failed\n");
+ return VO_FALSE;
+ }
+ }
+
+ // No conversion needed we are done
+ if(dst != vo->priv->cv_buf) return VO_TRUE;
+
+ memset(&blit,0,sizeof(tdfx_vid_blit_t));
+ blit.src = vo->priv->cv_buf;
+ blit.src_stride = vo->priv->cv_stride;
+ blit.src_x = 0;
+ blit.src_y = 0;
+ blit.src_w = vo->buffer_w;
+ blit.src_h = vo->buffer_h;
+ blit.src_format = vo->priv->cv_fmt;
+
+ blit.dst = vo->priv->ov_buf[buf];
+ blit.dst_stride = vo->priv->ov.src_stride;
+ blit.dst_x = 0;
+ blit.dst_y = 0;
+ blit.dst_w = vo->priv->ov.src_width;
+ blit.dst_h = vo->priv->ov.src_height;
+ blit.dst_format = vo->priv->ov.format;
+
+ if(ioctl(vo->priv->fd,TDFX_VID_BLIT,&blit)) {
+ printf("tdfx_vid: Blit failed\n");
+ return VO_FALSE;
+ }
+
+ return VO_TRUE;
+}
+
+static void show_frame(struct vo_instance_s* vo, vo_buffer_t* buffer,
+ float pts){
+ tdfx_vid_swap_t swap = {
+ vo->priv->ov_buf[(int)buffer->priv],
+ 1 // wait v-sync
+ };
+
+ //printf("\nGot pts %f\n",pts);
+ if(pts > 0)
+ swap.sync = pts*vo->priv->v_rate; // My refersh rate
+ //printf("Waiting %d\n",swap.sync);
+
+ if(!ioctl(vo->priv->fd,TDFX_VID_OVERLAY_ON)) { // X11 killed the overlay :(
+ if(ioctl(vo->priv->fd,TDFX_VID_SET_OVERLAY,&vo->priv->ov))
+ mp_msg(MSGT_VO, MSGL_ERR, "tdfx_vid: set_overlay failed\n");
+ }
+
+ if(ioctl(vo->priv->fd,TDFX_VID_OVERLAY_SWAP,&swap))
+ printf("tdfx_vid: Flip buffer failed\n");
+}
+
+static void uninit(struct vo_instance_s* vo) {
+ if(!vo->priv) return;
+
+ if(vo->priv->fd) {
+ ioctl(vo->priv->fd,TDFX_VID_OVERLAY_OFF);
+ close(vo->priv->fd);
+ }
+
+ free(vo->priv);
+ vo->priv = NULL;
+}
+
+static vo_instance_t* preinit(char* args,void* x11_display){
+ int fd;
+ unsigned char* agp_mem;
+ tdfx_vid_config_t tdfx_cfg;
+ vo_instance_t* vo;
+ config_data_t* cfg = args ? (config_data_t*)args : &options_def;
+
+ fd = open(cfg->dev, O_RDWR);
+ if(fd < 0) {
+ printf("tdfx_vid: Can't open %s: %s\n",cfg->dev,strerror(errno));
+ return NULL;
+ }
+
+ if(ioctl(fd,TDFX_VID_GET_CONFIG,&tdfx_cfg)) {
+ printf("tdfx_vid: Can't get current cfg: %s\n",strerror(errno));
+ close(fd);
+ return NULL;
+ }
+
+ printf("tdfx_vid version %d\n"
+ " Ram: %d\n"
+ " Screen: %d x %d\n"
+ " Format: %c%c%c%d\n"
+ " Screen start: 0x%x\n"
+ " Triple buffering: %s\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,
+ tdfx_cfg.screen_start,
+ tdfx_cfg.triple_buffering ? "on" : "off");
+
+ agp_mem = mmap( NULL, 1024*768*4, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, 0);
+
+ if(agp_mem == MAP_FAILED) {
+ printf("tdfx_vid: Memmap failed !!!!!\n");
+ close(fd);
+ return NULL;
+ }
+
+ vo=calloc(sizeof(vo_instance_t),1);
+ vo->query_format=query_format;
+ vo->control=control;
+ vo->config=config;
+ vo->frame_done=frame_done;
+ vo->show_frame=show_frame;
+ vo->uninit=uninit;
+
+ vo->priv = calloc(1,sizeof(struct vo_priv_s));
+ vo->priv->fd = fd;
+ vo->priv->agp_mem = agp_mem;
+ vo->priv->v_rate = cfg->v_rate;
+ memcpy(&vo->priv->cfg,&tdfx_cfg,sizeof(tdfx_vid_config_t));
+
+
+ return vo;
+}
+
+vo_info_t vo_driver_tdfx_vid = {
+ MODULE_TYPE_VO, MODULE_VERSION,
+ preinit,
+ "tdfx_vid",
+ "AGP Banshee/Voodoo3 driver",
+ "Albeu",
+ "Albeu",
+ "untested on Voodoo3",
+ VO_MODULE_CAPS_CHILD,
+ options, &options_def, sizeof(struct config_data_s)
+};
--- /dev/null Mon Jul 18 01:46:18 1994
+++ /home/alban/MP/g2.dev/libvo2/vo_xover.c Fri Jul 18 11:45:07 2003
@@ -0,0 +1,273 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "mp_msg.h"
+#include "video_out.h"
+#include "video/vfcap.h"
+
+/*
+ * TODO
+ *
+ * - Finish the colorkey stuff
+ * - Make different colorkey for 24/32 bit depth
+ * - Is passing only the raw x11 color ok for everyone ?
+ *
+ */
+
+
+static struct config_data_s {
+ config_modlist_t* vo_list;
+} options_def = {
+ NULL
+};
+
+static config_t options[] = {
+ { "vo", &options_def.vo_list, CONF_TYPE_MODLIST, 0, 0, 0, vo2_find_module, "Sub driver name" },
+ { NULL, NULL, 0, 0, 0, 0, 0, NULL }
+};
+
+struct vo_priv_s {
+ Window win;
+ Display* dpy;
+ XGCValues xgcv;
+ GC gc;
+ vo_instance_t* subvo;
+ uint32_t fgColor;
+ uint32_t bgColor;
+};
+
+static void get_win(struct vo_priv_s* priv,int* x,int* y,int* w,int* h) {
+ // Dummy stuff
+ Window mRoot;
+ int drwX,drwY,drwW,drwH,drwBorderWidth,drwDepth;
+
+ if(!priv || !priv->dpy || !priv->win) return;
+
+ XGetGeometry(priv->dpy, priv->win, &mRoot,&drwX, &drwY , &drwW,
+ &drwH, &drwBorderWidth, &drwDepth);
+ XTranslateCoordinates(priv->dpy, priv->win, mRoot, 0, 0,
+ &drwX, &drwY, &mRoot);
+ if(x) *x = drwX;
+ if(y) *y = drwY;
+ if(w) *w = drwW;
+ if(h) *h = drwH;
+}
+
+static void draw_colorkey(struct vo_instance_s* vo) {
+ if(vo->x < 0 || vo->y < 0 ||
+ vo->w <= 0 || vo->h <= 0 ||
+ vo->priv->gc == None) return;
+
+ XSetBackground(vo->priv->dpy,vo->priv->gc,vo->priv->bgColor );
+ XClearWindow(vo->priv->dpy ,vo->priv->win );
+ XSetForeground(vo->priv->dpy,vo->priv->gc , vo->priv->fgColor);
+ XFillRectangle(vo->priv->dpy,vo->priv->win,vo->priv->gc,
+ vo->x,vo->y,vo->w,vo->h);
+ XFlush(vo->priv->dpy);
+}
+
+static int control(struct vo_instance_s* vo,
+ int request, void *data, ...){
+ switch(request) {
+ case VOCTRL_SET_WINDOW:
+ vo->priv->win=*((Window*)data);
+ // FIXME: check if we already have win, and move GC from it!
+ if(vo->priv->gc != None)
+ XFreeGC( vo->priv->dpy,vo->priv->gc );
+ vo->priv->gc = XCreateGC(vo->priv->dpy, vo->priv->win, 0L, &vo->priv->xgcv);
+ vo->x = vo->y = 0;
+ get_win(vo->priv,NULL,NULL,&vo->w,&vo->h);
+ draw_colorkey(vo);
+ break;
+ case VOCTRL_RESIZE_DEST: {
+ int* a = data;
+ // printf("\nGot resize %dx%d %d-%d\n",a[0],a[1],a[2],a[3]);
+
+ // set the requested overlay pos/size
+ if(a[0] >= 0) vo->x = a[0];
+ if(a[1] >= 0) vo->y = a[1];
+ if(a[2] > 0) vo->w = a[2];
+ if(a[3] > 0) vo->h = a[3];
+
+ // Get the real window size
+ get_win(vo->priv,&a[0],&a[1],&a[2],&a[3]);
+ // Adjust x and y
+ // Checks ?
+ a[0] += vo->x;
+ a[1] += vo->y;
+ // Clamp w/h to the window size
+ if(vo->w > a[2])
+ vo->w = a[2];
+ else
+ a[2] = vo->w;
+ if(vo->h > a[3])
+ vo->h = a[3];
+ else
+ a[3] = vo->h;
+ draw_colorkey(vo);
+ }
+ default:
+ // Fix me !!! We must past the ... arguments but how ?
+ if(vo->priv->subvo->control)
+ return vo->priv->subvo->control(vo->priv->subvo,request,data);
+ }
+ return VO_NOTIMPL;
+}
+
+static unsigned int query_format(struct vo_instance_s* vo,
+ unsigned int format, int width, int height){
+ return vo->priv->subvo->query_format(vo->priv->subvo,format,
+ width,height);
+}
+
+static int config(struct vo_instance_s* vo,
+ int width, int height, int d_width, int d_height,
+ unsigned int format){
+
+ if(vo->priv->subvo->config(vo->priv->subvo,width,height,d_width,d_height,
+ format) != VO_TRUE)
+ return VO_FALSE;
+ vo->priv->subvo->config_count++;
+
+ vo->num_buffers=vo->priv->subvo->num_buffers;
+ vo->buffers = vo->priv->subvo->buffers;
+ vo->buffer_w=vo->priv->subvo->buffer_w;
+ vo->buffer_h=vo->priv->subvo->buffer_h;
+ vo->format=vo->priv->subvo->format;
+ vo->buffer_flags=vo->priv->subvo->buffer_flags;
+ vo->w=vo->priv->subvo->w;
+ vo->h=vo->priv->subvo->h;
+
+
+
+
+
+ return VO_TRUE;
+}
+
+
+static vo_buffer_t* get_buffer(struct vo_instance_s* vo) {
+ return vo->priv->subvo->get_buffer(vo->priv->subvo);
+}
+
+static void release_buffer(struct vo_instance_s* vo, vo_buffer_t* buffer) {
+ return vo->priv->subvo->release_buffer(vo->priv->subvo,buffer);
+}
+
+static int frame_start(struct vo_instance_s* vo, vo_buffer_t* buffer) {
+ return vo->priv->subvo->frame_start(vo->priv->subvo,buffer);
+}
+
+static void draw_slice(struct vo_instance_s* vo, vo_buffer_t* buffer,
+ unsigned char* src[], int stride[], int w,int h, int x,int y){
+ vo->priv->subvo->draw_slice(vo->priv->subvo,buffer,
+ src,stride,w,h,x,y);
+}
+
+static int frame_done(struct vo_instance_s* vo, vo_buffer_t* buffer) {
+ return vo->priv->subvo->frame_done(vo->priv->subvo,buffer);
+}
+
+static void show_frame(struct vo_instance_s* vo, vo_buffer_t* buffer,
+ float pts){
+ vo->priv->subvo->show_frame(vo->priv->subvo,buffer,pts);
+}
+
+static void uninit(struct vo_instance_s* vo) {
+ if(vo->priv->subvo->uninit)
+ vo->priv->subvo->uninit(vo->priv->subvo);
+
+}
+
+static vo_instance_t* preinit(char* arg,void* x11_display){
+ vo_info_t* module;
+ vo_instance_t* subvo = NULL;
+ vo_instance_t* vo;
+ config_data_t* opts = (config_data_t*)arg;
+ int i;
+
+ if(!arg || !opts->vo_list) {
+ mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay need a subdriver\n");
+ return NULL;
+ }
+
+ if(!x11_display) {
+ mp_msg(MSGT_VO, MSGL_ERR, "VO XOverlay need a X11 display\n");
+ return NULL;
+ }
+
+
+ for(i = 0 ; opts->vo_list[i].mod ; i++) {
+ module = opts->vo_list[i].mod;
+
+ // Check child caps
+ if(!(module->flags &VO_MODULE_CAPS_CHILD)) {
+ mp_msg(MSGT_VO, MSGL_ERR, "Subvo %s can't be used as child\n",
+ module->name);
+ continue;
+ }
+
+ subvo = ((vo2_preinit_t)module->entry)(opts->vo_list[i].cfg,NULL);
+ if(!subvo) {
+ mp_msg(MSGT_VO, MSGL_ERR, "Subvo %s preinit failed\n",
+ module->name);
+ continue;
+ }
+ subvo->info = module;
+ // We have everything now
+ break;
+ }
+
+ if(!subvo) {
+ mp_msg(MSGT_VO, MSGL_ERR, "No useable subdriver found\n");
+ return NULL;
+ }
+
+ vo=calloc(sizeof(vo_instance_t),1);
+ vo->query_format=query_format;
+ vo->control=control;
+ vo->config=config;
+ if(subvo->get_buffer)
+ vo->get_buffer = get_buffer;
+ if(subvo->release_buffer)
+ vo->release_buffer = release_buffer;
+ if(subvo->frame_start)
+ vo->frame_start = frame_start;
+ if(subvo->draw_slice)
+ vo->draw_slice=draw_slice;
+ if(subvo->frame_done)
+ vo->frame_done = frame_done;
+ vo->show_frame=show_frame;
+ vo->uninit=uninit;
+
+
+ vo->priv = calloc(sizeof(struct vo_priv_s),1);
+ vo->priv->subvo = subvo;
+ vo->priv->dpy = x11_display;
+ vo->priv->bgColor = 0x0L;
+ // Fix ME
+ vo->priv->fgColor = 0xf81fL;
+
+ if(subvo->control)
+ subvo->control(subvo,VOCTRL_SET_COLORKEY,&vo->priv->fgColor);
+ return vo;
+}
+
+vo_info_t vo_driver_xover = {
+ MODULE_TYPE_VO, MODULE_VERSION,
+ preinit,
+ "xover",
+ "X11 overlay",
+ "Albeu",
+ "Albeu",
+ "need a subdriver",
+ VO_MODULE_CAPS_X11|VO_MODULE_CAPS_WINDOW|VO_MODULE_CAPS_GUI|VO_MODULE_CAPS_PARENT,
+ options, &options_def, sizeof(struct config_data_s)
+};
--- /home/alban/MP/g2/libvo2/x11_helper.c Sun Jul 13 00:40:03 2003
+++ /home/alban/MP/g2.dev/libvo2/x11_helper.c Thu Jul 17 18:18:03 2003
@@ -455,11 +455,14 @@
}
break;
// events generated by vo_x11_check_events():
+ case VO_EVENT_EXPOSE:
case VO_EVENT_MOVE:
mp_msg(MSGT_CPLAYER,MSGL_V,"vo-event: moved to %d x %d\n",x,y);
// dont do that, we're moving the window, not the picture inside the window!
-// tmp[2]=tmp[3]=-1; tmp[0]=x; tmp[1]=y;
-// vo->control(vo,VOCTRL_RESIZE_DEST,tmp);
+ { int tmp[4];
+ tmp[2]=tmp[3]=-1; tmp[0]=-1; tmp[1]=-1;
+ vo->control(vo,VOCTRL_RESIZE_DEST,tmp);
+ }
break;
default:
vo_default_event_callback(vo,type,flags,x,y);
--- /home/alban/MP/g2/test-play.c Sun Jul 13 23:03:00 2003
+++ /home/alban/MP/g2.dev/test-play.c Thu Jul 17 01:26:57 2003
@@ -468,16 +468,19 @@
// time_frame=0;
}
// do sleeping!
- if(time_frame>0){
+ if( !(video_out->buffer_flags & VO_BUFFER_FLAG_SLEEP) ||
+ frame_time_remaining ) {
+ if(time_frame>0){
time_frame/=playback_speed;
mp_msg(MSGT_AVSYNC,MSGL_DBG2,"time_frame=%5.3f\n",time_frame);
//usec_sleep((int)(time_frame*1000000.0));
time_frame=sleep_accurate(time_frame)*playback_speed;
+ }
}
// display!
if(!frame_time_remaining){
if(mpi && mpi->priv && video_out->show_frame)
- video_out->show_frame(video_out,(vo_buffer_t*)mpi->priv,0);
+ video_out->show_frame(video_out,(vo_buffer_t*)mpi->priv,video_out->buffer_flags & VO_BUFFER_FLAG_SLEEP && time_frame > 0 ? time_frame/playback_speed : 0);
if(d_sub && !d_sub->eof)
test_subs(d_sub,v_pts);
mpi=NULL;
@@ -509,7 +512,7 @@
#endif
sh_audio->delay+=x; c_total+=x;
time_frame-=x; // for -autosync
- mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%8.3f (%5.3f) V:%8.3f (%5.3f) A-V:%+7.4f ct:%7.4f d:%5.3f x:%+5.3f \r",
+ mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%8.3f (%5.3f) V:%8.3f (%+5.3f) A-V:%+7.4f ct:%7.4f d:%5.3f x:%+5.3f \r",
(float)(a_pts-delay), (float)((a_pts-delay) - old_apts),
(float)v_pts, (float)(v_pts - old_vpts),
AV_delay, c_total, delay, x);
--- /home/alban/MP/g2/video/Makefile Mon May 12 01:47:03 2003
+++ /home/alban/MP/g2.dev/video/Makefile Fri Jul 18 18:13:06 2003
@@ -12,7 +12,7 @@
VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT)
# vf_vo.c
-VFILTER_SRCS=vf.c vf_scale.c vf_vo2.c vf_vd.c vf_pp.c vf_format.c vf_tfields.c # vf_crop.c vf_expand.c # vf_format.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_rectangle.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c
+VFILTER_SRCS=vf.c vf_scale.c vf_vo2.c vf_vd.c vf_pp.c vf_format.c vf_tfields.c vf_osd.c # vf_crop.c vf_expand.c # vf_format.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_rectangle.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c
ENCODER_SRCS=ve.c # ve_lavc.c # ve_divx4.c ve_vfw.c ve_rawrgb.c ve_libdv.c ve_xvid.c ve_qtvideo.c ve_nuv.c
# NATIVE_SRCS=native/RTjpegN.c native/cinepak.c native/fli.c native/minilzo.c native/msvidc.c native/nuppelvideo.c native/qtrle.c native/qtrpza.c native/qtsmc.c native/roqav.c native/xa_gsm.c native/svq1.c