/* * tv-dgatest.c * * Test program for XFree86 DGA extension to test blasting of TV tuner * data onto the frame buffer * * COMPILE USING: * cc -o tv-dgatest tv-dgatest.c -I/usr/X11R6/include -L/usr/X11R6/lib \ * -lX11 -lXext -lXxf86dga * * (C) 1999 Randall Hopper * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. 2. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #ifdef __NetBSD__ # include # include #else # include # include #endif #include #include #include /* req's Xlib.h */ /*#define OVERRIDE_PIXEL_FORMAT*/ #define FRAME_WIDTH 320 #define FRAME_HEIGHT 200 #define DEV_BT848 "/dev/bktr0" #define DEV_TUNER "/dev/tuner0" #define MIN(x,y) ((x)<(y)?(x):(y)) typedef struct { char *aperture_addr; /* Address of 2D linear frame buffer */ int pitch; /* Buffer row stride, in pixels */ int bank_bytes; /* Bank size in bytes */ int ram_bytes; /* Aperature size in Kbytes */ int Bpp; /* Bytes per pixel */ int RGB_shifts[3]; /* Packing shifts for R,G,B */ int RGB_masks[3]; /* Post-shift packing masks for R,G,B */ int RGB_byteswapped; /* T if bytes stored swapped */ } DGAParms; /*---------------------------------------------------------------------------*/ void BuzzDGA( Display *display, DGAParms *p ) { int dga_major_vers, dga_minor_vers, screen = DefaultScreen( display ), dv_flags, width, bank_size, mem_size; char *addr; if ( !XF86DGAQueryVersion( display, &dga_major_vers, &dga_minor_vers ) ) { fprintf( stderr, "XF86DGAQueryVersion() failed\n" ); exit(1); } printf( "\tVersion = %d.%.2d\n", dga_major_vers, dga_minor_vers ); if ( !XF86DGAQueryDirectVideo( display, screen, &dv_flags ) ) { fprintf( stderr, "XF86DGAQueryDirectVideo() failed\n" ); exit(1); } printf( "\tDirect Video = " ); printf( "%s ", ( dv_flags & XF86DGADirectGraphics ) ? "DirectGraphics" : "NO-DirectGraphics" ); printf( "%s ", ( dv_flags & XF86DGADirectMouse ) ? "DirectMouse" : "NO-DirectMouse" ); printf( "%s ", ( dv_flags & XF86DGADirectKeyb ) ? "DirectKeyb" : "NO-DirectKeyb" ); printf( "\n" ); if ( !XF86DGAGetVideo( display, screen, &addr, &width, &bank_size, &mem_size ) ) { fprintf( stderr, "XF86DGAGetVideo() failed\n" ); exit(1); } printf( "\nXF86DGAGetVideo:\n" ); printf( "\tVideo Address = 0x%.8x\n", (int) addr ); printf( "\t Width = %d\n", width ); printf( "\t BankSize = %dK\n", bank_size/1024 ); printf( "\t MemSize = %dK\n", mem_size ); if ( !XF86DGAGetVideoLL( display, screen, (int*) &addr, &width, &bank_size, &mem_size ) ) { fprintf( stderr, "XF86DGAGetVideoLL() failed\n" ); exit(1); } printf( "\nXF86DGAGetVideoLL:\n" ); printf( "\tVideo Address = 0x%.8x\n", (int)addr ); printf( "\t Width = %d\n", width ); printf( "\t BankSize = %dK\n", bank_size/1024 ); printf( "\t MemSize = %dK\n", mem_size ); p->aperture_addr = addr; p->pitch = width; p->bank_bytes = bank_size; p->ram_bytes = mem_size * 1024; } /*---------------------------------------------------------------------------*/ int GetBktrPixFmt( int fd, DGAParms *p ) { int i, found = 0; struct meteor_pixfmt pf; for ( i = 0; !found; i++ ) { pf.index = i; if ( ioctl( fd, METEORGSUPPIXFMT, &pf ) < 0 ) { if ( errno == EINVAL ) break; perror( "METEORGSUPPIXFMT failed" ); exit(1); } if ( pf.type == METEOR_PIXTYPE_RGB && pf.Bpp == p->Bpp && pf.masks[0] == p->RGB_masks[0] && pf.masks[1] == p->RGB_masks[1] && pf.masks[2] == p->RGB_masks[2] && pf.swap_bytes == p->RGB_byteswapped && (( pf.Bpp < 4 ) || ( pf.swap_shorts == p->RGB_byteswapped )) ) found = 1; } if ( !found ) { fprintf( stderr, "Pixel format not supported in bktr driver.\n" ); exit(1); } return pf.index; } /*---------------------------------------------------------------------------*/ void Blast( Display *display, DGAParms *p, int fd, int tfd, int x, int y ) { struct meteor_video video; struct meteor_geomet geom; long larg; geom.oformat = METEOR_GEO_RGB16; /* Ignored since SACTPIXFMT called */ geom.columns = FRAME_WIDTH; geom.rows = FRAME_HEIGHT; geom.frames = 1; if ( ioctl( fd, METEORSETGEO, &geom ) < 0 ) { perror( "METEORSETGEO failed" ); exit(1); } video.addr = (long)(p->aperture_addr + (y * p->pitch + x) * p->Bpp); video.width = p->pitch * p->Bpp; video.banksize = p->bank_bytes; video.ramsize = p->ram_bytes / 1024; if ( ioctl( fd, METEORSVIDEO, &video ) < 0 ) { perror( "METEORSVIDEO failed" ); exit(1); } larg = METEOR_CAP_SINGLE; if ( ioctl( fd, METEORCAPTUR, &larg ) < 0 ) { perror( "METEORCAPTUR(SINGLE) failed" ); exit(1); } } /*---------------------------------------------------------------------------*/ void SweepUpTrash( Display *display ) { Window refresh_win; XSetWindowAttributes xswa; int screen = DefaultScreen( display ); xswa.override_redirect = True; refresh_win = XCreateWindow( display, DefaultRootWindow(display), 0, 0, DisplayWidth ( display, screen ), DisplayHeight( display, screen ), 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &xswa ); XSelectInput( display, refresh_win, StructureNotifyMask ); XMapWindow ( display, refresh_win ); XRaiseWindow( display, refresh_win ); XSync( display, False ); XUnmapWindow( display, refresh_win ); XSync( display, False ); } /*---------------------------------------------------------------------------*/ void BuzzBktr( Display *display, DGAParms *p ) { int fd, tfd, width, height, arg, i, x, y, dx, dy, screen = DefaultScreen( display ); int pix_fmt; if ( !p->aperture_addr ) { fprintf( stderr, "Aperture address is 0. No DGA-TV test possible.\n" ); exit(1); } fd = open( DEV_BT848, O_RDONLY ); if ( fd < 0 ) { fprintf( stderr, "open(\"%s\") failed: %s\n", DEV_BT848, strerror(errno) ); exit(1); } tfd = open( DEV_TUNER, O_RDONLY ); if ( tfd < 0 ) { fprintf( stderr, "open(\"%s\") failed: %s\n", DEV_BT848, strerror(errno) ); exit(1); } width = DisplayWidth ( display, screen ); height = DisplayHeight( display, screen ); assert( width >= FRAME_WIDTH && height >= FRAME_HEIGHT ); if ( ioctl( tfd, BT848_SCBARS, &arg ) < 0 ) { perror( "BT848_SCBARS failed" ); exit(1); } pix_fmt = GetBktrPixFmt( fd, p ); if ( ioctl( fd, METEORSACTPIXFMT, &pix_fmt ) < 0 ) { perror( "METEORSACTPIXFMT failed" ); exit(1); } /* Blast a frame to the upper left of the desktop */ Blast( display, p, fd, tfd, 0, 0 ); sleep(2); /* And the top right */ Blast( display, p, fd, tfd, width - FRAME_WIDTH, 0 ); sleep(2); /* Now the bottom left */ Blast( display, p, fd, tfd, 0, height - FRAME_HEIGHT ); sleep(2); /* And the bottom right */ Blast( display, p, fd, tfd, width - FRAME_WIDTH, height - FRAME_HEIGHT ); sleep(2); if ( ioctl( tfd, BT848_CCBARS, &arg ) < 0 ) { perror( "BT848_SCBARS failed" ); exit(1); } /* Now goof off */ arg = METEOR_INPUT_DEV1; if ( ioctl( fd, METEORSINPUT, &arg ) < 0 ) { perror( "METEORSINPUT failed" ); exit(1); } x = y = 0, dx = dy = 20; for ( i = 0; i < 200; i++ ) { Blast( display, p, fd, tfd, x, y ); x += dx; y += dy; if ( x > width-FRAME_WIDTH ) x -= 2*(x-(width-FRAME_WIDTH)), dx = -dx; if ( y > height-FRAME_HEIGHT ) y -= 2*(y-(height-FRAME_HEIGHT)), dy = -dy; if ( x < 0 ) x = -x, dx = -dx; if ( y < 0 ) y = -y, dy = -dy; } close( fd ); close( tfd ); /* And clean up */ sleep(2); SweepUpTrash( display ); } /*---------------------------------------------------------------------------*/ void WildGuessFrameBufferPixelFormat( Display *display, DGAParms *p ) /* Really, X server doesn't tell us this. So just hope that it's the */ /* same as the pixmap format. */ { int screen = DefaultScreen( display ); Visual *fb_vis = DefaultVisual( display, screen ); XVisualInfo vinfo_pref, *vi; XPixmapFormatValues *pf; int num_vis, i, j, num_pf, pfi, Bpp = 0, tmp; vinfo_pref.screen = screen; vinfo_pref.visualid = XVisualIDFromVisual( fb_vis ); vi = XGetVisualInfo( display, VisualScreenMask | VisualIDMask, &vinfo_pref, &num_vis ); assert( num_vis == 1 ); /* Guess Bpp from supported pixmap formats (an unreliable hack) */ pf = XListPixmapFormats( display, &num_pf ); if ( pf != NULL ) { for ( pfi = 0; pfi < num_pf; pfi++ ) if ( pf[ pfi ].depth == vi->depth ) break; if ( pfi < num_pf ) Bpp = ( pf[ pfi ].bits_per_pixel + 7 ) / 8; XFree ( pf ); } /* No luck. Fall back to using depth from visual. */ if ( Bpp == 0 ) Bpp = ( vi->depth + 7 ) / 8; p->Bpp = Bpp; /* Now for the masks and shifts. Not stored in the pixmap formats, */ /* So extract this from default visual (another unreliable hack). */ p->RGB_masks[0] = vi->red_mask; p->RGB_masks[1] = vi->green_mask; p->RGB_masks[2] = vi->blue_mask; for ( j = 0; j < 3; j++ ) { assert( p->RGB_masks[j] != 0 ); for ( i = 0, tmp=p->RGB_masks[j]; !(tmp & 0x01); i++, tmp >>= 1 ) ; p->RGB_shifts[j] = i; } /* We'll just blindly assume that frame buffer is byte swapped */ p->RGB_byteswapped = 1; #ifdef OVERRIDE_PIXEL_FORMAT p->Bpp = 4; p->RGB_shifts[0] = 16; p->RGB_shifts[1] = 8; p->RGB_shifts[2] = 0; p->RGB_masks[0] = 0xff0000; p->RGB_masks[1] = 0x00ff00; p->RGB_masks[2] = 0x0000ff; p->RGB_byteswapped = 1; #endif printf( "\nUsing Pixel Format:\n" "\tBpp,shifts[R,G,B],masks[R,G,B],byteswap = \n" "\t%d,%d,%d,%d,%.6x,%.6x,%.6x,%d\n", p->Bpp,p->RGB_shifts[0],p->RGB_shifts[1],p->RGB_shifts[2], p->RGB_masks[0],p->RGB_masks[1],p->RGB_masks[2],p->RGB_byteswapped ); } /*---------------------------------------------------------------------------*/ int main( int argc, char *argv[] ) { Display *display; DGAParms parms; int c, aperture_fuzz = 0; if ( geteuid() != 0 ) { fprintf( stderr, "Must be root to run this program.\n" ); exit(1); } /* Get command-line options */ while( (c = getopt(argc,argv,"f:")) != -1 ) { switch (c) { case 'f' : aperture_fuzz = atoi(optarg); break; default : fprintf( stderr, "Supported options:\n" " -f - Frame buffer 'fuzz' offset\n" ); exit(1); } } display = XOpenDisplay( NULL ); if ( display == NULL ) { fprintf( stderr, "XOpenDisplay() failed\n" ); exit(1); } printf( "XF86 DGA Extension Test\n\n" ); BuzzDGA( display, &parms ); parms.aperture_addr += aperture_fuzz; sleep(2); /* A nasty hack -- DGA doesn't tell us so we can only guess */ WildGuessFrameBufferPixelFormat( display, &parms ); printf( "DGA-bktr Combo Test" ); BuzzBktr( display, &parms ); XCloseDisplay( display ); return 0; }