#ifdef JA2_PRECOMPILED_HEADERS #include "JA2 SGP ALL.H" #elif defined( WIZ8_PRECOMPILED_HEADERS ) #include "WIZ8 SGP ALL.H" #else #include "DirectDraw Calls.h" #include #include #include "debug.h" #if defined( JA2 ) || defined( UTIL ) #include "video.h" #else #include "video2.h" #endif #include "himage.h" #include "vsurface.h" #include "vsurface_private.h" #include "video_private.h" #include "wcheck.h" #include "vobject_blitters.h" #endif extern void SetClippingRect(SGPRect *clip); extern void GetClippingRect(SGPRect *clip); /////////////////////////////////////////////////////////////////////////////////////////////////// // // Video Surface SGP Module // // Second Revision: Dec 10, 1996, Andrew Emmons // /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// // // Defines // /////////////////////////////////////////////////////////////////////////////////////////////////// // // This define is sent to CreateList SGP function. It dynamically re-sizes if // the list gets larger // #define DEFAULT_NUM_REGIONS 5 #define DEFAULT_VIDEO_SURFACE_LIST_SIZE 10 /////////////////////////////////////////////////////////////////////////////////////////////////// // // LOCAL functions // /////////////////////////////////////////////////////////////////////////////////////////////////// BOOLEAN UpdateBackupSurface( HVSURFACE hVSurface ); BOOLEAN ClipReleatedSrcAndDestRectangles( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, RECT *DestRect, RECT *SrcRect ); BOOLEAN FillSurface( HVSURFACE hDestVSurface, blt_vs_fx *pBltFx ); BOOLEAN FillSurfaceRect( HVSURFACE hDestVSurface, blt_vs_fx *pBltFx ); BOOLEAN BltVSurfaceUsingDD( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, UINT32 fBltFlags, INT32 iDestX, INT32 iDestY, RECT *SrcRect ); BOOLEAN BltVSurfaceUsingDDBlt( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, UINT32 fBltFlags, INT32 iDestX, INT32 iDestY, RECT *SrcRect, RECT *DestRect ); BOOLEAN GetVSurfaceRect( HVSURFACE hVSurface, RECT *pRect); void DeletePrimaryVideoSurfaces( ); /////////////////////////////////////////////////////////////////////////////////////////////////// // // LOCAL global variables // /////////////////////////////////////////////////////////////////////////////////////////////////// typedef struct VSURFACE_NODE { HVSURFACE hVSurface; UINT32 uiIndex; struct VSURFACE_NODE *next, *prev; #ifdef SGP_VIDEO_DEBUGGING UINT8 *pName; UINT8 *pCode; #endif }VSURFACE_NODE; VSURFACE_NODE *gpVSurfaceHead = NULL; VSURFACE_NODE *gpVSurfaceTail = NULL; UINT32 guiVSurfaceIndex = 0; UINT32 guiVSurfaceSize = 0; UINT32 guiVSurfaceTotalAdded = 0; #ifdef _DEBUG enum { DEBUGSTR_NONE, DEBUGSTR_SETVIDEOSURFACETRANSPARENCY, DEBUGSTR_ADDVIDEOSURFACEREGION, DEBUGSTR_GETVIDEOSURFACEDESCRIPTION, DEBUGSTR_BLTVIDEOSURFACE_DST, DEBUGSTR_BLTVIDEOSURFACE_SRC, DEBUGSTR_COLORFILLVIDEOSURFACEAREA, DEBUGSTR_SHADOWVIDEOSURFACERECT, DEBUGSTR_BLTSTRETCHVIDEOSURFACE_DST, DEBUGSTR_BLTSTRETCHVIDEOSURFACE_SRC, DEBUGSTR_DELETEVIDEOSURFACEFROMINDEX }; UINT8 gubVSDebugCode = 0; void CheckValidVSurfaceIndex( UINT32 uiIndex ); #endif INT32 giMemUsedInSurfaces; //OBSOLETE!!!!!!!!! HLIST ghVideoSurfaces = NULL; //OBSOLETE!!!!!!!!! HVSURFACE ghPrimary = NULL; HVSURFACE ghBackBuffer = NULL; HVSURFACE ghFrameBuffer = NULL; HVSURFACE ghMouseBuffer = NULL; /////////////////////////////////////////////////////////////////////////////////////////////////// // // Video Surface Manager functions // /////////////////////////////////////////////////////////////////////////////////////////////////// BOOLEAN InitializeVideoSurfaceManager( ) { //Shouldn't be calling this if the video surface manager already exists. //Call shutdown first... Assert( !gpVSurfaceHead ); Assert( !gpVSurfaceTail ); RegisterDebugTopic(TOPIC_VIDEOSURFACE, "Video Surface Manager"); gpVSurfaceHead = gpVSurfaceTail = NULL; giMemUsedInSurfaces = 0; // Create primary and backbuffer from globals if ( !SetPrimaryVideoSurfaces( ) ) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_1, String( "Could not create primary surfaces" ) ); return FALSE; } return TRUE ; } BOOLEAN ShutdownVideoSurfaceManager( ) { VSURFACE_NODE *curr; DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_0, "Shutting down the Video Surface manager"); // Delete primary viedeo surfaces DeletePrimaryVideoSurfaces( ); while( gpVSurfaceHead ) { curr = gpVSurfaceHead; gpVSurfaceHead = gpVSurfaceHead->next; DeleteVideoSurface( curr->hVSurface ); #ifdef SGP_VIDEO_DEBUGGING if( curr->pName ) MemFree( curr->pName ); if( curr->pCode ) MemFree( curr->pCode ); #endif MemFree( curr ); } gpVSurfaceHead = NULL; gpVSurfaceTail = NULL; guiVSurfaceIndex = 0; guiVSurfaceSize = 0; guiVSurfaceTotalAdded = 0; UnRegisterDebugTopic(TOPIC_VIDEOSURFACE, "Video Objects"); return TRUE; } BOOLEAN RestoreVideoSurfaces( ) { VSURFACE_NODE *curr; // // Loop through Video Surfaces and Restore // curr = gpVSurfaceTail; while( curr ) { if( !RestoreVideoSurface( curr->hVSurface ) ) { return FALSE; } curr = curr->prev; } return TRUE; } BOOLEAN AddStandardVideoSurface( VSURFACE_DESC *pVSurfaceDesc, UINT32 *puiIndex ) { HVSURFACE hVSurface; // Assertions Assert( puiIndex ); Assert( pVSurfaceDesc ); // Create video object hVSurface = CreateVideoSurface( pVSurfaceDesc ); if( !hVSurface ) { // Video Object will set error condition. return FALSE ; } // Set transparency to default SetVideoSurfaceTransparencyColor( hVSurface, FROMRGB( 0, 0, 0 ) ); // Set into video object list if( gpVSurfaceHead ) { //Add node after tail gpVSurfaceTail->next = (VSURFACE_NODE*)MemAlloc( sizeof( VSURFACE_NODE ) ); Assert( gpVSurfaceTail->next ); //out of memory? gpVSurfaceTail->next->prev = gpVSurfaceTail; gpVSurfaceTail->next->next = NULL; gpVSurfaceTail = gpVSurfaceTail->next; } else { //new list gpVSurfaceHead = (VSURFACE_NODE*)MemAlloc( sizeof( VSURFACE_NODE ) ); Assert( gpVSurfaceHead ); //out of memory? gpVSurfaceHead->prev = gpVSurfaceHead->next = NULL; gpVSurfaceTail = gpVSurfaceHead; } #ifdef SGP_VIDEO_DEBUGGING gpVSurfaceTail->pName = NULL; gpVSurfaceTail->pCode = NULL; #endif //Set the hVSurface into the node. gpVSurfaceTail->hVSurface = hVSurface; gpVSurfaceTail->uiIndex = guiVSurfaceIndex+=2; *puiIndex = gpVSurfaceTail->uiIndex; Assert( guiVSurfaceIndex < 0xfffffff0 ); //unlikely that we will ever use 2 billion VSurfaces! //We would have to create about 70 VSurfaces per second for 1 year straight to achieve this... guiVSurfaceSize++; guiVSurfaceTotalAdded++; return TRUE ; } BYTE *LockVideoSurface( UINT32 uiVSurface, UINT32 *puiPitch ) { VSURFACE_NODE *curr; // // Check if given backbuffer or primary buffer // #ifdef JA2 if ( uiVSurface == PRIMARY_SURFACE ) { return LockPrimarySurface( puiPitch ); } if ( uiVSurface == BACKBUFFER ) { return LockBackBuffer( puiPitch ); } #endif if ( uiVSurface == FRAME_BUFFER ) { return LockFrameBuffer( puiPitch ); } if ( uiVSurface == MOUSE_BUFFER ) { return LockMouseBuffer( puiPitch ); } // // Otherwise, use list // curr = gpVSurfaceHead; while( curr ) { if( curr->uiIndex == uiVSurface ) { break; } curr = curr->next; } if( !curr ) { return FALSE; } // // Lock buffer // return LockVideoSurfaceBuffer( curr->hVSurface, puiPitch ); } void UnLockVideoSurface( UINT32 uiVSurface ) { VSURFACE_NODE *curr; // // Check if given backbuffer or primary buffer // #ifdef JA2 if ( uiVSurface == PRIMARY_SURFACE ) { UnlockPrimarySurface(); return; } if ( uiVSurface == BACKBUFFER ) { UnlockBackBuffer(); return; } #endif if ( uiVSurface == FRAME_BUFFER ) { UnlockFrameBuffer(); return; } if ( uiVSurface == MOUSE_BUFFER ) { UnlockMouseBuffer(); return; } curr = gpVSurfaceHead; while( curr ) { if( curr->uiIndex == uiVSurface ) { break; } curr = curr->next; } if( !curr ) { return; } // // unlock buffer // UnLockVideoSurfaceBuffer( curr->hVSurface ); } BOOLEAN SetVideoSurfaceTransparency( UINT32 uiIndex, COLORVAL TransColor ) { HVSURFACE hVSurface; // // Get Video Surface // #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_SETVIDEOSURFACETRANSPARENCY; #endif CHECKF( GetVideoSurface( &hVSurface, uiIndex ) ); // // Set transparency // SetVideoSurfaceTransparencyColor( hVSurface, TransColor ); return( TRUE ); } BOOLEAN AddVideoSurfaceRegion( UINT32 uiIndex, VSURFACE_REGION *pNewRegion ) { HVSURFACE hVSurface; // // Get Video Surface // #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_ADDVIDEOSURFACEREGION; #endif CHECKF( GetVideoSurface( &hVSurface, uiIndex ) ); // // Add Region // CHECKF( AddVSurfaceRegion( hVSurface, pNewRegion ) ); return( TRUE ); } BOOLEAN GetVideoSurfaceDescription( UINT32 uiIndex, UINT16 *usWidth, UINT16 *usHeight, UINT8 *ubBitDepth ) { HVSURFACE hVSurface; Assert( usWidth != NULL ); Assert( usHeight != NULL ); Assert( ubBitDepth != NULL ); // // Get Video Surface // #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_GETVIDEOSURFACEDESCRIPTION; #endif CHECKF( GetVideoSurface( &hVSurface, uiIndex ) ); *usWidth = hVSurface->usWidth; *usHeight = hVSurface->usHeight; *ubBitDepth = hVSurface->ubBitDepth; return TRUE; } BOOLEAN GetVideoSurface( HVSURFACE *hVSurface, UINT32 uiIndex ) { VSURFACE_NODE *curr; #ifdef _DEBUG CheckValidVSurfaceIndex( uiIndex ); #endif if ( uiIndex == PRIMARY_SURFACE ) { *hVSurface = ghPrimary; return TRUE; } if ( uiIndex == BACKBUFFER ) { *hVSurface = ghBackBuffer; return TRUE; } if ( uiIndex == FRAME_BUFFER ) { *hVSurface = ghFrameBuffer; return TRUE; } if ( uiIndex == MOUSE_BUFFER ) { *hVSurface = ghMouseBuffer; return TRUE; } curr = gpVSurfaceHead; while( curr ) { if( curr->uiIndex == uiIndex ) { *hVSurface = curr->hVSurface; return TRUE; } curr = curr->next; } return FALSE; } BOOLEAN SetPrimaryVideoSurfaces( ) { LPDIRECTDRAWSURFACE2 pSurface; // Delete surfaces if they exist DeletePrimaryVideoSurfaces( ); // // Get Primary surface // #ifdef JA2 pSurface = GetPrimarySurfaceObject(); CHECKF( pSurface != NULL ); ghPrimary = CreateVideoSurfaceFromDDSurface( pSurface ); CHECKF( ghPrimary != NULL ); // // Get Backbuffer surface // pSurface = GetBackBufferObject( ); CHECKF( pSurface != NULL ); ghBackBuffer = CreateVideoSurfaceFromDDSurface( pSurface ); CHECKF( ghBackBuffer != NULL ); // // Get mouse buffer surface // pSurface = GetMouseBufferObject( ); CHECKF( pSurface != NULL ); ghMouseBuffer = CreateVideoSurfaceFromDDSurface( pSurface ); CHECKF( ghMouseBuffer != NULL ); #endif // // Get frame buffer surface // pSurface = GetFrameBufferObject( ); CHECKF( pSurface != NULL ); ghFrameBuffer = CreateVideoSurfaceFromDDSurface( pSurface ); CHECKF( ghFrameBuffer != NULL ); return( TRUE ); } void DeletePrimaryVideoSurfaces( ) { // // If globals are not null, delete them // if ( ghPrimary != NULL ) { DeleteVideoSurface( ghPrimary ); ghPrimary = NULL; } if ( ghBackBuffer != NULL ) { DeleteVideoSurface( ghBackBuffer ); ghBackBuffer = NULL; } if ( ghFrameBuffer != NULL ) { DeleteVideoSurface( ghFrameBuffer ); ghFrameBuffer = NULL; } if ( ghMouseBuffer != NULL ) { DeleteVideoSurface( ghMouseBuffer ); ghMouseBuffer = NULL; } } /////////////////////////////////////////////////////////////////////////////////////////////////// // // Given an index to the dest and src vobject contained in our private VSurface list // Based on flags, blit accordingly // There are two types, a BltFast and a Blt. BltFast is 10% faster, uses no // clipping lists // /////////////////////////////////////////////////////////////////////////////////////////////////// BOOLEAN BltVideoSurface(UINT32 uiDestVSurface, UINT32 uiSrcVSurface, UINT16 usRegionIndex, INT32 iDestX, INT32 iDestY, UINT32 fBltFlags, blt_vs_fx *pBltFx ) { HVSURFACE hDestVSurface; HVSURFACE hSrcVSurface; #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_BLTVIDEOSURFACE_DST; #endif if( !GetVideoSurface( &hDestVSurface, uiDestVSurface ) ) { return FALSE; } #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_BLTVIDEOSURFACE_SRC; #endif if( !GetVideoSurface( &hSrcVSurface, uiSrcVSurface ) ) { return FALSE; } if ( !BltVideoSurfaceToVideoSurface( hDestVSurface, hSrcVSurface, usRegionIndex, iDestX, iDestY, fBltFlags, pBltFx ) ) { // VO Blitter will set debug messages for error conditions return FALSE ; } return TRUE ; } /////////////////////////////////////////////////////////////////////////////////////////////////// // // Fills an rectangular area with a specified color value. // /////////////////////////////////////////////////////////////////////////////////////////////////// BOOLEAN ColorFillVideoSurfaceArea(UINT32 uiDestVSurface, INT32 iDestX1, INT32 iDestY1, INT32 iDestX2, INT32 iDestY2, UINT16 Color16BPP) { blt_vs_fx BltFx; HVSURFACE hDestVSurface; SGPRect Clip; #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_COLORFILLVIDEOSURFACEAREA; #endif if( !GetVideoSurface( &hDestVSurface, uiDestVSurface ) ) { return FALSE; } BltFx.ColorFill = Color16BPP; BltFx.DestRegion = 0; // // Clip fill region coords // GetClippingRect(&Clip); if(iDestX1 < Clip.iLeft) iDestX1 = Clip.iLeft; if(iDestX1 > Clip.iRight) return(FALSE); if(iDestX2 > Clip.iRight) iDestX2 = Clip.iRight; if(iDestX2 < Clip.iLeft) return(FALSE); if(iDestY1 < Clip.iTop) iDestY1 = Clip.iTop; if(iDestY1 > Clip.iBottom) return(FALSE); if(iDestY2 > Clip.iBottom) iDestY2 = Clip.iBottom; if(iDestY2 < Clip.iTop) return(FALSE); if((iDestX2 <= iDestX1) || (iDestY2 <= iDestY1)) return(FALSE); BltFx.SrcRect.iLeft = BltFx.FillRect.iLeft = iDestX1; BltFx.SrcRect.iTop = BltFx.FillRect.iTop = iDestY1; BltFx.SrcRect.iRight = BltFx.FillRect.iRight = iDestX2; BltFx.SrcRect.iBottom = BltFx.FillRect.iBottom = iDestY2; return( FillSurfaceRect( hDestVSurface, &BltFx ) ); } /////////////////////////////////////////////////////////////////////////////////////////////////// // // Fills an rectangular area with a specified image value. // /////////////////////////////////////////////////////////////////////////////////////////////////// BOOLEAN ImageFillVideoSurfaceArea(UINT32 uiDestVSurface, INT32 iDestX1, INT32 iDestY1, INT32 iDestX2, INT32 iDestY2, HVOBJECT BkgrndImg, UINT16 Index, INT16 Ox, INT16 Oy) { INT16 xc,yc,hblits,wblits,aw,pw,ah,ph,w,h,xo,yo; ETRLEObject *pTrav; SGPRect NewClip,OldClip; pTrav = &(BkgrndImg->pETRLEObject[Index]); ph = (INT16)(pTrav->usHeight+pTrav->sOffsetY); pw = (INT16)(pTrav->usWidth+pTrav->sOffsetX); ah = (INT16)(iDestY2-iDestY1); aw = (INT16)(iDestX2-iDestX1); Ox %= pw; Oy %= ph; if(Ox>0) Ox -= pw; xo = (-Ox)%pw; if(Oy>0) Oy -= ph; yo = (-Oy)%ph; if(Ox<0) xo = (-Ox)%pw; else { xo = pw-(Ox%pw); Ox -= pw; } if(Oy<0) yo = (-Oy)%ph; else { yo = ph-(Oy%pw); Oy -= ph; } hblits = ((ah+yo)/ph) + (((ah+yo)%ph)?1:0); wblits = ((aw+xo)/pw) + (((aw+xo)%pw)?1:0); if((hblits==0) || (wblits==0)) return(FALSE); // // Clip fill region coords // GetClippingRect(&OldClip); NewClip.iLeft=iDestX1; NewClip.iTop=iDestY1; NewClip.iRight=iDestX2; NewClip.iBottom=iDestY2; if(NewClip.iLeft < OldClip.iLeft) NewClip.iLeft = OldClip.iLeft; if(NewClip.iLeft > OldClip.iRight) return(FALSE); if(NewClip.iRight > OldClip.iRight) NewClip.iRight = OldClip.iRight; if(NewClip.iRight < OldClip.iLeft) return(FALSE); if(NewClip.iTop < OldClip.iTop) NewClip.iTop = OldClip.iTop; if(NewClip.iTop > OldClip.iBottom) return(FALSE); if(NewClip.iBottom > OldClip.iBottom) NewClip.iBottom = OldClip.iBottom; if(NewClip.iBottom < OldClip.iTop) return(FALSE); if((NewClip.iRight <= NewClip.iLeft) || (NewClip.iBottom <= NewClip.iTop)) return(FALSE); SetClippingRect(&NewClip); yc = (INT16)iDestY1; for(h=0;hfCreateFlags; #else fMemUsage = VSURFACE_SYSTEM_MEM_USAGE; #endif // // Check creation options // do { // // Check if creating from file // if ( VSurfaceDesc->fCreateFlags & VSURFACE_CREATE_FROMFILE ) { // // Create himage object from file // hImage = CreateImage( VSurfaceDesc->ImageFile, IMAGE_ALLIMAGEDATA ); if ( hImage == NULL ) { DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_2, "Invalid Image Filename given" ); return( NULL ); } // // Set values from himage // usHeight = hImage->usHeight; usWidth = hImage->usWidth; ubBitDepth = hImage->ubBitDepth; break; } // // If here, no special options given, // Set values from given description structure // usHeight = VSurfaceDesc->usHeight; usWidth = VSurfaceDesc->usWidth; ubBitDepth = VSurfaceDesc->ubBitDepth; } while( FALSE ); // // Assertions // Assert ( usHeight > 0 ); Assert ( usWidth > 0 ); // // Setup Direct Draw Description // First do Pixel Format // memset( &PixelFormat, 0, sizeof( PixelFormat ) ); PixelFormat.dwSize = sizeof( DDPIXELFORMAT ); switch( ubBitDepth ) { case 8: PixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; PixelFormat.dwRGBBitCount = 8; break; case 16: PixelFormat.dwFlags = DDPF_RGB; PixelFormat.dwRGBBitCount = 16; // // Get current Pixel Format from DirectDraw // // We're using pixel formats too -- DB/Wiz //#ifdef JA2 CHECKF( GetPrimaryRGBDistributionMasks( &uiRBitMask, &uiGBitMask, &uiBBitMask ) ); PixelFormat.dwRBitMask = uiRBitMask; PixelFormat.dwGBitMask = uiGBitMask; PixelFormat.dwBBitMask = uiBBitMask; //#else // PixelFormat.dwRBitMask = 0xf800; // PixelFormat.dwGBitMask = 0x7e0; // PixelFormat.dwBBitMask = 0x1f; //#endif break; default: // // If Here, an invalid format was given // DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_2, "Invalid BPP value, can only be 8 or 16." ); return( FALSE ); } SurfaceDescription.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; // // Do memory description, based on specified flags // do { if ( fMemUsage & VSURFACE_DEFAULT_MEM_USAGE ) { SurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; break; } if ( fMemUsage & VSURFACE_VIDEO_MEM_USAGE ) { SurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; break; } if ( fMemUsage & VSURFACE_SYSTEM_MEM_USAGE ) { SurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; break; } // // Once here, no mem flags were given, use default // SurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; } while( FALSE ); // // Set other, common structure elements // SurfaceDescription.dwSize = sizeof(DDSURFACEDESC); SurfaceDescription.dwWidth = usWidth; SurfaceDescription.dwHeight = usHeight; SurfaceDescription.ddpfPixelFormat = PixelFormat; // // Create Surface // DDCreateSurface ( lpDD2Object, &SurfaceDescription, &lpDDS, &lpDDS2 ); // // Allocate memory for Video Surface data and initialize // hVSurface = MemAlloc( sizeof( SGPVSurface ) ); memset( hVSurface, 0, sizeof( SGPVSurface ) ); CHECKF( hVSurface != NULL ); hVSurface->usHeight = usHeight; hVSurface->usWidth = usWidth; hVSurface->ubBitDepth = ubBitDepth; hVSurface->pSurfaceData1 = (PTR)lpDDS; hVSurface->pSurfaceData = (PTR)lpDDS2; hVSurface->pSavedSurfaceData1 = NULL; hVSurface->pSavedSurfaceData = NULL; hVSurface->pPalette = NULL; hVSurface->p16BPPPalette = NULL; hVSurface->TransparentColor = FROMRGB( 0, 0, 0 ); hVSurface->RegionList = CreateList( DEFAULT_NUM_REGIONS, sizeof( VSURFACE_REGION ) ); hVSurface->fFlags = 0; hVSurface->pClipper = NULL; // // Determine memory and other attributes of newly created surface // DDGetSurfaceDescription ( lpDDS2, &SurfaceDescription ); // // Fail if create tried for video but it's in system // if ( VSurfaceDesc->fCreateFlags & VSURFACE_VIDEO_MEM_USAGE && SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) { // // Return failure due to not in video // DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed to create Video Surface in video memory" ) ); DDReleaseSurface ( &lpDDS, &lpDDS2 ); MemFree( hVSurface ); return( NULL ); } // // Look for system memory // if ( SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) { hVSurface->fFlags |= VSURFACE_SYSTEM_MEM_USAGE; } // // Look for video memory // if ( SurfaceDescription.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) { hVSurface->fFlags |= VSURFACE_VIDEO_MEM_USAGE; } // // If in video memory, create backup surface // if ( hVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE ) { SurfaceDescription.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; SurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; SurfaceDescription.dwSize = sizeof(DDSURFACEDESC); SurfaceDescription.dwWidth = usWidth; SurfaceDescription.dwHeight = usHeight; SurfaceDescription.ddpfPixelFormat = PixelFormat; // // Create Surface // DDCreateSurface ( lpDD2Object, &SurfaceDescription, &lpDDS, &lpDDS2 ); // // Save surface to backup // hVSurface->pSavedSurfaceData1 = lpDDS; hVSurface->pSavedSurfaceData = lpDDS2; } // // Initialize surface with hImage , if given // if ( VSurfaceDesc->fCreateFlags & VSURFACE_CREATE_FROMFILE ) { tempRect.iLeft = 0; tempRect.iTop = 0; tempRect.iRight = hImage->usWidth-1; tempRect.iBottom = hImage->usHeight-1; SetVideoSurfaceDataFromHImage( hVSurface, hImage, 0, 0, &tempRect ); // // Set palette from himage // if ( hImage->ubBitDepth == 8 ) { SetVideoSurfacePalette( hVSurface, hImage->pPalette ); } // // Delete himage object // DestroyImage( hImage ); } // // All is well // hVSurface->usHeight = usHeight; hVSurface->usWidth = usWidth; hVSurface->ubBitDepth = ubBitDepth; giMemUsedInSurfaces += ( hVSurface->usHeight * hVSurface->usWidth * ( hVSurface->ubBitDepth / 8 ) ); DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_3, String("Success in Creating Video Surface" ) ); return( hVSurface ); } /////////////////////////////////////////////////////////////////////////////////////////////////// // // Called when surface is lost, for the most part called by utility functions // /////////////////////////////////////////////////////////////////////////////////////////////////// BOOLEAN RestoreVideoSurface( HVSURFACE hVSurface ) { LPDIRECTDRAWSURFACE2 lpDDSurface; LPDIRECTDRAWSURFACE2 lpBackupDDSurface; RECT aRect; Assert( hVSurface != NULL ); // // Restore is only for VIDEO MEMORY - should check if VIDEO and QUIT if not // if ( !( hVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE ) ) { // // No second surfaace has been allocated, return failure // DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String("Failed to restore Video Surface surface" ) ); return( FALSE ); } // // Check for valid secondary surface // if ( hVSurface->pSavedSurfaceData1 == NULL ) { // // No secondary surface available // DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String("Failure in retoring- no secondary surface found" ) ); return( FALSE ); } // Restore primary surface lpDDSurface = ( LPDIRECTDRAWSURFACE2 )hVSurface->pSurfaceData; DDRestoreSurface( lpDDSurface ); // Blit backup surface data into primary lpBackupDDSurface = ( LPDIRECTDRAWSURFACE2 )hVSurface->pSavedSurfaceData; aRect.top = (int)0; aRect.left = (int)0; aRect.bottom = (int)hVSurface->usHeight; aRect.right = (int)hVSurface->usWidth; DDBltFastSurface( (LPDIRECTDRAWSURFACE2)hVSurface->pSavedSurfaceData, 0, 0, (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData, &aRect, DDBLTFAST_NOCOLORKEY ); return( TRUE ); } // Lock must be followed by release // Pitch MUST be used for all width calculations ( Pitch is in bytes ) // The time between Locking and unlocking must be minimal BYTE *LockVideoSurfaceBuffer( HVSURFACE hVSurface, UINT32 *pPitch ) { DDSURFACEDESC SurfaceDescription; // Assertions if ( hVSurface == NULL ) { int i = 0; } Assert( hVSurface != NULL ); Assert( pPitch != NULL ); #ifndef JA2 if(hVSurface==ghFrameBuffer) return(LockFrameBuffer(pPitch)); #endif DDLockSurface( (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData, NULL, &SurfaceDescription, 0, NULL); *pPitch = SurfaceDescription.lPitch; return SurfaceDescription.lpSurface; } void UnLockVideoSurfaceBuffer( HVSURFACE hVSurface ) { Assert( hVSurface != NULL ); #ifndef JA2 if(hVSurface==ghFrameBuffer) { UnlockFrameBuffer(); return; } #endif DDUnlockSurface( (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData, NULL ); // Copy contents if surface is in video if ( hVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE && !hVSurface->fFlags & VSURFACE_RESERVED_SURFACE ) { UpdateBackupSurface( hVSurface ); } } // Given an HIMAGE object, blit imagery into existing Video Surface. Can be from 8->16 BPP BOOLEAN SetVideoSurfaceDataFromHImage( HVSURFACE hVSurface, HIMAGE hImage, UINT16 usX, UINT16 usY, SGPRect *pSrcRect ) { BYTE *pDest; UINT32 fBufferBPP = 0; UINT32 uiPitch; UINT16 usEffectiveWidth; SGPRect aRect; // Assertions Assert( hVSurface != NULL ); Assert( hImage != NULL ); // Get Size of hImage and determine if it can fit CHECKF( hImage->usWidth >= hVSurface->usWidth ); CHECKF( hImage->usHeight >= hVSurface->usHeight ); // Check BPP and see if they are the same if ( hImage->ubBitDepth != hVSurface->ubBitDepth ) { // They are not the same, but we can go from 8->16 without much cost if ( hImage->ubBitDepth == 8 && hVSurface->ubBitDepth == 16 ) { fBufferBPP = BUFFER_16BPP; } } else { // Set buffer BPP switch ( hImage->ubBitDepth ) { case 8: fBufferBPP = BUFFER_8BPP; break; case 16: fBufferBPP = BUFFER_16BPP; break; } } Assert( fBufferBPP != 0 ); // Get surface buffer data pDest = LockVideoSurfaceBuffer( hVSurface, &uiPitch ); // Effective width ( in PIXELS ) is Pitch ( in bytes ) converted to pitch ( IN PIXELS ) usEffectiveWidth = (UINT16)( uiPitch / ( hVSurface->ubBitDepth / 8 ) ); CHECKF( pDest != NULL ); // Blit Surface // If rect is NULL, use entrie image size if ( pSrcRect == NULL ) { aRect.iLeft = 0; aRect.iTop = 0; aRect.iRight = hImage->usWidth; aRect.iBottom = hImage->usHeight; } else { aRect.iLeft = pSrcRect->iLeft; aRect.iTop = pSrcRect->iTop; aRect.iRight = pSrcRect->iRight; aRect.iBottom = pSrcRect->iBottom; } // This HIMAGE function will transparently copy buffer if ( !CopyImageToBuffer( hImage, fBufferBPP, pDest, usEffectiveWidth, hVSurface->usHeight, usX, usY, &aRect ) ) { DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Error Occured Copying HIMAGE to HVSURFACE" )); UnLockVideoSurfaceBuffer( hVSurface ); return( FALSE ); } // All is OK UnLockVideoSurfaceBuffer( hVSurface ); return( TRUE ); } // Palette setting is expensive, need to set both DDPalette and create 16BPP palette BOOLEAN SetVideoSurfacePalette( HVSURFACE hVSurface, SGPPaletteEntry *pSrcPalette ) { Assert( hVSurface != NULL ); // Create palette object if not already done so if ( hVSurface->pPalette == NULL ) { DDCreatePalette( GetDirectDraw2Object(), (DDPCAPS_8BIT | DDPCAPS_ALLOW256), (LPPALETTEENTRY)(&pSrcPalette[0]), &((LPDIRECTDRAWPALETTE)hVSurface->pPalette), NULL); // Set into surface //DDSetSurfacePalette( (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData, (LPDIRECTDRAWPALETTE)hVSurface->pPalette ); } else { // Just Change entries DDSetPaletteEntries( (LPDIRECTDRAWPALETTE)hVSurface->pPalette, 0, 0, 256, ( PALETTEENTRY*)pSrcPalette ); } // Delete 16BPP Palette if one exists if ( hVSurface->p16BPPPalette != NULL ) { MemFree( hVSurface->p16BPPPalette ); hVSurface->p16BPPPalette = NULL; } // Create 16BPP Palette hVSurface->p16BPPPalette = Create16BPPPalette( pSrcPalette ); DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_3, String("Video Surface Palette change successfull" )); return( TRUE ); } // Transparency needs to take RGB value and find best fit and place it into DD Surface // colorkey value. BOOLEAN SetVideoSurfaceTransparencyColor( HVSURFACE hVSurface, COLORVAL TransColor ) { DDCOLORKEY ColorKey; DWORD fFlags = CLR_INVALID; LPDIRECTDRAWSURFACE2 lpDDSurface; // Assertions Assert( hVSurface != NULL ); //Set trans color into Video Surface hVSurface->TransparentColor = TransColor; // Get surface pointer lpDDSurface = (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData; CHECKF( lpDDSurface != NULL ); // Get right pixel format, based on bit depth switch( hVSurface->ubBitDepth ) { case 8: // Use color directly ColorKey.dwColorSpaceLowValue = TransColor; ColorKey.dwColorSpaceHighValue = TransColor; break; case 16: fFlags = Get16BPPColor( TransColor ); //fFlags now contains our closest match ColorKey.dwColorSpaceLowValue = fFlags; ColorKey.dwColorSpaceHighValue = ColorKey.dwColorSpaceLowValue; break; } DDSetSurfaceColorKey( lpDDSurface, DDCKEY_SRCBLT, &ColorKey); return( TRUE ); } BOOLEAN GetVSurfacePaletteEntries( HVSURFACE hVSurface, SGPPaletteEntry *pPalette ) { CHECKF( hVSurface->pPalette != NULL ); DDGetPaletteEntries( (LPDIRECTDRAWPALETTE)hVSurface->pPalette, 0, 0, 256, (PALETTEENTRY*)pPalette ); return( TRUE ); } BOOLEAN DeleteVideoSurfaceFromIndex( UINT32 uiIndex ) { VSURFACE_NODE *curr; #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_DELETEVIDEOSURFACEFROMINDEX; CheckValidVSurfaceIndex( uiIndex ); #endif curr = gpVSurfaceHead; while( curr ) { if( curr->uiIndex == uiIndex ) { //Found the node, so detach it and delete it. //Deallocate the memory for the video surface DeleteVideoSurface( curr->hVSurface ); if( curr == gpVSurfaceHead ) { //Advance the head, because we are going to remove the head node. gpVSurfaceHead = gpVSurfaceHead->next; } if( curr == gpVSurfaceTail ) { //Back up the tail, because we are going to remove the tail node. gpVSurfaceTail = gpVSurfaceTail->prev; } //Detach the node from the vsurface list if( curr->next ) { //Make the prev node point to the next curr->next->prev = curr->prev; } if( curr->prev ) { //Make the next node point to the prev curr->prev->next = curr->next; } //The node is now detached. Now deallocate it. #ifdef SGP_VIDEO_DEBUGGING if( curr->pName ) { MemFree( curr->pName ); } if( curr->pCode ) { MemFree( curr->pCode ); } #endif MemFree( curr ); guiVSurfaceSize--; return TRUE; } curr = curr->next; } return FALSE; } // Deletes all palettes, surfaces and region data BOOLEAN DeleteVideoSurface( HVSURFACE hVSurface ) { LPDIRECTDRAWSURFACE2 lpDDSurface; // Assertions CHECKF( hVSurface != NULL ); // Release palette if ( hVSurface->pPalette != NULL ) { DDReleasePalette( (LPDIRECTDRAWPALETTE)hVSurface->pPalette ); hVSurface->pPalette = NULL; } //if ( hVSurface->pClipper != NULL ) //{ // Release Clipper // DDReleaseClipper( (LPDIRECTDRAWCLIPPER)hVSurface->pClipper ); //} // Get surface pointer lpDDSurface = (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData; // Release surface if ( hVSurface->pSurfaceData1 != NULL ) { DDReleaseSurface( &(LPDIRECTDRAWSURFACE)hVSurface->pSurfaceData1, &lpDDSurface ); } // Release backup surface if ( hVSurface->pSavedSurfaceData != NULL ) { DDReleaseSurface( &(LPDIRECTDRAWSURFACE)hVSurface->pSavedSurfaceData1, &(LPDIRECTDRAWSURFACE2)hVSurface->pSavedSurfaceData ); } // Release region data DeleteList( hVSurface->RegionList ); //If there is a 16bpp palette, free it if( hVSurface->p16BPPPalette != NULL ) { MemFree( hVSurface->p16BPPPalette ); hVSurface->p16BPPPalette = NULL; } giMemUsedInSurfaces -= ( hVSurface->usHeight * hVSurface->usWidth * ( hVSurface->ubBitDepth / 8 ) ); // Release object MemFree( hVSurface ); return( TRUE ); } // ******************************************************** // // Clipper manipulation functions // // ******************************************************** BOOLEAN SetClipList( HVSURFACE hVSurface, SGPRect *RegionData, UINT16 usNumRegions ) { RGNDATA *pRgnData; UINT16 cnt; RECT aRect; LPDIRECTDRAW2 lpDD2Object; // Get Direct Draw Object lpDD2Object = GetDirectDraw2Object( ); // Assertions Assert( hVSurface != NULL ); Assert( RegionData != NULL ); // Varifications CHECKF( usNumRegions > 0 ); // If Clipper already created, release if ( hVSurface->pClipper != NULL ) { // Release Clipper DDReleaseClipper( (LPDIRECTDRAWCLIPPER)hVSurface->pClipper ); } // Create Clipper Object DDCreateClipper( lpDD2Object, 0, &((LPDIRECTDRAWCLIPPER)hVSurface->pClipper) ); // Allocate region data pRgnData = ( LPRGNDATA )MemAlloc( sizeof( RGNDATAHEADER) + ( usNumRegions * sizeof( RECT ) ) ); CHECKF( pRgnData ); // Setup header pRgnData->rdh.dwSize = sizeof( RGNDATA ); pRgnData->rdh.iType = RDH_RECTANGLES; pRgnData->rdh.nCount = usNumRegions; pRgnData->rdh.nRgnSize = usNumRegions * sizeof( RECT ); pRgnData->rdh.rcBound.top = 0; pRgnData->rdh.rcBound.left = 0; pRgnData->rdh.rcBound.bottom = (int)hVSurface->usHeight; pRgnData->rdh.rcBound.right = (int)hVSurface->usWidth; // Copy rectangles into region for ( cnt = 0; cnt < usNumRegions; cnt++ ) { aRect.top = (UINT32)RegionData[ cnt ].iTop; aRect.left = (UINT32)RegionData[ cnt ].iLeft; aRect.bottom = (UINT32)RegionData[ cnt ].iBottom; aRect.right = (UINT32)RegionData[ cnt ].iRight; memcpy( pRgnData + sizeof( RGNDATAHEADER) + ( cnt * sizeof( RECT ) ), &aRect, sizeof( RECT ) ); } // Set items into clipper DDSetClipperList( (LPDIRECTDRAWCLIPPER)hVSurface->pClipper, pRgnData, 0 ); // Set Clipper into Surface DDSetClipper( (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData, (LPDIRECTDRAWCLIPPER)hVSurface->pClipper ); // Delete region data MemFree( pRgnData ); return( TRUE ); } // ******************************************************** // // Region manipulation functions // // ******************************************************** BOOLEAN GetNumRegions( HVSURFACE hVSurface , UINT32 *puiNumRegions ) { Assert( hVSurface ); *puiNumRegions = ListSize( hVSurface->RegionList ); return( TRUE ); } BOOLEAN AddVSurfaceRegion( HVSURFACE hVSurface, VSURFACE_REGION *pNewRegion ) { Assert( hVSurface != NULL ); Assert( pNewRegion != NULL ); // Add new region to list hVSurface->RegionList = AddtoList( hVSurface->RegionList, pNewRegion, ListSize( hVSurface->RegionList ) ); return( TRUE ); } // Add a group of regions BOOLEAN AddVSurfaceRegions( HVSURFACE hVSurface, VSURFACE_REGION **ppNewRegions, UINT16 uiNumRegions ) { UINT16 cnt; Assert( hVSurface != NULL ); Assert( ppNewRegions != NULL ); for ( cnt = 0; cnt < uiNumRegions; cnt++ ) { AddVSurfaceRegion( hVSurface, ppNewRegions[ cnt ] ); } return( TRUE ); } BOOLEAN RemoveVSurfaceRegion( HVSURFACE hVSurface, UINT16 usIndex ) { VSURFACE_REGION aRegion; Assert( hVSurface != NULL ); return( RemfromList( hVSurface->RegionList, &aRegion, usIndex ) ); } BOOLEAN ClearAllVSurfaceRegions( HVSURFACE hVSurface ) { UINT32 uiListSize, cnt; Assert( hVSurface != NULL ); uiListSize = ListSize( hVSurface->RegionList ); for ( cnt = uiListSize - 1; cnt >= 0; cnt-- ) { RemoveVSurfaceRegion( hVSurface, (UINT16)cnt ); } return( TRUE ); } BOOLEAN GetVSurfaceRegion( HVSURFACE hVSurface, UINT16 usIndex, VSURFACE_REGION *aRegion ) { Assert( hVSurface != NULL ); if ( !PeekList( hVSurface->RegionList, aRegion, usIndex ) ) { return( FALSE ); } return( TRUE ); } BOOLEAN GetVSurfaceRect( HVSURFACE hVSurface, RECT *pRect) { Assert( hVSurface != NULL ); Assert( pRect != NULL ); pRect->left=0; pRect->top=0; pRect->right=hVSurface->usWidth; pRect->bottom=hVSurface->usHeight; return( TRUE ); } BOOLEAN ReplaceVSurfaceRegion( HVSURFACE hVSurface , UINT16 usIndex, VSURFACE_REGION *aRegion ) { VSURFACE_REGION OldRegion; Assert( hVSurface != NULL ); // Validate index given if ( !PeekList( hVSurface->RegionList, &OldRegion, usIndex ) ) { return( FALSE ); } // Replace information hVSurface->RegionList = AddtoList( hVSurface->RegionList, aRegion, usIndex ); return( TRUE ); } BOOLEAN AddVSurfaceRegionAtIndex( HVSURFACE hVSurface, UINT16 usIndex, VSURFACE_REGION *pNewRegion ) { Assert( hVSurface != NULL ); Assert( pNewRegion != NULL ); // Add new region to list hVSurface->RegionList = AddtoList( hVSurface->RegionList, pNewRegion, usIndex ); return( TRUE ); } // ******************************************************************* // // Blitting Functions // // ******************************************************************* // Blt will use DD Blt or BltFast depending on flags. // Will drop down into user-defined blitter if 8->16 BPP blitting is being done BOOLEAN BltVideoSurfaceToVideoSurface( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, UINT16 usIndex, INT32 iDestX, INT32 iDestY, INT32 fBltFlags, blt_vs_fx *pBltFx ) { VSURFACE_REGION aRegion; RECT SrcRect, DestRect; UINT8 *pSrcSurface8, *pDestSurface8; UINT16 *pDestSurface16, *pSrcSurface16; UINT32 uiSrcPitch, uiDestPitch, uiWidth, uiHeight; // Assertions Assert( hDestVSurface != NULL ); // Check that both region and subrect are not given if ((fBltFlags&VS_BLT_SRCREGION) && (fBltFlags&VS_BLT_SRCSUBRECT)) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Inconsistant blit flags given" )); return( FALSE ); } // Check for dest src options if ( fBltFlags & VS_BLT_DESTREGION ) { CHECKF( pBltFx != NULL ); CHECKF( GetVSurfaceRegion( hDestVSurface, pBltFx->DestRegion, &aRegion ) ); // Set starting coordinates from destination region iDestY = aRegion.RegionCoords.iTop; iDestX = aRegion.RegionCoords.iLeft; } // Check for fill, if true, fill entire region with color if ( fBltFlags & VS_BLT_COLORFILL ) { return( FillSurface( hDestVSurface, pBltFx ) ); } // Check for colorfill rectangle if ( fBltFlags & VS_BLT_COLORFILLRECT ) { return( FillSurfaceRect( hDestVSurface, pBltFx ) ); } // Check for source coordinate options - from region, specific rect or full src dimensions do { // Get Region from index, if specified if ( fBltFlags & VS_BLT_SRCREGION ) { CHECKF( GetVSurfaceRegion( hSrcVSurface, usIndex, &aRegion ) ) SrcRect.top = (int)aRegion.RegionCoords.iTop; SrcRect.left = (int)aRegion.RegionCoords.iLeft; SrcRect.bottom = (int)aRegion.RegionCoords.iBottom; SrcRect.right = (int)aRegion.RegionCoords.iRight; break; } // Use SUBRECT if specified if ( fBltFlags & VS_BLT_SRCSUBRECT ) { SGPRect aSubRect; CHECKF( pBltFx != NULL ); aSubRect = pBltFx->SrcRect; SrcRect.top = (int)aSubRect.iTop; SrcRect.left = (int)aSubRect.iLeft; SrcRect.bottom = (int)aSubRect.iBottom; SrcRect.right = (int)aSubRect.iRight; break; } // Here, use default, which is entire Video Surface // Check Sizes, SRC size MUST be <= DEST size if ( hDestVSurface->usHeight < hSrcVSurface->usHeight ) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Incompatible height size given in Video Surface blit" )); return( FALSE ); } if ( hDestVSurface->usWidth < hSrcVSurface->usWidth ) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Incompatible height size given in Video Surface blit" )); return( FALSE ); } SrcRect.top = (int)0; SrcRect.left = (int)0; SrcRect.bottom = (int)hSrcVSurface->usHeight; SrcRect.right = (int)hSrcVSurface->usWidth; } while( FALSE ); // Once here, assert valid Src Assert( hSrcVSurface != NULL ); // clipping -- added by DB GetVSurfaceRect( hDestVSurface, &DestRect); uiWidth=SrcRect.right-SrcRect.left; uiHeight=SrcRect.bottom-SrcRect.top; // check for position entirely off the screen if(iDestX >= DestRect.right) return(FALSE); if(iDestY >= DestRect.bottom) return(FALSE); if((iDestX+(INT32)uiWidth) < (INT32)DestRect.left) return(FALSE); if((iDestY+(INT32)uiHeight) < (INT32)DestRect.top) return(FALSE); // DB The mirroring stuff has to do it's own clipping because // it needs to invert some of the numbers if(!(fBltFlags & VS_BLT_MIRROR_Y)) { if((iDestX+(INT32)uiWidth) >= (INT32)DestRect.right) { SrcRect.right-=((iDestX+uiWidth)-DestRect.right); uiWidth-=((iDestX+uiWidth)-DestRect.right); } if((iDestY+(INT32)uiHeight) >= (INT32)DestRect.bottom) { SrcRect.bottom-=((iDestY+uiHeight)-DestRect.bottom); uiHeight-=((iDestY+uiHeight)-DestRect.bottom); } if(iDestX < DestRect.left) { SrcRect.left+=(DestRect.left-iDestX); uiWidth-=(DestRect.left-iDestX); iDestX=DestRect.left; } if(iDestY < (INT32)DestRect.top) { SrcRect.top+=(DestRect.top-iDestY); uiHeight-=(DestRect.top-iDestY); iDestY=DestRect.top; } } // Send dest position, rectangle, etc to DD bltfast function // First check BPP values for compatibility if ( hDestVSurface->ubBitDepth == 16 && hSrcVSurface->ubBitDepth == 16 ) { if(fBltFlags & VS_BLT_MIRROR_Y) { if((pSrcSurface16=(UINT16 *)LockVideoSurfaceBuffer(hSrcVSurface, &uiSrcPitch))==NULL) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed on lock of 16BPP surface for blitting" )); return(FALSE); } if((pDestSurface16=(UINT16 *)LockVideoSurfaceBuffer(hDestVSurface, &uiDestPitch))==NULL) { UnLockVideoSurfaceBuffer(hSrcVSurface); DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed on lock of 16BPP dest surface for blitting" )); return(FALSE); } Blt16BPPTo16BPPMirror(pDestSurface16, uiDestPitch, pSrcSurface16, uiSrcPitch, iDestX, iDestY, SrcRect.left, SrcRect.top, uiWidth, uiHeight); UnLockVideoSurfaceBuffer(hSrcVSurface); UnLockVideoSurfaceBuffer(hDestVSurface); return(TRUE); } // For testing with non-DDraw blitting, uncomment to test -- DB #ifndef JA2 else { if((pSrcSurface16=(UINT16 *)LockVideoSurfaceBuffer(hSrcVSurface, &uiSrcPitch))==NULL) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed on lock of 16BPP surface for blitting" )); return(FALSE); } if((pDestSurface16=(UINT16 *)LockVideoSurfaceBuffer(hDestVSurface, &uiDestPitch))==NULL) { UnLockVideoSurfaceBuffer(hSrcVSurface); DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed on lock of 16BPP dest surface for blitting" )); return(FALSE); } Blt16BPPTo16BPP(pDestSurface16, uiDestPitch, pSrcSurface16, uiSrcPitch, iDestX, iDestY, SrcRect.left, SrcRect.top, uiWidth, uiHeight); UnLockVideoSurfaceBuffer(hSrcVSurface); UnLockVideoSurfaceBuffer(hDestVSurface); return(TRUE); } #endif CHECKF( BltVSurfaceUsingDD( hDestVSurface, hSrcVSurface, fBltFlags, iDestX, iDestY, &SrcRect ) ); } else if ( hDestVSurface->ubBitDepth == 8 && hSrcVSurface->ubBitDepth == 8 ) { if((pSrcSurface8=(UINT8 *)LockVideoSurfaceBuffer(hSrcVSurface, &uiSrcPitch))==NULL) { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed on lock of 8BPP surface for blitting" )); return(FALSE); } if((pDestSurface8=(UINT8 *)LockVideoSurfaceBuffer(hDestVSurface, &uiDestPitch))==NULL) { UnLockVideoSurfaceBuffer(hSrcVSurface); DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Failed on lock of 8BPP dest surface for blitting" )); return(FALSE); } //Blt8BPPDataTo8BPPBuffer( UINT8 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); Blt8BPPTo8BPP(pDestSurface8, uiDestPitch, pSrcSurface8, uiSrcPitch, iDestX, iDestY, SrcRect.left, SrcRect.top, uiWidth, uiHeight); UnLockVideoSurfaceBuffer(hSrcVSurface); UnLockVideoSurfaceBuffer(hDestVSurface); return(TRUE); } else { DbgMessage(TOPIC_VIDEOSURFACE, DBG_LEVEL_2, String( "Incompatible BPP values with src and dest Video Surfaces for blitting" )); return( FALSE ); } return( TRUE ); } // ****************************************************************************************** // // UTILITY FUNCTIONS // // ****************************************************************************************** // Blt to backup buffer BOOLEAN UpdateBackupSurface( HVSURFACE hVSurface ) { RECT aRect; // Assertions Assert( hVSurface != NULL ); // Validations CHECKF( hVSurface->pSavedSurfaceData != NULL ); aRect.top = (int)0; aRect.left = (int)0; aRect.bottom = (int)hVSurface->usHeight; aRect.right = (int)hVSurface->usWidth; // Copy all contents into backup buffer DDBltFastSurface( (LPDIRECTDRAWSURFACE2)hVSurface->pSurfaceData, 0, 0, (LPDIRECTDRAWSURFACE2)hVSurface->pSavedSurfaceData, &aRect, DDBLTFAST_NOCOLORKEY ); return( TRUE ); } // ***************************************************************************** // // Private DirectDraw manipulation functions // // ***************************************************************************** LPDIRECTDRAWSURFACE2 GetVideoSurfaceDDSurface( HVSURFACE hVSurface ) { Assert( hVSurface != NULL ); return( (LPDIRECTDRAWSURFACE2) hVSurface->pSurfaceData ); } LPDIRECTDRAWSURFACE GetVideoSurfaceDDSurfaceOne( HVSURFACE hVSurface ) { Assert( hVSurface != NULL ); return( (LPDIRECTDRAWSURFACE) hVSurface->pSurfaceData1 ); } LPDIRECTDRAWPALETTE GetVideoSurfaceDDPalette( HVSURFACE hVSurface ) { Assert( hVSurface != NULL ); return( (LPDIRECTDRAWPALETTE) hVSurface->pPalette ); } HVSURFACE CreateVideoSurfaceFromDDSurface( LPDIRECTDRAWSURFACE2 lpDDSurface ) { // Create Video Surface DDPIXELFORMAT PixelFormat; HVSURFACE hVSurface; DDSURFACEDESC DDSurfaceDesc; LPDIRECTDRAWPALETTE pDDPalette; SGPPaletteEntry SGPPalette[ 256 ]; HRESULT ReturnCode; // Allocate Video Surface struct hVSurface = MemAlloc( sizeof( SGPVSurface ) ); // Set values based on DD Surface given DDGetSurfaceDescription ( lpDDSurface, &DDSurfaceDesc ); PixelFormat = DDSurfaceDesc.ddpfPixelFormat; hVSurface->usHeight = (UINT16)DDSurfaceDesc.dwHeight; hVSurface->usWidth = (UINT16)DDSurfaceDesc.dwWidth; hVSurface->ubBitDepth = (UINT8)PixelFormat.dwRGBBitCount; hVSurface->pSurfaceData = (PTR)lpDDSurface; hVSurface->pSurfaceData1 = NULL; hVSurface->pSavedSurfaceData = NULL; hVSurface->RegionList = CreateList( DEFAULT_NUM_REGIONS, sizeof( VSURFACE_REGION ) ); hVSurface->fFlags = 0; // Get and Set palette, if attached, allow to fail ReturnCode = IDirectDrawSurface2_GetPalette( lpDDSurface, &pDDPalette ); if ( ReturnCode == DD_OK ) { // Set 8-bit Palette and 16 BPP palette hVSurface->pPalette = pDDPalette; // Create 16-BPP Palette DDGetPaletteEntries( pDDPalette, 0, 0, 256, ( LPPALETTEENTRY )SGPPalette ); hVSurface->p16BPPPalette = Create16BPPPalette( SGPPalette ); } else { hVSurface->pPalette = NULL; hVSurface->p16BPPPalette = NULL; } // Set meory flags if ( DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) { hVSurface->fFlags |= VSURFACE_SYSTEM_MEM_USAGE; } if ( DDSurfaceDesc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY ) { hVSurface->fFlags |= VSURFACE_VIDEO_MEM_USAGE; } // All is well DbgMessage( TOPIC_VIDEOSURFACE, DBG_LEVEL_0, String("Success in Creating Video Surface from DD Surface" ) ); return( hVSurface ); } HVSURFACE GetPrimaryVideoSurface( ) { return( ghPrimary ); } HVSURFACE GetBackBufferVideoSurface( ) { return( ghBackBuffer ); } HVSURFACE GetFrameBufferVideoSurface( ) { return( ghFrameBuffer ); } HVSURFACE GetMouseBufferVideoSurface( ) { return( ghMouseBuffer ); } // UTILITY FUNCTIONS FOR BLITTING BOOLEAN ClipReleatedSrcAndDestRectangles( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, RECT *DestRect, RECT *SrcRect ) { Assert( hDestVSurface != NULL ); Assert( hSrcVSurface != NULL ); // Check for invalid start positions and clip by ignoring blit if ( DestRect->left >= hDestVSurface->usWidth || DestRect->top >= hDestVSurface->usHeight ) { return( FALSE ); } if ( SrcRect->left >= hSrcVSurface->usWidth || SrcRect->top >= hSrcVSurface->usHeight ) { return( FALSE ); } // For overruns // Clip destination rectangles if ( DestRect->right > hDestVSurface->usWidth ) { // Both have to be modified or by default streching occurs DestRect->right = hDestVSurface->usWidth; SrcRect->right = SrcRect->left + ( DestRect->right - DestRect->left ); } if ( DestRect->bottom > hDestVSurface->usHeight ) { // Both have to be modified or by default streching occurs DestRect->bottom = hDestVSurface->usHeight; SrcRect->bottom = SrcRect->top + ( DestRect->bottom - DestRect->top ); } // Clip src rectangles if ( SrcRect->right > hSrcVSurface->usWidth ) { // Both have to be modified or by default streching occurs SrcRect->right = hSrcVSurface->usWidth; DestRect->right = DestRect->left + ( SrcRect->right - SrcRect->left ); } if ( SrcRect->bottom > hSrcVSurface->usHeight ) { // Both have to be modified or by default streching occurs SrcRect->bottom = hSrcVSurface->usHeight; DestRect->bottom = DestRect->top + ( SrcRect->bottom - SrcRect->top ); } // For underruns // Clip destination rectangles if ( DestRect->left < 0 ) { // Both have to be modified or by default streching occurs DestRect->left = 0; SrcRect->left = SrcRect->right - ( DestRect->right - DestRect->left ); } if ( DestRect->top < 0 ) { // Both have to be modified or by default streching occurs DestRect->top = 0; SrcRect->top = SrcRect->bottom - ( DestRect->bottom - DestRect->top ); } // Clip src rectangles if ( SrcRect->left < 0 ) { // Both have to be modified or by default streching occurs SrcRect->left = 0; DestRect->left = DestRect->right - ( SrcRect->right - SrcRect->left ); } if ( SrcRect->top < 0 ) { // Both have to be modified or by default streching occurs SrcRect->top = 0; DestRect->top = DestRect->bottom - ( SrcRect->bottom - SrcRect->top ); } return( TRUE ); } BOOLEAN FillSurface( HVSURFACE hDestVSurface, blt_vs_fx *pBltFx ) { DDBLTFX BlitterFX; Assert( hDestVSurface != NULL ); CHECKF( pBltFx != NULL ); BlitterFX.dwSize = sizeof( DDBLTFX ); BlitterFX.dwFillColor = pBltFx->ColorFill; DDBltSurface( (LPDIRECTDRAWSURFACE2)hDestVSurface->pSurfaceData, NULL, NULL, NULL, DDBLT_COLORFILL, &BlitterFX ); if ( hDestVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE && !hDestVSurface->fFlags & VSURFACE_RESERVED_SURFACE ) { UpdateBackupSurface( hDestVSurface ); } return( TRUE ); } BOOLEAN FillSurfaceRect( HVSURFACE hDestVSurface, blt_vs_fx *pBltFx ) { DDBLTFX BlitterFX; Assert( hDestVSurface != NULL ); CHECKF( pBltFx != NULL ); BlitterFX.dwSize = sizeof( DDBLTFX ); BlitterFX.dwFillColor = pBltFx->ColorFill; DDBltSurface( (LPDIRECTDRAWSURFACE2)hDestVSurface->pSurfaceData, (LPRECT)&(pBltFx->FillRect), NULL, NULL, DDBLT_COLORFILL, &BlitterFX ); if ( hDestVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE && !hDestVSurface->fFlags & VSURFACE_RESERVED_SURFACE ) { UpdateBackupSurface( hDestVSurface ); } return( TRUE ); } BOOLEAN BltVSurfaceUsingDD( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, UINT32 fBltFlags, INT32 iDestX, INT32 iDestY, RECT *SrcRect ) { UINT32 uiDDFlags; RECT DestRect; // Blit using the correct blitter if ( fBltFlags & VS_BLT_FAST ) { // Validations CHECKF( iDestX >= 0 ); CHECKF( iDestY >= 0 ); // Default flags uiDDFlags = 0; // Convert flags into DD flags, ( for transparency use, etc ) if ( fBltFlags & VS_BLT_USECOLORKEY ) { uiDDFlags |= DDBLTFAST_SRCCOLORKEY; } // Convert flags into DD flags, ( for transparency use, etc ) if ( fBltFlags & VS_BLT_USEDESTCOLORKEY ) { uiDDFlags |= DDBLTFAST_DESTCOLORKEY; } if ( uiDDFlags == 0 ) { // Default here is no colorkey uiDDFlags = DDBLTFAST_NOCOLORKEY; } DDBltFastSurface( (LPDIRECTDRAWSURFACE2)hDestVSurface->pSurfaceData, iDestX, iDestY, (LPDIRECTDRAWSURFACE2)hSrcVSurface->pSurfaceData, SrcRect, uiDDFlags ); } else { // Normal, specialized blit for clipping, etc // Default flags uiDDFlags = DDBLT_WAIT; // Convert flags into DD flags, ( for transparency use, etc ) if ( fBltFlags & VS_BLT_USECOLORKEY ) { uiDDFlags |= DDBLT_KEYSRC; } // Setup dest rectangle DestRect.top = (int)iDestY; DestRect.left = (int)iDestX; DestRect.bottom = (int)iDestY + ( SrcRect->bottom - SrcRect->top ); DestRect.right = (int)iDestX + ( SrcRect->right - SrcRect->left ); // Do Clipping of rectangles if ( !ClipReleatedSrcAndDestRectangles( hDestVSurface, hSrcVSurface, &DestRect, SrcRect ) ) { // Returns false because dest start is > dest size return( TRUE ); } // Check values for 0 size if ( DestRect.top == DestRect.bottom || DestRect.right == DestRect.left ) { return( TRUE ); } // Check for -ve values DDBltSurface( (LPDIRECTDRAWSURFACE2)hDestVSurface->pSurfaceData, &DestRect, (LPDIRECTDRAWSURFACE2)hSrcVSurface->pSurfaceData, SrcRect, uiDDFlags, NULL ); } // Update backup surface with new data if ( hDestVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE && !hDestVSurface->fFlags & VSURFACE_RESERVED_SURFACE ) { UpdateBackupSurface( hDestVSurface ); } return( TRUE ); } BOOLEAN Blt16BPPBufferShadowRectAlternateTable(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, SGPRect *area); BOOLEAN InternalShadowVideoSurfaceRect( UINT32 uiDestVSurface, INT32 X1, INT32 Y1, INT32 X2, INT32 Y2, BOOLEAN fLowPercentShadeTable ) { UINT16 *pBuffer; UINT32 uiPitch; SGPRect area; HVSURFACE hVSurface; // CLIP IT! // FIRST GET SURFACE // // Get Video Surface // #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_SHADOWVIDEOSURFACERECT; #endif CHECKF( GetVideoSurface( &hVSurface, uiDestVSurface ) ); if ( X1 < 0 ) X1 = 0; if ( X2 < 0 ) return( FALSE ); if ( Y2 < 0 ) return( FALSE ); if ( Y1 < 0 ) Y1 = 0; if ( X2 >= hVSurface->usWidth ) X2 = hVSurface->usWidth-1; if ( Y2 >= hVSurface->usHeight ) Y2 = hVSurface->usHeight-1; if ( X1 >= hVSurface->usWidth ) return( FALSE ); if ( Y1 >= hVSurface->usHeight ) return( FALSE ); if ( ( X2 - X1 ) <= 0 ) return( FALSE ); if ( ( Y2 - Y1 ) <= 0 ) return( FALSE ); area.iTop=Y1; area.iBottom=Y2; area.iLeft=X1; area.iRight=X2; // Lock video surface pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch ); //UnLockVideoSurface( uiDestVSurface ); if ( pBuffer == NULL ) { return( FALSE ); } if ( !fLowPercentShadeTable ) { // Now we have the video object and surface, call the shadow function if(!Blt16BPPBufferShadowRect(pBuffer, uiPitch, &area)) { // Blit has failed if false returned return( FALSE ); } } else { // Now we have the video object and surface, call the shadow function if(!Blt16BPPBufferShadowRectAlternateTable(pBuffer, uiPitch, &area)) { // Blit has failed if false returned return( FALSE ); } } // Mark as dirty if it's the backbuffer //if ( uiDestVSurface == BACKBUFFER ) //{ // InvalidateBackbuffer( ); //} UnLockVideoSurface( uiDestVSurface ); return( TRUE ); } BOOLEAN ShadowVideoSurfaceRect( UINT32 uiDestVSurface, INT32 X1, INT32 Y1, INT32 X2, INT32 Y2) { return( InternalShadowVideoSurfaceRect( uiDestVSurface, X1, Y1, X2, Y2, FALSE ) ); } BOOLEAN ShadowVideoSurfaceRectUsingLowPercentTable( UINT32 uiDestVSurface, INT32 X1, INT32 Y1, INT32 X2, INT32 Y2) { return( InternalShadowVideoSurfaceRect( uiDestVSurface, X1, Y1, X2, Y2, TRUE ) ); } // // BltVSurfaceUsingDDBlt will always use Direct Draw Blt,NOT BltFast BOOLEAN BltVSurfaceUsingDDBlt( HVSURFACE hDestVSurface, HVSURFACE hSrcVSurface, UINT32 fBltFlags, INT32 iDestX, INT32 iDestY, RECT *SrcRect, RECT *DestRect ) { UINT32 uiDDFlags; // Default flags uiDDFlags = DDBLT_WAIT; // Convert flags into DD flags, ( for transparency use, etc ) if ( fBltFlags & VS_BLT_USECOLORKEY ) { uiDDFlags |= DDBLT_KEYSRC; } DDBltSurface( (LPDIRECTDRAWSURFACE2)hDestVSurface->pSurfaceData, DestRect, (LPDIRECTDRAWSURFACE2)hSrcVSurface->pSurfaceData, SrcRect, uiDDFlags, NULL ); // Update backup surface with new data if ( hDestVSurface->fFlags & VSURFACE_VIDEO_MEM_USAGE && !hDestVSurface->fFlags & VSURFACE_RESERVED_SURFACE ) { UpdateBackupSurface( hDestVSurface ); } return( TRUE ); } // // This function will stretch the source image to the size of the dest rect. // // If the 2 images are not 16 Bpp, it returns false. // BOOLEAN BltStretchVideoSurface(UINT32 uiDestVSurface, UINT32 uiSrcVSurface, INT32 iDestX, INT32 iDestY, UINT32 fBltFlags, SGPRect *SrcRect, SGPRect *DestRect ) { HVSURFACE hDestVSurface; HVSURFACE hSrcVSurface; #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_BLTSTRETCHVIDEOSURFACE_DST; #endif if( !GetVideoSurface( &hDestVSurface, uiDestVSurface ) ) { return FALSE; } #ifdef _DEBUG gubVSDebugCode = DEBUGSTR_BLTSTRETCHVIDEOSURFACE_SRC; #endif if( !GetVideoSurface( &hSrcVSurface, uiSrcVSurface ) ) { return FALSE; } //if the 2 images are not both 16bpp, return FALSE if( (hDestVSurface->ubBitDepth != 16) && (hSrcVSurface->ubBitDepth != 16) ) return(FALSE); if(!BltVSurfaceUsingDDBlt( hDestVSurface, hSrcVSurface, fBltFlags, iDestX, iDestY, (RECT*)SrcRect, (RECT*)DestRect ) ) { // // VO Blitter will set debug messages for error conditions // return( FALSE ); } return( TRUE ); } BOOLEAN ShadowVideoSurfaceImage( UINT32 uiDestVSurface, HVOBJECT hImageHandle, INT32 iPosX, INT32 iPosY) { //Horizontal shadow ShadowVideoSurfaceRect( uiDestVSurface, iPosX+3, iPosY+hImageHandle->pETRLEObject->usHeight, iPosX+hImageHandle->pETRLEObject->usWidth, iPosY+ hImageHandle->pETRLEObject->usHeight+3); //vertical shadow ShadowVideoSurfaceRect( uiDestVSurface, iPosX+hImageHandle->pETRLEObject->usWidth, iPosY+3, iPosX+hImageHandle->pETRLEObject->usWidth+3, iPosY+ hImageHandle->pETRLEObject->usHeight); return( TRUE ); } BOOLEAN MakeVSurfaceFromVObject(UINT32 uiVObject, UINT16 usSubIndex, UINT32 *puiVSurface) { HVOBJECT hSrcVObject; UINT32 uiVSurface; VSURFACE_DESC hDesc; if(GetVideoObject(&hSrcVObject, uiVObject)) { // ATE: Memset memset( &hDesc, 0, sizeof( VSURFACE_DESC ) ); hDesc.fCreateFlags=VSURFACE_CREATE_DEFAULT; hDesc.usWidth=hSrcVObject->pETRLEObject[ usSubIndex ].usWidth; hDesc.usHeight=hSrcVObject->pETRLEObject[ usSubIndex ].usHeight; hDesc.ubBitDepth=PIXEL_DEPTH; if(AddVideoSurface(&hDesc, &uiVSurface)) { if(BltVideoObjectFromIndex(uiVSurface, uiVObject, usSubIndex, 0, 0, VO_BLT_SRCTRANSPARENCY, NULL)) { *puiVSurface=uiVSurface; return(TRUE); } else DeleteVideoSurfaceFromIndex(uiVSurface); } } return(FALSE); } #ifdef _DEBUG void CheckValidVSurfaceIndex( UINT32 uiIndex ) { BOOLEAN fAssertError = FALSE; if( uiIndex == 0xffffffff ) { //-1 index -- deleted fAssertError = TRUE; } else if( uiIndex % 2 && uiIndex < 0xfffffff0 ) { //odd numbers are reserved for vobjects fAssertError = TRUE; } if( fAssertError ) { UINT8 str[60]; switch( gubVSDebugCode ) { case DEBUGSTR_SETVIDEOSURFACETRANSPARENCY: sprintf( str, "SetVideoSurfaceTransparency" ); break; case DEBUGSTR_ADDVIDEOSURFACEREGION: sprintf( str, "AddVideoSurfaceRegion" ); break; case DEBUGSTR_GETVIDEOSURFACEDESCRIPTION: sprintf( str, "GetVideoSurfaceDescription" ); break; case DEBUGSTR_BLTVIDEOSURFACE_DST: sprintf( str, "BltVideoSurface (dest)" ); break; case DEBUGSTR_BLTVIDEOSURFACE_SRC: sprintf( str, "BltVideoSurface (src)" ); break; case DEBUGSTR_COLORFILLVIDEOSURFACEAREA: sprintf( str, "ColorFillVideoSurfaceArea" ); break; case DEBUGSTR_SHADOWVIDEOSURFACERECT: sprintf( str, "ShadowVideoSurfaceRect" ); break; case DEBUGSTR_BLTSTRETCHVIDEOSURFACE_DST: sprintf( str, "BltStretchVideoSurface (dest)" ); break; case DEBUGSTR_BLTSTRETCHVIDEOSURFACE_SRC: sprintf( str, "BltStretchVideoSurface (src)" ); break; case DEBUGSTR_DELETEVIDEOSURFACEFROMINDEX: sprintf( str, "DeleteVideoSurfaceFromIndex" ); break; case DEBUGSTR_NONE: default: sprintf( str, "GetVideoSurface" ); break; } if( uiIndex == 0xffffffff ) { AssertMsg( 0, String( "Trying to %s with deleted index -1." , str ) ); } else { AssertMsg( 0, String( "Trying to %s using a VOBJECT ID %d!", str, uiIndex ) ); } } } #endif #ifdef SGP_VIDEO_DEBUGGING typedef struct DUMPFILENAME { UINT8 str[256]; }DUMPFILENAME; void DumpVSurfaceInfoIntoFile( UINT8 *filename, BOOLEAN fAppend ) { VSURFACE_NODE *curr; FILE *fp; DUMPFILENAME *pName, *pCode; UINT32 *puiCounter; UINT8 tempName[ 256 ]; UINT8 tempCode[ 256 ]; UINT32 i, uiUniqueID; BOOLEAN fFound; if( !guiVSurfaceSize ) { return; } if( fAppend ) { fp = fopen( filename, "a" ); } else { fp = fopen( filename, "w" ); } Assert( fp ); //Allocate enough strings and counters for each node. pName = (DUMPFILENAME*)MemAlloc( sizeof( DUMPFILENAME ) * guiVSurfaceSize ); pCode = (DUMPFILENAME*)MemAlloc( sizeof( DUMPFILENAME ) * guiVSurfaceSize ); memset( pName, 0, sizeof( DUMPFILENAME ) * guiVSurfaceSize ); memset( pCode, 0, sizeof( DUMPFILENAME ) * guiVSurfaceSize ); puiCounter = (UINT32*)MemAlloc( 4 * guiVSurfaceSize ); memset( puiCounter, 0, 4 * guiVSurfaceSize ); //Loop through the list and record every unique filename and count them uiUniqueID = 0; curr = gpVSurfaceHead; while( curr ) { strcpy( tempName, curr->pName ); strcpy( tempCode, curr->pCode ); fFound = FALSE; for( i = 0; i < uiUniqueID; i++ ) { if( !_stricmp( tempName, pName[i].str ) && !_stricmp( tempCode, pCode[i].str ) ) { //same string fFound = TRUE; (puiCounter[ i ])++; break; } } if( !fFound ) { strcpy( pName[i].str, tempName ); strcpy( pCode[i].str, tempCode ); (puiCounter[ i ])++; uiUniqueID++; } curr = curr->next; } //Now dump the info. fprintf( fp, "-----------------------------------------------\n" ); fprintf( fp, "%d unique vSurface names exist in %d VSurfaces\n", uiUniqueID, guiVSurfaceSize ); fprintf( fp, "-----------------------------------------------\n\n" ); for( i = 0; i < uiUniqueID; i++ ) { fprintf( fp, "%d occurrences of %s\n", puiCounter[i], pName[i].str ); fprintf( fp, "%s\n\n", pCode[i].str ); } fprintf( fp, "\n-----------------------------------------------\n\n" ); //Free all memory associated with this operation. MemFree( pName ); MemFree( pCode ); MemFree( puiCounter ); fclose( fp ); } //Debug wrapper for adding vsurfaces BOOLEAN _AddAndRecordVSurface( VSURFACE_DESC *VSurfaceDesc, UINT32 *uiIndex, UINT32 uiLineNum, UINT8 *pSourceFile ) { UINT16 usLength; UINT8 str[256]; if( !AddStandardVideoSurface( VSurfaceDesc, uiIndex ) ) { return FALSE; } //record the filename of the vsurface (some are created via memory though) usLength = strlen( VSurfaceDesc->ImageFile ) + 1; gpVSurfaceTail->pName = (UINT8*)MemAlloc( usLength ); memset( gpVSurfaceTail->pName, 0, usLength ); strcpy( gpVSurfaceTail->pName, VSurfaceDesc->ImageFile ); //record the code location of the calling creating function. sprintf( str, "%s -- line(%d)", pSourceFile, uiLineNum ); usLength = strlen( str ) + 1; gpVSurfaceTail->pCode = (UINT8*)MemAlloc( usLength ); memset( gpVSurfaceTail->pCode, 0, usLength ); strcpy( gpVSurfaceTail->pCode, str ); return TRUE; } #endif