home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / Third Party SDKs / ATI RAVE SDK / Samples / QD3D Tests / BackGround (ATI) / BackGroundShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-09  |  19.3 KB  |  775 lines  |  [TEXT/CWIE]

  1. // Quickdraw 3D sample code
  2. //
  3. // This file illustrates how to set up a pixmap based draw context.
  4. // A metafile is read into and imaged in the pixmap, this pixmap is combined
  5. // with a pixmap containing a background, so that the 3d data is drawn over 
  6. // the background
  7. //
  8. // Nick Thompson, AppleLink: DEVSUPPORT (devsupport@applelink.apple.com)
  9. //
  10. // ©1994-5 Apple Computer Inc., All Rights Reserved
  11.  
  12.  
  13. // system headers
  14. #include <Menus.h>
  15. #include <Devices.h>
  16. #include <Events.h>
  17. #include <Dialogs.h>
  18. #include <DiskInit.h>
  19. #include <Fonts.h>
  20. #include <Menus.h>
  21. #include <PictUtils.h>
  22. #include <QDOffScreen.h>
  23. #include <QuickDraw.h>
  24. #include <SegLoad.h>
  25. #include <StandardFile.h>
  26. #include <TextEdit.h>
  27. #include <ToolUtils.h>
  28. #include <Timer.h>
  29. #include <Processes.h>
  30. #include <string.h>
  31.  
  32. // for QuickDraw 3D
  33. #include "QD3D.h"
  34. #include "QD3DMath.h"
  35. #include "QD3DDrawContext.h"
  36. #include "QD3DShader.h"
  37. #include "QD3DTransform.h"
  38. #include "QD3DGroup.h"
  39. #include "QD3DCamera.h"
  40.  
  41.  
  42. #include "BackGroundShell.h"
  43. #include "BackGroundSupport.h"
  44.  
  45. // get the interface to my error handler routines
  46. #include "MyErrorHandler.h"
  47.  
  48. #define ONE_SECOND                    1000000
  49. #define MILLIONTHS                    0.000001F
  50. #define MAX( a, b )                    ( ((a) > (b)) ? (a) : (b) )
  51.  
  52. /*
  53.  * control use of ATI VRAM for GWorld pixmaps
  54.  */
  55. #define USE_ATI_OFF_SCREEN_MEM_MANAGER        1
  56. #if USE_ATI_OFF_SCREEN_MEM_MANAGER
  57.     #include "atimem.h"
  58.  
  59.     QDErr NewGWorldVRAM( GWorldPtr *offscreenGWorld, short PixelDepth, const Rect *boundsRect, 
  60.                          CTabHandle cTable, GDHandle aGDevice, GWorldFlags flags, GDHandle gdh );
  61.     void DisposeGWorldVRAM( GWorldPtr offscreenGWorld );
  62.     void VRAMCallBack( GDHandle hGDevice, unsigned int flag, void *data );
  63.     int ATI_IsVRAMGWorld( GWorldPtr offscreenGWorld );
  64.     int gCallbackIndex;
  65.     int    gNumGWorldVRAM = 0;
  66. #endif
  67.  
  68. const RGBColor    kClearColor = { 0x0000, 0xffff, 0x0000 } ;
  69. const RGBColor    kWhiteColor = { 0xffff, 0xffff, 0xffff } ;
  70.  
  71. //-------------------------------------------------------------------------------------------
  72. // function prototypes
  73.  
  74. static void InitToolbox( void ) ;
  75. static void MainEventLoop( void ) ;
  76. static void    HandleKeyPress(EventRecord *event) ;
  77. static void    HandleOSEvent(EventRecord *event) ;
  78. void         InitDocumentData( DocumentPtr theDocument ) ;
  79. TQ3Status     DocumentDraw3DData( DocumentPtr theDocument ) ;
  80. void        DisposeDocumentData( DocumentPtr theDocument) ;
  81. void         DocumentDrawOnscreen(DocumentPtr theDocument, Rect *clipRect) ;
  82.  
  83. OSErr        WritePict( PicHandle myPic, short  dstPictFRef ) ;
  84. OSErr        GetOutputFileRef(short    *dstPictFRef ) ;
  85. PicHandle    ImageToPict( DocumentPtr theDocument, WindowPtr theWindow ) ;
  86. void        DoSaveAs(DocumentPtr theDocument)  ;
  87. unsigned long MicrosecondCount( void );
  88. void         DisplayString( int x, int y, char *str );
  89.  
  90. //-------------------------------------------------------------------------------------------
  91. //
  92.  
  93. Boolean         gQuitFlag         = false ;
  94. WindowPtr        gMainWindow        = nil ;
  95. DocumentRec        gDocument ;
  96.  
  97. unsigned long    start, end;
  98. float            seconds;
  99. unsigned long    count = 0;
  100. char             str[100];
  101. RGBColor        BLACK = { 0, 0, 0 };
  102.  
  103. //-------------------------------------------------------------------------------------------
  104. // main()
  105. // entry point for the application, initialize the toolbox, initialize QuickDraw 3D
  106. // and enter the main event loop.  On exit from the main event loop, we want to call
  107. // the QuickDraw 3D exit function to clean up QuickDraw 3d.
  108.  
  109. void main(void)
  110. {
  111.     TQ3Status    myStatus;
  112.     int            stat = true;
  113.     Rect        rBounds = { 50, 50, 200, 200 };
  114.     Str255        title = "\pSpinning Box" ;        
  115.     FSSpec        theFileSpec ;                    // the file we are opening
  116.     GDHandle    gdh;
  117.     
  118.     InitToolbox() ;
  119.     
  120.  
  121.     if(MetafileFileSpecify( &theFileSpec )) {
  122.     
  123.         SetCursor(*(GetCursor(watchCursor)));
  124.         
  125.         //    Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
  126.         myStatus = Q3Initialize();
  127.         if ( myStatus == kQ3Failure )
  128.             DebugStr("\pErInitialize returned failure.");            
  129.     
  130.         // install the error & warning handler - these get called whenever
  131.         // errors or warnings occur, which means we don't have to check so 
  132.         // much
  133.         Q3Error_Register( MyErrorHandler, 0L );        
  134.         Q3Warning_Register( MyWarningHandler, 0L );        
  135.     
  136.         // set up our globals
  137.         gQuitFlag = false ;
  138.         gMainWindow = NewCWindow(nil,&rBounds,title,false,noGrowDocProc,(WindowPtr)-1,true,nil); ;
  139.  
  140.         // initialise our document structure
  141.         InitDocumentData( &gDocument ) ;
  142.         
  143.         // try to read the file into the main display group
  144.         if((gDocument.fModel = MyNewModelFromFile(&theFileSpec)) != NULL ) {        
  145.         
  146.             // get a bg picture
  147.             if(PictureFileSpecify(&theFileSpec)) {
  148.                 PicHandle thePicture ;
  149.                 if((thePicture = OpenPICTFile( &theFileSpec )) != nil ) {
  150.                     
  151.                     CGrafPtr    savedPort ;
  152.                     OSErr        theErr ;
  153.                     Rect        bounds = (**thePicture).picFrame ;
  154.                     
  155.                     GetGWorld( &savedPort, &gdh );
  156.                                         
  157.                 #if USE_ATI_OFF_SCREEN_MEM_MANAGER
  158.                     /*
  159.                      * try to allocate GWorld for background image
  160.                      * on VRAM - if "background_image"is NULL then
  161.                      * VRAM allocation failed and GWorld is ordinary
  162.                      * one in system memory
  163.                      */
  164.                     theErr = NewGWorldVRAM( &gDocument.fBgPicture, 
  165.                                             (**((**gdh).gdPMap)).pixelSize, 
  166.                                             &bounds, 
  167.                                             nil, 
  168.                                             nil, 
  169.                                             0L, 
  170.                                             gdh );
  171.                 #else
  172.                     // create the offscreen for the picture, this is faster than
  173.                     // calling DrawPicture each time through our update onscreen routine.
  174.                     theErr = NewGWorld(     &gDocument.fBgPicture, 
  175.                                             (**((**gdh).gdPMap)).pixelSize, 
  176.                                             &bounds, 
  177.                                             nil, 
  178.                                             nil, 
  179.                                             0L );
  180.                 #endif
  181.                          
  182.                     if( theErr != noErr || stat == false )
  183.                         ExitToShell() ;
  184.                     
  185.                     SetGWorld( gDocument.fBgPicture, nil ) ;
  186.                     DrawPicture( thePicture, &bounds ) ;
  187.                     KillPicture( thePicture ) ;
  188.                     
  189.                 #if USE_ATI_OFF_SCREEN_MEM_MANAGER
  190.                     /*
  191.                      * try to allocate GWorld for composite image
  192.                      * on VRAM - if "composite_image"is NULL then
  193.                      * VRAM allocation failed and GWorld is ordinary
  194.                      * one in system memory
  195.                      */
  196.                     theErr = NewGWorldVRAM( &gDocument.fCompositeBuffer, 
  197.                                             (**((**gdh).gdPMap)).pixelSize, 
  198.                                             &bounds, 
  199.                                             nil, 
  200.                                             nil, 
  201.                                             0L, 
  202.                                             gdh );
  203.                 #else    
  204.                     theErr = NewGWorld(        &gDocument.fCompositeBuffer, 
  205.                                             (**((**gdh).gdPMap)).pixelSize, 
  206.                                             &bounds,
  207.                                             nil,
  208.                                             nil,
  209.                                             0L );
  210.                 #endif
  211.                     if( theErr != noErr )
  212.                         ExitToShell() ;
  213.                 
  214.                     // clear our compositing buffer        
  215.                     SetGWorld( gDocument.fCompositeBuffer, nil ) ;
  216.                     RGBBackColor( &kClearColor ) ;
  217.                     EraseRect(  &bounds ) ;
  218.                 
  219.                     // restore the environment                
  220.                     SetGWorld( savedPort, gdh );
  221.  
  222.                     AdjustCamera(    &gDocument,
  223.                                     (bounds.right - bounds.left),
  224.                                     (bounds.bottom - bounds.top) ) ;
  225.         
  226.                     SetWTitle( gMainWindow, theFileSpec.name );
  227.                     
  228.                     SizeWindow(    gMainWindow,
  229.                                 (bounds.right - bounds.left),
  230.                                 (bounds.bottom - bounds.top),
  231.                                 false );
  232.                                 
  233.                     ShowWindow( gMainWindow ) ;
  234.                     SetPort( gMainWindow ) ;
  235.             
  236.                     SetCursor(&qd.arrow) ;
  237.                     MainEventLoop();
  238.                 }
  239.             }
  240.             
  241.         }
  242.  
  243.         DisposeDocumentData( &gDocument );
  244.                         
  245.         //    Close our connection to the QuickDraw 3D library
  246.         myStatus = Q3Exit();
  247.         if ( myStatus == kQ3Failure )
  248.             DebugStr("\pErExit returned failure.");            
  249.     }    
  250. }
  251.  
  252. //-------------------------------------------------------------------------------------------
  253. //
  254.  
  255. void InitDocumentData( DocumentPtr theDocument ) 
  256. {
  257.     GWorldPtr        theOffscreen ;
  258.     GDHandle        theDevice ;
  259.     TQ3Point3D        myOrigin = { 0, 0, 0 } ;
  260.     OSErr            myErr;
  261.     
  262.     GetGWorld( &theOffscreen, &theDevice ) ;
  263.     
  264. #if USE_ATI_OFF_SCREEN_MEM_MANAGER
  265.     /*
  266.      * try to allocate GWorld for drawing image
  267.      * on VRAM - if "draw_image"is NULL then
  268.      * VRAM allocation failed and GWorld is
  269.      * ordinary one in system memory
  270.      */
  271.     myErr = NewGWorldVRAM(     &gDocument.fGWorld, 
  272.                             (**((**theDevice).gdPMap)).pixelSize, 
  273.                             &gMainWindow->portRect, 
  274.                             nil, 
  275.                             nil, 
  276.                             0L, 
  277.                             theDevice );
  278. #else
  279.     // create the offscreen for the picture, this is faster than
  280.     // calling DrawPicture each time through our update onscreen routine.
  281.     myErr = NewGWorld(         &gDocument.fGWorld, 
  282.                             (**((**theDevice).gdPMap)).pixelSize, 
  283.                             &gMainWindow->portRect, 
  284.                             nil, 
  285.                             nil, 
  286.                             0L );
  287. #endif
  288.         
  289.     if(myErr != noErr )
  290.         goto bail ;
  291.             
  292.     SetGWorld( theDocument->fGWorld, nil ) ;
  293.     EraseRect( &gMainWindow->portRect ) ;
  294.     SetGWorld( theOffscreen, theDevice ) ;
  295.     
  296.     // sets up the 3d data for the scene
  297.     //    Create view for QuickDraw 3D.
  298.     theDocument->fView = MyNewView( theDocument->fGWorld );
  299.  
  300.     // the main display group:
  301.     theDocument->fModel = NULL ;
  302.     
  303.     // scale and group center
  304.     theDocument->fGroupScale = 1;                
  305.     theDocument->fGroupCenter = myOrigin ;    
  306.     
  307.     // the drawing styles:
  308.     theDocument->fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  309.     theDocument->fBackFacing = Q3BackfacingStyle_New( kQ3BackfacingStyleBoth ) ;
  310.     theDocument->fFillStyle = Q3FillStyle_New(kQ3FillStyleFilled ) ;
  311.  
  312.     // set the rotation matrix the identity matrix
  313.     Q3Matrix4x4_SetIdentity(&theDocument->fRotation);    
  314.                     
  315.     return ;
  316.     
  317. bail:
  318.     // we failed setting up the GWorld
  319.     // so we want to quit here
  320.     ExitToShell() ;
  321.     
  322. }
  323.  
  324. void DisposeDocumentData( DocumentPtr theDocument)
  325. {
  326.  
  327. #if USE_ATI_OFF_SCREEN_MEM_MANAGER
  328.     if( theDocument->fGWorld )
  329.         DisposeGWorldVRAM( theDocument->fGWorld );
  330.         
  331.     if( theDocument->fBgPicture )
  332.         DisposeGWorldVRAM( theDocument->fBgPicture );
  333.         
  334.     if( theDocument->fCompositeBuffer )
  335.         DisposeGWorldVRAM( theDocument->fCompositeBuffer );    
  336. #else
  337.     if( theDocument->fGWorld )
  338.         DisposeGWorld( theDocument->fGWorld );
  339.     
  340.     if( theDocument->fBgPicture )    
  341.         DisposeGWorld( theDocument->fBgPicture );
  342.  
  343.     if( theDocument->fCompositeBuffer )
  344.         DisposeGWorld( theDocument->fCompositeBuffer );
  345. #endif
  346.     
  347.     if(theDocument->fView)
  348.         Q3Object_Dispose(theDocument->fView) ;                // the view for the scene
  349.  
  350.     if(theDocument->fModel)
  351.         Q3Object_Dispose(theDocument->fModel) ;                // object in the scene being modelled
  352.  
  353.     if(theDocument->fInterpolation)
  354.         Q3Object_Dispose(theDocument->fInterpolation) ;        // interpolation style used when rendering
  355.  
  356.     if(theDocument->fBackFacing)
  357.         Q3Object_Dispose(theDocument->fBackFacing) ;        // whether to draw shapes that face away from the camera
  358.  
  359.     if(theDocument->fFillStyle)
  360.         Q3Object_Dispose(theDocument->fFillStyle) ;            // whether drawn as solid filled object or decomposed to components
  361. }
  362. //-----------------------------------------------------------------------------
  363. // assumes the port is set up before being called
  364.  
  365. TQ3Status DocumentDraw3DData( DocumentPtr theDocument )
  366. {    
  367.     TQ3Status theStatus ;    
  368.  
  369.     //    Start rendering.
  370.     Q3View_StartRendering(theDocument->fView) ;
  371.     do {
  372.         theStatus = SubmitScene( theDocument ) ;
  373.     } while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
  374.  
  375.     return theStatus ;    
  376. }
  377.  
  378. //-------------------------------------------------------------------------------------------
  379. //
  380.  
  381. void DocumentDrawOnscreen(DocumentPtr theDocument, Rect *clipRect)
  382. {
  383.     if (theDocument->fGWorld) {
  384.     
  385.         CGrafPtr            savedPort;
  386.         GDHandle            savedDevice;
  387.         RGBColor            savedColor ;
  388.  
  389.         GetGWorld( &savedPort, &savedDevice);
  390.         // composite the image in the offscreen
  391.         // first draw the BG Pict
  392.         SetGWorld( theDocument->fCompositeBuffer,  nil);
  393.         
  394.         GetBackColor(&savedColor);
  395.         RGBBackColor(&kWhiteColor) ;
  396.                 
  397.         CopyBits ((BitMapPtr) &theDocument->fBgPicture->portPixMap,
  398.                   (BitMapPtr) &theDocument->fCompositeBuffer->portPixMap,
  399.                   &theDocument->fBgPicture->portRect, 
  400.                   &theDocument->fCompositeBuffer->portRect, 
  401.                   srcCopy, 
  402.                   0L);
  403.         
  404.         RGBBackColor(&savedColor) ;
  405.         OpColor(&kClearColor);
  406.               
  407.         // next draw the 3d image over the bg pict using transparent copy
  408.         CopyBits ((BitMapPtr) &theDocument->fGWorld->portPixMap,
  409.                   (BitMapPtr) &theDocument->fCompositeBuffer->portPixMap,
  410.                   &theDocument->fGWorld->portRect, 
  411.                   &theDocument->fCompositeBuffer->portRect, 
  412.                   srcCopy | transparent, 
  413.                   0L);
  414.         SetGWorld( (CGrafPtr)gMainWindow,  nil);
  415.         
  416.         ClipRect( clipRect ) ;
  417.         
  418.         
  419.         // don't need to lockPixels on the GWorld as the 
  420.         // offscreen remains locked (see IM: QD3D), the
  421.         // pixmap for a pixmap draw context must remain locked
  422.         
  423.         CopyBits ((BitMapPtr) &theDocument->fCompositeBuffer->portPixMap,
  424.                   &gMainWindow->portBits,
  425.                   &theDocument->fCompositeBuffer->portRect, 
  426.                   &gMainWindow->portRect,
  427.                   srcCopy, 
  428.                   0L);
  429.                   
  430.         SetGWorld( savedPort, savedDevice);
  431.       }
  432. }
  433.  
  434.  
  435. //-------------------------------------------------------------------------------------------
  436. //
  437.  
  438. short HiWrd(long aLong)
  439. {
  440.     return    (((aLong) >> 16) & 0xFFFF) ;
  441. }
  442.  
  443. //-------------------------------------------------------------------------------------------
  444. //
  445.  
  446. short LoWrd(long aLong)
  447. {
  448.     return    ((aLong) & 0xFFFF) ;
  449.  
  450. }
  451.  
  452. //-------------------------------------------------------------------------------------------
  453. //
  454.  
  455. void InitToolbox()
  456. {
  457.     Handle        menuBar = nil;
  458.  
  459.     MaxApplZone() ;
  460.     MoreMasters() ; MoreMasters() ; MoreMasters() ; 
  461.     
  462.     InitGraf( &qd.thePort );
  463.     InitFonts();
  464.     InitWindows();
  465.  
  466.     FlushEvents( everyEvent, 0 ) ;
  467.     // initialize application globals
  468.     
  469.     gQuitFlag = false;
  470.     InitCursor();
  471.     
  472. }
  473.  
  474. //-------------------------------------------------------------------------------------------
  475. //
  476. void MainEventLoop()
  477. {
  478.     EventRecord     event;
  479.     WindowPtr       window;
  480.     short           thePart;
  481.     Rect            screenRect, updateRect;
  482.     Point            aPoint = {100, 100};
  483.  
  484.     start = MicrosecondCount();
  485.  
  486.     while( !gQuitFlag )
  487.     {
  488.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  489.         {
  490.  
  491.             switch (event.what) {
  492.                 case mouseDown:
  493.                 
  494.                     thePart = FindWindow( event.where, &window );
  495.                     
  496.                     switch( thePart ) {
  497.                         case inMenuBar: 
  498.                             break;
  499.                         
  500.                         case inDrag:
  501.                     
  502.                             screenRect = (**GetGrayRgn()).rgnBBox;
  503.                             DragWindow( window, event.where, &screenRect );
  504.                             break ;
  505.                     
  506.                         case inContent:
  507.                     
  508.                             if (window != FrontWindow())
  509.                                 SelectWindow( window );
  510.                             break ;
  511.                     
  512.                         case inGoAway:
  513.                             if (TrackGoAway( window, event.where )) {
  514.                                 DisposeWindow ( window );
  515.                                 gQuitFlag = true;
  516.  
  517.                             }
  518.                             break ;
  519.                             
  520.                         default:
  521.                             break ;
  522.                     }
  523.                     break ;
  524.                             
  525.                         
  526.                 case updateEvt:
  527.                 
  528.                     window = (WindowPtr)event.message;
  529.                     updateRect = (**(window->visRgn)).rgnBBox;
  530.                     SetPort( window ) ;
  531.                                         
  532.                     BeginUpdate( window );
  533.                     DocumentDraw3DData( &gDocument ) ;
  534.                     DocumentDrawOnscreen( &gDocument, &updateRect ) ;
  535.                     EndUpdate( window );
  536.  
  537.                     /*
  538.                      * display frame rate
  539.                      */
  540.                     end     = MicrosecondCount();
  541.                     seconds = (float)(MAX((end-start),1))*MILLIONTHS;        
  542.                     sprintf( str, "fps = %5.2f", ++count/seconds);
  543.                     DisplayString( 2, 10, str );
  544.                     break ;
  545.                     
  546.                 case keyDown:
  547.                 case autoKey:
  548.                     HandleKeyPress(&event);
  549.                     break;
  550.                     
  551.                 case diskEvt:
  552.                     if ( HiWrd(event.message) != noErr ) 
  553.                         (void) DIBadMount(aPoint, event.message);
  554.                     break;
  555.                     
  556.                 case osEvt:
  557.                 case activateEvt:
  558.                     break;
  559.             }
  560.         }
  561.         else {
  562.             // we received a null event, rotate the cube
  563.             TQ3Matrix4x4    tmp;
  564.             Rect        theRect = ((GrafPtr)gMainWindow)->portRect ;
  565.             
  566.             SetPort((GrafPtr)gMainWindow) ;
  567.             Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
  568.             Q3Matrix4x4_Multiply(&gDocument.fRotation, &tmp, &gDocument.fRotation);
  569.  
  570.             InvalRect( &theRect ) ;
  571.         }
  572.     }
  573. }
  574.  
  575.  
  576. //-------------------------------------------------------------------------------------------
  577. //
  578. void HandleKeyPress(EventRecord *event)
  579. {}
  580.  
  581. //-------------------------------------------------------------------------------------------
  582. //
  583.  
  584. /*
  585.  *    Function:    MicrosecondCount()
  586.  *
  587.  */
  588. unsigned long MicrosecondCount( void )
  589. {    
  590.     UnsignedWide currentCount;
  591.     
  592.     Microseconds(¤tCount);
  593.     
  594.     return( currentCount.lo );
  595. }
  596.  
  597. /*
  598.  *    Function:    DisplayString()
  599.  *
  600.  */
  601. void DisplayString( int x, int y, char *str )
  602. {
  603.     char buf[256];
  604.                 
  605.     RGBForeColor( &BLACK );
  606.     MoveTo( x, y );
  607.     
  608.     strcpy( buf+1, str );
  609.     buf[0] = strlen( buf+1 );
  610.     DrawString( (const unsigned char *)buf );
  611. }
  612.  
  613. #if USE_ATI_OFF_SCREEN_MEM_MANAGER
  614.  
  615. QDErr NewGWorldVRAM( GWorldPtr *offscreenGWorld, short PixelDepth, const Rect *boundsRect, 
  616.                      CTabHandle cTable, GDHandle aGDevice, GWorldFlags flags, GDHandle gdh )
  617. {
  618.     OSErr             myErr;
  619.     unsigned long    rowBytes;
  620.     Ptr                data;
  621.             
  622.     /*
  623.      * create a GWorld the size of the boundsRect
  624.      */
  625.     myErr = NewGWorld(    offscreenGWorld,
  626.                         PixelDepth,
  627.                         boundsRect,
  628.                         cTable,
  629.                         aGDevice,
  630.                         flags );
  631.     
  632.     if( myErr != noErr || HAS_ATI_OFFSCREEN_MEM() == false )
  633.         return( myErr );
  634.         
  635.     /*
  636.      * allocate block of VRAM on HW accelerator card
  637.      */
  638.     data = (Ptr)ATIMem_AllocVRAM(   gdh,
  639.                                       boundsRect->right - boundsRect->left,
  640.                                     boundsRect->bottom - boundsRect->top,         
  641.                                     PixelDepth,
  642.                                     &rowBytes,                         
  643.                                     NULL,                
  644.                                     false, 0, 0,
  645.                                     NULL );
  646.  
  647.     if( data )
  648.     {
  649.         /*
  650.          * get PixMapHandle for GWorld + handle to pixel data
  651.          * for PixMap of GWorld. Note: Inside Macintosh - Imaging
  652.          * with Quickdraw, p. 4-46 states, "The baseAddr field
  653.          * of the PixMap record for an offscreen graphics world
  654.          * contains a handle instead of a pointer."
  655.          */
  656.         PixMapPtr    pixPtr     = *GetGWorldPixMap( *offscreenGWorld );
  657.         Handle        hndl    = NewEmptyHandle();
  658.         
  659.         /*
  660.          * lock handle and delete pixel memory of PixMap
  661.          */
  662.         DisposeHandle( (Handle)pixPtr->baseAddr );
  663.         
  664.         *hndl                = data;
  665.         pixPtr->baseAddr     = (Ptr)hndl;
  666.         
  667.         //HLock( pixPtr->baseAddr );
  668.         
  669.         /*
  670.          * set baseAddr to be handle to VRAM allocated on card +
  671.          * adjust rowBytes to requirements of VRAM
  672.          */
  673.         pixPtr->rowBytes &= 0xC000;
  674.         pixPtr->rowBytes |= rowBytes & 0x3FFF;
  675.  
  676.         /*
  677.          * register for callback in case of mode switch
  678.          * where contents of VRAM are deleted
  679.          */        
  680.         if( gNumGWorldVRAM++ == 0 )
  681.             gCallbackIndex = ATIMem_RegHeapCallback( gdh, VRAMCallBack, NULL );
  682.     }
  683.     
  684.     return( noErr );
  685. }
  686.  
  687. void DisposeGWorldVRAM( GWorldPtr offscreenGWorld )
  688. {
  689.     PixMapHandle     pixHndl;
  690.     PixMapPtr         pixPtr;
  691.     CGrafPtr        savedPort;
  692.     GDHandle        gdh;
  693.     
  694.      if( !offscreenGWorld )
  695.          return;
  696.          
  697.      if( !HAS_ATI_OFFSCREEN_MEM() )
  698.      {
  699.          DisposeGWorld( offscreenGWorld );
  700.          return;
  701.      }
  702.     
  703.     pixHndl    = GetGWorldPixMap( offscreenGWorld );
  704.     
  705.     if( pixHndl )
  706.     {
  707.         pixPtr     = *pixHndl;
  708.         
  709.         if( pixPtr && pixPtr->baseAddr && ATI_IsVRAMGWorld(offscreenGWorld) )
  710.         {
  711.             /*
  712.              * free VRAM allocated on card + then set 
  713.              * baseAddr to NULL so DisposeGWorld doesn't
  714.              * try to free VRAM
  715.              */
  716.             GetGWorld( &savedPort, &gdh );        
  717.         
  718.             ATIMem_FreeVRAM( gdh, pixPtr->baseAddr );
  719.             ATIMem_FreeVRAM( gdh, *((Handle)(pixPtr->baseAddr)) );    
  720.             *(pixPtr->baseAddr)    = NULL;
  721.             
  722.             if( --gNumGWorldVRAM == 0 )
  723.                 ATIMem_DeregHeapCallback( gdh, gCallbackIndex );
  724.         }
  725.     }
  726.     
  727.     DisposeGWorld( offscreenGWorld );
  728. }
  729.  
  730. int ATI_IsVRAMGWorld( GWorldPtr offscreenGWorld )
  731. {
  732.     PixMapHandle    pixHndl;
  733.     PixMapPtr        pixPtr;
  734.     CGrafPtr        savedPort;
  735.     GDHandle        gdh;
  736.     
  737.      if( !offscreenGWorld || !HAS_ATI_OFFSCREEN_MEM() )
  738.          return( false );
  739.  
  740.     if( (pixHndl = GetGWorldPixMap(offscreenGWorld)) == NULL ||
  741.         (pixPtr = *pixHndl) == NULL || pixPtr->baseAddr == NULL )
  742.         return( false );
  743.     
  744.     GetGWorld( &savedPort, &gdh );
  745.  
  746.     if( ATIMem_IsOnVRAM(gdh, pixPtr->baseAddr) ||
  747.         ATIMem_IsOnVRAM(gdh, *((Handle)(pixPtr->baseAddr))) )
  748.     {
  749.         return( true );
  750.     }
  751.             
  752.     return( false );
  753. }
  754.  
  755. void VRAMCallBack( GDHandle hGDevice, unsigned int flag, void *data )
  756. {
  757.     /*
  758.      * set baseAddr to NULL so DisposeGWorld doesn't 
  759.      * try to free VRAM when DisposeDocumentData() is
  760.      * called
  761.      */
  762.     DisposeGWorldVRAM( gDocument.fGWorld );
  763.     gDocument.fGWorld            = NULL;
  764.     
  765.     DisposeGWorldVRAM( gDocument.fBgPicture );
  766.     gDocument.fBgPicture        = NULL;
  767.  
  768.     DisposeGWorldVRAM( gDocument.fCompositeBuffer );
  769.     gDocument.fCompositeBuffer     = NULL;
  770.     
  771.     gQuitFlag = true;
  772. }
  773.  
  774. #endif
  775.