/* * dgafbtest.c * * Test program for XFree86 DGA extension to verify that the correct base * address for the video card's linear frame buffer is being returned. * (This is essential for direct transfer of TV tuner card frames onto * the frame buffer.) * * COMPILE USING: * cc -o dgafbtest dgafbtest.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 /* req's Xlib.h */ /*#define OVERRIDE_PIXEL_FORMAT*/ #define SWAP(x,y,tmp) ((tmp)=(x),(x)=(y),(y)=(tmp)) 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; assert( p->aperture_addr ); assert( p->bank_bytes >= p->ram_bytes ); } /*---------------------------------------------------------------------------*/ void DrawDGAPoint( DGAParms *p, int mem_fd, int x, int y, unsigned RGB[3] ) { short endian_test = 0x1234; union { unsigned long val; unsigned char buf[4]; } pixel; unsigned char *addr, *buf = pixel.buf; int itmp; /* Little-endian specific */ assert( ((unsigned char *)&endian_test)[0] == 0x34 ); assert( sizeof(long) == 4 ); assert( p->Bpp >= 2 && p->Bpp <= 4 ); /*************************************************************************/ /* FIXME: XFree86 should tell us masks, shifts, and byte-swap Y/N for */ /* frame buffer pixel geometry (not just for visuals, which could */ /* all have different pixel geometries from frame buffer's). */ /*************************************************************************/ /* Generate pixel value */ pixel.val = ( ( RGB[0] << p->RGB_shifts[0] ) & p->RGB_masks[0] ) | ( ( RGB[1] << p->RGB_shifts[1] ) & p->RGB_masks[1] ) | ( ( RGB[2] << p->RGB_shifts[2] ) & p->RGB_masks[2] ); if ( !p->RGB_byteswapped ) if ( p->Bpp == 2 ) SWAP(buf[0],buf[1],itmp); else if ( p->Bpp == 3 ) SWAP(buf[0],buf[2],itmp); else SWAP(buf[0],buf[3],itmp),SWAP(buf[1],buf[2],itmp); /* Plot point */ addr = p->aperture_addr + (y * p->pitch + x) * p->Bpp; lseek( mem_fd, (unsigned) addr, SEEK_SET ); write( mem_fd, buf, p->Bpp ); } void DrawDGA( Display *display, DGAParms *p ) { unsigned color[3]; int mem_fd, i, screen = DefaultScreen( display ), w = DisplayWidth ( display, screen ), h = DisplayHeight( display, screen ); if ( (mem_fd = open( "/dev/mem", O_RDWR, 0 )) < 0 ) { perror( "Failed to open /dev/mem" ); exit(1); } color[0] = 0xFF, color[1] = 0xFF, color[2] = 0x00; for ( i = 0; i < 100; i++ ) { DrawDGAPoint( p, mem_fd, i, 0, color ); DrawDGAPoint( p, mem_fd, (w-1)-i, 0, color ); DrawDGAPoint( p, mem_fd, i, h-1, color ); DrawDGAPoint( p, mem_fd, (w-1)-i, h-1, color ); DrawDGAPoint( p, mem_fd, 0, i, color ); DrawDGAPoint( p, mem_fd, 0, (h-1)-i, color ); DrawDGAPoint( p, mem_fd, w-1, i, color ); DrawDGAPoint( p, mem_fd, w-1, (h-1)-i, color ); } close( mem_fd ); } /*---------------------------------------------------------------------------*/ 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 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 Query Test ==========\n" ); BuzzDGA( display, &parms ); parms.aperture_addr += aperture_fuzz; /* A nasty hack -- DGA doesn't tell us so we can only guess */ WildGuessFrameBufferPixelFormat( display, &parms ); printf( "\n========== XF86 DGA Draw Test ==========\n\n" ); printf( " Next we'll draw 8 yellow radial lines from the corners of \n" " your desktop. Check that:\n\n" " 1) you see all 8 lines (2 in each corner: 1 horiz, 1 vert),\n" " 2) they are in the corners of your desktop, and\n" " 3) they are all pure yellow (no odd-color borders)\n\n" ); printf( "Move everything away from the corners of your desktop,\n" "and then hit .\n" ); getchar(); SweepUpTrash( display ); DrawDGA( display, &parms ); printf( "Testing complete. Examine the screen, and then hit .\n" ); getchar(); SweepUpTrash( display ); printf( "\n========== Any problems? ==========\n\n" ); printf( "\nIf you observe a DGA bug, first verify that the XFree86 FAQ\n" "does not discuss it:\n" " http://www.xfree86.org/FAQ/\n" "If not, report it to the XFree86 Team. See the FAQ for details.\n" " (http://www.xfree86.org/cgi-bin/bugform.cgi)\n\n" "Be sure to report the -f number (fuzz) required to shift the\n" "lines into place. For debugging, it might also be helpful to\n" "include a URL to where you grabbed this program.\n\n" "-f NOTE: If all looks well with 'dgafbtest -f 1024', then\n" "the frame buffer is really 1024 bytes positive offset from\n" "where DGA says it is.\n\n" ); XCloseDisplay( display ); return 0; }