[comp.sys.mac.programmer] CopyBits/QD vs. NuVista?

morris@ucunix.san.uc.edu (Ted Morris) (02/06/91)

Our contract programmer is having a problem getting a custom
application up and running with the TrueVision NuVista (not
NuVista+) board and software.  We've discussed it with TrueVision
and they feel it's a QuickDraw problem, not a NuVista problem. 
I'm inclined to believe them, because he can successfully grab a
frame, set up a window to display the image in--but the app
crashes at copying the image from his offscreen buffer to the
window.
 
Any special tricks you might think he's overlooked (he's pretty
sharp, and has been in contact with a TrueVision engineer off and
on for several -months- trying to hammer this out...)-: )?
 
Thanks for any insights!
 
His summary follows:
 
 
"For the last few months I have been working on a project that
requires drawing to a 32 bit off screen bitmap after capturing an
image from a digitizing board.  I have been running into trouble
with the CopyBits routine blowing up on me.  I don't think that
it is a CopyBits routine problem but something to do with the way
I am setting up the off screen bitmap.
 
"Am I setting the off screen bitmap correctly or am I missing
something that is critical to this operation?  I got the original
code from Tech Notes.
 
"Also,  would any one have an idea why GetMaxDevice() only
returns the first device it runs across. The linked list in mem
does have all the video boards. You don't have to cycle this
through a loop, do you?
 
"Note-- the SwapMMU() call is being used but I have no reason to
believe after looking at the disassembly that it is being
switched back after calls to the digitizing board are made.
 
**************** CODE FOLLOWS ********************
 
#include <MacTypes.h>
#include <Color.h>
#include <ColorToolBox.h>
#include <SlotMgr.h>
#include <EventMgr.h>
#include <QuickDraw.h>
#include <Video.h>
#include <WindowMgr.h>
#include "NV Test.h"
 
#define TRUE   1
#define NIL      0L
 
#define    OffLeft     30   /* for the offscreen Rect   */
#define    OffTop      30
#define    OffBottom   510
#define    OffRight    630
 
/* typedef BitMapPtr for use during CopyBits operation */
typedef    BitMap    *BitMapPtr;
 
unsigned short   height, width;
int              linesPerRow, srcRowBytes,gotOne,i,err;
RTblEntry        startValue;
unsigned short   rowStart,rowCnt;
long             waitTicks, offRowBytes;
NVParamBlkHdl    paramBlkHdl;
LUTValueHdl      lutBufHdl;
LUTValue         startColor, endColor;
RTblEntryHdl     rtblHdl1, rtblHdl2;
Ptr              srcAddr;
unsigned short   imrSwixel;
Rect             NVRect,destRect;
EventRecord      theEvent;
int              slotNum,ret,theDepth;
Point            tempP;
long             sizeOfOff;
Ptr              myBits;
CTabHandle       ourCMHandle;
 
CGrafPort        myCGrafPort;
CGrafPtr         myCGrafPtr;
WindowPtr        myCWindow;
GDHandle         oldDevice,theMaxDevice,aDevice;
 
CWindowRecord   theCWindowRec;
Rect            CwindowBounds, globRect,bRect;
RgnHandle       theGrayRgn;
 
 
main()
{
   InitGraf(&thePort);
   InitFonts();
   InitWindows();
   InitMenus();
   TEInit();
   InitDialogs(0L);
   InitCursor();
   MaxApplZone();
 
   FlushEvents( everyEvent, 0);
 
   /* find out total screen size available   */
   theGrayRgn = (RgnHandle) GetGrayRgn();
 
   height = (*thePort).bottom;
   width = (*thePort).right;
   HideCursor();
 
   /* find the NuVista boards slot #   */
   /* its should be between 9-E he      */
   /* error? then leave                  */
   for( slotNum=0xe; slotNum >= 0x9; slotNum-- ) {
      ret = CheckSlotNuVista( slotNum );
      if( ret == 1  || ret == 2 ) break;
   }
 
   /* there ain't no NV board here      */
   if( slotNum < 0x9 ) {
      printf("Can't find NuVista Board!\n");
      exit(0);
   }
 
   /* set the # for future calls      */
   SetSlotNuVista( slotNum );
 
   /* save registers needed to restore */
   /*   current NV board operation      */
   paramBlkHdl = (NVParamBlkHdl)NewHandle( sizeof(NVParamBlk) );
   SaveNuVistaState( *paramBlkHdl );
 
   /* setup a look up table with 256 entries   */
   lutBufHdl = NewLUTBuffer(256);
 
   /* give initial values for colors         */
   startColor.argb.alpha =
   startColor.argb.red =
   startColor.argb.green =
   startColor.argb.blue = 0;
 
   /* also for the alpha channels            */
   endColor.argb.alpha =
   endColor.argb.red =
   endColor.argb.green =
   endColor.argb.blue = 0xff;
 
   /* linear map from 0 to 255    */
   /* dump to hardware map 7      */
   /* then release the memory      */
   SpreadLUTBuffer( lutBufHdl, 0, 255, startColor, endColor );
   DumpLUTBuffer( 7, 0, lutBufHdl,  256 );
   DisposeLUTBuffer( lutBufHdl );
 
   /* give maps time to load   */
   FieldWait( 3 );
 
   /* now let's save registers needed to   */
   /* restore the NV board to its current   */
   /*    function                           */
   /* create rowtable to hold 800 entries   */
   /* save hardware table into rtblHdl1   */
   rtblHdl1 = NewRTblBuffer( 800 );
   LoadRTblBuffer( 8, rtblHdl1, 800 );
 
   /*
   ** make a row table for use with the frame grab and dump it out
   ** to the hardware. We are grabbing at 32 bits per pixel so we will
want
   ** only one line/row if the horizontal resolution is greater than
512.
   */
   if( width > 512 ) {
      linesPerRow = 1;
      srcRowBytes = 4096L;
   }
   else {
      linesPerRow = 2;
      srcRowBytes = 2048L;
   }
 
   /* make another storage table and               */
   /* put image at top with top 16 lines reserved   */
   rtblHdl2 = NewRTblBuffer( 800 );
   startValue.rtbl.row = 1024-16-(height/linesPerRow);
 
   /* set for display                     */
   /* set for capture                     */
   /* don't want it to be a lut load line */
   /* start at tap 0                        */
   startValue.rtbl.dsply = 1;
   startValue.rtbl.cap = 1;
   startValue.rtbl.lut = 0;
   startValue.rtbl.tap = 0;
   rowStart = 0;
   rowCnt = height;
 
    Live();
 
   /* give genlock time to settle            */
   FieldWait( 10 );
 
   /* set delay timeout for loop               */
   waitTicks = TickCount() + 300L;
 
   /* loop until timeout, or mouse/key hit   */
   while (TRUE) {
      if( Button() ) break;
      if (GetNextEvent(keyDownMask,&theEvent) != false) break;
      if (TickCount() > waitTicks) break;
   }
 
   /* clear the event que      */
   FlushEvents(keyDownMask+mDownMask,0);
 
   /* grab the frame of video */
   GrabFrame();
 
   /* get the current swixel mode              */
   /* set to 32 bit swixel - ie. no swixel     */
   /* set base address of stored video image   */
   imrSwixel = GetIMRVramSwixel();
   SetIMRVramSwixel( SWIXEL32 );
   srcAddr =   (Ptr)(0xf0000000 |
            ((long)slotNum<<24) |
            0x00b00000 +
(1024L-16L-(long)(height/linesPerRow))*srcRowBytes);
 
   /* give window a size */
   SetRect(&CwindowBounds,50,50,300,150);
 
    /* put up a window that WE CAN SEE */
    myCWindow = NewWindow (&theCWindowRec,&CwindowBounds,
       "\pCapture Window",TRUE,documentProc,(WindowPtr) - 1,
       TRUE,0);
 
   SetPort((WindowPtr)myCWindow);
 
   /* set up offscreen Rect   */
    SetRect(&bRect,OffLeft,OffTop,OffRight,OffBottom);
 
    /* find a common area      */
    if(!SectRect(&(*myCWindow).portRect,&bRect,&globRect)) {
      LoadNuVistaState( *paramBlkHdl );
      DumpRTblBuffer( 8, rtblHdl1, 800 );
      DisposeRTblBuffer( rtblHdl2 );
      if( paramBlkHdl ) DisposHandle( paramBlkHdl );
      ExitToShell();
   }
 
   /* turn globRect points      */
   /* into true global coord's   */
    tempP.v = globRect.top;
    tempP.h = globRect.left;
   LocalToGlobal(&tempP);
   globRect.top = tempP.v;
   globRect.left = tempP.h;
 
   tempP.v = globRect.bottom;
   tempP.h = globRect.right;
   LocalToGlobal(&tempP);
   globRect.bottom = tempP.v;
   globRect.right = tempP.h;
 
   /* where globRect lays         */
   theMaxDevice = GetMaxDevice(&globRect)
 
   /* store old device            */
   oldDevice = GetGDevice();
 
    /* set to MaxDevice            */
   SetGDevice(theMaxDevice);
 
   /* now setup offscreen bitmap   */
   myCGrafPtr = &myCGrafPort;
 
   /* open the new color port          */
   OpenCPort(myCGrafPtr);
 
   /* get the GrapPorts pix depth      */
   theDepth = (**(*myCGrafPtr).portPixMap).pixelSize;
 
   /* Bitshift and adjust for local coordinates */
   offRowBytes = (((theDepth *
      (OffRight - OffLeft)) + 15) >> 4) << 1;
   sizeOfOff = (long) (OffBottom - OffTop) * offRowBytes;
   OffsetRect(&bRect, -OffLeft, -OffTop);
 
   myBits = NewPtr(sizeOfOff);
 
   /* Remember to be a PixMap */
   (**(*myCGrafPtr).portPixMap).baseAddr = myBits;
   (**(*myCGrafPtr).portPixMap).rowBytes = offRowBytes + 0x8000;
   (**(*myCGrafPtr).portPixMap).bounds = bRect;
 
   ourCMHandle = (**(**theMaxDevice).gdPMap).pmTable;
   err = HandToHand(&ourCMHandle);
 
   for (i = 0; i <= (**ourCMHandle ).ctSize; ++i)
      (**ourCMHandle ).ctTable[i].value = i;
   (**ourCMHandle ).ctFlags &= 0x7fff;
   (**ourCMHandle ).ctSeed = GetCTSeed();
   /* This code is necessary for converting */
   /* GDevice cluts to Pixmap cluts            */
 
   /* give pixmap to offscreen   */
   /* make offscreen active      */
   /* clear it out               */
   (**(*myCGrafPtr).portPixMap).pmTable = ourCMHandle;
   SetPort((GrafPtr) myCGrafPtr);
   EraseRect(&(*thePort).portRect);
 
 
   SetRect(&NVRect,0,0,600,480);
 
   CopyBits((BitMapPtr) srcAddr,
      (BitMapPtr)*(*myCGrafPtr).portPixMap,&NVRect,
      &bRect, 0, NIL);
 
 
 
   SetPort((WindowPtr) myCWindow);
   SetGDevice(oldDevice);
 
   destRect = bRect;
   OffsetRect(&destRect,OffLeft,OffTop);
 
   SetRect(&destRect,0,0,600,480);
   CopyBits((BitMapPtr) *(*myCGrafPtr).portPixMap,
      &(*myCWindow).portBits,&bRect,&destRect, 0, NIL);
 
 
   /* clean up our offscreen port   */
   /* give back memory               */
   CloseCPort(myCGrafPtr);
   DisposPtr(myBits);
   DisposHandle((Handle) ourCMHandle);
 
   /* restore the swixel mode */
   SetIMRVramSwixel( imrSwixel );
 
   /* restore the original NV board state         */
   /* restore original row table to the hardware   */
   /* give buffer memory back to heap               */
   /* ditch  paramBlk   space               */
   LoadNuVistaState( *paramBlkHdl );
   DumpRTblBuffer( 8, rtblHdl1, 800 );
   DisposeRTblBuffer( rtblHdl2 );
   if( paramBlkHdl ) DisposHandle( paramBlkHdl );
 
   /*InvalRect(&wData->viewRect);*/
 
   /* tell quickdraw to redraw the screen    */
   /* tell quickdraw to reload the cluts in   */
   /* case clut 7 was used (used in 1,2 and   */
   /* 4 bit per pixel modes)                  */
   /*   InvalScrn( hNVGDev );   */
   /*   InvalCLUTs( hNVGDev );   */
 
   ShowCursor();
   CloseWindow (myCWindow);
 
   ExitToShell();
}
 

Please reply directly to me and I'll pass it along to our programmer.
He can then reply/discuss with you via e-mail himself.  Thanks!

Theodore Allan Morris, U. Cincinnati, Med Ctr Info & Comm, Info Rsrch
& Dev, 231 Bethesda Av, ML#574, Cinti, OH  45267-0574, 513-558-6046V, 
513-558-0758F, MORRISTA@UCMCIC.OA.UC.EDU / MORRISTA@UCUNIX.SAN.UC.EDU,
NTS WB8VNV, AppleLink U1091 | Call me up and I'll talk data to ya!