radeon: enable vertex splitting for IBs
[mesa.git] / src / mesa / drivers / d3d / D3DTextureMgr.cpp
index ac9d2621fcc62c9bdd36919ff3e9423773d972eb..a6600cab02c4caffdc2b9d513561e3aacf2d1895 100644 (file)
-/*===========================================================================*/\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
+/*===========================================================================*/
+/*                                                                           */
+/* 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;
+}
+
+