Commit 2cb77865 authored by Aaron Holtzman's avatar Aaron Holtzman
Browse files

3dfx build fixes from Rick Niles.

ah
parent 2aaf19ea
......@@ -16,6 +16,8 @@ Contributions by (in no particular order):
Ryan C. Gordon <icculus@lokigames.com> - SDL support
Stephen Crowley <stephenc@dns2.digitalpassage.com> - build fixes
Bruno Barreyra <barreyra@ufl.edu> - build fixes
Rick Niles <niles@scyld.com> - build fixes
(let me know if I've forgotten anyone)
First of all, this is very early code. If you're not interested
......
......@@ -31,6 +31,7 @@ if test "x$DISPLAY_DRIVER" = x -a x$enable_3dfx = xyes; then
if test -c "/dev/3dfx"; then
AC_MSG_RESULT(found)
DISPLAY_DRIVER=display_3dfx.o
X_LIBS="$X_LIBS -lXxf86dga"
else
AC_MSG_RESULT(not found)
fi
......
......@@ -78,193 +78,204 @@ uint_32 baseAddr0, baseAddr1;
Display *display;
void restore() {
reg_IO->vidDesktopStartAddr = vidpage0offset;
XF86DGADirectVideo(display,0,0);
void restore()
{
reg_IO->vidDesktopStartAddr = vidpage0offset;
XF86DGADirectVideo(display,0,0);
}
void sighup() {
reg_IO->vidDesktopStartAddr = vidpage0offset;
XF86DGADirectVideo(display,0,0);
exit(0);
void sighup()
{
reg_IO->vidDesktopStartAddr = vidpage0offset;
XF86DGADirectVideo(display,0,0);
exit(0);
}
uint_32
display_init(uint_32 width, uint_32 height, uint_32 fullscreen, char *title)
int fd;
pioData data;
uint_32 retval;
display = XOpenDisplay(NULL);
screenwidth = XDisplayWidth(display,0);
screenheight = XDisplayHeight(display,0);
page_space = screenwidth*screenheight*2;
vidpage0offset = 0;
vidpage1offset = page_space;
vidpage2offset = page_space << 1;
signal(SIGALRM,sighup);
//alarm(120);
// Open driver device
if ( (fd = open("/dev/3dfx",O_RDWR) ) == -1) {
fprintf(stderr,"Couldn't open /dev/3dfx\n");
exit(1);
}
// Store sizes for later
vidwidth = width;
vidheight = height;
// Ask 3dfx driver for base memory address 0
data.port = 0x10; // PCI_BASE_ADDRESS_0_LINUX;
data.size = 4;
data.value = &baseAddr0;
data.device = 0;
if ((retval = ioctl(fd,_IOC(_IOC_READ,'3',3,0),&data)) < 0) {
printf("Error: %d\n",retval);
// return 0;
}
// Ask 3dfx driver for base memory address 1
data.port = 0x14; // PCI_BASE_ADDRESS_1_LINUX;
data.size = 4;
data.value = &baseAddr1;
data.device = 0;
if ((retval = ioctl(fd,_IOC(_IOC_READ,'3',3,0),&data)) < 0) {
printf("Error: %d\n",retval);
// return 0;
}
// Map all 3dfx memory areas
memBase0 = mmap(0,0x1000000,PROT_READ | PROT_WRITE,MAP_SHARED,fd,baseAddr0);
memBase1 = mmap(0,3*page_space,PROT_READ | PROT_WRITE,MAP_SHARED,fd,baseAddr1);
if (memBase0 == 0xFFFFFFFF || memBase1 == 0xFFFFFFFF) {
printf("Couldn't map 3dfx memory areas: %d,%d,%d\n",memBase0,memBase1,errno);
}
// Set up global pointers
reg_IO = (void *)memBase0 + VOODOO_IO_REG_OFFSET;
reg_2d = (void *)memBase0 + VOODOO_2D_REG_OFFSET;
reg_YUV = (void *)memBase0 + VOODOO_YUV_REG_OFFSET;
fb_YUV = (void *)memBase0 + VOODOO_YUV_PLANE_OFFSET;
vidpage0 = (void *)memBase1 + (unsigned long int)vidpage0offset;
vidpage1 = (void *)memBase1 + (unsigned long int)vidpage1offset;
vidpage2 = (void *)memBase1 + (unsigned long int)vidpage2offset;
// Clear pages 1,2,3
// leave page 0, that belongs to X.
// So does part of 1. Oops.
memset(vidpage1,0x00,page_space);
memset(vidpage2,0x00,page_space);
{
int fd;
pioData data;
uint_32 retval;
display = XOpenDisplay(NULL);
screenwidth = XDisplayWidth(display,0);
screenheight = XDisplayHeight(display,0);
page_space = screenwidth*screenheight*2;
vidpage0offset = 0;
vidpage1offset = page_space;
vidpage2offset = page_space << 1;
signal(SIGALRM,sighup);
//alarm(120);
// Open driver device
if ( (fd = open("/dev/3dfx",O_RDWR) ) == -1)
{
fprintf(stderr,"Couldn't open /dev/3dfx\n");
exit(1);
}
// Store sizes for later
vidwidth = width;
vidheight = height;
// Ask 3dfx driver for base memory address 0
data.port = 0x10; // PCI_BASE_ADDRESS_0_LINUX;
data.size = 4;
data.value = &baseAddr0;
data.device = 0;
if ((retval = ioctl(fd,_IOC(_IOC_READ,'3',3,0),&data)) < 0)
{
printf("Error: %ld\n",retval);
// return 0;
}
// Ask 3dfx driver for base memory address 1
data.port = 0x14; // PCI_BASE_ADDRESS_1_LINUX;
data.size = 4;
data.value = &baseAddr1;
data.device = 0;
if ((retval = ioctl(fd,_IOC(_IOC_READ,'3',3,0),&data)) < 0)
{
printf("Error: %ld\n",retval);
// return 0;
}
// Map all 3dfx memory areas
memBase0 = mmap(0,0x1000000,PROT_READ | PROT_WRITE,MAP_SHARED,fd,baseAddr0);
memBase1 = mmap(0,3*page_space,PROT_READ | PROT_WRITE,MAP_SHARED,fd,baseAddr1);
if (memBase0 == (uint_32 *) 0xFFFFFFFF || memBase1 == (uint_32 *) 0xFFFFFFFF) {
printf("Couldn't map 3dfx memory areas: %p,%p,%d\n",
memBase0,memBase1,errno);
}
// Set up global pointers
reg_IO = (void *)memBase0 + VOODOO_IO_REG_OFFSET;
reg_2d = (void *)memBase0 + VOODOO_2D_REG_OFFSET;
reg_YUV = (void *)memBase0 + VOODOO_YUV_REG_OFFSET;
fb_YUV = (void *)memBase0 + VOODOO_YUV_PLANE_OFFSET;
vidpage0 = (void *)memBase1 + (unsigned long int)vidpage0offset;
vidpage1 = (void *)memBase1 + (unsigned long int)vidpage1offset;
vidpage2 = (void *)memBase1 + (unsigned long int)vidpage2offset;
// Clear pages 1,2,3
// leave page 0, that belongs to X.
// So does part of 1. Oops.
memset(vidpage1,0x00,page_space);
memset(vidpage2,0x00,page_space);
#ifndef VOODOO_DEBUG
// Show page 0 (unblanked)
reg_IO->vidDesktopStartAddr = vidpage0offset;
/* Stop X from messing with my video registers!
Find a better way to do this?
Currently I use DGA to tell XF86 to not screw with registers, but I can't really use it
to do FB stuff because I need to know the absolute FB position and offset FB position
to feed to BLT command
*/
XF86DGADirectVideo(display,0,XF86DGADirectGraphics & XF86DGADirectMouse & XF86DGADirectKeyb);
// Show page 0 (unblanked)
reg_IO->vidDesktopStartAddr = vidpage0offset;
/* Stop X from messing with my video registers!
Find a better way to do this?
Currently I use DGA to tell XF86 to not screw with registers, but I can't really use it
to do FB stuff because I need to know the absolute FB position and offset FB position
to feed to BLT command
*/
XF86DGADirectVideo(display,0,XF86DGADirectGraphics & XF86DGADirectMouse & XF86DGADirectKeyb);
#endif
/* fd is deliberately not closed - if it were, mmaps might be released??? */
/* fd is deliberately not closed - if it were, mmaps might be released??? */
atexit(restore);
atexit(restore);
dprintf("(display) 3dfx initialized %p\n",memBase1);
printf("(display) 3dfx initialized %p\n",memBase1);
return 0;
}
void dump_yuv_planar_frame(uint_32 *y, uint_32 *u, uint_32 *v) {
uint_32 j;
uint_32 y_imax, uv_imax, jmax;
jmax = vidheight>>1; // vidheight/2, height of U and V planes
uv_imax = vidwidth>>3; // vidwidth/2/4, width of U and V planes in 32-bit words
y_imax = uv_imax << 1; // Y plane is twice as wide as U and V planes
for (j=0;j<jmax;j++) {
wmemcpy(fb_YUV->U + (unsigned long int)VOODOO_YUV_STRIDE* j ,u+(unsigned long int)uv_imax* j ,uv_imax);
wmemcpy(fb_YUV->V + (unsigned long int)VOODOO_YUV_STRIDE* j ,v+(unsigned long int)uv_imax* j ,uv_imax);
wmemcpy(fb_YUV->Y + (unsigned long int)VOODOO_YUV_STRIDE* (j<<1) ,y+(unsigned long int)y_imax * (j<<1) ,y_imax);
wmemcpy(fb_YUV->Y + (unsigned long int)VOODOO_YUV_STRIDE*((j<<1)+1),y+(unsigned long int)y_imax *((j<<1)+1),y_imax);
}
void
dump_yuv_planar_frame(uint_32 *y, uint_32 *u, uint_32 *v)
{
uint_32 j;
uint_32 y_imax, uv_imax, jmax;
jmax = vidheight>>1; // vidheight/2, height of U and V planes
uv_imax = vidwidth>>3; // vidwidth/2/4, width of U and V planes in 32-bit words
y_imax = uv_imax << 1; // Y plane is twice as wide as U and V planes
for (j=0;j<jmax;j++)
{
wmemcpy(fb_YUV->U + (unsigned long int)VOODOO_YUV_STRIDE* j ,u+(unsigned long int)uv_imax* j ,uv_imax);
wmemcpy(fb_YUV->V + (unsigned long int)VOODOO_YUV_STRIDE* j ,v+(unsigned long int)uv_imax* j ,uv_imax);
wmemcpy(fb_YUV->Y + (unsigned long int)VOODOO_YUV_STRIDE* (j<<1) ,y+(unsigned long int)y_imax * (j<<1) ,y_imax);
wmemcpy(fb_YUV->Y + (unsigned long int)VOODOO_YUV_STRIDE*((j<<1)+1),y+(unsigned long int)y_imax *((j<<1)+1),y_imax);
}
}
uint_32
display_frame(uint_8 *src[])
{
uint_32 *y, *u, *v;
voodoo_2d_reg saved_regs;
uint_32 *y, *u, *v;
voodoo_2d_reg saved_regs;
// Get nice 32 bit pointers to Y, U, and V planes
y = (uint_32 *)src[0];
u = (uint_32 *)src[1];
v = (uint_32 *)src[2];
// Get nice 32 bit pointers to Y, U, and V planes
y = (uint_32 *)src[0];
u = (uint_32 *)src[1];
v = (uint_32 *)src[2];
// Save VGA regs (so X kinda works when we're done)
saved_regs = *reg_2d;
// Save VGA regs (so X kinda works when we're done)
saved_regs = *reg_2d;
/* YUV conversion works like this:
We write the Y, U, and V planes separately into 3dfx YUV Planar memory
region. The nice chip then takes these and packs them into the YUYV
format in the regular frame buffer, starting at yuvBaseAddr, page 2 here.
Then we tell the 3dfx to do a Screen to Screen Stretch BLT to copy all
of the data on page 2 onto page 1, converting it to 16 bpp RGB as it goes.
The result is a nice image on page 1 ready for display.
*/
/* YUV conversion works like this:
We write the Y, U, and V planes separately into 3dfx YUV Planar memory
region. The nice chip then takes these and packs them into the YUYV
format in the regular frame buffer, starting at yuvBaseAddr, page 2 here.
Then we tell the 3dfx to do a Screen to Screen Stretch BLT to copy all
of the data on page 2 onto page 1, converting it to 16 bpp RGB as it goes.
The result is a nice image on page 1 ready for display.
*/
// Put packed data onto page 2
reg_YUV->yuvBaseAddr = vidpage2offset;
reg_YUV->yuvStride = screenwidth*2;
// Put packed data onto page 2
reg_YUV->yuvBaseAddr = vidpage2offset;
reg_YUV->yuvStride = screenwidth*2;
// Dump Y, U and V planes into planar buffers (must use 32 bit writes)
// Any way to speed this up?? Yes - see next loop
/*for (i=0;i<vidheight;i++) {
for (j=0;j<vidwidth/4;j++) {
if (!(j & 1 || i & 1)) {
// Dump Y, U and V planes into planar buffers (must use 32 bit writes)
// Any way to speed this up?? Yes - see next loop
/*for (i=0;i<vidheight;i++) {
for (j=0;j<vidwidth/4;j++) {
if (!(j & 1 || i & 1)) {
fb_YUV->U[(j>>1)+1024/4*(i>>1)] = u[(j>>1)+vidwidth/4/2*(i>>1)];
fb_YUV->V[(j>>1)+1024/4*(i>>1)] = v[(j>>1)+vidwidth/4/2*(i>>1)];
}
fb_YUV->Y[j+1024/4*i] = y[j+vidwidth/4*i];
}
}*/
dump_yuv_planar_frame(y,u,v);
}
fb_YUV->Y[j+1024/4*i] = y[j+vidwidth/4*i];
}
}*/
dump_yuv_planar_frame(y,u,v);
#ifndef VOODOO_DEBUG
/* The following lines set up the screen to screen stretch blt from page2 to
page 1
*/
reg_2d->commandExtra = 4; //disable colorkeying, enable wait for v-refresh
reg_2d->clip0Min = 0;
reg_2d->clip0Max = 0xFFFFFFFF; //no clipping
reg_2d->srcBaseAddr = vidpage2offset;
reg_2d->srcXY = 0;
reg_2d->srcFormat = screenwidth*2 | VOODOO_BLT_FORMAT_YUYV; // | 1<<21;
reg_2d->srcSize = vidwidth | (vidheight << 16);
reg_2d->dstBaseAddr = vidpage0offset;
reg_2d->dstXY = 0;
reg_2d->dstFormat = screenwidth*2 | VOODOO_BLT_FORMAT_16;
reg_2d->dstSize = dispwidth | (dispheight << 16);
// Executes screen to screen stretch blt
reg_2d->command = 2 | 1<<8 | 0xCC<<24;
// Restore registers (get rid of this!)
*reg_2d = saved_regs;
#endif
/* The following lines set up the screen to screen stretch blt from page2 to
page 1
*/
reg_2d->commandExtra = 4; //disable colorkeying, enable wait for v-refresh
reg_2d->clip0Min = 0;
reg_2d->clip0Max = 0xFFFFFFFF; //no clipping
reg_2d->srcBaseAddr = vidpage2offset;
reg_2d->srcXY = 0;
reg_2d->srcFormat = screenwidth*2 | VOODOO_BLT_FORMAT_YUYV; // | 1<<21;
reg_2d->srcSize = vidwidth | (vidheight << 16);
reg_2d->dstBaseAddr = vidpage0offset;
reg_2d->dstXY = 0;
reg_2d->dstFormat = screenwidth*2 | VOODOO_BLT_FORMAT_16;
reg_2d->dstSize = dispwidth | (dispheight << 16);
// Executes screen to screen stretch blt
reg_2d->command = 2 | 1<<8 | 0xCC<<24;
// Restore registers (get rid of this!)
*reg_2d = saved_regs;
#endif
return 0;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment