-/*===========================================================================*/\r
-/* */\r
-/* Mesa-3.0 DirectX 6 Driver */\r
-/* */\r
-/* By Leigh McRae */\r
-/* */\r
-/* http://www.altsoftware.com/ */\r
-/* */\r
-/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */\r
-/*===========================================================================*/\r
-#include "D3DHAL.h"\r
-/*===========================================================================*/\r
-/* Local function prototypes. */\r
-/*===========================================================================*/\r
-static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels );\r
-static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj );\r
-static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );\r
-static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );\r
-HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext );\r
-/*===========================================================================*/\r
-/* This function will simply set the top of stack to NULL. I only used it */\r
-/* just incase I want to add something later. */\r
-/*===========================================================================*/\r
-/* RETURN: TRUE. */\r
-/*===========================================================================*/\r
-BOOL InitTMgrHAL( PMESAD3DHAL pHAL )\r
-{\r
- DPF(( DBG_FUNC, "InitTMgrHAL();" ));\r
-\r
- /* Be clean my friend. */\r
- pHAL->pTMList = NULL;\r
-\r
- return TRUE;\r
-}\r
-/*===========================================================================*/\r
-/* This function will walk the Texture Managers linked list and destroy all */\r
-/* surfaces (SYSTEM/VIDEO). The texture objects themselves also will be */\r
-/* freed. */\r
-/* NOTE: this is per/context. */\r
-/*===========================================================================*/\r
-/* RETURN: */\r
-/*===========================================================================*/\r
-void TermTMgrHAL( PMESAD3DHAL pHAL )\r
-{\r
- DPF(( DBG_FUNC, "TermTMgrHAL();" ));\r
-\r
- if ( pHAL && pHAL->pTMList )\r
- {\r
- /* Destroy the surface and remove the TMO from the stack. */\r
- while( DestroyTextureObject(pHAL,NULL) );\r
-\r
- /* Be clean my friend. */\r
- pHAL->pTMList = NULL;\r
- }\r
-}\r
-/*===========================================================================*/\r
-/* This function is a HACK as I don't know how I can disable a texture with-*/\r
-/* out booting it out. Is there know state change? */\r
-/*===========================================================================*/\r
-/* RETURN: */\r
-/*===========================================================================*/\r
-extern "C" void DisableTMgrHAL( PMESAD3DSHARED pShared )\r
-{\r
- PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;\r
-\r
- DPF(( DBG_FUNC, "DisableTMgrHAL();" ));\r
-\r
- /* Check too see that we have a valid context. */\r
- if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) ) \r
- {\r
- DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));\r
- return;\r
- }\r
-\r
- // TODO: This is a hack to shut off textures.\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
-}\r
-/*===========================================================================*/\r
-/* This function is the only entry into the TextureManager that Mesa/wgl */\r
-/* will see. It uses a dwAction to specify what we are doing. I did this as*/\r
-/* depending on the cards resources the action taken can change. */\r
-/* When this function is called we will always search the Texture Managers */\r
-/* linked list (per context remember) and try and find a structure that has */\r
-/* the same dwName. If we have a match we pull it out of the list and put it*/\r
-/* at the top of the list (TOL). If we don't find one then we create a struc*/\r
-/* and put it a TOL. This TOL idea makes for some caching as we will always */\r
-/* destroy Texture Surfaces from the bottom up... */\r
-/* All texture objects at this point will create a texture surface in System*/\r
-/* memory (SMEM). Then we will copy the Mesa texture into the surface using */\r
-/* the 'pixel' struc to get the translation info. So now this means that all*/\r
-/* textures that Mesa gives me I will have a Surface with a copy. If Mesa */\r
-/* changes the texture the I update the surface in (SMEM). */\r
-/* Now we have a texture struc and a Texture Surface in SMEM. At this point*/\r
-/* we create another surface on the card (VMEM). Finally we blt from the */\r
-/* SMEM to the VMEM and set the texture as current. Why do I need two? First*/\r
-/* this solves square textures. If the cards CAPS is square textures only */\r
-/* then I change the dimensions of the VMEM surface and the blt solves it for*/\r
-/* me. Second it saves me from filling D3D textures over and over if the */\r
-/* card needs to be creating and destroying surfaces because of low memory. */\r
-/* The surface in SMEM is expected to work always. When a surface has to be*/\r
-/* created in VMEM then we put it in a loop that tries to create the surface.*/\r
-/* If we create the surface ok then we brake from the loop. If we fail then */\r
-/* we will call 'FreeTextureMemory' that will return TRUE/FALSE as to whether*/\r
-/* memory was freed. If memory was freed then we can try again. If no memory*/\r
-/* was freed then it just can't fit. */\r
-/* 'FreeTextureMemory' will find the end of the list and start freeing VMEM */\r
-/* (never SMEM) surfaces that are not locked. */\r
-/* BIND - when we bind and there is a texture struct with a texture surface */\r
-/* in VMEM then we just make it current. If we have a struct and a surface */\r
-/* in SMEM but no VMEM surface then we create the surface in VMEM and blt */\r
-/* from the SMEM surface. If we have nothing its just like a creation... */\r
-/*===========================================================================*/\r
-/* RETURN: TRUE, FALSE. */\r
-/*===========================================================================*/\r
-extern "C" BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags, \r
- RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels )\r
-{\r
- PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;\r
- PTM_OBJECT pTMObj,\r
- pTemp;\r
- DDSURFACEDESC2 ddsd2;\r
- HRESULT rc;\r
-\r
-\r
- DPF(( DBG_FUNC, "CreateTMgrHAL();" ));\r
-\r
- DPF(( DBG_TXT_INFO, "Texture:" ));\r
- DPF(( DBG_TXT_INFO, "cx: %d cy: %d", dwWidth, dwHeight ));\r
- DPF(( DBG_TXT_INFO, "Rect:" ));\r
- if ( rectDirty )\r
- {\r
- DPF(( DBG_TXT_INFO, "x0: %d y0: %d", rectDirty->left, rectDirty->top ));\r
- DPF(( DBG_TXT_INFO, "x1: %d y1: %d", rectDirty->right, rectDirty->bottom ));\r
- }\r
-\r
- /* Check too see that we have a valid context. */\r
- if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) ) \r
- {\r
- DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));\r
- return FALSE;\r
- }\r
-\r
- /*=================================================*/\r
- /* See if we can find this texture object by name. */\r
- /*=================================================*/\r
- for( pTMObj = pHAL->pTMList; pTMObj && (pTMObj->dwName != dwName); pTMObj = pTMObj->next );\r
-\r
- /*=========================================================*/\r
- /* Allocate a new object if we didn't get a matching name. */\r
- /*=========================================================*/\r
- if ( pTMObj == NULL )\r
- {\r
- pTMObj = (PTM_OBJECT)ALLOC( sizeof(TM_OBJECT) );\r
- if ( pTMObj == NULL )\r
- return FALSE;\r
- memset( pTMObj, 0, sizeof(TM_OBJECT) );\r
-\r
- /* Put the object at the beginning of the list. */\r
- pTMObj->next = pHAL->pTMList;\r
- if ( pTMObj->next )\r
- {\r
- pTemp = pTMObj->next;\r
- pTemp->prev = pTMObj;\r
- }\r
- pHAL->pTMList = pTMObj;\r
- }\r
- else\r
- {\r
- /*===============================================================*/\r
- /* Make some caching happen by pulling this object to the front. */ \r
- /*===============================================================*/\r
- if ( pHAL->pTMList != pTMObj )\r
- {\r
- /* Pull the object out of the list. */\r
- if ( pTMObj->prev )\r
- {\r
- pTemp = pTMObj->prev;\r
- pTemp->next = pTMObj->next;\r
- }\r
- if ( pTMObj->next )\r
- {\r
- pTemp = pTMObj->next;\r
- pTemp->prev = pTMObj->prev;\r
- }\r
-\r
- pTMObj->prev = NULL;\r
- pTMObj->next = NULL;\r
-\r
- /* Put the object at the front of the list. */\r
- pTMObj->next = pHAL->pTMList;\r
- if ( pTMObj->next )\r
- {\r
- pTemp = pTMObj->next;\r
- pTemp->prev = pTMObj;\r
- }\r
- pHAL->pTMList = pTMObj;\r
- }\r
- }\r
-\r
- /*========================================================*/\r
- /* If we are doing BIND and the texture is in VID memory. */\r
- /*========================================================*/\r
- if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_Video )\r
- {\r
- DPF(( DBG_TXT_PROFILE, "Cache HIT (%d)", dwName ));\r
- \r
- /* Make this the current texture. */\r
- rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );\r
- if ( FAILED(rc) )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- } \r
-\r
- return TRUE;\r
- } \r
-\r
- /*=================================================================*/\r
- /* If we are doing BIND and the texture is at least in SYS memory. */\r
- /*=================================================================*/\r
- if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_System )\r
- {\r
- DPF(( DBG_TXT_PROFILE, "Cache MISS (%d)", dwName ));\r
-\r
- /* Create the texture on the card. */\r
- rc = LoadTextureInVideo( pHAL, pTMObj );\r
- if ( rc == FALSE )\r
- return FALSE;\r
- \r
- /* Make this the current texture. */\r
- rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );\r
- if ( FAILED(rc) )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- } \r
-\r
- return TRUE;\r
- } \r
-\r
- /*=========================================================*/\r
- /* If we are doing UPDATE then try in VID first for speed. */\r
- /*=========================================================*/\r
- if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_Video &&\r
- !(pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) )\r
- {\r
- DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));\r
-\r
- /* Update the texture on the card. */\r
- UpdateTexture( pTMObj, TRUE, rectDirty, (UCHAR *)pPixels );\r
-\r
- /* We updated the texture in VID so kill the SYS so we know its dirty. */\r
- if ( pTMObj->lpDDS_System )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));\r
- DX_RESTORE( pTMObj->lpDDS_System );\r
- pTMObj->lpDDS_System->Release();\r
- pTMObj->lpDDS_System = NULL;\r
- }\r
-\r
- /* Make this the current texture. */\r
- rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );\r
- if ( FAILED(rc) )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- } \r
-\r
- return TRUE;\r
- }\r
-\r
- /*===========================================================*/\r
- /* If we are doing UPDATE then try in SYS still gives speed. */\r
- /*===========================================================*/\r
- if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_System )\r
- {\r
- DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));\r
-\r
- /* Update the texture in SYS. */\r
- UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );\r
-\r
- /* We updated the SYS texture only so now blt to the VID. */\r
- rc = LoadTextureInVideo( pHAL, pTMObj );\r
- if ( rc == FALSE )\r
- return FALSE;\r
-\r
- /* Make this the current texture. */\r
- rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );\r
- if ( FAILED(rc) )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- } \r
-\r
- return TRUE;\r
- }\r
-\r
- /* At this point we have a valid Texture Manager Object with updated */\r
- /* links. We now need to create or update a texture surface that is */\r
- /* in system memory. Every texture has a copy in system so we can use*/\r
- /* blt to solve problems with textures allocated on the card (square */\r
- /* only textures, pixelformats...). */\r
- \r
- // TODO: make support for update also. Dirty rectangle basicly...\r
-\r
- /* Kill the interface if we have one no matter what. */\r
- if ( pTMObj->lpD3DTexture2 )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release Texture2" ));\r
- pTMObj->lpD3DTexture2->Release();\r
- pTMObj->lpD3DTexture2 = NULL;\r
- } \r
-\r
- /* Kill the system surface. TODO: should try to get the SubIMage going again */\r
- if ( pTMObj->lpDDS_System )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));\r
- DX_RESTORE( pTMObj->lpDDS_System );\r
- pTMObj->lpDDS_System->Release();\r
- pTMObj->lpDDS_System = NULL;\r
- }\r
-\r
- /* Kill the Video surface. TODO: need some reuse system... */\r
- if ( pTMObj->lpDDS_Video )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (VID)" ));\r
- DX_RESTORE( pTMObj->lpDDS_Video );\r
- pTMObj->lpDDS_Video->Release();\r
- pTMObj->lpDDS_Video = NULL;\r
- }\r
-\r
- /*================================================================*/\r
- /* Translate the the Mesa/OpenGL pixel channels to the D3D flags. */\r
- /*================================================================*/\r
- switch( dwRequestFlags )\r
- {\r
- case GL_ALPHA:\r
- dwRequestFlags = DDPF_ALPHA; \r
- DPF(( DBG_TXT_WARN, "GL_ALPHA not supported!)" ));\r
- return FALSE;\r
- \r
- case GL_INTENSITY:\r
- case GL_LUMINANCE:\r
- DPF(( DBG_TXT_WARN, "GL_INTENSITY/GL_LUMINANCE not supported!)" ));\r
- dwRequestFlags = DDPF_LUMINANCE; \r
- return FALSE;\r
- \r
- case GL_LUMINANCE_ALPHA:\r
- DPF(( DBG_TXT_WARN, "GL_LUMINANCE_ALPHA not supported!)" ));\r
- dwRequestFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS; \r
- return FALSE;\r
- \r
- case GL_RGB:\r
- DPF(( DBG_TXT_INFO, "Texture -> GL_RGB" ));\r
- dwRequestFlags = DDPF_RGB; \r
- break;\r
-\r
- case GL_RGBA:\r
- DPF(( DBG_TXT_INFO, "Texture -> GL_RGBA" ));\r
- dwRequestFlags = DDPF_RGB | DDPF_ALPHAPIXELS; \r
- break;\r
- }\r
-\r
- /*==============================*/\r
- /* Populate the texture object. */\r
- /*==============================*/\r
- pTMObj->dwName = dwName;\r
- pTMObj->lpD3DDevice = pHAL->lpD3DDevice;\r
- pTMObj->dwFlags = dwRequestFlags;\r
- if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )\r
- {\r
- DPF(( DBG_TXT_INFO, "Convert to Square..." ));\r
- pTMObj->dwSHeight = dwHeight;\r
- pTMObj->dwSWidth = dwWidth;\r
-\r
- /* Shrink non-square textures. */\r
- pTMObj->dwVHeight = (dwHeight > dwWidth) ? dwWidth : dwHeight;\r
- pTMObj->dwVWidth = (dwHeight > dwWidth) ? dwWidth : dwHeight;\r
- }\r
- else\r
- {\r
- pTMObj->dwSHeight = dwHeight;\r
- pTMObj->dwSWidth = dwWidth;\r
- pTMObj->dwVHeight = dwHeight;\r
- pTMObj->dwVWidth = dwWidth;\r
- }\r
-\r
- /*========================*/ \r
- /* Create SYSTEM surface. */\r
- /*========================*/\r
-\r
- /* Request a surface in system memory. */\r
- memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );\r
- ddsd2.dwSize = sizeof( DDSURFACEDESC2 );\r
- ddsd2.dwWidth = pTMObj->dwSWidth;\r
- ddsd2.dwHeight = pTMObj->dwSHeight;\r
- ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;\r
- ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;\r
- ddsd2.ddsCaps.dwCaps2 = 0L;\r
- memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );\r
- ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );\r
- ddsd2.ddpfPixelFormat.dwFlags = dwRequestFlags;\r
- rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );\r
- if ( FAILED(rc) )\r
- {\r
- RIP( pHAL, "EnumerTextureFormats (SYSTEM)->", ErrorStringD3D(rc) );\r
- return FALSE;\r
- }\r
-\r
- /* Create the surface using the enumerated pixelformat. */\r
- rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_System, NULL );\r
- if ( FAILED(rc) )\r
- {\r
- RIP( pHAL, "CreateSurface (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );\r
- return FALSE;\r
- }\r
-\r
- /* Solve the pixel mapping info using the surface pixelformat. */\r
- Solve8BitChannelPixelFormat( &ddsd2.ddpfPixelFormat, &pTMObj->pixel );\r
-\r
- /*===================================================================*/\r
- /* Fill the texture using the PixelInfo structure to do the mapping. */\r
- /*===================================================================*/\r
- UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );\r
-\r
- /*=======================*/\r
- /* Create VIDEO surface. */\r
- /*=======================*/\r
- rc = LoadTextureInVideo( pHAL, pTMObj );\r
- if ( rc == FALSE )\r
- return FALSE;\r
-\r
- /* Make this the current texture. */\r
- rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );\r
- if ( FAILED(rc) )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-/*===========================================================================*/\r
-/* This function will handle the creation and destruction of the texture */\r
-/* surfaces on the card. Using the dw'V'Width/Height dimensions the call */\r
-/* try and create the texture on the card and keep using FreeTextureMemory */\r
-/* until the surace can be created. Once the surface is created we get the */\r
-/* interface that we will use to make it the current texture. I didn't put */\r
-/* the code to make the texture current in this function as BIND needs to */\r
-/* use the same code and this function doesn't always get called when we do a*/\r
-/* bind. */\r
-/*===========================================================================*/\r
-/* RETURN: TRUE, FALSE. */\r
-/*===========================================================================*/\r
-static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj )\r
-{\r
- DDSURFACEDESC2 ddsd2;\r
- HRESULT rc;\r
-\r
- DPF(( DBG_FUNC, "LoadTextureInVideo();" ));\r
-\r
- /* Kill the interface if we have one no matter what. */\r
- if ( pTMObj->lpD3DTexture2 )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release Texture2" ));\r
- pTMObj->lpD3DTexture2->Release();\r
- pTMObj->lpD3DTexture2 = NULL;\r
- } \r
-\r
- /* Kill the Video surface. TODO: need some reuse system... */\r
- if ( pTMObj->lpDDS_Video )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (VID)" ));\r
- DX_RESTORE( pTMObj->lpDDS_Video );\r
- pTMObj->lpDDS_Video->Release();\r
- pTMObj->lpDDS_Video = NULL;\r
- }\r
-\r
- /* Request a surface in Video memory. */\r
- memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );\r
- ddsd2.dwSize = sizeof( DDSURFACEDESC2 );\r
- ddsd2.dwWidth = pTMObj->dwVWidth;\r
- ddsd2.dwHeight = pTMObj->dwVHeight;\r
- ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;\r
- ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;\r
- ddsd2.ddsCaps.dwCaps2 = 0L;\r
- memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );\r
- ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );\r
- ddsd2.ddpfPixelFormat.dwFlags = pTMObj->dwFlags;\r
- rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );\r
- if ( FAILED(rc) )\r
- {\r
- RIP( pHAL, "EnumerTextureFormats ->", ErrorStringD3D(rc) );\r
- return FALSE;\r
- }\r
-\r
- /* Make sure we lock so we don't nuke this texture trying to free memory for it. */\r
- pTMObj->bLock = TRUE;\r
-\r
- /* Start a loop that will free all textures until we have created the texture */\r
- /* surface or we can't free up more memory. */\r
- do\r
- {\r
- /* Try to create the texture surface. */\r
- rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_Video, NULL );\r
- if ( !FAILED(rc) )\r
- break;\r
-\r
- DPF(( DBG_TXT_INFO, "Free Texture Memory" ));\r
-\r
- /* DestroyTexture will return TRUE if a surface was freed. */\r
- } while( FreeTextureMemory(pHAL,NULL) );\r
-\r
- /* Make sure we unlock or we won't be able to nuke the TMO later. */\r
- pTMObj->bLock = FALSE;\r
-\r
- /* Did we create a valid texture surface? */\r
- if ( FAILED(rc) )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed to load texture" ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- }\r
-\r
- DX_RESTORE( pTMObj->lpDDS_System );\r
- DX_RESTORE( pTMObj->lpDDS_Video );\r
-\r
- DPF(( DBG_TXT_INFO, "Texture Blt SYSTEM -> VID" ));\r
-\r
- /* Now blt the texture in system memory to the card. */\r
- rc = pTMObj->lpDDS_Video->Blt( NULL, pTMObj->lpDDS_System, NULL, DDBLT_WAIT, NULL );\r
- if ( FAILED(rc) )\r
- {\r
- RIP( pHAL, "Blt (TEXTURE) ->", ErrorStringD3D(rc) );\r
- return FALSE;\r
- }\r
-\r
- /* Get the Texture interface that is used to render with. */\r
- pTMObj->lpDDS_Video->QueryInterface( IID_IDirect3DTexture2, (void **)&pTMObj->lpD3DTexture2 ); \r
- if ( pTMObj->lpD3DTexture2 == NULL )\r
- {\r
- DPF(( DBG_TXT_WARN, "Failed QueryTextureInterface" ));\r
- pHAL->lpD3DDevice->SetTexture( 0, NULL );\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-/*===========================================================================*/\r
-/* If this function gets a texture object struc then we will try and free */\r
-/* it. If we get a NULL then we will search from the bottom up and free one */\r
-/* VMEM surface. I can only free when the surface isn't locked and of course*/\r
-/* there must be a VMEM surface. We never free SMEM surfaces as that isn't */\r
-/* the point. */\r
-/* TODO: should have a pointer to the bottom of the stack really. */\r
-/*===========================================================================*/\r
-/* RETURN: */\r
-/*===========================================================================*/\r
-static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )\r
-{\r
- PTM_OBJECT pCurrent;\r
- BOOL bFreed = FALSE;\r
-\r
- DPF(( DBG_FUNC, "FreeTextureMemory();" ));\r
- DPF(( DBG_TXT_WARN, "FREE TEXTURE!" ));\r
-\r
- /* Just to be safe. */\r
- if ( !pHAL || !pHAL->pTMList )\r
- {\r
- DPF(( DBG_TXT_WARN, "FreeTextureMemory() -> NULL pHAL/pHAL->pTMList" ));\r
- return FALSE;\r
- }\r
-\r
- /* Free the last texture in the list. */\r
- if ( pTMObject == NULL )\r
- {\r
- DPF(( DBG_TXT_INFO, "Free Last texture in cache" ));\r
-\r
- /* Find the last texture object. */\r
- for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );\r
-\r
- /* Now backup until we find a texture on the card. */\r
- while( pCurrent && (pCurrent->lpDDS_Video == NULL) && (pCurrent->bLock == FALSE) )\r
- pCurrent = pCurrent->prev;\r
-\r
- /* Didn't find anything. */\r
- if ( pCurrent == NULL )\r
- {\r
- DPF(( DBG_TXT_INFO, "No texture memory freed" ));\r
- return FALSE;\r
- }\r
- }\r
- else\r
- {\r
- /* See if we can find this texture object. */\r
- for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );\r
-\r
- /* Didn't find anything. */\r
- if ( pCurrent == NULL )\r
- {\r
- DPF(( DBG_TXT_INFO, "Requested texture to be freed NOT FOUND" ));\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Can't free this baby. */\r
- if ( pCurrent->bLock == TRUE )\r
- {\r
- DPF(( DBG_TXT_WARN, "Requested texture LOCKED" ));\r
- return FALSE;\r
- }\r
-\r
- /* Free the texture memory. */\r
- if ( pCurrent->lpD3DTexture2 )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release Texture2" ));\r
- pCurrent->lpD3DTexture2->Release();\r
- pCurrent->lpD3DTexture2 = NULL;\r
- bFreed = TRUE;\r
- }\r
- if ( pCurrent->lpDDS_Video )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (VID):" ));\r
- DPF(( DBG_TXT_INFO, "dwName: %d", pCurrent->dwName ));\r
- DPF(( DBG_TXT_INFO, "cx: %d, cy: %d", pCurrent->dwVWidth, pCurrent->dwVHeight ));\r
- pCurrent->lpDDS_Video->Release();\r
- pCurrent->lpDDS_Video = NULL;\r
- bFreed = TRUE;\r
- }\r
- \r
- return bFreed;\r
-}\r
-/*===========================================================================*/\r
-/* This function searches the linked list of texture objects in the supplied*/\r
-/* D3Dwrapper structure. If it finds a match it will free it and pull it out*/\r
-/* of the linked list. The function works on the bases of a matching pointer*/\r
-/* to the object (not matching content). */\r
-/* If the function gets passed a NULL then we want to free the last texture */\r
-/* object in the list. Used in a loop to destory all. */\r
-/*===========================================================================*/\r
-/* RETURN: TRUE, FALSE. */\r
-/*===========================================================================*/\r
-static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )\r
-{\r
- PTM_OBJECT pCurrent;\r
-\r
- DPF(( DBG_FUNC, "DestoryTextureObject();" ));\r
-\r
- /* Just to be safe. */\r
- if ( !pHAL || !pHAL->pTMList )\r
- {\r
- DPF(( DBG_TXT_WARN, "DestroyTextureObject() -> NULL pHAL/pHAL->pTMList" ));\r
- return FALSE;\r
- }\r
-\r
- /* Free the last texture in the list. */\r
- if ( pTMObject == NULL )\r
- {\r
- /* Find the last texture object. */\r
- for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );\r
- }\r
- else\r
- {\r
- /* See if we can find this texture object. */\r
- for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );\r
-\r
- /* Didn't find anything. */\r
- if ( pCurrent == NULL )\r
- {\r
- DPF(( DBG_TXT_WARN, "No textures to be freed" ));\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Can't free this baby. */\r
- if ( pCurrent->bLock == TRUE )\r
- {\r
- DPF(( DBG_TXT_WARN, "Requested texture to be freed LOCKED" ));\r
- return FALSE;\r
- }\r
-\r
- /* Free the texture memory. */\r
- if ( pCurrent->lpD3DTexture2 )\r
- { \r
- DPF(( DBG_TXT_INFO, "Release Texture2" ));\r
- pCurrent->lpD3DTexture2->Release();\r
- pCurrent->lpD3DTexture2 = NULL;\r
- }\r
- if ( pCurrent->lpDDS_Video )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (VID):" ));\r
- pCurrent->lpDDS_Video->Release();\r
- pCurrent->lpDDS_Video = NULL;\r
- }\r
- if ( pCurrent->lpDDS_System )\r
- {\r
- DPF(( DBG_TXT_INFO, "Release texture (SYS):" ));\r
- pCurrent->lpDDS_System->Release();\r
- pCurrent->lpDDS_System = NULL;\r
- }\r
-\r
- /* Pull this texture out of the list. */\r
- if ( pCurrent == pHAL->pTMList )\r
- pHAL->pTMList = NULL;\r
- if ( pCurrent->prev )\r
- (pCurrent->prev)->next = pCurrent->next;\r
- if ( pCurrent->next )\r
- (pCurrent->next)->prev = pCurrent->prev;\r
- FREE( pCurrent );\r
-\r
- return TRUE;\r
-}\r
-/*===========================================================================*/\r
-/* This function is the callback function that gets called when we are doing*/\r
-/* an enumeration of the texture formats supported by this device. The choice*/\r
-/* is made by checking to see if we have a match with the supplied D3D pixel-*/\r
-/* format. So the enumeration has to pass a desired D3D PF as the user var. */\r
-/*===========================================================================*/\r
-/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */\r
-/*===========================================================================*/\r
-static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels )\r
-{\r
- LPDIRECTDRAWSURFACE4 lpDDS;\r
- DDSURFACEDESC2 ddsd2;\r
- DWORD srcPitch,\r
- dwHeight, \r
- dwWidth,\r
- dwCol,\r
- dwColor;\r
- UCHAR *pSrc,\r
- *pSrcRow,\r
- *pDest,\r
- *pDestRow;\r
- int rc;\r
-\r
- // TODO: Do I need to pass the h/w when its in the object!\r
- DPF(( DBG_FUNC, "UpdateTexture();" ));\r
-\r
- /* Get the surface pointer we are looking for. */\r
- lpDDS = (bVideo) ? pTMObj->lpDDS_Video : pTMObj->lpDDS_System;\r
-\r
- /*===================================================================*/\r
- /* Fill the texture using the PixelInfo structure to do the mapping. */\r
- /*===================================================================*/\r
- \r
- /* Get the surface pointer. */\r
- memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );\r
- ddsd2.dwSize = sizeof(DDSURFACEDESC2);\r
- rc = lpDDS->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );\r
- if ( FAILED(rc) )\r
- {\r
- RIP( NULL, "Lock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );\r
- return;\r
- }\r
-\r
- /* For now we are only updating the system surface so use its dimensions. */\r
- dwWidth = (bVideo) ? pTMObj->dwVWidth : pTMObj->dwSWidth;\r
- dwHeight = (bVideo) ? pTMObj->dwVHeight : pTMObj->dwSHeight;\r
-\r
- /* If we are updating the whole surface then the pDest/pSrc will */\r
- /* always be the same. */\r
- if ( pRect == NULL )\r
- {\r
- pDest = (UCHAR *)ddsd2.lpSurface;\r
- pSrc = pixels;\r
- }\r
-\r
- /* Fill the texture surface based on the pixelformat flags. */\r
- if ( pTMObj->dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS) )\r
- {\r
- srcPitch = dwWidth * 4;\r
- if ( pRect )\r
- {\r
- pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);\r
- pSrc = pixels + (pRect->top * dwWidth * 4) + (pRect->left * 4);\r
- dwHeight = (pRect->bottom - pRect->top);\r
- dwWidth = (pRect->right - pRect->left);\r
- }\r
-\r
- for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )\r
- {\r
- for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )\r
- {\r
- dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );\r
- dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );\r
- dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );\r
- if ( pTMObj->pixel.aScale == -1.0 )\r
- dwColor |= ( (*(pSrc+3) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );\r
- else\r
- dwColor |= ( ((DWORD)(*(pSrc+3) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );\r
- memcpy( pDest, &dwColor, pTMObj->pixel.cb );\r
- pDest += pTMObj->pixel.cb;\r
- pSrc += 4;\r
- }\r
- }\r
- }\r
- else if ( pTMObj->dwFlags == DDPF_RGB )\r
- {\r
- srcPitch = dwWidth * 3;\r
- if ( pRect )\r
- {\r
- pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);\r
- pSrc = pixels + (pRect->top * dwWidth * 3) + (pRect->left * 3);\r
- dwHeight = (pRect->bottom - pRect->top);\r
- dwWidth = (pRect->right - pRect->left);\r
- }\r
-\r
- for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )\r
- {\r
- for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )\r
- {\r
- dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );\r
- dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );\r
- dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );\r
- memcpy( pDest, &dwColor, pTMObj->pixel.cb );\r
- pDest += pTMObj->pixel.cb;\r
- pSrc += 3;\r
- }\r
- }\r
- }\r
- else if ( pTMObj->dwFlags == (DDPF_LUMINANCE | DDPF_ALPHAPIXELS) )\r
- {\r
- srcPitch = dwWidth * 2;\r
- if ( pRect )\r
- {\r
- pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);\r
- pSrc = pixels + (pRect->top * dwWidth * 2) + (pRect->left * 2);\r
- dwHeight = (pRect->bottom - pRect->top);\r
- dwWidth = (pRect->right - pRect->left);\r
- }\r
-\r
- for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )\r
- {\r
- for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )\r
- {\r
- dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );\r
- if ( pTMObj->pixel.aScale == -1.0 )\r
- dwColor |= ( (*(pSrc+1) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );\r
- else\r
- dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );\r
- memcpy( pDest, &dwColor, pTMObj->pixel.cb );\r
- pDest += pTMObj->pixel.cb;\r
- pSrc += 2;\r
- }\r
- }\r
- }\r
- else if ( pTMObj->dwFlags == DDPF_LUMINANCE )\r
- {\r
- srcPitch = dwWidth;\r
- if ( pRect )\r
- {\r
- pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);\r
- pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);\r
- dwHeight = (pRect->bottom - pRect->top);\r
- dwWidth = (pRect->right - pRect->left);\r
- }\r
-\r
- for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )\r
- {\r
- for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )\r
- {\r
- dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );\r
- memcpy( pDest, &dwColor, pTMObj->pixel.cb );\r
- pDest += pTMObj->pixel.cb;\r
- pSrc++;\r
- }\r
- }\r
- }\r
- else if ( pTMObj->dwFlags == DDPF_ALPHAPIXELS )\r
- {\r
- srcPitch = dwWidth;\r
- if ( pRect )\r
- {\r
- pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);\r
- pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);\r
- dwHeight = (pRect->bottom - pRect->top);\r
- dwWidth = (pRect->right - pRect->left);\r
- }\r
-\r
- for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )\r
- {\r
- for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )\r
- {\r
- if ( pTMObj->pixel.aScale == -1.0 )\r
- dwColor = ( (*pSrc & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );\r
- else\r
- dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );\r
- memcpy( pDest, &dwColor, pTMObj->pixel.cb );\r
- pDest += pTMObj->pixel.cb;\r
- pSrc++;\r
- }\r
- }\r
- }\r
-\r
- /* Unlock the surface. */\r
- rc = lpDDS->Unlock( NULL );\r
- if ( FAILED(rc) )\r
- {\r
- RIP( NULL, "Unlock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );\r
- }\r
-}\r
-/*===========================================================================*/\r
-/* This function is the callback function that gets called when we are doing*/\r
-/* an enumeration of the texture formats supported by this device. The choice*/\r
-/* is made by checking to see if we have a match with the supplied D3D pixel-*/\r
-/* format. So the enumeration has to pass a desired D3D PF as the user var. */\r
-/*===========================================================================*/\r
-/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */\r
-/*===========================================================================*/\r
-HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )\r
-{\r
- LPDDPIXELFORMAT lpDDPixFmtRequest = (LPDDPIXELFORMAT)lpContext;\r
- PIXELINFO pixel;\r
-\r
- DPF(( DBG_FUNC, "EnumPFHook();" ));\r
-\r
- if ( lpDDPixFmt->dwFlags == lpDDPixFmtRequest->dwFlags )\r
- {\r
- /* Are we looking for an alpha channel? */\r
- if ( lpDDPixFmtRequest->dwFlags & DDPF_ALPHAPIXELS )\r
- {\r
- /* Try for something that has more then 1bits of Alpha. */\r
- Solve8BitChannelPixelFormat( lpDDPixFmt, &pixel );\r
- if ( pixel.aScale == -1.0 )\r
- {\r
- /* Save this format no matter what as its a match of sorts. */\r
- memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );\r
- return D3DENUMRET_OK;\r
- }\r
- }\r
-\r
- /* Save this format as its a good match. */\r
- memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );\r
-\r
- /* We are happy at this point so lets leave. */\r
- return D3DENUMRET_CANCEL;\r
- }\r
- \r
- return D3DENUMRET_OK;\r
-}\r
-\r
-\r
-\1a
\ No newline at end of file
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local function prototypes. */
+/*===========================================================================*/
+static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels );
+static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj );
+static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
+static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
+HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext );
+/*===========================================================================*/
+/* This function will simply set the top of stack to NULL. I only used it */
+/* just incase I want to add something later. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL InitTMgrHAL( PMESAD3DHAL pHAL )
+{
+ DPF(( DBG_FUNC, "InitTMgrHAL();" ));
+
+ /* Be clean my friend. */
+ pHAL->pTMList = NULL;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will walk the Texture Managers linked list and destroy all */
+/* surfaces (SYSTEM/VIDEO). The texture objects themselves also will be */
+/* freed. */
+/* NOTE: this is per/context. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void TermTMgrHAL( PMESAD3DHAL pHAL )
+{
+ DPF(( DBG_FUNC, "TermTMgrHAL();" ));
+
+ if ( pHAL && pHAL->pTMList )
+ {
+ /* Destroy the surface and remove the TMO from the stack. */
+ while( DestroyTextureObject(pHAL,NULL) );
+
+ /* Be clean my friend. */
+ pHAL->pTMList = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function is a HACK as I don't know how I can disable a texture with-*/
+/* out booting it out. Is there know state change? */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void DisableTMgrHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+ DPF(( DBG_FUNC, "DisableTMgrHAL();" ));
+
+ /* Check too see that we have a valid context. */
+ if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) )
+ {
+ DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
+ return;
+ }
+
+ // TODO: This is a hack to shut off textures.
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+}
+/*===========================================================================*/
+/* This function is the only entry into the TextureManager that Mesa/wgl */
+/* will see. It uses a dwAction to specify what we are doing. I did this as*/
+/* depending on the cards resources the action taken can change. */
+/* When this function is called we will always search the Texture Managers */
+/* linked list (per context remember) and try and find a structure that has */
+/* the same dwName. If we have a match we pull it out of the list and put it*/
+/* at the top of the list (TOL). If we don't find one then we create a struc*/
+/* and put it a TOL. This TOL idea makes for some caching as we will always */
+/* destroy Texture Surfaces from the bottom up... */
+/* All texture objects at this point will create a texture surface in System*/
+/* memory (SMEM). Then we will copy the Mesa texture into the surface using */
+/* the 'pixel' struc to get the translation info. So now this means that all*/
+/* textures that Mesa gives me I will have a Surface with a copy. If Mesa */
+/* changes the texture the I update the surface in (SMEM). */
+/* Now we have a texture struc and a Texture Surface in SMEM. At this point*/
+/* we create another surface on the card (VMEM). Finally we blt from the */
+/* SMEM to the VMEM and set the texture as current. Why do I need two? First*/
+/* this solves square textures. If the cards CAPS is square textures only */
+/* then I change the dimensions of the VMEM surface and the blt solves it for*/
+/* me. Second it saves me from filling D3D textures over and over if the */
+/* card needs to be creating and destroying surfaces because of low memory. */
+/* The surface in SMEM is expected to work always. When a surface has to be*/
+/* created in VMEM then we put it in a loop that tries to create the surface.*/
+/* If we create the surface ok then we brake from the loop. If we fail then */
+/* we will call 'FreeTextureMemory' that will return TRUE/FALSE as to whether*/
+/* memory was freed. If memory was freed then we can try again. If no memory*/
+/* was freed then it just can't fit. */
+/* 'FreeTextureMemory' will find the end of the list and start freeing VMEM */
+/* (never SMEM) surfaces that are not locked. */
+/* BIND - when we bind and there is a texture struct with a texture surface */
+/* in VMEM then we just make it current. If we have a struct and a surface */
+/* in SMEM but no VMEM surface then we create the surface in VMEM and blt */
+/* from the SMEM surface. If we have nothing its just like a creation... */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags,
+ RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ PTM_OBJECT pTMObj,
+ pTemp;
+ DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+
+ DPF(( DBG_FUNC, "CreateTMgrHAL();" ));
+
+ DPF(( DBG_TXT_INFO, "Texture:" ));
+ DPF(( DBG_TXT_INFO, "cx: %d cy: %d", dwWidth, dwHeight ));
+ DPF(( DBG_TXT_INFO, "Rect:" ));
+ if ( rectDirty )
+ {
+ DPF(( DBG_TXT_INFO, "x0: %d y0: %d", rectDirty->left, rectDirty->top ));
+ DPF(( DBG_TXT_INFO, "x1: %d y1: %d", rectDirty->right, rectDirty->bottom ));
+ }
+
+ /* Check too see that we have a valid context. */
+ if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) )
+ {
+ DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
+ return FALSE;
+ }
+
+ /*=================================================*/
+ /* See if we can find this texture object by name. */
+ /*=================================================*/
+ for( pTMObj = pHAL->pTMList; pTMObj && (pTMObj->dwName != dwName); pTMObj = pTMObj->next );
+
+ /*=========================================================*/
+ /* Allocate a new object if we didn't get a matching name. */
+ /*=========================================================*/
+ if ( pTMObj == NULL )
+ {
+ pTMObj = (PTM_OBJECT)ALLOC( sizeof(TM_OBJECT) );
+ if ( pTMObj == NULL )
+ return FALSE;
+ memset( pTMObj, 0, sizeof(TM_OBJECT) );
+
+ /* Put the object at the beginning of the list. */
+ pTMObj->next = pHAL->pTMList;
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj;
+ }
+ pHAL->pTMList = pTMObj;
+ }
+ else
+ {
+ /*===============================================================*/
+ /* Make some caching happen by pulling this object to the front. */
+ /*===============================================================*/
+ if ( pHAL->pTMList != pTMObj )
+ {
+ /* Pull the object out of the list. */
+ if ( pTMObj->prev )
+ {
+ pTemp = pTMObj->prev;
+ pTemp->next = pTMObj->next;
+ }
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj->prev;
+ }
+
+ pTMObj->prev = NULL;
+ pTMObj->next = NULL;
+
+ /* Put the object at the front of the list. */
+ pTMObj->next = pHAL->pTMList;
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj;
+ }
+ pHAL->pTMList = pTMObj;
+ }
+ }
+
+ /*========================================================*/
+ /* If we are doing BIND and the texture is in VID memory. */
+ /*========================================================*/
+ if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_PROFILE, "Cache HIT (%d)", dwName ));
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*=================================================================*/
+ /* If we are doing BIND and the texture is at least in SYS memory. */
+ /*=================================================================*/
+ if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_PROFILE, "Cache MISS (%d)", dwName ));
+
+ /* Create the texture on the card. */
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*=========================================================*/
+ /* If we are doing UPDATE then try in VID first for speed. */
+ /*=========================================================*/
+ if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_Video &&
+ !(pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) )
+ {
+ DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
+
+ /* Update the texture on the card. */
+ UpdateTexture( pTMObj, TRUE, rectDirty, (UCHAR *)pPixels );
+
+ /* We updated the texture in VID so kill the SYS so we know its dirty. */
+ if ( pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
+ DX_RESTORE( pTMObj->lpDDS_System );
+ pTMObj->lpDDS_System->Release();
+ pTMObj->lpDDS_System = NULL;
+ }
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*===========================================================*/
+ /* If we are doing UPDATE then try in SYS still gives speed. */
+ /*===========================================================*/
+ if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
+
+ /* Update the texture in SYS. */
+ UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
+
+ /* We updated the SYS texture only so now blt to the VID. */
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /* At this point we have a valid Texture Manager Object with updated */
+ /* links. We now need to create or update a texture surface that is */
+ /* in system memory. Every texture has a copy in system so we can use*/
+ /* blt to solve problems with textures allocated on the card (square */
+ /* only textures, pixelformats...). */
+
+ // TODO: make support for update also. Dirty rectangle basicly...
+
+ /* Kill the interface if we have one no matter what. */
+ if ( pTMObj->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pTMObj->lpD3DTexture2->Release();
+ pTMObj->lpD3DTexture2 = NULL;
+ }
+
+ /* Kill the system surface. TODO: should try to get the SubIMage going again */
+ if ( pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
+ DX_RESTORE( pTMObj->lpDDS_System );
+ pTMObj->lpDDS_System->Release();
+ pTMObj->lpDDS_System = NULL;
+ }
+
+ /* Kill the Video surface. TODO: need some reuse system... */
+ if ( pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
+ DX_RESTORE( pTMObj->lpDDS_Video );
+ pTMObj->lpDDS_Video->Release();
+ pTMObj->lpDDS_Video = NULL;
+ }
+
+ /*================================================================*/
+ /* Translate the the Mesa/OpenGL pixel channels to the D3D flags. */
+ /*================================================================*/
+ switch( dwRequestFlags )
+ {
+ case GL_ALPHA:
+ dwRequestFlags = DDPF_ALPHA;
+ DPF(( DBG_TXT_WARN, "GL_ALPHA not supported!)" ));
+ return FALSE;
+
+ case GL_INTENSITY:
+ case GL_LUMINANCE:
+ DPF(( DBG_TXT_WARN, "GL_INTENSITY/GL_LUMINANCE not supported!)" ));
+ dwRequestFlags = DDPF_LUMINANCE;
+ return FALSE;
+
+ case GL_LUMINANCE_ALPHA:
+ DPF(( DBG_TXT_WARN, "GL_LUMINANCE_ALPHA not supported!)" ));
+ dwRequestFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS;
+ return FALSE;
+
+ case GL_RGB:
+ DPF(( DBG_TXT_INFO, "Texture -> GL_RGB" ));
+ dwRequestFlags = DDPF_RGB;
+ break;
+
+ case GL_RGBA:
+ DPF(( DBG_TXT_INFO, "Texture -> GL_RGBA" ));
+ dwRequestFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
+ break;
+ }
+
+ /*==============================*/
+ /* Populate the texture object. */
+ /*==============================*/
+ pTMObj->dwName = dwName;
+ pTMObj->lpD3DDevice = pHAL->lpD3DDevice;
+ pTMObj->dwFlags = dwRequestFlags;
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
+ {
+ DPF(( DBG_TXT_INFO, "Convert to Square..." ));
+ pTMObj->dwSHeight = dwHeight;
+ pTMObj->dwSWidth = dwWidth;
+
+ /* Shrink non-square textures. */
+ pTMObj->dwVHeight = (dwHeight > dwWidth) ? dwWidth : dwHeight;
+ pTMObj->dwVWidth = (dwHeight > dwWidth) ? dwWidth : dwHeight;
+ }
+ else
+ {
+ pTMObj->dwSHeight = dwHeight;
+ pTMObj->dwSWidth = dwWidth;
+ pTMObj->dwVHeight = dwHeight;
+ pTMObj->dwVWidth = dwWidth;
+ }
+
+ /*========================*/
+ /* Create SYSTEM surface. */
+ /*========================*/
+
+ /* Request a surface in system memory. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ ddsd2.dwWidth = pTMObj->dwSWidth;
+ ddsd2.dwHeight = pTMObj->dwSHeight;
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
+ ddsd2.ddsCaps.dwCaps2 = 0L;
+ memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = dwRequestFlags;
+ rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumerTextureFormats (SYSTEM)->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the surface using the enumerated pixelformat. */
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_System, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "CreateSurface (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Solve the pixel mapping info using the surface pixelformat. */
+ Solve8BitChannelPixelFormat( &ddsd2.ddpfPixelFormat, &pTMObj->pixel );
+
+ /*===================================================================*/
+ /* Fill the texture using the PixelInfo structure to do the mapping. */
+ /*===================================================================*/
+ UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
+
+ /*=======================*/
+ /* Create VIDEO surface. */
+ /*=======================*/
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will handle the creation and destruction of the texture */
+/* surfaces on the card. Using the dw'V'Width/Height dimensions the call */
+/* try and create the texture on the card and keep using FreeTextureMemory */
+/* until the surace can be created. Once the surface is created we get the */
+/* interface that we will use to make it the current texture. I didn't put */
+/* the code to make the texture current in this function as BIND needs to */
+/* use the same code and this function doesn't always get called when we do a*/
+/* bind. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj )
+{
+ DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "LoadTextureInVideo();" ));
+
+ /* Kill the interface if we have one no matter what. */
+ if ( pTMObj->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pTMObj->lpD3DTexture2->Release();
+ pTMObj->lpD3DTexture2 = NULL;
+ }
+
+ /* Kill the Video surface. TODO: need some reuse system... */
+ if ( pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
+ DX_RESTORE( pTMObj->lpDDS_Video );
+ pTMObj->lpDDS_Video->Release();
+ pTMObj->lpDDS_Video = NULL;
+ }
+
+ /* Request a surface in Video memory. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ ddsd2.dwWidth = pTMObj->dwVWidth;
+ ddsd2.dwHeight = pTMObj->dwVHeight;
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
+ ddsd2.ddsCaps.dwCaps2 = 0L;
+ memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = pTMObj->dwFlags;
+ rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumerTextureFormats ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Make sure we lock so we don't nuke this texture trying to free memory for it. */
+ pTMObj->bLock = TRUE;
+
+ /* Start a loop that will free all textures until we have created the texture */
+ /* surface or we can't free up more memory. */
+ do
+ {
+ /* Try to create the texture surface. */
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_Video, NULL );
+ if ( !FAILED(rc) )
+ break;
+
+ DPF(( DBG_TXT_INFO, "Free Texture Memory" ));
+
+ /* DestroyTexture will return TRUE if a surface was freed. */
+ } while( FreeTextureMemory(pHAL,NULL) );
+
+ /* Make sure we unlock or we won't be able to nuke the TMO later. */
+ pTMObj->bLock = FALSE;
+
+ /* Did we create a valid texture surface? */
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed to load texture" ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ DX_RESTORE( pTMObj->lpDDS_System );
+ DX_RESTORE( pTMObj->lpDDS_Video );
+
+ DPF(( DBG_TXT_INFO, "Texture Blt SYSTEM -> VID" ));
+
+ /* Now blt the texture in system memory to the card. */
+ rc = pTMObj->lpDDS_Video->Blt( NULL, pTMObj->lpDDS_System, NULL, DDBLT_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Blt (TEXTURE) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the Texture interface that is used to render with. */
+ pTMObj->lpDDS_Video->QueryInterface( IID_IDirect3DTexture2, (void **)&pTMObj->lpD3DTexture2 );
+ if ( pTMObj->lpD3DTexture2 == NULL )
+ {
+ DPF(( DBG_TXT_WARN, "Failed QueryTextureInterface" ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* If this function gets a texture object struc then we will try and free */
+/* it. If we get a NULL then we will search from the bottom up and free one */
+/* VMEM surface. I can only free when the surface isn't locked and of course*/
+/* there must be a VMEM surface. We never free SMEM surfaces as that isn't */
+/* the point. */
+/* TODO: should have a pointer to the bottom of the stack really. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
+{
+ PTM_OBJECT pCurrent;
+ BOOL bFreed = FALSE;
+
+ DPF(( DBG_FUNC, "FreeTextureMemory();" ));
+ DPF(( DBG_TXT_WARN, "FREE TEXTURE!" ));
+
+ /* Just to be safe. */
+ if ( !pHAL || !pHAL->pTMList )
+ {
+ DPF(( DBG_TXT_WARN, "FreeTextureMemory() -> NULL pHAL/pHAL->pTMList" ));
+ return FALSE;
+ }
+
+ /* Free the last texture in the list. */
+ if ( pTMObject == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "Free Last texture in cache" ));
+
+ /* Find the last texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
+
+ /* Now backup until we find a texture on the card. */
+ while( pCurrent && (pCurrent->lpDDS_Video == NULL) && (pCurrent->bLock == FALSE) )
+ pCurrent = pCurrent->prev;
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "No texture memory freed" ));
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* See if we can find this texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "Requested texture to be freed NOT FOUND" ));
+ return FALSE;
+ }
+ }
+
+ /* Can't free this baby. */
+ if ( pCurrent->bLock == TRUE )
+ {
+ DPF(( DBG_TXT_WARN, "Requested texture LOCKED" ));
+ return FALSE;
+ }
+
+ /* Free the texture memory. */
+ if ( pCurrent->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pCurrent->lpD3DTexture2->Release();
+ pCurrent->lpD3DTexture2 = NULL;
+ bFreed = TRUE;
+ }
+ if ( pCurrent->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
+ DPF(( DBG_TXT_INFO, "dwName: %d", pCurrent->dwName ));
+ DPF(( DBG_TXT_INFO, "cx: %d, cy: %d", pCurrent->dwVWidth, pCurrent->dwVHeight ));
+ pCurrent->lpDDS_Video->Release();
+ pCurrent->lpDDS_Video = NULL;
+ bFreed = TRUE;
+ }
+
+ return bFreed;
+}
+/*===========================================================================*/
+/* This function searches the linked list of texture objects in the supplied*/
+/* D3Dwrapper structure. If it finds a match it will free it and pull it out*/
+/* of the linked list. The function works on the bases of a matching pointer*/
+/* to the object (not matching content). */
+/* If the function gets passed a NULL then we want to free the last texture */
+/* object in the list. Used in a loop to destory all. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
+{
+ PTM_OBJECT pCurrent;
+
+ DPF(( DBG_FUNC, "DestoryTextureObject();" ));
+
+ /* Just to be safe. */
+ if ( !pHAL || !pHAL->pTMList )
+ {
+ DPF(( DBG_TXT_WARN, "DestroyTextureObject() -> NULL pHAL/pHAL->pTMList" ));
+ return FALSE;
+ }
+
+ /* Free the last texture in the list. */
+ if ( pTMObject == NULL )
+ {
+ /* Find the last texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
+ }
+ else
+ {
+ /* See if we can find this texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_WARN, "No textures to be freed" ));
+ return FALSE;
+ }
+ }
+
+ /* Can't free this baby. */
+ if ( pCurrent->bLock == TRUE )
+ {
+ DPF(( DBG_TXT_WARN, "Requested texture to be freed LOCKED" ));
+ return FALSE;
+ }
+
+ /* Free the texture memory. */
+ if ( pCurrent->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pCurrent->lpD3DTexture2->Release();
+ pCurrent->lpD3DTexture2 = NULL;
+ }
+ if ( pCurrent->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
+ pCurrent->lpDDS_Video->Release();
+ pCurrent->lpDDS_Video = NULL;
+ }
+ if ( pCurrent->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS):" ));
+ pCurrent->lpDDS_System->Release();
+ pCurrent->lpDDS_System = NULL;
+ }
+
+ /* Pull this texture out of the list. */
+ if ( pCurrent == pHAL->pTMList )
+ pHAL->pTMList = NULL;
+ if ( pCurrent->prev )
+ (pCurrent->prev)->next = pCurrent->next;
+ if ( pCurrent->next )
+ (pCurrent->next)->prev = pCurrent->prev;
+ FREE( pCurrent );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function is the callback function that gets called when we are doing*/
+/* an enumeration of the texture formats supported by this device. The choice*/
+/* is made by checking to see if we have a match with the supplied D3D pixel-*/
+/* format. So the enumeration has to pass a desired D3D PF as the user var. */
+/*===========================================================================*/
+/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
+/*===========================================================================*/
+static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels )
+{
+ LPDIRECTDRAWSURFACE4 lpDDS;
+ DDSURFACEDESC2 ddsd2;
+ DWORD srcPitch,
+ dwHeight,
+ dwWidth,
+ dwCol,
+ dwColor;
+ UCHAR *pSrc,
+ *pSrcRow,
+ *pDest,
+ *pDestRow;
+ int rc;
+
+ // TODO: Do I need to pass the h/w when its in the object!
+ DPF(( DBG_FUNC, "UpdateTexture();" ));
+
+ /* Get the surface pointer we are looking for. */
+ lpDDS = (bVideo) ? pTMObj->lpDDS_Video : pTMObj->lpDDS_System;
+
+ /*===================================================================*/
+ /* Fill the texture using the PixelInfo structure to do the mapping. */
+ /*===================================================================*/
+
+ /* Get the surface pointer. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+ rc = lpDDS->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( NULL, "Lock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ return;
+ }
+
+ /* For now we are only updating the system surface so use its dimensions. */
+ dwWidth = (bVideo) ? pTMObj->dwVWidth : pTMObj->dwSWidth;
+ dwHeight = (bVideo) ? pTMObj->dwVHeight : pTMObj->dwSHeight;
+
+ /* If we are updating the whole surface then the pDest/pSrc will */
+ /* always be the same. */
+ if ( pRect == NULL )
+ {
+ pDest = (UCHAR *)ddsd2.lpSurface;
+ pSrc = pixels;
+ }
+
+ /* Fill the texture surface based on the pixelformat flags. */
+ if ( pTMObj->dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS) )
+ {
+ srcPitch = dwWidth * 4;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 4) + (pRect->left * 4);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
+ dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor |= ( (*(pSrc+3) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor |= ( ((DWORD)(*(pSrc+3) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 4;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_RGB )
+ {
+ srcPitch = dwWidth * 3;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 3) + (pRect->left * 3);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
+ dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 3;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == (DDPF_LUMINANCE | DDPF_ALPHAPIXELS) )
+ {
+ srcPitch = dwWidth * 2;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 2) + (pRect->left * 2);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor |= ( (*(pSrc+1) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 2;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_LUMINANCE )
+ {
+ srcPitch = dwWidth;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc++;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_ALPHAPIXELS )
+ {
+ srcPitch = dwWidth;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor = ( (*pSrc & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc++;
+ }
+ }
+ }
+
+ /* Unlock the surface. */
+ rc = lpDDS->Unlock( NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( NULL, "Unlock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ }
+}
+/*===========================================================================*/
+/* This function is the callback function that gets called when we are doing*/
+/* an enumeration of the texture formats supported by this device. The choice*/
+/* is made by checking to see if we have a match with the supplied D3D pixel-*/
+/* format. So the enumeration has to pass a desired D3D PF as the user var. */
+/*===========================================================================*/
+/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
+/*===========================================================================*/
+HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )
+{
+ LPDDPIXELFORMAT lpDDPixFmtRequest = (LPDDPIXELFORMAT)lpContext;
+ PIXELINFO pixel;
+
+ DPF(( DBG_FUNC, "EnumPFHook();" ));
+
+ if ( lpDDPixFmt->dwFlags == lpDDPixFmtRequest->dwFlags )
+ {
+ /* Are we looking for an alpha channel? */
+ if ( lpDDPixFmtRequest->dwFlags & DDPF_ALPHAPIXELS )
+ {
+ /* Try for something that has more then 1bits of Alpha. */
+ Solve8BitChannelPixelFormat( lpDDPixFmt, &pixel );
+ if ( pixel.aScale == -1.0 )
+ {
+ /* Save this format no matter what as its a match of sorts. */
+ memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
+ return D3DENUMRET_OK;
+ }
+ }
+
+ /* Save this format as its a good match. */
+ memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
+
+ /* We are happy at this point so lets leave. */
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+