/******************************Module*Header**********************************\ * * ********************* * * DDraw SAMPLE CODE * * ********************* * * Module Name: ddblt.c * * Content: DirectDraw Blt and AlphaBlt callbacks * * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. \*****************************************************************************/ #include "precomp.h" #include "directx.h" #include "dd.h" // // lookup table to get shift values from Permedia format definition DWORD ShiftLookup[5] = { 0, 0, 1, 0, 2}; //@@BEGIN_DDKSPLIT #if DX7_ALPHABLT //--------------------------------------------------------------------------- // BOOL Intersect // // Function: // Check the integration of two input rectangles (RECTL* pRcl1, // RECTL* pRcl2) and set the intersection result in (RECTL* pRclResult) // // Return: // TRUE---If 'prcl1' and 'prcl2' intersect. The intersection will be in // 'prclResult' // FALSE--If they don't intersect. 'prclResult' is undefined. // //--------------------------------------------------------------------------- BOOL Intersect(RECTL* pRcl1, RECT* pRcl2, RECTL* pRclResult) { pRclResult->left = max(pRcl1->left, pRcl2->left); pRclResult->right = min(pRcl1->right, pRcl2->right); // // Check if there is a horizontal intersection // if ( pRclResult->left < pRclResult->right ) { pRclResult->top = max(pRcl1->top, pRcl2->top); pRclResult->bottom = min(pRcl1->bottom, pRcl2->bottom); // // Check if there a vertical intersection // if (pRclResult->top < pRclResult->bottom) return(TRUE); } // // Return FALSE if there is no intersection // return(FALSE); }// Intersect() //----------------------------------------------------------------------------- // IsDstRectClipped // // check if the destination rectangle of a blit is clipped by the given clip // rectangles. The function takes the rectangles as is and there can be cases // where a dest. rectangle is not clipped, but do not detect it... // // pDstRect---destination rectangle for blt // iClipRects-number of clip regions // pClipRects-clipping regions // //Return: // TRUE---dest rectangle is clipped // FALSE--dest rectangle is not clipped //----------------------------------------------------------------------------- BOOL IsDstRectClipped(RECTL *pDstRect, INT iClipRects, RECT *pClipRects) { INT i; RECTL rClippedRect; for ( i=0; ileft==rClippedRect.left && pDstRect->right==rClippedRect.right && pDstRect->top==rClippedRect.top && pDstRect->bottom==rClippedRect.bottom ) { // dest rect is not clipped!!! return FALSE; } } } return TRUE; } #endif //@@END_DDKSPLIT //----------------------------------------------------------------------------- // // DdPermediaBlt // // implements DirectDraw Blt callback // // lpBlt----structure for passing information to DDHAL Blt // //----------------------------------------------------------------------------- DWORD CALLBACK DdBlt( LPDDHAL_BLTDATA lpBlt ) { PPDev ppdev=(PPDev)lpBlt->lpDD->dhpdev; PERMEDIA_DEFS(ppdev); DWORD dwWindowBase; RECTL rSrc; RECTL rDest; DWORD dwFlags; LONG lPixPitchDest; LONG lPixPitchSrc; HRESULT ddrval; LPDDRAWI_DDRAWSURFACE_LCL pSrcLcl; LPDDRAWI_DDRAWSURFACE_LCL pDestLcl; LPDDRAWI_DDRAWSURFACE_GBL pSrcGbl; LPDDRAWI_DDRAWSURFACE_GBL pDestGbl; PermediaSurfaceData* pPrivateSource; PermediaSurfaceData* pPrivateDest; pDestLcl = lpBlt->lpDDDestSurface; pSrcLcl = lpBlt->lpDDSrcSurface; DBG_DD((2,"DDraw: Blt, ppdev: 0x%x",ppdev)); pDestGbl = pDestLcl->lpGbl; pPrivateDest= (PermediaSurfaceData*)pDestGbl->dwReserved1; DD_CHECK_PRIMARY_SURFACE_DATA(pDestLcl,pPrivateDest); DBG_DD((10, "Dest Surface:")); DUMPSURFACE(10, pDestLcl, NULL); ULONG ulDestPixelShift=DDSurf_GetPixelShift(pDestLcl); dwFlags = lpBlt->dwFlags; // For the future, drivers should ignore the DDBLT_ASYNC // flag, because its hardly used by applications and // nowadays drivers can queue up lots of blits, so that // the applications do not have to wait for it. // get local copy of src and dest rect rSrc = lpBlt->rSrc; rDest = lpBlt->rDest; // Switch to DirectDraw context DDCONTEXT; if (DDSurf_BitDepth(pDestLcl)==24) { return DDHAL_DRIVER_NOTHANDLED; } dwWindowBase = (DWORD)((UINT_PTR)(pDestGbl->fpVidMem) >> ulDestPixelShift); // get pitch for destination in pixels lPixPitchDest = pDestGbl->lPitch >> ulDestPixelShift; if (dwFlags & DDBLT_ROP) { if ((lpBlt->bltFX.dwROP >> 16) != (SRCCOPY >> 16)) { DBG_DD((1,"DDraw:Blt:BLT ROP case not supported!")); return DDHAL_DRIVER_NOTHANDLED; } LONG srcOffset; DBG_DD((3,"DDBLT_ROP: SRCCOPY")); if (pSrcLcl != NULL) { pSrcGbl = pSrcLcl->lpGbl; pPrivateSource = (PermediaSurfaceData*)pSrcGbl->dwReserved1; DD_CHECK_PRIMARY_SURFACE_DATA(pSrcLcl,pPrivateSource); DBG_DD((10, "Source Surface:")); DUMPSURFACE(10, pSrcLcl, NULL); } else { return DDHAL_DRIVER_NOTHANDLED; } if (DDSurf_BitDepth(pSrcLcl)==24) return DDHAL_DRIVER_NOTHANDLED; // determine src pitch in pixels lPixPitchSrc = pSrcGbl->lPitch >> ulDestPixelShift; // Operation is System -> Video memory blit, // as a texture download or an image download. if ((pSrcLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) && (pDestLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { ASSERTDD(!(pDestLcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM), "unsupported texture download to AGP memory"); if ((pDestLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) && (NULL != pPrivateDest) ) { // texture download DBG_DD((3,"SYSMEM->MANAGED MEM Blit" "(texture to system memory)")); pPrivateDest->dwFlags |= P2_SURFACE_NEEDUPDATE; SysMemToSysMemSurfaceCopy( pSrcGbl->fpVidMem, pSrcGbl->lPitch, DDSurf_BitDepth(pSrcLcl), pDestGbl->fpVidMem, pDestGbl->lPitch, DDSurf_BitDepth(pDestLcl), &rSrc, &rDest); goto BltDone; } else if (pPrivateDest!=NULL) { if ( (pDestLcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE) && ((rSrc.right-rSrc.left)==(LONG)pSrcGbl->wWidth) && ((rSrc.bottom-rSrc.top)==(LONG)pSrcGbl->wHeight) ) { // // patched texture download can only be done // when the texture is downloaded as a whole! // DBG_DD((3,"SYSMEM->VIDMEM Blit (texture to videomemory)")); PermediaPatchedTextureDownload( ppdev, pPrivateDest, pSrcGbl->fpVidMem, pSrcGbl->lPitch, &rSrc, pDestGbl->fpVidMem, pDestGbl->lPitch, &rDest); } else { // Image download DBG_DD((3,"SYSMEM->VIDMEM Blit (system to videomemory)")); PermediaPackedDownload( ppdev, pPrivateDest, pSrcLcl, &rSrc, pDestLcl, &rDest); } goto BltDone; } else { DBG_DD((0,"DDraw: Blt, privatedest invalid")); return DDHAL_DRIVER_NOTHANDLED; } } if (pPrivateSource == NULL || pPrivateDest == NULL) { DBG_DD((0,"DDraw: Blt, privatesource or dest invalid")); return DDHAL_DRIVER_NOTHANDLED; } BOOL bNonLocalToVideo=FALSE; // set base of source if ( DDSCAPS_NONLOCALVIDMEM & pSrcLcl->ddsCaps.dwCaps) { // turn on AGP bus texture source srcOffset = (LONG) DD_AGPSURFACEPHYSICAL(pSrcGbl); srcOffset |= 1 << 30; bNonLocalToVideo=TRUE; } else { srcOffset = (LONG)((pSrcGbl->fpVidMem) >> pPrivateSource->SurfaceFormat.PixelSize); } // Operation is YUV->RGB conversion if ((pPrivateSource != NULL) && (pPrivateSource->SurfaceFormat.Format == PERMEDIA_YUV422) && (pPrivateSource->SurfaceFormat.FormatExtension == PERMEDIA_YUV422_EXTENSION)) { DBG_DD((3,"YUV to RGB blt")); // We are only doing blits from YUV422 to RGB ! if (pPrivateDest->SurfaceFormat.Format != PERMEDIA_YUV422) { DBG_DD((4,"Blitting from Source YUV to RGB")); // YUV to RGB blt PermediaYUVtoRGB( ppdev, &lpBlt->bltFX, pPrivateDest, pPrivateSource, &rDest, &rSrc, dwWindowBase, srcOffset); goto BltDone; } else { DBG_DD((0,"Couldn't handle YUV to YUV blt")); lpBlt->ddRVal = DD_OK; return DDHAL_DRIVER_NOTHANDLED; } } ASSERTDD(DDSurf_BitDepth(pSrcLcl)==DDSurf_BitDepth(pDestLcl), "Blt between surfaces of different" "color depths are not supported"); BOOL bMirror=(dwFlags & DDBLT_DDFX)==DDBLT_DDFX; if (bMirror) { bMirror= (lpBlt->bltFX.dwDDFX & DDBLTFX_MIRRORUPDOWN) || (lpBlt->bltFX.dwDDFX & DDBLTFX_MIRRORLEFTRIGHT); } BOOL bStretched=((rSrc.right - rSrc.left) != (rDest.right - rDest.left) || (rSrc.bottom - rSrc.top) != (rDest.bottom - rDest.top)); // Is it a colorkey blt? if (dwFlags & DDBLT_KEYSRCOVERRIDE) { DBG_DD((3,"DDBLT_KEYSRCOVERRIDE")); // If the surface sizes don't match, then we are stretching. if (bStretched || bMirror) { PermediaStretchCopyChromaBlt( ppdev, lpBlt, pPrivateDest, pPrivateSource, &rDest, &rSrc, dwWindowBase, srcOffset); } else { PermediaSourceChromaBlt( ppdev, lpBlt, pPrivateDest, pPrivateSource, &rDest, &rSrc, dwWindowBase, srcOffset); } goto BltDone; } else { // If the surface sizes don't match, then we are stretching. // Also the blits from Nonlocal- to Videomemory have to go through // the texture unit! if ( bStretched || bMirror || bNonLocalToVideo) { DBG_DD((3,"DDBLT_ROP: STRETCHCOPYBLT OR " "MIRROR OR BOTH OR AGPVIDEO")); PermediaStretchCopyBlt( ppdev, lpBlt, pPrivateDest, pPrivateSource, &rDest, &rSrc, dwWindowBase, srcOffset); } else { DBG_DD((3,"DDBLT_ROP: COPYBLT %08lx %08lx %08lx", pSrcGbl->fpVidMem,pDestGbl->fpVidMem,ulDestPixelShift)); // Work out the source offset // (offset in pixels from dst to src) srcOffset = (LONG)((pSrcGbl->fpVidMem - pDestGbl->fpVidMem) >> ulDestPixelShift); // For some reason, the user might want // to do a conversion on the data as it is // blitted from VRAM->VRAM by turning on Patching. // If Surf1Patch XOR Surf2Patch then // do a special blit that isn't packed and does patching. if (((pPrivateDest->dwFlags & P2_CANPATCH) ^ (pPrivateSource->dwFlags & P2_CANPATCH)) & P2_CANPATCH) { DBG_DD((4,"Doing Patch-Conversion!")); PermediaPatchedCopyBlt( ppdev, lPixPitchDest, lPixPitchSrc, pPrivateDest, pPrivateSource, &rDest, &rSrc, dwWindowBase, srcOffset); } else { PermediaPackedCopyBlt( ppdev, lPixPitchDest, lPixPitchSrc, pPrivateDest, pPrivateSource, &rDest, &rSrc, dwWindowBase, srcOffset); } } goto BltDone; } } else if (pPrivateDest==NULL) { DBG_DD((0,"Private Surface data invalid!")); DUMPSURFACE(0, pDestLcl, NULL); } else if (dwFlags & DDBLT_COLORFILL) { DBG_DD((3,"DDBLT_COLORFILL: Color=0x%x", lpBlt->bltFX.dwFillColor)); if (pDestLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) { PermediaClearManagedSurface(pPrivateDest->SurfaceFormat.PixelSize, &rDest, pDestGbl->fpVidMem, pDestGbl->lPitch, lpBlt->bltFX.dwFillColor); pPrivateDest->dwFlags |= P2_SURFACE_NEEDUPDATE; } else { PermediaFastClear( ppdev, pPrivateDest, &rDest, dwWindowBase, lpBlt->bltFX.dwFillColor); } } else if (dwFlags & DDBLT_DEPTHFILL) { DBG_DD((3,"DDBLT_DEPTHFILL: Value=0x%x", lpBlt->bltFX.dwFillColor)); // Work out the window base for the LB clear, acount for the depth size dwWindowBase = (DWORD)((UINT_PTR)(pDestGbl->fpVidMem) >> __PERMEDIA_16BITPIXEL); // Call the LB Solid Fill Function. PermediaFastLBClear( ppdev, pPrivateDest, &rDest, dwWindowBase, lpBlt->bltFX.dwFillColor); } else { DBG_DD((1,"DDraw:Blt:Blt case not supported %08lx", dwFlags)); return DDHAL_DRIVER_NOTHANDLED; } BltDone: lpBlt->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } // DdBlt ()