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!