123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947 |
- /*===========================================================================*/
- /* */
- /* 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;
- }
-
-
|