/******************************Module*Header**********************************\ * * ************************** * * DirectDraw SAMPLE CODE * * ************************** * * Module Name: ddsurf.c * * Content: * * 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" #include "heap.h" #include "d3dtxman.h" #define ALLOC_TAG ALLOC_TAG_US2P // Texture tables defined in the D3D side of the driver (d3d.c) // TODO: move to dd.h or d3d.h extern ULONG gD3DNumberOfTextureFormats; extern DDSURFACEDESC gD3DTextureFormats[]; //--------------------------------------------------------------------------- // BOOL bComparePixelFormat // // Function used to compare 2 pixels formats for equality. This is a // helper function to bCheckTextureFormat. A return value of TRUE indicates // equality // //--------------------------------------------------------------------------- BOOL bComparePixelFormat(LPDDPIXELFORMAT lpddpf1, LPDDPIXELFORMAT lpddpf2) { if (lpddpf1->dwFlags != lpddpf2->dwFlags) { return FALSE; } // same bitcount for non-YUV surfaces? if (!(lpddpf1->dwFlags & (DDPF_YUV | DDPF_FOURCC))) { if (lpddpf1->dwRGBBitCount != lpddpf2->dwRGBBitCount ) { return FALSE; } } // same RGB properties? if (lpddpf1->dwFlags & DDPF_RGB) { if ((lpddpf1->dwRBitMask != lpddpf2->dwRBitMask) || (lpddpf1->dwGBitMask != lpddpf2->dwGBitMask) || (lpddpf1->dwBBitMask != lpddpf2->dwBBitMask) || (lpddpf1->dwRGBAlphaBitMask != lpddpf2->dwRGBAlphaBitMask)) { return FALSE; } } // same YUV properties? if (lpddpf1->dwFlags & DDPF_YUV) { if ((lpddpf1->dwFourCC != lpddpf2->dwFourCC) || (lpddpf1->dwYUVBitCount != lpddpf2->dwYUVBitCount) || (lpddpf1->dwYBitMask != lpddpf2->dwYBitMask) || (lpddpf1->dwUBitMask != lpddpf2->dwUBitMask) || (lpddpf1->dwVBitMask != lpddpf2->dwVBitMask) || (lpddpf1->dwYUVAlphaBitMask != lpddpf2->dwYUVAlphaBitMask)) { return FALSE; } } else if (lpddpf1->dwFlags & DDPF_FOURCC) { if (lpddpf1->dwFourCC != lpddpf2->dwFourCC) { return FALSE; } } // If Interleaved Z then check Z bit masks are the same if (lpddpf1->dwFlags & DDPF_ZPIXELS) { if (lpddpf1->dwRGBZBitMask != lpddpf2->dwRGBZBitMask) { return FALSE; } } return TRUE; } // bComparePixelFormat //--------------------------------------------------------------------------- // // BOOL bCheckTextureFormat // // Function used to determine if a texture format is supported. It traverses // the deviceTextureFormats list. We use this in DdCanCreateSurface32. A // return value of TRUE indicates that we do support the requested texture // format. // //--------------------------------------------------------------------------- BOOL bCheckTextureFormat(LPDDPIXELFORMAT lpddpf) { DWORD i; // Run the list for a matching format for (i=0; i < gD3DNumberOfTextureFormats; i++) { if (bComparePixelFormat(lpddpf, &gD3DTextureFormats[i].ddpfPixelFormat)) { return TRUE; } } return FALSE; } // bCheckTextureFormat //----------------------------------------------------------------------------- // // DdCanCreateSurface32 // // This entry point is called after parameter validation but before // any object creation. You can decide here if it is possible for // you to create this surface. For example, if the person is trying // to create an overlay, and you already have the maximum number of // overlays created, this is the place to fail the call. // // You also need to check if the pixel format specified can be supported. // //----------------------------------------------------------------------------- DWORD CALLBACK DdCanCreateSurface(LPDDHAL_CANCREATESURFACEDATA pccsd) { PPDev ppdev=(PPDev)pccsd->lpDD->dhpdev; PERMEDIA_DEFS(ppdev); PDD_SURFACEDESC lpDDS=pccsd->lpDDSurfaceDesc; DBG_DD((2,"DDraw:DdCanCreateSurface")); if(lpDDS->dwLinearSize == 0) { // rectangular surface // Reject all widths larger than we can create partial products for. DUMPSURFACE(10, NULL, lpDDS); if (lpDDS->dwWidth > (ULONG)(2 << MAX_PARTIAL_PRODUCT_P2)) { DBG_DD((1,"DDraw:DdCanCreateSurface: Surface rejected:")); DBG_DD((1," Width Requested: %ld (max. %ld)", lpDDS->dwWidth,(2 << MAX_PARTIAL_PRODUCT_P2))); pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT; return DDHAL_DRIVER_HANDLED; } } // We only support 16bits & 15bits (for stencils) Z-Buffer on PERMEDIA if ((lpDDS->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && (lpDDS->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { DWORD dwBitDepth; // verify where the right z buffer bit depth is if (DDSD_ZBUFFERBITDEPTH & lpDDS->dwFlags) dwBitDepth = lpDDS->dwZBufferBitDepth; else dwBitDepth = lpDDS->ddpfPixelFormat.dwZBufferBitDepth; // Notice we have to check for a BitDepth of 16 even if a stencil // buffer is present. dwZBufferBitDepth in this case will be the // sum of the z buffer and the stencil buffer bit depth. if (dwBitDepth == 16) { pccsd->ddRVal = DD_OK; } else { DBG_DD((2,"DDraw:DdCanCreateSurface: ERROR: " "Depth buffer not 16Bits! - %d", dwBitDepth)); pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT; } return DDHAL_DRIVER_HANDLED; } // pccsd->bIsDifferentPixelFormat tells us if the pixel format of the // surface being created matches that of the primary surface. It can be // true for Z buffer and alpha buffers, so don't just reject it out of // hand... if (pccsd->bIsDifferentPixelFormat) { DBG_DD((3," Pixel Format is different to primary")); if(lpDDS->ddpfPixelFormat.dwFlags & DDPF_FOURCC) { DBG_DD((3, " FourCC requested (%4.4hs, 0x%08lx)", (LPSTR) &lpDDS->ddpfPixelFormat.dwFourCC, lpDDS->ddpfPixelFormat.dwFourCC )); switch (lpDDS->ddpfPixelFormat.dwFourCC) { case FOURCC_YUV422: DBG_DD((3," Surface requested is YUV422")); if (ppdev->iBitmapFormat == BMF_8BPP) { pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT; } else { lpDDS->ddpfPixelFormat.dwYUVBitCount = 16; pccsd->ddRVal = DD_OK; } return DDHAL_DRIVER_HANDLED; default: DBG_DD((3," ERROR: Invalid FOURCC requested, refusing")); pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT; return DDHAL_DRIVER_HANDLED; } } else if((lpDDS->ddsCaps.dwCaps & DDSCAPS_TEXTURE)) { if (bCheckTextureFormat(&pccsd->lpDDSurfaceDesc->ddpfPixelFormat)) { // texture surface is in one or our supported texture formats DBG_DD((3, " Texture Surface - OK" )); pccsd->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } else { // we don't support this kind of texture format DBG_DD((3, " ERROR: Texture Surface - NOT OK" )); pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT; return DDHAL_DRIVER_HANDLED; } } //@@BEGIN_DDKSPLIT #if DX7_ALPHABLT else if (ValidRGBAlphaSurfaceformat( &lpDDS->ddpfPixelFormat, NULL)) { DBG_DD((3, " RGB alpha Surface - OK" )); if (lpDDS->ddpfPixelFormat.dwRGBBitCount!=24) { pccsd->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } } #endif //@@END_DDKSPLIT pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT; return DDHAL_DRIVER_HANDLED; } pccsd->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } // DdCanCreateSurface32 //----------------------------------------------------------------------------- // // DdCreateSurface // // This function is called by DirectDraw if a new surface is created. If the // driver has its own memory manager, here is the place to allocate the // videomemory or to fail the call. Note that we return // DDHAL_DRIVER_NOTHANDLED here to indicate that we do not manage the heap. // fpVidMem is set to DDHAL_PLEASEALLOC_BLOCKSIZE, and the DDraw memory // manager wll allocate the memory for us. // // Note that the Permedia chip requires a partial product // to be setup for each surface. They also limit the widths to a multiple // of 32 for the Partial Products to work. The below code adjusts the // surfaces to meet this requirement. Note that if we are using a // rectangular allocation scheme, the surface is already OK as the desktop // is a good width anyway. This code also handles YUV 16 Bit colour space // compressed format (FOURCC_YUV422) which will always be 16 bits, regardless // of the desktop resolution/requested depth. // //----------------------------------------------------------------------------- DWORD CALLBACK DdCreateSurface(PDD_CREATESURFACEDATA lpCreateSurface) { PPDev ppdev= (PPDev)lpCreateSurface->lpDD->dhpdev; PERMEDIA_DEFS(ppdev); DWORD dwBitDepth; DD_SURFACE_LOCAL* lpSurfaceLocal; DD_SURFACE_GLOBAL* lpSurfaceGlobal; LPDDSURFACEDESC lpSurfaceDesc; BOOL bYUV = FALSE; BOOL bResize = FALSE; DWORD dwExtraBytes; PermediaSurfaceData*pPrivateData = NULL; DBG_DD((2, "DdCreateSurface called")); // // See if any of these surfaces are Z buffers. If they are, ensure that the // pitch is a valid LB width. The minimum partial product is 32 words or // 32 pixels on Permedia 2 // // On Windows NT, dwSCnt will always be 1, so there will only ever // be one entry in the 'lplpSList' array: // ASSERTDD(lpCreateSurface->dwSCnt == 1, "DdCreateSurface: Unexpected dwSCnt value not equal to one"); lpSurfaceLocal = lpCreateSurface->lplpSList[0]; lpSurfaceGlobal = lpSurfaceLocal->lpGbl; lpSurfaceDesc = lpCreateSurface->lpDDSurfaceDesc; // // We repeat the same checks we did in 'DdCanCreateSurface' because // it's possible that an application doesn't call 'DdCanCreateSurface' // before calling 'DdCreateSurface'. // ASSERTDD(lpSurfaceGlobal->ddpfSurface.dwSize == sizeof(DDPIXELFORMAT), "NT is supposed to guarantee that ddpfSurface.dwSize is valid"); // // If the surface has already been allocated, don't reallocate it, just // reset it. This will happen if the surface is the primary surface. // if ( lpSurfaceGlobal->dwReserved1 != 0 ) { pPrivateData = (PermediaSurfaceData*)lpSurfaceGlobal->dwReserved1; if ( CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData) ) { DBG_DD((0, " Already allocated Private Surface data 0x%x", pPrivateData)); memset(pPrivateData, 0, sizeof(PermediaSurfaceData)); } else { pPrivateData = NULL; } } // // If the data isn't valid allocate it. // if ( pPrivateData == NULL ) { pPrivateData = (PermediaSurfaceData *) ENGALLOCMEM(FL_ZERO_MEMORY, sizeof(PermediaSurfaceData), ALLOC_TAG); if ( pPrivateData == NULL ) { DBG_DD((0, "DDraw:DdCreateSurface: " "Not enough memory for private surface data!")); lpCreateSurface->ddRVal = DDERR_OUTOFMEMORY; return DDHAL_DRIVER_HANDLED; } } // // Store the pointer to the new data // lpSurfaceGlobal->dwReserved1 = (UINT_PTR)pPrivateData; DBG_DD((3,"DDraw:DdCreateSurface privatedata=0x%x lpGbl=0x%x lpLcl=0x%x " "dwFlags=%08lx &dwReserved1=0x%x", pPrivateData, lpSurfaceGlobal, lpSurfaceLocal, lpSurfaceLocal->dwFlags, &lpSurfaceGlobal->dwReserved1)); // // Set the magic number // pPrivateData->MagicNo = SURF_MAGIC_NO; // // Store away the important information // SetupPrivateSurfaceData(ppdev, pPrivateData, lpSurfaceLocal); if ( pPrivateData->SurfaceFormat.PixelSize != __PERMEDIA_24BITPIXEL ) { dwBitDepth = (8 << pPrivateData->SurfaceFormat.PixelSize); } else { dwBitDepth = 24; } // // If the surface is a Z Buffer, then we always need to check the // pitch/partial products, and we need to get the depth from the // dwZBufferBitDepth field. // bYUV = FALSE; bResize = FALSE; dwExtraBytes = 0; // // get correct bit depth for Z buffers // if ( (lpSurfaceLocal->dwFlags & DDRAWISURF_HASPIXELFORMAT) &&(lpSurfaceGlobal->ddpfSurface.dwFlags & DDPF_ZBUFFER) ) { DBG_DD((5," Surface is Z Buffer - Adjusting")); dwBitDepth = lpSurfaceGlobal->ddpfSurface.dwZBufferBitDepth; } if ( lpSurfaceGlobal->ddpfSurface.dwFlags & DDPF_FOURCC ) { // // The surface is a YUV format surface or we fail // switch ( lpSurfaceGlobal->ddpfSurface.dwFourCC ) { case FOURCC_YUV422: DBG_DD((3," Surface is YUV422 - Adjusting")); lpSurfaceGlobal->ddpfSurface.dwYUVBitCount = 16; dwBitDepth = 16; bYUV = TRUE; break; default: // // We should never get here, as CanCreateSurface will // validate the YUV format for us. // ASSERTDD(0, "Trying to create an invalid YUV surface!"); break; } } // // If the surface is a p2 texture and it is using a LUT, then we need to // allocate extra local buffer memory for the LUT entries (only on p2). // if ( (lpSurfaceLocal->ddsCaps.dwCaps & DDSCAPS_TEXTURE) &&(pPrivateData->SurfaceFormat.Format == PERMEDIA_8BIT_PALETTEINDEX) ) { DBG_DD((7," Texture is a P2 8Bit LUT")); bResize = TRUE; dwExtraBytes = (256 * sizeof(DWORD)); } DBG_DD((5," Surface Pitch is: 0x%x", lpSurfaceGlobal->lPitch)); // // Width is in pixels/texels // LONG lPitch; lPitch = lpSurfaceGlobal->wWidth; DBG_DD((4," Source Surface is %d texels/depth values across", lpSurfaceGlobal->wWidth)); // align before hand to a DWPORD boundary if (pPrivateData->SurfaceFormat.PixelSize == __PERMEDIA_4BITPIXEL) { lPitch = ((lPitch >> 1) + 31) & ~31; } else { lPitch = (lPitch + 31) & ~31; } ULONG ulPackedPP; vCalcPackedPP( lPitch, &lPitch, &ulPackedPP); DBG_DD((7," Surface is 0x%x bits deep", dwBitDepth)); if ( pPrivateData->SurfaceFormat.PixelSize != __PERMEDIA_4BITPIXEL ) { // // Convert back to BYTES // if ( dwBitDepth != 24 ) { lPitch <<= ((int)dwBitDepth) >> 4; } else { lPitch *= 3; } } pPrivateData->dwFlags |= P2_PPVALID; DWORD dwExtraLines = 0; if ( !bYUV ) { // // PM Textures must be at least 32 high // if ( lpSurfaceGlobal->wHeight < 32 ) { dwExtraLines = 32 - lpSurfaceGlobal->wHeight; } } lpSurfaceGlobal->dwBlockSizeX = lPitch * (DWORD)(lpSurfaceGlobal->wHeight + dwExtraLines); lpSurfaceGlobal->dwBlockSizeY = 1; lpSurfaceGlobal->lPitch = lPitch; // // Store the partial productes in the structure // pPrivateData->ulPackedPP = ulPackedPP; DBG_DD((4, " New Width of surface in Bytes: %d", lPitch)); // // This flag is set if the surface needs resizing. This is currently only // used for the P2 LUT based textures. // if ( bResize ) { DWORD dwExtraScanlines = 0; LONG lExtraRemaining = (LONG)dwExtraBytes; // // ExtraScanlines is the count x, which * pitch is what we need to get // enough memory to hold the LUT. This algorithm will ensure that even // requests for sizes less than a pitch length will get allocated. // do { dwExtraScanlines++; lExtraRemaining -= (LONG)lpSurfaceGlobal->lPitch; } while ( lExtraRemaining > 0 ); DBG_DD((4, "Calculated extra Pitch lines = %d", dwExtraScanlines)); // // Stretch the surface a little more in multiples of pitch. // lpSurfaceGlobal->dwBlockSizeX +=dwExtraScanlines * lpSurfaceGlobal->lPitch; }// if ( bResize ) // // Modify surface descriptions as appropriate and let Direct // Draw perform the allocation if the surface was not the primary // if (lpSurfaceLocal->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { lpSurfaceGlobal->fpVidMem = NULL; } else { lpSurfaceGlobal->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE; } lpSurfaceDesc->lPitch = lpSurfaceGlobal->lPitch; lpSurfaceDesc->dwFlags |= DDSD_PITCH; if (lpSurfaceLocal->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) { if (lpSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) { lPitch = lpSurfaceDesc->lPitch = lpSurfaceGlobal->lPitch = ((lpSurfaceDesc->ddpfPixelFormat.dwRGBBitCount* lpSurfaceGlobal->wWidth+31)/32)*4; //make it DWORD aligned } lpSurfaceGlobal->dwUserMemSize = lPitch * (DWORD)(lpSurfaceGlobal->wHeight); lpSurfaceGlobal->fpVidMem = DDHAL_PLEASEALLOC_USERMEM; } lpCreateSurface->ddRVal = DD_OK; return DDHAL_DRIVER_NOTHANDLED; }// DdCreateSurface() //----------------------------------------------------------------------------- // // DdDestroySurface // // Frees up the private memory allocated with this surface. Note that // we return DDHAL_DRIVER_NOTHANDLED indicating that we didn't actually // free the surface, since the heap is managed by DDraw. // //----------------------------------------------------------------------------- extern TextureCacheManager P2TextureManager; DWORD CALLBACK DdDestroySurface( LPDDHAL_DESTROYSURFACEDATA psdd ) { PermediaSurfaceData *pPrivateData= (PermediaSurfaceData*)psdd->lpDDSurface->lpGbl->dwReserved1; DBG_DD((3,"DDraw:DdDestroySurface pPrivateData=0x%x " "lpGbl=0x%x lpLcl=0x%x dwFlags=%08lx &dwReserved1=0x%x", pPrivateData, psdd->lpDDSurface->lpGbl, psdd->lpDDSurface, psdd->lpDDSurface->dwFlags, &psdd->lpDDSurface->lpGbl->dwReserved1)); if (CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData)) { PPERMEDIA_D3DTEXTURE pTexture=NULL; if ((psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle) && (HandleList[psdd->lpDDSurface->dwReserved1].dwSurfaceList) && (psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle < PtrToUlong(HandleList[psdd->lpDDSurface->dwReserved1]. dwSurfaceList[0]))) pTexture=HandleList[psdd->lpDDSurface->dwReserved1].dwSurfaceList [psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle]; DBG_DD((3,"psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2=%08lx", psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2)); if (psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) { DBG_D3D((3, "free fpVidMem=%08lx fpVidMem=%08lx", pPrivateData->fpVidMem,psdd->lpDDSurface->lpGbl->fpVidMem)); if ((pPrivateData->fpVidMem) && pTexture) { ASSERTDD(CHECK_D3DSURFACE_VALIDITY(pTexture), "Invalid pTexture in DdDestroySurface"); TextureCacheManagerRemove(&P2TextureManager,pTexture); } if (DDRAWISURF_INVALID & psdd->lpDDSurface->dwFlags) { // indicate that driver takes care of the lost surface already psdd->ddRVal = DD_OK; return DDHAL_DRIVER_HANDLED; } } if (pTexture) { ENGFREEMEM(pTexture); HandleList[psdd->lpDDSurface->dwReserved1].dwSurfaceList [psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle]=0; } pPrivateData->MagicNo = NULL; ENGFREEMEM(pPrivateData); psdd->lpDDSurface->lpGbl->dwReserved1 = 0; } #if DBG else { if (pPrivateData) { ASSERTDD(0, "DDraw:DdDestroySurface:ERROR:" "Private Surface data not valid??"); } DBG_DD((0, "DDraw:DdDestroySurface:WARNING:" "No Private data in destroyed surface")); } #endif return DDHAL_DRIVER_NOTHANDLED; } // DdDestroySurface //----------------------------------------------------------------------------- // // SetupPrivateSurfaceData // // Function to get info about DDRAW surface and store it away in the // private structure. Useful for partial products, pixel depths, // texture setup (patching/formats), etc. // //----------------------------------------------------------------------------- VOID SetupPrivateSurfaceData( PPDev ppdev, PermediaSurfaceData* pPrivateData, LPDDRAWI_DDRAWSURFACE_LCL pSurface) { DDPIXELFORMAT* pPixFormat = NULL; ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData), "SetupPrivateSurfaceData: Private Surface data pointer invalid!!"); ASSERTDD(pSurface, "SetupPrivateSurfaceData: Surface pointer invalid"); DBG_DD((5,"DDraw:SetupPrivateSurfaceData")); DBG_DD((6," Width: %d, Height: %d", pSurface->lpGbl->wWidth, pSurface->lpGbl->wHeight)); // Surface is the primary surface if (pSurface->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { DBG_DD((6," Surface is Primary")); pPrivateData->dwFlags |= P2_SURFACE_PRIMARY; pPixFormat = &ppdev->ddpfDisplay; } // Either the surface is a texture or it has a valid pixel format. else { DUMPSURFACE(6, pSurface, NULL); pPixFormat = &pSurface->lpGbl->ddpfSurface; } // At surface creation the surface has not been patched. pPrivateData->dwFlags &= ~P2_ISPATCHED; if (pSurface->ddsCaps.dwCaps & DDSCAPS_TEXTURE) { // If the user has chosen the normal mechanism, then patch the surface. if (pSurface->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) { DBG_DD((6," Remembering to patch this surface")); pPrivateData->dwFlags |= P2_CANPATCH; } else { pPrivateData->dwFlags &= ~P2_CANPATCH; } } // Initially assume no Alpha pPrivateData->SurfaceFormat.bAlpha = FALSE; if (pPixFormat != NULL) { if (pPixFormat->dwFlags & DDPF_FOURCC) { pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID; switch( pPixFormat->dwFourCC ) { case FOURCC_YUV422: DBG_DD((6," Surface is 4:2:2 YUV")); pPrivateData->SurfaceFormat.Format = PERMEDIA_YUV422; pPrivateData->SurfaceFormat.FormatExtension = PERMEDIA_YUV422_EXTENSION; pPrivateData->SurfaceFormat.PixelSize = __PERMEDIA_16BITPIXEL; pPrivateData->SurfaceFormat.FBReadPixel= __PERMEDIA_16BITPIXEL; pPrivateData->SurfaceFormat.PixelMask = 1; pPrivateData->SurfaceFormat.PixelShift= 1; pPrivateData->SurfaceFormat.ColorComponents = 2; pPrivateData->SurfaceFormat.logPixelSize = log2(16); pPrivateData->SurfaceFormat.ColorOrder = 0; break; } } else if (pPixFormat->dwFlags & DDPF_PALETTEINDEXED4) { DBG_DD((6," Surface is 4-Bit Palette")); pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID; pPrivateData->dwFlags |= P2_SURFACE_FORMAT_PALETTE; pPrivateData->SurfaceFormat.Format = PERMEDIA_4BIT_PALETTEINDEX; pPrivateData->SurfaceFormat.FormatExtension = 0; pPrivateData->SurfaceFormat.PixelSize = __PERMEDIA_4BITPIXEL; pPrivateData->SurfaceFormat.FBReadPixel= __PERMEDIA_8BITPIXEL; pPrivateData->SurfaceFormat.PixelMask = 7; pPrivateData->SurfaceFormat.PixelShift= 0; pPrivateData->SurfaceFormat.ColorComponents = 3; pPrivateData->SurfaceFormat.logPixelSize = log2(4); pPrivateData->SurfaceFormat.ColorOrder = 0; pPrivateData->dwFlags &= ~P2_CANPATCH; } else if (pPixFormat->dwFlags & DDPF_PALETTEINDEXED8) { DBG_DD((6," Surface is 8-Bit Palette")); pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID; pPrivateData->dwFlags |= P2_SURFACE_FORMAT_PALETTE; pPrivateData->SurfaceFormat.Format = PERMEDIA_8BIT_PALETTEINDEX; pPrivateData->SurfaceFormat.FormatExtension = 0; pPrivateData->SurfaceFormat.PixelSize = __PERMEDIA_8BITPIXEL; pPrivateData->SurfaceFormat.FBReadPixel= __PERMEDIA_8BITPIXEL; pPrivateData->SurfaceFormat.PixelMask = 3; pPrivateData->SurfaceFormat.PixelShift= 0; pPrivateData->SurfaceFormat.ColorComponents = 3; pPrivateData->SurfaceFormat.Texture16BitMode = 1; pPrivateData->SurfaceFormat.logPixelSize = log2(8); pPrivateData->SurfaceFormat.ColorOrder = 0; } else { if (SetRGBAlphaSurfaceFormat( pPixFormat, &pPrivateData->SurfaceFormat)) { pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID; } else { pPrivateData->dwFlags &= ~P2_SURFACE_FORMAT_VALID; } } } else { ASSERTDD(0, "SetupPrivateSurfaceData:" "Can't get valid surface format pointer"); } } // SetupPrivateSurfaceData //----------------------------------------------------------------------------- // // list all valid pixel formats for Permedia 2 // The P2 supports BGR for all formats, so these formats are not // explicitely listed here, also formats having no alpha channel are permitted // //----------------------------------------------------------------------------- DDPIXELFORMAT Permedia2PixelFormats[] = { // 32 bit RGBa {PERMEDIA_8888_RGB,0,0,32,0x000000ff,0x0000ff00,0x00ff0000,0xff000000}, // 16 bit 5:6:5, RGB {PERMEDIA_565_RGB ,0,0,16,0x0000001f,0x000007e0,0x0000f800,0x00000000}, // 16 bit 4:4:4:4RGBa {PERMEDIA_444_RGB ,0,0,16,0x0000000f,0x000000f0,0x00000f00,0x0000f000}, // 15 bit 5:5:5, RGBa {PERMEDIA_5551_RGB,0,0,16,0x0000001f,0x000003e0,0x00007c00,0x00008000}, // 8 bit 3:3:2 RGB // 332 format is not symmetric. Its listed twice for BGR/RGB case {PERMEDIA_332_RGB ,1,0, 8,0x00000007,0x00000038,0x000000c0,0x00000000}, {PERMEDIA_332_RGB ,0,0, 8,0x00000003,0x0000001c,0x000000e0,0x00000000}, //@@BEGIN_DDKSPLIT // there are no testcases against the 2321 format, so disable it for now // 8 bit 2:3:2:1RGBa // {PERMEDIA_2321_RGB,0,0, 8,0x00000003,0x0000001c,0x00000060,0x00000080}, //@@END_DDKSPLIT // 24 bit RGB {PERMEDIA_888_RGB ,0,0,24,0x000000ff,0x0000ff00,0x00ff0000,0x00000000} }; #define N_PERMEDIA2PIXELFORMATS \ (sizeof(Permedia2PixelFormats)/sizeof(DDPIXELFORMAT)) BOOL ValidRGBAlphaSurfaceformat( DDPIXELFORMAT *pPixFormat, INT *pIndex) { INT i; if (pPixFormat==NULL) return FALSE; if (pPixFormat->dwSize < sizeof(DDPIXELFORMAT)) return FALSE; // The Z-Buffer is a special case. Its basically a 16 bit surface if (pPixFormat->dwFlags & DDPF_ZBUFFER) { if (pIndex!=0) *pIndex=1; return TRUE; } if ((pPixFormat->dwFlags & DDPF_RGB)==0) return FALSE; for ( i=0; idwRBitMask == Permedia2PixelFormats[i].dwRBitMask) && (pPixFormat->dwBBitMask == Permedia2PixelFormats[i].dwBBitMask)) || ((pPixFormat->dwRBitMask == Permedia2PixelFormats[i].dwBBitMask) && (pPixFormat->dwBBitMask == Permedia2PixelFormats[i].dwRBitMask))) && (pPixFormat->dwGBitMask == Permedia2PixelFormats[i].dwGBitMask) && ((pPixFormat->dwRGBAlphaBitMask == Permedia2PixelFormats[i].dwRGBAlphaBitMask) || (pPixFormat->dwRGBAlphaBitMask == 0) || ((pPixFormat->dwFlags&DDPF_ALPHAPIXELS)==0)) && (pPixFormat->dwRGBBitCount== Permedia2PixelFormats[i].dwRGBBitCount) ) { if (pIndex!=NULL) { *pIndex = i; } return TRUE; } } // no pixel format matched... return FALSE; } // ValidRGBAlphaSurfaceformat //----------------------------------------------------------------------------- // // SetRGBAlphaSurfaceFormat // // Store away pixel format information of a surface in the Permedia native // format // //----------------------------------------------------------------------------- BOOL SetRGBAlphaSurfaceFormat(DDPIXELFORMAT *pPixFormat, PERMEDIA_SURFACE *pSurfaceFormat) { INT iFormatIndex; if (!ValidRGBAlphaSurfaceformat( pPixFormat, &iFormatIndex)) { DBG_DD((1,"couldn't set SurfaceFormat")); return FALSE; } DBG_DD((6," Surface RGB Data Valid")); pSurfaceFormat->RedMask = pPixFormat->dwRBitMask; pSurfaceFormat->GreenMask = pPixFormat->dwGBitMask; pSurfaceFormat->BlueMask = pPixFormat->dwBBitMask; pSurfaceFormat->bPreMult = FALSE; if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS) { pSurfaceFormat->AlphaMask = pPixFormat->dwRGBAlphaBitMask; if (pSurfaceFormat->AlphaMask!=0) { pSurfaceFormat->bAlpha = TRUE; } if (pPixFormat->dwFlags & DDPF_ALPHAPREMULT) { pSurfaceFormat->bPreMult = TRUE; } } pSurfaceFormat->ColorOrder = Permedia2PixelFormats[iFormatIndex].dwFlags; // check for the BGR case if (pPixFormat->dwRBitMask == Permedia2PixelFormats[iFormatIndex].dwRBitMask) pSurfaceFormat->ColorOrder = !pSurfaceFormat->ColorOrder; switch (pPixFormat->dwRGBBitCount) { case 24: DBG_DD((6," Surface is 8:8:8 Packed 24 Bit")); pSurfaceFormat->Format = PERMEDIA_888_RGB; pSurfaceFormat->FormatExtension = PERMEDIA_888_RGB_EXTENSION; pSurfaceFormat->PixelSize = __PERMEDIA_24BITPIXEL; pSurfaceFormat->FBReadPixel= __PERMEDIA_24BITPIXEL; pSurfaceFormat->PixelMask = 0; // not valid for 24 bit pSurfaceFormat->PixelShift= 0; pSurfaceFormat->logPixelSize = 0; pSurfaceFormat->ColorComponents = 3; break; case 32: DBG_DD((6," Surface is 8:8:8:8")); pSurfaceFormat->Format = PERMEDIA_8888_RGB; pSurfaceFormat->FormatExtension = PERMEDIA_8888_RGB_EXTENSION; pSurfaceFormat->PixelSize = __PERMEDIA_32BITPIXEL; pSurfaceFormat->FBReadPixel= __PERMEDIA_32BITPIXEL; pSurfaceFormat->PixelMask = 0; pSurfaceFormat->PixelShift= 2; pSurfaceFormat->logPixelSize = log2(32); pSurfaceFormat->ColorComponents = 3; break; case 16: pSurfaceFormat->logPixelSize = log2(16); pSurfaceFormat->PixelSize = __PERMEDIA_16BITPIXEL; pSurfaceFormat->FBReadPixel= __PERMEDIA_16BITPIXEL; pSurfaceFormat->PixelMask = 1; // not valid for 24 bit pSurfaceFormat->PixelShift= 1; switch (Permedia2PixelFormats[iFormatIndex].dwSize) { case PERMEDIA_565_RGB: pSurfaceFormat->Texture16BitMode = 0; pSurfaceFormat->Format = PERMEDIA_565_RGB; pSurfaceFormat->FormatExtension = PERMEDIA_565_RGB_EXTENSION; pSurfaceFormat->ColorComponents = 2; DBG_DD((6," Surface is 5:6:5")); break; case PERMEDIA_444_RGB: pSurfaceFormat->Format = PERMEDIA_444_RGB; pSurfaceFormat->FormatExtension = 0; pSurfaceFormat->ColorComponents = 3; if (pPixFormat->dwRGBAlphaBitMask != 0) { DBG_DD((6," Surface is 4:4:4:4")); } else { DBG_DD((6," Surface is 4:4:4:0")); } break; case PERMEDIA_5551_RGB: pSurfaceFormat->Texture16BitMode = 1; pSurfaceFormat->Format = PERMEDIA_5551_RGB; pSurfaceFormat->FormatExtension = PERMEDIA_5551_RGB_EXTENSION; if (pPixFormat->dwRGBAlphaBitMask != 0) { DBG_DD((6," Surface is 5:5:5:1")); pSurfaceFormat->ColorComponents = 3; } else { DBG_DD((6," Surface is 5:5:5")); pSurfaceFormat->ColorComponents = 2; } break; default: ASSERTDD( FALSE, " 16 bit Surface has unknown format"); break; } break; case 8: pSurfaceFormat->PixelSize = __PERMEDIA_8BITPIXEL; pSurfaceFormat->FBReadPixel= __PERMEDIA_8BITPIXEL; pSurfaceFormat->PixelMask = 3; pSurfaceFormat->PixelShift= 0; pSurfaceFormat->logPixelSize = log2(8); if (Permedia2PixelFormats[iFormatIndex].dwSize==PERMEDIA_2321_RGB) { pSurfaceFormat->Format = PERMEDIA_2321_RGB; pSurfaceFormat->FormatExtension = PERMEDIA_2321_RGB_EXTENSION; pSurfaceFormat->ColorComponents = 3; } else if (Permedia2PixelFormats[iFormatIndex].dwSize==PERMEDIA_332_RGB) { pSurfaceFormat->Format = PERMEDIA_332_RGB; pSurfaceFormat->FormatExtension = PERMEDIA_332_RGB_EXTENSION; pSurfaceFormat->ColorComponents = 2; } else { ASSERTDD( FALSE, " Surface (8bit) has unknown format"); } break; case 0: DBG_DD((6," Surface is palleted")); pSurfaceFormat->Format = PERMEDIA_8BIT_PALETTEINDEX; pSurfaceFormat->FormatExtension = PERMEDIA_8BIT_PALETTEINDEX_EXTENSION; pSurfaceFormat->PixelSize = __PERMEDIA_8BITPIXEL; pSurfaceFormat->FBReadPixel= __PERMEDIA_8BITPIXEL; pSurfaceFormat->PixelMask = 3; // not valid for 24 bit pSurfaceFormat->PixelShift= 0; pSurfaceFormat->logPixelSize = log2(8); pSurfaceFormat->ColorComponents = 0; break; default: ASSERTDD( FALSE, " Surface has unknown pixelformat"); return FALSE; } return TRUE; } // SetRGBAlphaSurfaceFormat