home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / VideoToolbox 95.04.18 / Demos / TestGDVideo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-18  |  16.1 KB  |  488 lines  |  [TEXT/MPCC]

  1. /* 
  2. TestGDVideo.c by Denis G. Pelli
  3. Tests all the documented Control and Status calls implemented in GDVideo.c
  4. The calls are documented in Designing Cards and Drivers, 3rd Edition.
  5.  
  6. The main purpose of this program is to find bugs in video drivers. If you do
  7. find a bug that isn't already listed in the table at the end of “Video synch”
  8. then please send it to denis@xp.psych.nyu.edu 
  9.  
  10. Unfortunately, the most common way to discover a new bug is for this program to
  11. crash. Please report crashes to denis@xp.psych.nyu.edu
  12.  
  13. BUGS:
  14.  
  15. HISTORY:
  16. 8/11/89    dgp    wrote it
  17. 3/23/90    dgp    introduced special case conditionals to skip tests known to crash
  18.             particular drivers.
  19. 3/23/90    dgp    made it compatible with MPW C, as a tool.
  20. 3/24/90    dgp    made some of the printouts less cryptic.
  21. 3/31/90    dgp    introduced RestoreDeviceClut after SetMode call.
  22. 7/12/90    dgp    tidied up the initial printf
  23. 7/19/90    dgp    Renamed VideoTest.c 
  24.             Open & close a window on each screen and DrawMenuBar()
  25.             so that QuickDraw will restore each screen.
  26. 7/28/90    dgp    italicized name of book.
  27. 9/9/90    dgp    Added quit by Command-. for graceful exit from bad situations.
  28. 10/17/90 dgp Removed unused variables. Replaced TRUE & FALSE by 1 & 0.
  29. 10/20/90    dgp    Apple has renamed the control and status calls, so I followed suit:
  30.                 GDGetPageBase replaces GDGetBaseAddr
  31.                 GDReset replaces GDInit
  32.                 GDGrayPage replace GDGrayScreen
  33.                 GDGetPageCnt replaces GDGetPages
  34. 10/22/90 dgp Print out number of pages for all modes, not just current mode.
  35.          dgp Restore clut manually since RestoreDeviceClut() doesn't
  36.              work on NuVista.
  37. 10/28/90 dgp Only test GetInterrupt & SetInterrupt if System is 6.05 or higher. This
  38.             avoids SetInterrupt() crash on old Apple TFB video driver.
  39. 2/12/91    dgp    Preceded GDGrayPage() call by GDSetMode() to cure crash when running
  40.             program immediately after rebooting. Mysterious.
  41.             Added SelectWindow() at end of program.
  42. 3/9/91    dgp    Print out mode names.
  43. 4/15/91    dgp    Make sure that new palette manager exists before calling RestoreDeviceClut.
  44.             Thanks to Chuck Stein for alerting me to the bug.
  45. 6/6/91    dgp    Time and print out how long GDSetEntries takes.
  46. 8/24/91    dgp    Made compatible with THINK C 5.0.
  47. 1/19/92    dgp    Cosmetic improvements to the printout.
  48. 2/25/92    dgp    Put timing info in bold.
  49. 8/22/92    dgp Display results of calling GDFrameRate() and GDFramesPerClutUpdate().
  50. 8/27/92    dgp    replace SysEnvirons() by Gestalt()
  51. 12/17/92 dgp enhanced to work with any dac size.
  52. 12/30/92 dgp Use GDClutSize() to determine clut size.
  53. 1/6/93    dgp    Tidied up the GetEntries/SetEntries code, now that we don't have
  54.             to test for the Mac IIci driver.
  55.             Skip GetEntries on Relax driver.
  56. 1/7/93 dgp    1.1 First numbered version.
  57. 1/18/93    dgp    Renamed ModeName() to GDModeName().
  58. 1/18/93    dgp    Moved the code that checked for bad drivers into GDGetEntries() in GDVideo.c,
  59.             where it belongs.
  60. 2/1/93    dgp Report whether driver is RAM- or ROM-based.
  61. 2/5/93    dgp    1.2. Recompiled with latest version of GDVideo, which now supports
  62.             patching of Mac IIci ROM-based driver.
  63. 2/6/93    dgp    1.3. Report ROM version, if driver is ROM-based.
  64. 2/7/93    dgp    1.4. Recompiled after fixing endless loop in PatchMacIIciVideoDriver
  65.             in GDVideo.c
  66. 2/18/93    dgp    1.5 Made compatible with PowerBook 160, by omitting call to GDSetInterrupt.
  67. 2/22/93    dgp    1.6 No longer assume that driver uses a version 0 gamma table.
  68. 4/17/93    dgp    1.7 Replaced obsolete GDFramesPerClutUpdate and GDTimeClutUpdate by 
  69.             GDTimeClut.
  70. 7/7/93    dgp    1.8 A bit more error checking of GDGetGamma.
  71. 7/29/94 dgp Eliminated use of "#s" printf format, since it's not supported by
  72.             Metrowerks CodeWarrior C.
  73. 9/5/94 dgp removed assumption in printf's that int==short.
  74. */
  75. #include "VideoToolbox.h"
  76. #include <assert.h>
  77. #include <Files.h>
  78. #include <Menus.h>
  79. #if UNIVERSAL_HEADERS
  80.     #include <LowMem.h>
  81. #else
  82.     #define LMGetMBarHeight() (* (short *) 0x0BAA)
  83.     #define LMSetMBarHeight(MBarHeightValue) ((* (short *) 0x0BAA) = (MBarHeightValue))
  84. #endif
  85. int PatchMacIIciVideoDriver(void);
  86. void GammaReport(GammaTbl *gamma);
  87. void main(void);
  88. void TestGDVideo(void);
  89. static void Error(int error);
  90. #define dRAMBased        0x0040
  91. #define VERSION "1.8"
  92. #define SCREENS 8
  93. static Boolean printGammaTable=0;    // Set this to 1 to enable printing of gamma table.
  94.  
  95. void main(void)
  96. {
  97.     StackGrow(20000);
  98.     Require(gestalt8BitQD);
  99.     TestGDVideo();
  100. }
  101.     
  102. CWindowPtr cw;            // just for poking around in the debugger
  103. GDHandle mainDevice;    // just for poking around in the debugger
  104. void TestGDVideo(void)
  105. {
  106.     WindowPtr window[SCREENS],oldPort;
  107.     static ColorSpec myTable[1024];    // Enough for 10-bit dacs
  108.     ColorSpec black={0,0,0,0};
  109.     WindowPtr theWindow;
  110.     GDHandle device;
  111.     short i,error,screen,mode,page,pages,start,count,pixelSize,type,clutSize;
  112.     short textSize=12,dacSize,dataSize,dataCnt,fontNumber,where;
  113.     short gammaDataWidth;
  114.     long systemVersion=0;
  115.     Boolean flag,keepWaiting;
  116.     GammaTbl *gamma=NULL,*myGamma=NULL;
  117.     char *name;
  118.     Ptr baseAddr;
  119.     Rect myRect;
  120.     double f;
  121.     unsigned char *byte;
  122.     unsigned short *word;
  123.     Boolean patch;
  124.     char typeName[][16]={"clutType","fixedType","directType"};
  125.     AuxDCE **auxDCEHandle;
  126.     long size;
  127.     Ptr ptr;
  128.     long romSize,romVersion;
  129.     double s,frames,missingFrames,frameRate;
  130.     EventRecord event;
  131.     
  132.     InitGraf(&qd.thePort);
  133.     InitFonts();
  134.     InitWindows();
  135.     InitCursor();
  136.     GetPort(&oldPort);
  137.     _atexit(RestoreCluts);
  138.     patch=PatchMacIIciVideoDriver();
  139.     for(screen=0;screen<SCREENS;screen++){
  140.         SetPort(oldPort);
  141.         device = GetScreenDevice(screen);
  142.         if(device == NULL) break;
  143.  
  144.         /*
  145.         For reasons that I don't understand, calling cscGrayPage() first,
  146.         immediately after rebooting, results in a crash when using an Apple's
  147.         old "Toby" video card. Preceding the call by
  148.         a call to cscSetMode() cures the symptom. Later calls to cscGrayPage()
  149.         seem to always work fine. Presumably something is not properly initialized
  150.         in the Apple video card driver. (Toby card driver version 4.)
  151.         */
  152.         error=GDGetMode(device,&mode,&page,&baseAddr);
  153.         error=GDSetMode(device,mode,page,&baseAddr);
  154.         GDRestoreDeviceClut(device);
  155.         
  156.         error=GDGrayPage(device,page);
  157.         if(screen==0)DrawMenuBar();    /* restore menu bar after GrayScreen */
  158.  
  159.         /* Open window */
  160.         myRect = (*device)->gdRect;    /* rect of desired screen in global coordinates */
  161.         if(screen==0)myRect.top+=LMGetMBarHeight();    /* allow for menu bar */
  162.         myRect.top+=17;                                /* allow for title bar */
  163.         InsetRect(&myRect,1,1);
  164.         name=GDCardName(device);
  165.         c2pstr(name);
  166.         window[screen]=
  167.             NewCWindow(NULL,&myRect,(unsigned char *)name,TRUE,documentProc,(WindowPtr) -1L,TRUE,123L);
  168.         cw=(CWindowPtr)window[screen];    // just for poking around in the debugger
  169.         mainDevice=GetMainDevice();        // just for poking around in the debugger
  170.         /* Write in window */
  171.         SetPort(window[screen]);
  172.         myRect=window[screen]->portRect;
  173.         GetFNum("\pTimes",&fontNumber);
  174.         TextFont(fontNumber);
  175.         TextSize(textSize);
  176.         DrawPrintf("\n");
  177.         if(screen==0)DrawPrintf("Welcome to TestGDVideo " VERSION ". Now testing all your video drivers."
  178.         " Please report any crash to denis@xp.psych.nyu.edu\n");
  179.  
  180.         DrawPrintf("Driver: %s version %d",GDNameStr(device),(int)GDVersion(device));
  181.         auxDCEHandle = (AuxDCE **) GetDCtlEntry((*device)->gdRefNum);
  182.         if((**auxDCEHandle).dCtlFlags & dRAMBased){
  183.             /* RAM-based driver. */
  184.             size=GetHandleSize((Handle)(**auxDCEHandle).dCtlDriver);
  185.             DrawPrintf(", occupying %ld bytes in RAM.",size);
  186.         }else{
  187.             /* ROM-based driver. */
  188.             ptr=(**auxDCEHandle).dCtlDriver;
  189.             Gestalt(gestaltROMSize,&romSize);
  190.             Gestalt(gestaltROMVersion,&romVersion);
  191.             DrawPrintf(", at 0x%lx in ROM. %ld K ROM version %ld (%ld)."
  192.                 ,ptr,romSize/1024,romVersion%256,(romVersion/256));
  193.         }
  194.         DrawPrintf("\n");
  195.         if(GetDeviceSlot(device)>=0)DrawPrintf("Slot: %d\n",(int)GetDeviceSlot(device));
  196.         else DrawPrintf("Slot: none\n");
  197.     
  198.         DrawPrintf("GrayPage: ");
  199.         if(error) Error(error);
  200.         else DrawPrintf("ok\n");
  201.  
  202.         DrawPrintf("cscGetMode: ");
  203.         error=GDGetMode(device,&mode,&page,&baseAddr);
  204.         if(error) Error(error);
  205.         else DrawPrintf("%d-bit mode, page %d base address 0x%lX\n"
  206.             ,(int)GDPixelSize(device),(int)page,baseAddr);
  207.     
  208.         DrawPrintf("cscSetMode: ");
  209.         error=GDSetMode(device,mode,page,&baseAddr);
  210.         if(error) Error(error);
  211.         else DrawPrintf("ok\n");
  212.  
  213.         /* 
  214.             GDSetMode has the annoying side effect of 
  215.             setting the clut to uniform gray, so let's restore the clut.
  216.         */
  217.         GDRestoreDeviceClut(device);
  218.  
  219.         for(i=0x80;i<=0x85;i++){
  220.             pixelSize=GDModePixelSize(device,i);
  221.             if(pixelSize>0){
  222.                 DrawPrintf("cscGetPageCnt: ");
  223.                 error=GDGetPageCnt(device,i,&pages);
  224.                 if(error)DrawPrintf("%d-bit mode n/a\n",(int)pixelSize);
  225.                 else DrawPrintf("%d-bit mode has %d pages available\n",(int)pixelSize,(int)pages);
  226.             }
  227.         }
  228.  
  229.         DrawPrintf("cscGetPageBase: ");
  230.         page=0;    /* Ask for first page */
  231.         error=GDGetPageBase(device,page,&baseAddr);
  232.         if(error) Error(error);
  233.         else DrawPrintf("%d-bit mode, page %d base address 0x%lX\n"
  234.             ,(int)GDModePixelSize(device,mode),(int)page,baseAddr);
  235.         if(pages>1){
  236.             DrawPrintf("cscGetPageBase: ");
  237.             page=1;    /* Ask for second page */
  238.             error=GDGetPageBase(device,page,&baseAddr);
  239.             if(error) Error(error);
  240.             else DrawPrintf("%d-bit mode, page %d base address 0x%lX\n"
  241.                 ,(int)GDModePixelSize(device,mode),(int)page,baseAddr);
  242.         }
  243.     
  244.         DrawPrintf("cscGetGray: ");
  245.         error=GDGetGray(device,&flag);
  246.         if(error) Error(error);
  247.         else DrawPrintf("flag %d\n",(int)flag);
  248.     
  249.         DrawPrintf("cscSetGray: ");
  250.         flag=0;
  251.         error=GDSetGray(device,flag);
  252.         if(error) Error(error);
  253.         else DrawPrintf("ok\n");
  254.     
  255.         /* GetInterrupt crashes the NuVista driver.  */
  256.         if(!EqualString("\p.Display_Video_NuVista",GDName(device),0,0)){
  257.             /* SetInterrupt crashes the old Apple driver.  */
  258.             if(systemVersion>=0x605){
  259.                 DrawPrintf("cscGetInterrupt: ");
  260.                 error=GDGetInterrupt(device,&flag);
  261.                 if(error) Error(error);
  262.                 else DrawPrintf("%d\n",(int)flag);
  263.         
  264.                 if(0){
  265.                     // crashes built-in video on PowerBook 160
  266.                     DrawPrintf("cscSetInterrupt: ");
  267.                     error=GDSetInterrupt(device,flag);
  268.                     if(error) Error(error);
  269.                     else DrawPrintf("ok\n");
  270.                 }
  271.             }
  272.             else DrawPrintf("•••••Skipping GetInterrupt & SetInterrupt.\n");
  273.         }
  274.         else DrawPrintf("•••••Skipping GetInterrupt & SetInterrupt to avoid known bug in %s.\n",GDCardName(device));
  275.  
  276.         DrawPrintf("cscGetGamma: ");
  277.         gamma=NULL;
  278.         error=GDGetGamma(device,&gamma);
  279.         if(error) Error(error);
  280.         else GammaReport(gamma);
  281.         if(!error && gamma!=NULL)gammaDataWidth=gamma->gDataWidth;
  282.         else gammaDataWidth=0;
  283.         
  284.         DrawPrintf("cscSetGamma: ");
  285.         if(gamma==NULL || gamma->gDataWidth==0){
  286.             // Get the dac's size from the current gamma table.
  287.             if(gamma!=NULL && gamma->gDataWidth!=0){
  288.                 dacSize=gamma->gDataWidth;
  289.                 dataCnt=gamma->gDataCnt;
  290.             }else{ // The driver won't tell us, so assume 8-bit dacs.
  291.                 dacSize=8;
  292.                 dataCnt=1L<<dacSize;
  293.             }
  294.             if(dacSize<=8)dataSize=1;
  295.             else dataSize=2;
  296.             myGamma=(GammaTbl *)NewPtr(sizeof(GammaTbl)+dataCnt*dataSize);
  297.             assert(myGamma!=NULL);
  298.             myGamma->gVersion=0;
  299.             myGamma->gType=0;
  300.             myGamma->gFormulaSize=0;
  301.             myGamma->gChanCnt=1;
  302.             myGamma->gDataCnt=dataCnt;
  303.             myGamma->gDataWidth=dacSize;
  304.             byte=(unsigned char *)myGamma->gFormulaData+myGamma->gFormulaSize;
  305.             word=(unsigned short *)byte;
  306.             if(myGamma->gDataWidth<=8)
  307.                 for(i=0;i<myGamma->gDataCnt;i++) byte[i]=i;
  308.             else
  309.                 for(i=0;i<myGamma->gDataCnt;i++) word[i]=i;
  310.             gamma=myGamma;
  311.         }else myGamma=NULL;
  312.         error=GDSetGamma(device,gamma);
  313.         if(error) Error(error);
  314.         else DrawPrintf("ok.\n");
  315.         if(myGamma!=NULL){
  316.             DisposPtr((Ptr)myGamma);
  317.             myGamma=NULL;
  318.         }
  319.  
  320.     DrawPrintf("cscGetGamma: ");
  321.     gamma=NULL;
  322.     error=GDGetGamma(device,&gamma);
  323.     if(error) Error(error);
  324.     else GammaReport(gamma);
  325.     if(!error && gamma!=NULL)gammaDataWidth=gamma->gDataWidth;
  326.     else gammaDataWidth=0;
  327.     
  328.         // GetEntries
  329.         start=0;
  330.         count=GDClutSize(device)-1;
  331.         if(count>sizeof(myTable)/sizeof(myTable[0])-1)
  332.             count=sizeof(myTable)/sizeof(myTable[0])-1;
  333.         DrawPrintf("cscGetEntries: ");
  334.         error=GDGetEntries(device,start,count,myTable);
  335.         if(error)Error(error);
  336.         else DrawPrintf("ok\n");
  337.         
  338.         // SetEntries
  339.         count=GDClutSize(device)-1;
  340.         switch((*device)->gdType){
  341.             case clutType:
  342.                 DrawPrintf("cscSetEntries: ");
  343.                 error=GDSetEntries(device,0,count,((**(**(**device).gdPMap).pmTable)).ctTable);
  344.                 if(error)Error(error);
  345.                 else DrawPrintf("ok\n");
  346.                 break;
  347.             case directType:
  348.                 DrawPrintf("DirectSetEntries: ");
  349.                 error=GDDirectSetEntries(device,0,0,&black);
  350.                 if(error)Error(error);
  351.                 else DrawPrintf("ok\n");
  352.                 break;
  353.             case fixedType:
  354.                 DrawPrintf("A fixedType clut cannot be modified.\n");
  355.                 break;
  356.         }
  357.         
  358.         // Miscellaneous
  359.         clutSize=GDClutSize(device);
  360.         pixelSize=1<<(mode&7);
  361.         type=(*device)->gdType;
  362.         DrawPrintf("Currently in mode %d, pixelSize %d bits, clutSize %d entries, %s"
  363.             ,(int)mode,(int)pixelSize,(int)clutSize,typeName[type]);
  364.         if(gammaDataWidth!=0)DrawPrintf(", dacSize %d bits",(int)gammaDataWidth);
  365.         DrawPrintf(".\n");
  366.  
  367.         TextFace(bold);
  368.         f=GDFrameRate(device);
  369.         DrawPrintf("%.1f Hz frame rate (%.1f ms).\n",f,1000.0/f);
  370.         if((*device)->gdType!=fixedType){
  371.             if((*device)->gdType==clutType)name="cscSetEntries";
  372.             else name="cscDirectSetEntries";
  373.             error=GDTimeClut(device,GDSetEntries,0
  374.                 ,&s,&frames,&missingFrames,&frameRate);
  375.             DrawPrintf("Repeatedly loading the clut, by calling %s(), "
  376.                 "takes %.2f frame each time.\n",name,frames);
  377.             DrawPrintf("%.1f Hz clut update rate (%.1f ms).\n",1.0/s,1000.0*s);
  378.         }
  379.         TextFace(0);
  380.         
  381.         if(0){
  382.             /* I haven't found any use for these calls, so skip 'em */
  383.             DrawPrintf("cscGetDefaultMode: ");
  384.             error=GDGetDefaultMode(device,&mode);
  385.             if(error) Error(error);
  386.             else DrawPrintf("0x%X\n",mode);
  387.         
  388.             DrawPrintf("cscSetDefaultMode: ");
  389.             error=GDSetDefaultMode(device,mode);
  390.             if(error) Error(error);
  391.             else DrawPrintf("ok\n");
  392.         }
  393.         if(patch && EqualString("\p.Display_Video_Apple_RBV1",GDName(device),TRUE,FALSE))
  394.             DrawPrintf(
  395.             "This Mac IIci video driver has been patched (until reboot) to fix a bug\n"
  396.             "that prevents reading the clut. The version number was changed from 0 to %d.\n"
  397.             ,(int)GDVersion(device));
  398.     }
  399.     SelectWindow(window[0]);
  400.     SetPort(window[0]);
  401.     DrawPrintf(
  402.         "This completes the test of the known Control and Status calls for each\n"
  403.         "of your video devices. For an explanation of what these calls do, see\n"
  404.         "Apple’s book ");
  405.     TextFace(italic);
  406.     DrawPrintf("Designing Cards and Drivers,");
  407.     TextFace(0);
  408.     DrawPrintf(" 3rd Ed., Addison Wesley, Chapter 9.\n");
  409.     TextFace(bold);
  410.     DrawPrintf("Quit by closing any window, or hitting Command-.\n");
  411.     do{
  412.         keepWaiting=1;
  413.         while(!GetNextEvent(mDownMask+keyDownMask,&event)) ;
  414.         switch(event.what){
  415.         case mouseDown:
  416.             where=FindWindow(event.where,&theWindow);
  417.             switch(where){
  418.             case inContent:
  419.             case inDrag:
  420.             case inGrow:
  421.             case inGoAway:
  422.                 SelectWindow(theWindow);
  423.             }
  424.             if(where==inGoAway) keepWaiting = !TrackGoAway(theWindow,event.where);
  425.             break;
  426.         case keyDown:
  427.             if(event.modifiers & cmdKey) switch(event.message & charCodeMask) {
  428.                 case '.':
  429.                 case 'w':
  430.                 keepWaiting=0;
  431.             }
  432.             break;
  433.         }
  434.     } while (keepWaiting);
  435.     SetPort(oldPort);
  436.     for(i=0;i<screen;i++)DisposeWindow(window[i]);
  437.     _exit(0);
  438. }
  439.  
  440. void GammaReport(GammaTbl *gamma)
  441. {
  442.     short i,j,newFontNumber,fontNumber,textSize;
  443.     unsigned char *byte;
  444.     unsigned short *word;
  445.     WindowPtr window;
  446.  
  447.     if(gamma==NULL)DrawPrintf("error--NULL gamma table pointer\n");
  448.     else{
  449.         DrawPrintf("gamma table @%lx indicates that the video card has %d-bit dacs, "
  450.         "and %d entries in its clut.\n"
  451.         ,gamma,(int)gamma->gDataWidth,(int)gamma->gDataCnt);
  452.         DrawPrintf("gVersion %d, gType %d, gFormulaSize %d, gChanCnt %d\n"
  453.         ,(int)gamma->gVersion,(int)gamma->gType,(int)gamma->gFormulaSize,(int)gamma->gChanCnt);
  454.         if(printGammaTable && gamma->gVersion==0 && gamma->gType==0){
  455.             GetFNum("\pMonaco",&newFontNumber);
  456.             GetPort(&window);
  457.             fontNumber=window->txFont;
  458.             textSize=window->txSize;
  459.             TextFont(newFontNumber);
  460.             TextSize(9);
  461.             byte=(unsigned char *)gamma->gFormulaData+gamma->gFormulaSize;
  462.             word=(unsigned short *)byte;
  463.             DrawPrintf("Gamma Table:\n");
  464.             for(i=0;i<gamma->gDataCnt;i+=64) {
  465.                 DrawPrintf("%3d: ",i);
  466.                 if(gamma->gDataWidth<=8)
  467.                     for(j=0;j<64;j++) DrawPrintf(" %3u",byte[i+j]);
  468.                 else
  469.                     for(j=0;j<64;j++) DrawPrintf(" %3u",word[i+j]);
  470.                 DrawPrintf("\n");
  471.             }
  472.             TextFont(fontNumber);
  473.             TextSize(textSize);
  474.         }
  475.     }
  476. }
  477.  
  478. static void Error(int error)
  479. {
  480.     switch(error){
  481.     case -17:
  482.     case -18:
  483.         DrawPrintf("n/a\n");
  484.         break;
  485.     default:
  486.         DrawPrintf("error %d\n",error);
  487.     }
  488. }