From 60159c1b09c73c19f798035a15d4ef3b434f2fa0 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 28 Feb 2008 16:34:32 +0900 Subject: Convert crlf->lf line endings. Windows/DOS users should enable core.autocrlf from now on: git config --global core.autocrlf true --- src/mesa/drivers/d3d/D3DTextureMgr.cpp | 1894 ++++++++++++++++---------------- 1 file changed, 947 insertions(+), 947 deletions(-) (limited to 'src/mesa/drivers/d3d/D3DTextureMgr.cpp') diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.cpp b/src/mesa/drivers/d3d/D3DTextureMgr.cpp index ac9d2621fc..a6600cab02 100644 --- a/src/mesa/drivers/d3d/D3DTextureMgr.cpp +++ b/src/mesa/drivers/d3d/D3DTextureMgr.cpp @@ -1,947 +1,947 @@ -/*===========================================================================*/ -/* */ -/* 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; -} - - +/*===========================================================================*/ +/* */ +/* 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; +} + + -- cgit v1.2.3