1 /*===========================================================================*/
3 /* Mesa-3.0 DirectX 6 Driver */
7 /* http://www.altsoftware.com/ */
9 /* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
10 /*===========================================================================*/
12 /*===========================================================================*/
13 /* Local function prototypes. */
14 /*===========================================================================*/
15 static void UpdateTexture( PTM_OBJECT pTMObj
, BOOL bVideo
, RECT
*pRect
, UCHAR
*pixels
);
16 static BOOL
LoadTextureInVideo( PMESAD3DHAL pHAL
, PTM_OBJECT pTMObj
);
17 static BOOL
FreeTextureMemory( PMESAD3DHAL pHAL
, PTM_OBJECT pTMObject
);
18 static BOOL
DestroyTextureObject( PMESAD3DHAL pHAL
, PTM_OBJECT pTMObject
);
19 HRESULT CALLBACK
EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt
, LPVOID lpContext
);
20 /*===========================================================================*/
21 /* This function will simply set the top of stack to NULL. I only used it */
22 /* just incase I want to add something later. */
23 /*===========================================================================*/
25 /*===========================================================================*/
26 BOOL
InitTMgrHAL( PMESAD3DHAL pHAL
)
28 DPF(( DBG_FUNC
, "InitTMgrHAL();" ));
30 /* Be clean my friend. */
35 /*===========================================================================*/
36 /* This function will walk the Texture Managers linked list and destroy all */
37 /* surfaces (SYSTEM/VIDEO). The texture objects themselves also will be */
39 /* NOTE: this is per/context. */
40 /*===========================================================================*/
42 /*===========================================================================*/
43 void TermTMgrHAL( PMESAD3DHAL pHAL
)
45 DPF(( DBG_FUNC
, "TermTMgrHAL();" ));
47 if ( pHAL
&& pHAL
->pTMList
)
49 /* Destroy the surface and remove the TMO from the stack. */
50 while( DestroyTextureObject(pHAL
,NULL
) );
52 /* Be clean my friend. */
56 /*===========================================================================*/
57 /* This function is a HACK as I don't know how I can disable a texture with-*/
58 /* out booting it out. Is there know state change? */
59 /*===========================================================================*/
61 /*===========================================================================*/
62 extern "C" void DisableTMgrHAL( PMESAD3DSHARED pShared
)
64 PMESAD3DHAL pHAL
= (PMESAD3DHAL
)pShared
;
66 DPF(( DBG_FUNC
, "DisableTMgrHAL();" ));
68 /* Check too see that we have a valid context. */
69 if ( (pHAL
== NULL
) && (pHAL
->lpD3DDevice
!= NULL
) )
71 DPF(( DBG_TXT_WARN
, "Null HAL/Direct3D Device!" ));
75 // TODO: This is a hack to shut off textures.
76 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
78 /*===========================================================================*/
79 /* This function is the only entry into the TextureManager that Mesa/wgl */
80 /* will see. It uses a dwAction to specify what we are doing. I did this as*/
81 /* depending on the cards resources the action taken can change. */
82 /* When this function is called we will always search the Texture Managers */
83 /* linked list (per context remember) and try and find a structure that has */
84 /* the same dwName. If we have a match we pull it out of the list and put it*/
85 /* at the top of the list (TOL). If we don't find one then we create a struc*/
86 /* and put it a TOL. This TOL idea makes for some caching as we will always */
87 /* destroy Texture Surfaces from the bottom up... */
88 /* All texture objects at this point will create a texture surface in System*/
89 /* memory (SMEM). Then we will copy the Mesa texture into the surface using */
90 /* the 'pixel' struc to get the translation info. So now this means that all*/
91 /* textures that Mesa gives me I will have a Surface with a copy. If Mesa */
92 /* changes the texture the I update the surface in (SMEM). */
93 /* Now we have a texture struc and a Texture Surface in SMEM. At this point*/
94 /* we create another surface on the card (VMEM). Finally we blt from the */
95 /* SMEM to the VMEM and set the texture as current. Why do I need two? First*/
96 /* this solves square textures. If the cards CAPS is square textures only */
97 /* then I change the dimensions of the VMEM surface and the blt solves it for*/
98 /* me. Second it saves me from filling D3D textures over and over if the */
99 /* card needs to be creating and destroying surfaces because of low memory. */
100 /* The surface in SMEM is expected to work always. When a surface has to be*/
101 /* created in VMEM then we put it in a loop that tries to create the surface.*/
102 /* If we create the surface ok then we brake from the loop. If we fail then */
103 /* we will call 'FreeTextureMemory' that will return TRUE/FALSE as to whether*/
104 /* memory was freed. If memory was freed then we can try again. If no memory*/
105 /* was freed then it just can't fit. */
106 /* 'FreeTextureMemory' will find the end of the list and start freeing VMEM */
107 /* (never SMEM) surfaces that are not locked. */
108 /* BIND - when we bind and there is a texture struct with a texture surface */
109 /* in VMEM then we just make it current. If we have a struct and a surface */
110 /* in SMEM but no VMEM surface then we create the surface in VMEM and blt */
111 /* from the SMEM surface. If we have nothing its just like a creation... */
112 /*===========================================================================*/
113 /* RETURN: TRUE, FALSE. */
114 /*===========================================================================*/
115 extern "C" BOOL
CreateTMgrHAL( PMESAD3DSHARED pShared
, DWORD dwName
, int level
, DWORD dwRequestFlags
,
116 RECT
*rectDirty
, DWORD dwWidth
, DWORD dwHeight
, DWORD dwAction
, void *pPixels
)
118 PMESAD3DHAL pHAL
= (PMESAD3DHAL
)pShared
;
121 DDSURFACEDESC2 ddsd2
;
125 DPF(( DBG_FUNC
, "CreateTMgrHAL();" ));
127 DPF(( DBG_TXT_INFO
, "Texture:" ));
128 DPF(( DBG_TXT_INFO
, "cx: %d cy: %d", dwWidth
, dwHeight
));
129 DPF(( DBG_TXT_INFO
, "Rect:" ));
132 DPF(( DBG_TXT_INFO
, "x0: %d y0: %d", rectDirty
->left
, rectDirty
->top
));
133 DPF(( DBG_TXT_INFO
, "x1: %d y1: %d", rectDirty
->right
, rectDirty
->bottom
));
136 /* Check too see that we have a valid context. */
137 if ( (pHAL
== NULL
) && (pHAL
->lpD3DDevice
!= NULL
) )
139 DPF(( DBG_TXT_WARN
, "Null HAL/Direct3D Device!" ));
143 /*=================================================*/
144 /* See if we can find this texture object by name. */
145 /*=================================================*/
146 for( pTMObj
= pHAL
->pTMList
; pTMObj
&& (pTMObj
->dwName
!= dwName
); pTMObj
= pTMObj
->next
);
148 /*=========================================================*/
149 /* Allocate a new object if we didn't get a matching name. */
150 /*=========================================================*/
151 if ( pTMObj
== NULL
)
153 pTMObj
= (PTM_OBJECT
)ALLOC( sizeof(TM_OBJECT
) );
154 if ( pTMObj
== NULL
)
156 memset( pTMObj
, 0, sizeof(TM_OBJECT
) );
158 /* Put the object at the beginning of the list. */
159 pTMObj
->next
= pHAL
->pTMList
;
162 pTemp
= pTMObj
->next
;
163 pTemp
->prev
= pTMObj
;
165 pHAL
->pTMList
= pTMObj
;
169 /*===============================================================*/
170 /* Make some caching happen by pulling this object to the front. */
171 /*===============================================================*/
172 if ( pHAL
->pTMList
!= pTMObj
)
174 /* Pull the object out of the list. */
177 pTemp
= pTMObj
->prev
;
178 pTemp
->next
= pTMObj
->next
;
182 pTemp
= pTMObj
->next
;
183 pTemp
->prev
= pTMObj
->prev
;
189 /* Put the object at the front of the list. */
190 pTMObj
->next
= pHAL
->pTMList
;
193 pTemp
= pTMObj
->next
;
194 pTemp
->prev
= pTMObj
;
196 pHAL
->pTMList
= pTMObj
;
200 /*========================================================*/
201 /* If we are doing BIND and the texture is in VID memory. */
202 /*========================================================*/
203 if ( (dwAction
== TM_ACTION_BIND
) && pTMObj
->lpDDS_Video
)
205 DPF(( DBG_TXT_PROFILE
, "Cache HIT (%d)", dwName
));
207 /* Make this the current texture. */
208 rc
= pHAL
->lpD3DDevice
->SetTexture( 0, pTMObj
->lpD3DTexture2
);
211 DPF(( DBG_TXT_WARN
, "Failed SetTexture() (%s)", ErrorStringD3D(rc
) ));
212 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
219 /*=================================================================*/
220 /* If we are doing BIND and the texture is at least in SYS memory. */
221 /*=================================================================*/
222 if ( (dwAction
== TM_ACTION_BIND
) && pTMObj
->lpDDS_System
)
224 DPF(( DBG_TXT_PROFILE
, "Cache MISS (%d)", dwName
));
226 /* Create the texture on the card. */
227 rc
= LoadTextureInVideo( pHAL
, pTMObj
);
231 /* Make this the current texture. */
232 rc
= pHAL
->lpD3DDevice
->SetTexture( 0, pTMObj
->lpD3DTexture2
);
235 DPF(( DBG_TXT_WARN
, "Failed SetTexture() (%s)", ErrorStringD3D(rc
) ));
236 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
243 /*=========================================================*/
244 /* If we are doing UPDATE then try in VID first for speed. */
245 /*=========================================================*/
246 if ( (dwAction
== TM_ACTION_UPDATE
) && pTMObj
->lpDDS_Video
&&
247 !(pHAL
->D3DHWDevDesc
.dpcTriCaps
.dwTextureCaps
& D3DPTEXTURECAPS_SQUAREONLY
) )
249 DPF(( DBG_TXT_INFO
, "Fix the SubTexture update Leigh!" ));
251 /* Update the texture on the card. */
252 UpdateTexture( pTMObj
, TRUE
, rectDirty
, (UCHAR
*)pPixels
);
254 /* We updated the texture in VID so kill the SYS so we know its dirty. */
255 if ( pTMObj
->lpDDS_System
)
257 DPF(( DBG_TXT_INFO
, "Release texture (SYS)" ));
258 DX_RESTORE( pTMObj
->lpDDS_System
);
259 pTMObj
->lpDDS_System
->Release();
260 pTMObj
->lpDDS_System
= NULL
;
263 /* Make this the current texture. */
264 rc
= pHAL
->lpD3DDevice
->SetTexture( 0, pTMObj
->lpD3DTexture2
);
267 DPF(( DBG_TXT_WARN
, "Failed SetTexture() (%s)", ErrorStringD3D(rc
) ));
268 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
275 /*===========================================================*/
276 /* If we are doing UPDATE then try in SYS still gives speed. */
277 /*===========================================================*/
278 if ( (dwAction
== TM_ACTION_UPDATE
) && pTMObj
->lpDDS_System
)
280 DPF(( DBG_TXT_INFO
, "Fix the SubTexture update Leigh!" ));
282 /* Update the texture in SYS. */
283 UpdateTexture( pTMObj
, FALSE
, NULL
, (UCHAR
*)pPixels
);
285 /* We updated the SYS texture only so now blt to the VID. */
286 rc
= LoadTextureInVideo( pHAL
, pTMObj
);
290 /* Make this the current texture. */
291 rc
= pHAL
->lpD3DDevice
->SetTexture( 0, pTMObj
->lpD3DTexture2
);
294 DPF(( DBG_TXT_WARN
, "Failed SetTexture() (%s)", ErrorStringD3D(rc
) ));
295 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
302 /* At this point we have a valid Texture Manager Object with updated */
303 /* links. We now need to create or update a texture surface that is */
304 /* in system memory. Every texture has a copy in system so we can use*/
305 /* blt to solve problems with textures allocated on the card (square */
306 /* only textures, pixelformats...). */
308 // TODO: make support for update also. Dirty rectangle basicly...
310 /* Kill the interface if we have one no matter what. */
311 if ( pTMObj
->lpD3DTexture2
)
313 DPF(( DBG_TXT_INFO
, "Release Texture2" ));
314 pTMObj
->lpD3DTexture2
->Release();
315 pTMObj
->lpD3DTexture2
= NULL
;
318 /* Kill the system surface. TODO: should try to get the SubIMage going again */
319 if ( pTMObj
->lpDDS_System
)
321 DPF(( DBG_TXT_INFO
, "Release texture (SYS)" ));
322 DX_RESTORE( pTMObj
->lpDDS_System
);
323 pTMObj
->lpDDS_System
->Release();
324 pTMObj
->lpDDS_System
= NULL
;
327 /* Kill the Video surface. TODO: need some reuse system... */
328 if ( pTMObj
->lpDDS_Video
)
330 DPF(( DBG_TXT_INFO
, "Release texture (VID)" ));
331 DX_RESTORE( pTMObj
->lpDDS_Video
);
332 pTMObj
->lpDDS_Video
->Release();
333 pTMObj
->lpDDS_Video
= NULL
;
336 /*================================================================*/
337 /* Translate the the Mesa/OpenGL pixel channels to the D3D flags. */
338 /*================================================================*/
339 switch( dwRequestFlags
)
342 dwRequestFlags
= DDPF_ALPHA
;
343 DPF(( DBG_TXT_WARN
, "GL_ALPHA not supported!)" ));
348 DPF(( DBG_TXT_WARN
, "GL_INTENSITY/GL_LUMINANCE not supported!)" ));
349 dwRequestFlags
= DDPF_LUMINANCE
;
352 case GL_LUMINANCE_ALPHA
:
353 DPF(( DBG_TXT_WARN
, "GL_LUMINANCE_ALPHA not supported!)" ));
354 dwRequestFlags
= DDPF_LUMINANCE
| DDPF_ALPHAPIXELS
;
358 DPF(( DBG_TXT_INFO
, "Texture -> GL_RGB" ));
359 dwRequestFlags
= DDPF_RGB
;
363 DPF(( DBG_TXT_INFO
, "Texture -> GL_RGBA" ));
364 dwRequestFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
368 /*==============================*/
369 /* Populate the texture object. */
370 /*==============================*/
371 pTMObj
->dwName
= dwName
;
372 pTMObj
->lpD3DDevice
= pHAL
->lpD3DDevice
;
373 pTMObj
->dwFlags
= dwRequestFlags
;
374 if ( pHAL
->D3DHWDevDesc
.dpcTriCaps
.dwTextureCaps
& D3DPTEXTURECAPS_SQUAREONLY
)
376 DPF(( DBG_TXT_INFO
, "Convert to Square..." ));
377 pTMObj
->dwSHeight
= dwHeight
;
378 pTMObj
->dwSWidth
= dwWidth
;
380 /* Shrink non-square textures. */
381 pTMObj
->dwVHeight
= (dwHeight
> dwWidth
) ? dwWidth
: dwHeight
;
382 pTMObj
->dwVWidth
= (dwHeight
> dwWidth
) ? dwWidth
: dwHeight
;
386 pTMObj
->dwSHeight
= dwHeight
;
387 pTMObj
->dwSWidth
= dwWidth
;
388 pTMObj
->dwVHeight
= dwHeight
;
389 pTMObj
->dwVWidth
= dwWidth
;
392 /*========================*/
393 /* Create SYSTEM surface. */
394 /*========================*/
396 /* Request a surface in system memory. */
397 memset( &ddsd2
, 0, sizeof(DDSURFACEDESC2
) );
398 ddsd2
.dwSize
= sizeof( DDSURFACEDESC2
);
399 ddsd2
.dwWidth
= pTMObj
->dwSWidth
;
400 ddsd2
.dwHeight
= pTMObj
->dwSHeight
;
401 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
402 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
| DDSCAPS_SYSTEMMEMORY
;
403 ddsd2
.ddsCaps
.dwCaps2
= 0L;
404 memset( &ddsd2
.ddpfPixelFormat
, 0, sizeof(DDPIXELFORMAT
) );
405 ddsd2
.ddpfPixelFormat
.dwSize
= sizeof( DDPIXELFORMAT
);
406 ddsd2
.ddpfPixelFormat
.dwFlags
= dwRequestFlags
;
407 rc
= pHAL
->lpD3DDevice
->EnumTextureFormats( EnumPFHook
, &ddsd2
.ddpfPixelFormat
);
410 RIP( pHAL
, "EnumerTextureFormats (SYSTEM)->", ErrorStringD3D(rc
) );
414 /* Create the surface using the enumerated pixelformat. */
415 rc
= pHAL
->lpDD4
->CreateSurface( &ddsd2
, &pTMObj
->lpDDS_System
, NULL
);
418 RIP( pHAL
, "CreateSurface (TEXTURE/SYSTEM)->", ErrorStringD3D(rc
) );
422 /* Solve the pixel mapping info using the surface pixelformat. */
423 Solve8BitChannelPixelFormat( &ddsd2
.ddpfPixelFormat
, &pTMObj
->pixel
);
425 /*===================================================================*/
426 /* Fill the texture using the PixelInfo structure to do the mapping. */
427 /*===================================================================*/
428 UpdateTexture( pTMObj
, FALSE
, NULL
, (UCHAR
*)pPixels
);
430 /*=======================*/
431 /* Create VIDEO surface. */
432 /*=======================*/
433 rc
= LoadTextureInVideo( pHAL
, pTMObj
);
437 /* Make this the current texture. */
438 rc
= pHAL
->lpD3DDevice
->SetTexture( 0, pTMObj
->lpD3DTexture2
);
441 DPF(( DBG_TXT_WARN
, "Failed SetTexture() (%s)", ErrorStringD3D(rc
) ));
442 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
448 /*===========================================================================*/
449 /* This function will handle the creation and destruction of the texture */
450 /* surfaces on the card. Using the dw'V'Width/Height dimensions the call */
451 /* try and create the texture on the card and keep using FreeTextureMemory */
452 /* until the surace can be created. Once the surface is created we get the */
453 /* interface that we will use to make it the current texture. I didn't put */
454 /* the code to make the texture current in this function as BIND needs to */
455 /* use the same code and this function doesn't always get called when we do a*/
457 /*===========================================================================*/
458 /* RETURN: TRUE, FALSE. */
459 /*===========================================================================*/
460 static BOOL
LoadTextureInVideo( PMESAD3DHAL pHAL
, PTM_OBJECT pTMObj
)
462 DDSURFACEDESC2 ddsd2
;
465 DPF(( DBG_FUNC
, "LoadTextureInVideo();" ));
467 /* Kill the interface if we have one no matter what. */
468 if ( pTMObj
->lpD3DTexture2
)
470 DPF(( DBG_TXT_INFO
, "Release Texture2" ));
471 pTMObj
->lpD3DTexture2
->Release();
472 pTMObj
->lpD3DTexture2
= NULL
;
475 /* Kill the Video surface. TODO: need some reuse system... */
476 if ( pTMObj
->lpDDS_Video
)
478 DPF(( DBG_TXT_INFO
, "Release texture (VID)" ));
479 DX_RESTORE( pTMObj
->lpDDS_Video
);
480 pTMObj
->lpDDS_Video
->Release();
481 pTMObj
->lpDDS_Video
= NULL
;
484 /* Request a surface in Video memory. */
485 memset( &ddsd2
, 0, sizeof(DDSURFACEDESC2
) );
486 ddsd2
.dwSize
= sizeof( DDSURFACEDESC2
);
487 ddsd2
.dwWidth
= pTMObj
->dwVWidth
;
488 ddsd2
.dwHeight
= pTMObj
->dwVHeight
;
489 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
490 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
| DDSCAPS_VIDEOMEMORY
;
491 ddsd2
.ddsCaps
.dwCaps2
= 0L;
492 memset( &ddsd2
.ddpfPixelFormat
, 0, sizeof(DDPIXELFORMAT
) );
493 ddsd2
.ddpfPixelFormat
.dwSize
= sizeof( DDPIXELFORMAT
);
494 ddsd2
.ddpfPixelFormat
.dwFlags
= pTMObj
->dwFlags
;
495 rc
= pHAL
->lpD3DDevice
->EnumTextureFormats( EnumPFHook
, &ddsd2
.ddpfPixelFormat
);
498 RIP( pHAL
, "EnumerTextureFormats ->", ErrorStringD3D(rc
) );
502 /* Make sure we lock so we don't nuke this texture trying to free memory for it. */
503 pTMObj
->bLock
= TRUE
;
505 /* Start a loop that will free all textures until we have created the texture */
506 /* surface or we can't free up more memory. */
509 /* Try to create the texture surface. */
510 rc
= pHAL
->lpDD4
->CreateSurface( &ddsd2
, &pTMObj
->lpDDS_Video
, NULL
);
514 DPF(( DBG_TXT_INFO
, "Free Texture Memory" ));
516 /* DestroyTexture will return TRUE if a surface was freed. */
517 } while( FreeTextureMemory(pHAL
,NULL
) );
519 /* Make sure we unlock or we won't be able to nuke the TMO later. */
520 pTMObj
->bLock
= FALSE
;
522 /* Did we create a valid texture surface? */
525 DPF(( DBG_TXT_WARN
, "Failed to load texture" ));
526 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
530 DX_RESTORE( pTMObj
->lpDDS_System
);
531 DX_RESTORE( pTMObj
->lpDDS_Video
);
533 DPF(( DBG_TXT_INFO
, "Texture Blt SYSTEM -> VID" ));
535 /* Now blt the texture in system memory to the card. */
536 rc
= pTMObj
->lpDDS_Video
->Blt( NULL
, pTMObj
->lpDDS_System
, NULL
, DDBLT_WAIT
, NULL
);
539 RIP( pHAL
, "Blt (TEXTURE) ->", ErrorStringD3D(rc
) );
543 /* Get the Texture interface that is used to render with. */
544 pTMObj
->lpDDS_Video
->QueryInterface( IID_IDirect3DTexture2
, (void **)&pTMObj
->lpD3DTexture2
);
545 if ( pTMObj
->lpD3DTexture2
== NULL
)
547 DPF(( DBG_TXT_WARN
, "Failed QueryTextureInterface" ));
548 pHAL
->lpD3DDevice
->SetTexture( 0, NULL
);
554 /*===========================================================================*/
555 /* If this function gets a texture object struc then we will try and free */
556 /* it. If we get a NULL then we will search from the bottom up and free one */
557 /* VMEM surface. I can only free when the surface isn't locked and of course*/
558 /* there must be a VMEM surface. We never free SMEM surfaces as that isn't */
560 /* TODO: should have a pointer to the bottom of the stack really. */
561 /*===========================================================================*/
563 /*===========================================================================*/
564 static BOOL
FreeTextureMemory( PMESAD3DHAL pHAL
, PTM_OBJECT pTMObject
)
569 DPF(( DBG_FUNC
, "FreeTextureMemory();" ));
570 DPF(( DBG_TXT_WARN
, "FREE TEXTURE!" ));
572 /* Just to be safe. */
573 if ( !pHAL
|| !pHAL
->pTMList
)
575 DPF(( DBG_TXT_WARN
, "FreeTextureMemory() -> NULL pHAL/pHAL->pTMList" ));
579 /* Free the last texture in the list. */
580 if ( pTMObject
== NULL
)
582 DPF(( DBG_TXT_INFO
, "Free Last texture in cache" ));
584 /* Find the last texture object. */
585 for( pCurrent
= pHAL
->pTMList
; pCurrent
->next
; pCurrent
= pCurrent
->next
);
587 /* Now backup until we find a texture on the card. */
588 while( pCurrent
&& (pCurrent
->lpDDS_Video
== NULL
) && (pCurrent
->bLock
== FALSE
) )
589 pCurrent
= pCurrent
->prev
;
591 /* Didn't find anything. */
592 if ( pCurrent
== NULL
)
594 DPF(( DBG_TXT_INFO
, "No texture memory freed" ));
600 /* See if we can find this texture object. */
601 for( pCurrent
= pHAL
->pTMList
; pCurrent
&& (pCurrent
!= pTMObject
); pCurrent
= pCurrent
->next
);
603 /* Didn't find anything. */
604 if ( pCurrent
== NULL
)
606 DPF(( DBG_TXT_INFO
, "Requested texture to be freed NOT FOUND" ));
611 /* Can't free this baby. */
612 if ( pCurrent
->bLock
== TRUE
)
614 DPF(( DBG_TXT_WARN
, "Requested texture LOCKED" ));
618 /* Free the texture memory. */
619 if ( pCurrent
->lpD3DTexture2
)
621 DPF(( DBG_TXT_INFO
, "Release Texture2" ));
622 pCurrent
->lpD3DTexture2
->Release();
623 pCurrent
->lpD3DTexture2
= NULL
;
626 if ( pCurrent
->lpDDS_Video
)
628 DPF(( DBG_TXT_INFO
, "Release texture (VID):" ));
629 DPF(( DBG_TXT_INFO
, "dwName: %d", pCurrent
->dwName
));
630 DPF(( DBG_TXT_INFO
, "cx: %d, cy: %d", pCurrent
->dwVWidth
, pCurrent
->dwVHeight
));
631 pCurrent
->lpDDS_Video
->Release();
632 pCurrent
->lpDDS_Video
= NULL
;
638 /*===========================================================================*/
639 /* This function searches the linked list of texture objects in the supplied*/
640 /* D3Dwrapper structure. If it finds a match it will free it and pull it out*/
641 /* of the linked list. The function works on the bases of a matching pointer*/
642 /* to the object (not matching content). */
643 /* If the function gets passed a NULL then we want to free the last texture */
644 /* object in the list. Used in a loop to destory all. */
645 /*===========================================================================*/
646 /* RETURN: TRUE, FALSE. */
647 /*===========================================================================*/
648 static BOOL
DestroyTextureObject( PMESAD3DHAL pHAL
, PTM_OBJECT pTMObject
)
652 DPF(( DBG_FUNC
, "DestoryTextureObject();" ));
654 /* Just to be safe. */
655 if ( !pHAL
|| !pHAL
->pTMList
)
657 DPF(( DBG_TXT_WARN
, "DestroyTextureObject() -> NULL pHAL/pHAL->pTMList" ));
661 /* Free the last texture in the list. */
662 if ( pTMObject
== NULL
)
664 /* Find the last texture object. */
665 for( pCurrent
= pHAL
->pTMList
; pCurrent
->next
; pCurrent
= pCurrent
->next
);
669 /* See if we can find this texture object. */
670 for( pCurrent
= pHAL
->pTMList
; pCurrent
&& (pCurrent
!= pTMObject
); pCurrent
= pCurrent
->next
);
672 /* Didn't find anything. */
673 if ( pCurrent
== NULL
)
675 DPF(( DBG_TXT_WARN
, "No textures to be freed" ));
680 /* Can't free this baby. */
681 if ( pCurrent
->bLock
== TRUE
)
683 DPF(( DBG_TXT_WARN
, "Requested texture to be freed LOCKED" ));
687 /* Free the texture memory. */
688 if ( pCurrent
->lpD3DTexture2
)
690 DPF(( DBG_TXT_INFO
, "Release Texture2" ));
691 pCurrent
->lpD3DTexture2
->Release();
692 pCurrent
->lpD3DTexture2
= NULL
;
694 if ( pCurrent
->lpDDS_Video
)
696 DPF(( DBG_TXT_INFO
, "Release texture (VID):" ));
697 pCurrent
->lpDDS_Video
->Release();
698 pCurrent
->lpDDS_Video
= NULL
;
700 if ( pCurrent
->lpDDS_System
)
702 DPF(( DBG_TXT_INFO
, "Release texture (SYS):" ));
703 pCurrent
->lpDDS_System
->Release();
704 pCurrent
->lpDDS_System
= NULL
;
707 /* Pull this texture out of the list. */
708 if ( pCurrent
== pHAL
->pTMList
)
709 pHAL
->pTMList
= NULL
;
710 if ( pCurrent
->prev
)
711 (pCurrent
->prev
)->next
= pCurrent
->next
;
712 if ( pCurrent
->next
)
713 (pCurrent
->next
)->prev
= pCurrent
->prev
;
718 /*===========================================================================*/
719 /* This function is the callback function that gets called when we are doing*/
720 /* an enumeration of the texture formats supported by this device. The choice*/
721 /* is made by checking to see if we have a match with the supplied D3D pixel-*/
722 /* format. So the enumeration has to pass a desired D3D PF as the user var. */
723 /*===========================================================================*/
724 /* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
725 /*===========================================================================*/
726 static void UpdateTexture( PTM_OBJECT pTMObj
, BOOL bVideo
, RECT
*pRect
, UCHAR
*pixels
)
728 LPDIRECTDRAWSURFACE4 lpDDS
;
729 DDSURFACEDESC2 ddsd2
;
741 // TODO: Do I need to pass the h/w when its in the object!
742 DPF(( DBG_FUNC
, "UpdateTexture();" ));
744 /* Get the surface pointer we are looking for. */
745 lpDDS
= (bVideo
) ? pTMObj
->lpDDS_Video
: pTMObj
->lpDDS_System
;
747 /*===================================================================*/
748 /* Fill the texture using the PixelInfo structure to do the mapping. */
749 /*===================================================================*/
751 /* Get the surface pointer. */
752 memset( &ddsd2
, 0, sizeof(DDSURFACEDESC2
) );
753 ddsd2
.dwSize
= sizeof(DDSURFACEDESC2
);
754 rc
= lpDDS
->Lock( NULL
, &ddsd2
, DDLOCK_WAIT
, NULL
);
757 RIP( NULL
, "Lock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc
) );
761 /* For now we are only updating the system surface so use its dimensions. */
762 dwWidth
= (bVideo
) ? pTMObj
->dwVWidth
: pTMObj
->dwSWidth
;
763 dwHeight
= (bVideo
) ? pTMObj
->dwVHeight
: pTMObj
->dwSHeight
;
765 /* If we are updating the whole surface then the pDest/pSrc will */
766 /* always be the same. */
769 pDest
= (UCHAR
*)ddsd2
.lpSurface
;
773 /* Fill the texture surface based on the pixelformat flags. */
774 if ( pTMObj
->dwFlags
== (DDPF_RGB
| DDPF_ALPHAPIXELS
) )
776 srcPitch
= dwWidth
* 4;
779 pDest
= ((UCHAR
*)ddsd2
.lpSurface
) + (pRect
->top
* ddsd2
.lPitch
) + (pRect
->left
* pTMObj
->pixel
.cb
);
780 pSrc
= pixels
+ (pRect
->top
* dwWidth
* 4) + (pRect
->left
* 4);
781 dwHeight
= (pRect
->bottom
- pRect
->top
);
782 dwWidth
= (pRect
->right
- pRect
->left
);
785 for( pDestRow
= pDest
, pSrcRow
= pSrc
; dwHeight
> 0; dwHeight
--, pDestRow
+= ddsd2
.lPitch
, pSrcRow
+= srcPitch
)
787 for( dwCol
= 0, pDest
= pDestRow
, pSrc
= pSrcRow
; dwCol
< dwWidth
; dwCol
++ )
789 dwColor
= ( ((DWORD
)(*(pSrc
) * pTMObj
->pixel
.rScale
)) << pTMObj
->pixel
.rShift
);
790 dwColor
|= ( ((DWORD
)(*(pSrc
+1) * pTMObj
->pixel
.gScale
)) << pTMObj
->pixel
.gShift
);
791 dwColor
|= ( ((DWORD
)(*(pSrc
+2) * pTMObj
->pixel
.bScale
)) << pTMObj
->pixel
.bShift
);
792 if ( pTMObj
->pixel
.aScale
== -1.0 )
793 dwColor
|= ( (*(pSrc
+3) & 0x80) ? (1 << pTMObj
->pixel
.aShift
) : 0 );
795 dwColor
|= ( ((DWORD
)(*(pSrc
+3) * pTMObj
->pixel
.aScale
)) << pTMObj
->pixel
.aShift
);
796 memcpy( pDest
, &dwColor
, pTMObj
->pixel
.cb
);
797 pDest
+= pTMObj
->pixel
.cb
;
802 else if ( pTMObj
->dwFlags
== DDPF_RGB
)
804 srcPitch
= dwWidth
* 3;
807 pDest
= ((UCHAR
*)ddsd2
.lpSurface
) + (pRect
->top
* ddsd2
.lPitch
) + (pRect
->left
* pTMObj
->pixel
.cb
);
808 pSrc
= pixels
+ (pRect
->top
* dwWidth
* 3) + (pRect
->left
* 3);
809 dwHeight
= (pRect
->bottom
- pRect
->top
);
810 dwWidth
= (pRect
->right
- pRect
->left
);
813 for( pDestRow
= pDest
, pSrcRow
= pSrc
; dwHeight
> 0; dwHeight
--, pDestRow
+= ddsd2
.lPitch
, pSrcRow
+= srcPitch
)
815 for( dwCol
= 0, pDest
= pDestRow
, pSrc
= pSrcRow
; dwCol
< dwWidth
; dwCol
++ )
817 dwColor
= ( ((DWORD
)(*(pSrc
) * pTMObj
->pixel
.rScale
)) << pTMObj
->pixel
.rShift
);
818 dwColor
|= ( ((DWORD
)(*(pSrc
+1) * pTMObj
->pixel
.gScale
)) << pTMObj
->pixel
.gShift
);
819 dwColor
|= ( ((DWORD
)(*(pSrc
+2) * pTMObj
->pixel
.bScale
)) << pTMObj
->pixel
.bShift
);
820 memcpy( pDest
, &dwColor
, pTMObj
->pixel
.cb
);
821 pDest
+= pTMObj
->pixel
.cb
;
826 else if ( pTMObj
->dwFlags
== (DDPF_LUMINANCE
| DDPF_ALPHAPIXELS
) )
828 srcPitch
= dwWidth
* 2;
831 pDest
= ((UCHAR
*)ddsd2
.lpSurface
) + (pRect
->top
* ddsd2
.lPitch
) + (pRect
->left
* pTMObj
->pixel
.cb
);
832 pSrc
= pixels
+ (pRect
->top
* dwWidth
* 2) + (pRect
->left
* 2);
833 dwHeight
= (pRect
->bottom
- pRect
->top
);
834 dwWidth
= (pRect
->right
- pRect
->left
);
837 for( pDestRow
= pDest
, pSrcRow
= pSrc
; dwHeight
> 0; dwHeight
--, pDestRow
+= ddsd2
.lPitch
, pSrcRow
+= srcPitch
)
839 for( dwCol
= 0, pDest
= pDestRow
, pSrc
= pSrcRow
; dwCol
< dwWidth
; dwCol
++ )
841 dwColor
= ( ((DWORD
)(*(pSrc
) * pTMObj
->pixel
.rScale
)) << pTMObj
->pixel
.rShift
);
842 if ( pTMObj
->pixel
.aScale
== -1.0 )
843 dwColor
|= ( (*(pSrc
+1) & 0x80) ? (1 << pTMObj
->pixel
.aShift
) : 0 );
845 dwColor
|= ( ((DWORD
)(*(pSrc
+1) * pTMObj
->pixel
.aScale
)) << pTMObj
->pixel
.aShift
);
846 memcpy( pDest
, &dwColor
, pTMObj
->pixel
.cb
);
847 pDest
+= pTMObj
->pixel
.cb
;
852 else if ( pTMObj
->dwFlags
== DDPF_LUMINANCE
)
857 pDest
= ((UCHAR
*)ddsd2
.lpSurface
) + (pRect
->top
* ddsd2
.lPitch
) + (pRect
->left
* pTMObj
->pixel
.cb
);
858 pSrc
= pixels
+ (pRect
->top
* dwWidth
) + (pRect
->left
);
859 dwHeight
= (pRect
->bottom
- pRect
->top
);
860 dwWidth
= (pRect
->right
- pRect
->left
);
863 for( pDestRow
= pDest
, pSrcRow
= pSrc
; dwHeight
> 0; dwHeight
--, pDestRow
+= ddsd2
.lPitch
, pSrcRow
+= srcPitch
)
865 for( dwCol
= 0, pDest
= pDestRow
, pSrc
= pSrcRow
; dwCol
< dwWidth
; dwCol
++ )
867 dwColor
= ( ((DWORD
)(*pSrc
* pTMObj
->pixel
.rScale
)) << pTMObj
->pixel
.rShift
);
868 memcpy( pDest
, &dwColor
, pTMObj
->pixel
.cb
);
869 pDest
+= pTMObj
->pixel
.cb
;
874 else if ( pTMObj
->dwFlags
== DDPF_ALPHAPIXELS
)
879 pDest
= ((UCHAR
*)ddsd2
.lpSurface
) + (pRect
->top
* ddsd2
.lPitch
) + (pRect
->left
* pTMObj
->pixel
.cb
);
880 pSrc
= pixels
+ (pRect
->top
* dwWidth
) + (pRect
->left
);
881 dwHeight
= (pRect
->bottom
- pRect
->top
);
882 dwWidth
= (pRect
->right
- pRect
->left
);
885 for( pDestRow
= pDest
, pSrcRow
= pSrc
; dwHeight
> 0; dwHeight
--, pDestRow
+= ddsd2
.lPitch
, pSrcRow
+= srcPitch
)
887 for( dwCol
= 0, pDest
= pDestRow
, pSrc
= pSrcRow
; dwCol
< dwWidth
; dwCol
++ )
889 if ( pTMObj
->pixel
.aScale
== -1.0 )
890 dwColor
= ( (*pSrc
& 0x80) ? (1 << pTMObj
->pixel
.aShift
) : 0 );
892 dwColor
= ( ((DWORD
)(*pSrc
* pTMObj
->pixel
.aScale
)) << pTMObj
->pixel
.aShift
);
893 memcpy( pDest
, &dwColor
, pTMObj
->pixel
.cb
);
894 pDest
+= pTMObj
->pixel
.cb
;
900 /* Unlock the surface. */
901 rc
= lpDDS
->Unlock( NULL
);
904 RIP( NULL
, "Unlock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc
) );
907 /*===========================================================================*/
908 /* This function is the callback function that gets called when we are doing*/
909 /* an enumeration of the texture formats supported by this device. The choice*/
910 /* is made by checking to see if we have a match with the supplied D3D pixel-*/
911 /* format. So the enumeration has to pass a desired D3D PF as the user var. */
912 /*===========================================================================*/
913 /* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
914 /*===========================================================================*/
915 HRESULT CALLBACK
EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt
, LPVOID lpContext
)
917 LPDDPIXELFORMAT lpDDPixFmtRequest
= (LPDDPIXELFORMAT
)lpContext
;
920 DPF(( DBG_FUNC
, "EnumPFHook();" ));
922 if ( lpDDPixFmt
->dwFlags
== lpDDPixFmtRequest
->dwFlags
)
924 /* Are we looking for an alpha channel? */
925 if ( lpDDPixFmtRequest
->dwFlags
& DDPF_ALPHAPIXELS
)
927 /* Try for something that has more then 1bits of Alpha. */
928 Solve8BitChannelPixelFormat( lpDDPixFmt
, &pixel
);
929 if ( pixel
.aScale
== -1.0 )
931 /* Save this format no matter what as its a match of sorts. */
932 memcpy( lpDDPixFmtRequest
, lpDDPixFmt
, sizeof(DDPIXELFORMAT
) );
933 return D3DENUMRET_OK
;
937 /* Save this format as its a good match. */
938 memcpy( lpDDPixFmtRequest
, lpDDPixFmt
, sizeof(DDPIXELFORMAT
) );
940 /* We are happy at this point so lets leave. */
941 return D3DENUMRET_CANCEL
;
944 return D3DENUMRET_OK
;