1 #include "pch.h"
2 #include "texture.h"
3
4 #include "d3dframe.h"
5 extern CD3DFramework* g_pFramework;
6
7 ////////////////////////////////////////////////////////////////////////////
8
9 BOOL CTexture::s_bLocked = FALSE;
10 DDSURFACEDESC2 CTexture::s_ddsd;
11
12
Initialize(BYTE * rgbSource,ULONG ulWidth,ULONG ulHeight,ULONG ulPitch)13 HRESULT CTexture::Initialize (BYTE *rgbSource, ULONG ulWidth, ULONG ulHeight, ULONG ulPitch)
14 {
15 m_rgbSource = rgbSource;
16 m_ulWidthSource = ulWidth;
17 m_ulHeightSource = ulHeight;
18 m_ulPitchSource = ulPitch;
19
20 return S_OK;
21 }
22
Allocate(CPaletteInfo * ppi)23 HRESULT CTexture::Allocate (CPaletteInfo *ppi)
24 {
25 HRESULT hr;
26
27 ASSERT (m_spddsMemory == NULL);
28
29 if (ppi->IsPow2 ())
30 {
31 m_ulWidth = 1;
32 while (m_ulWidth < m_ulWidthSource)
33 m_ulWidth *= 2;
34
35 m_ulHeight = 1;
36 while (m_ulHeight < m_ulHeightSource)
37 m_ulHeight *= 2;
38 }
39 else
40 {
41 m_ulWidth = m_ulWidthSource;
42 m_ulHeight = m_ulHeightSource;
43 }
44
45 if (ppi->IsSquare ())
46 {
47 if (m_ulHeight > m_ulWidth)
48 {
49 m_ulWidth = m_ulHeight;
50 }
51 else
52 {
53 m_ulHeight = m_ulWidth;
54 }
55 }
56
57 m_flAdjX = (D3DVALUE) m_ulWidthSource / (D3DVALUE) m_ulWidth;
58 m_flAdjY = (D3DVALUE) m_ulHeightSource / (D3DVALUE) m_ulHeight;
59
60 DDSURFACEDESC2 ddsd;
61 ZeroMemory (&ddsd, sizeof (ddsd));
62 ddsd.dwSize = sizeof (ddsd);
63 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
64 ddsd.dwWidth = m_ulWidth;
65 ddsd.dwHeight = m_ulHeight;
66 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
67 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
68 ppi->GetPixelFormat (&ddsd.ddpfPixelFormat);
69
70 hr = g_pFramework->GetDirectDraw ()->CreateSurface(&ddsd, &m_spddsMemory, NULL);
71 ASSERT (SUCCEEDED (hr));
72 if (FAILED (hr))
73 return hr;
74
75 ASSERT (m_spddsMemory != NULL);
76
77 m_spddtMemory = m_spddsMemory;
78
79 DirtyMemory ();
80
81 DDCOLORKEY ddck;
82 if (ppi->IsIndexed ())
83 {
84 ddck.dwColorSpaceLowValue = 255;
85 ddck.dwColorSpaceHighValue = 255;
86 }
87 else
88 {
89 ddck.dwColorSpaceLowValue = 0;
90 ddck.dwColorSpaceHighValue = 0;
91 }
92 hr = m_spddsMemory->SetColorKey (DDCKEY_SRCBLT, &ddck);
93 ASSERT (SUCCEEDED (hr));
94
95 if (ppi->GetPalette () != NULL)
96 {
97 hr = m_spddsMemory->SetPalette (ppi->GetPalette ());
98 ASSERT (SUCCEEDED (hr));
99 }
100
101 return hr;
102 }
103
Free(void)104 HRESULT CTexture::Free (void)
105 {
106 HRESULT hr = S_OK;
107
108 m_spddtMemory = m_spddsMemory = NULL;
109
110 m_ulWidth = 0;
111 m_ulHeight = 0;
112
113 return hr;
114 }
115
Lock(void)116 HRESULT CTexture::Lock (void)
117 {
118 HRESULT hr;
119 if (!s_bLocked)
120 {
121 s_bLocked = TRUE;
122
123 s_ddsd.dwSize = sizeof (s_ddsd);
124 hr = m_spddsMemory->Lock (
125 NULL,
126 &s_ddsd,
127 #ifndef NDEBUG
128 DDLOCK_NOSYSLOCK |
129 #endif
130 DDLOCK_WAIT,
131 NULL);
132 ASSERT (SUCCEEDED (hr));
133 }
134 else
135 {
136 // already locked
137 hr = E_FAIL;
138 ASSERT (FALSE);
139 }
140 return hr;
141 }
142
Unlock(void)143 HRESULT CTexture::Unlock (void)
144 {
145 HRESULT hr;
146 if (s_bLocked)
147 {
148 hr = m_spddsMemory->Unlock (NULL);
149 ASSERT (SUCCEEDED (hr));
150
151 s_bLocked = FALSE;
152 }
153 else
154 {
155 // not locked
156 hr = E_FAIL;
157 ASSERT (FALSE);
158 }
159 return hr;
160 }
161
PlotPixel(ULONG ulX,ULONG ulY,BYTE b)162 void CTexture::PlotPixel (ULONG ulX, ULONG ulY, BYTE b)
163 {
164 ASSERT (ulX <= m_ulWidth);
165 ASSERT (ulY <= m_ulHeight);
166
167 ASSERT (s_bLocked);
168 ASSERT (s_ddsd.lpSurface != NULL);
169
170 switch (s_ddsd.ddpfPixelFormat.dwRGBBitCount)
171 {
172 case 8:
173 {
174 * (((LPBYTE) s_ddsd.lpSurface) + ulX + ulY * s_ddsd.lPitch) = b;
175
176 break;
177 }
178 case 16:
179 {
180 WORD w;
181 if (!(m_bTransparent && b == 255))
182 {
183 w = m_ppi->Read16 (b);
184 }
185 else
186 {
187 w = 0;
188 }
189 * (WORD *) (((LPBYTE) s_ddsd.lpSurface) + ulX * 2 + ulY * s_ddsd.lPitch) = w;
190 break;
191 }
192
193 default:
194 {
195 ASSERT (FALSE);
196 break;
197 }
198 }
199 }
200
SetBitmapData(BYTE * rgb,BOOL bRle)201 void CTexture::SetBitmapData (BYTE *rgb, BOOL bRle)
202 {
203 m_rgbSource = rgb;
204 m_bRle = bRle;
205 DirtyMemory ();
206 }
207
CopyFromSource(void)208 void CTexture::CopyFromSource (void)
209 {
210 if (SUCCEEDED (Lock ()))
211 {
212 if (m_bRle)
213 {
214 PBYTE pbLine = m_rgbSource + m_ulHeightSource + 4;;
215 for (ULONG y = 0; y < m_ulHeightSource; y ++)
216 {
217 ULONG x = 0;
218 PBYTE pbSrc = pbLine;
219
220 while (1)
221 {
222 const BYTE RLE_CODE = 0xE0;
223 BYTE b = *pbSrc++;
224 if ((b & RLE_CODE) != RLE_CODE)
225 {
226 PlotPixel (x++, y, b);
227 }
228 else
229 {
230 BYTE cb = b & (~RLE_CODE);
231 if (cb == 0)
232 break;
233
234 b = *pbSrc++;
235 while (cb--)
236 PlotPixel (x++, y, b);
237 }
238 }
239 ASSERT (x <= m_ulWidthSource);
240
241 pbLine += m_rgbSource [y + 4];
242 }
243 }
244 else
245 {
246 LPBYTE lpbDest = (LPBYTE) s_ddsd.lpSurface;
247 LPBYTE lpbSrc = m_rgbSource;
248
249 switch (s_ddsd.ddpfPixelFormat.dwRGBBitCount)
250 {
251 case 8:
252 {
253 for (ULONG y = m_ulHeightSource; y != 0; y--)
254 {
255 memcpy (lpbDest, lpbSrc, m_ulPitchSource);
256 lpbDest += s_ddsd.lPitch;
257 lpbSrc += m_ulPitchSource;
258 }
259 break;
260 }
261 case 16:
262 {
263 for (ULONG y = m_ulHeightSource; y != 0; y--)
264 {
265 LPBYTE lpbLineSrc = lpbSrc;
266 LPWORD lpwLineDest = (LPWORD) lpbDest;
267
268 if (m_bTransparent)
269 {
270 for (ULONG x = m_ulWidthSource; x != 0; x--)
271 {
272 BYTE b = *lpbLineSrc++;
273 *lpwLineDest++ = (b == 255) ? 0 : m_ppi->Read16 (b);
274 }
275 }
276 else
277 {
278 for (ULONG x = m_ulWidthSource; x != 0; x--)
279 {
280 *lpwLineDest++ = m_ppi->Read16 (*lpbLineSrc++);
281 }
282 }
283 lpbDest += s_ddsd.lPitch;
284 lpbSrc += m_ulPitchSource;
285 }
286 break;
287 }
288
289 default:
290 {
291 ASSERT (FALSE);
292 break;
293 }
294 }
295 }
296 Unlock ();
297 }
298 else
299 {
300 ASSERT (FALSE);
301 }
302 }
303
CleanMemory(void)304 HRESULT CTexture::CleanMemory (void)
305 {
306 CopyFromSource ();
307 m_bDirtyMemory = FALSE;
308 return S_OK;
309 }
310
GetTexture()311 IDirect3DTexture2 *CTexture::GetTexture ()
312 {
313 if (m_bDirtyMemory)
314 {
315 CleanMemory ();
316 }
317
318 return m_spddtMemory;
319 }
320
321 ////////////////////////////////////////////////////////////////////////////
322
323 struct FindTextureData
324 {
325 DWORD bpp; // we want a texture format of this bpp
326 DDPIXELFORMAT ddpf; // place the format here
327 };
328
329
FindTextureCallback(LPDDPIXELFORMAT pddpf,LPVOID lParam)330 HRESULT CALLBACK FindTextureCallback(LPDDPIXELFORMAT pddpf, LPVOID lParam)
331 {
332 FindTextureData * FindData = (FindTextureData *)lParam;
333
334 //
335 // we use GetDC/BitBlt to init textures so we only
336 // want to use formats that GetDC will support.
337 //
338 if (pddpf->dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS))
339 return DDENUMRET_OK;
340
341 /*
342 if (pddpf->dwRGBBitCount == 16)
343 {
344 FindData->ddpf = ddpf;
345 }
346
347 return DDENUMRET_OK;
348 */
349
350
351 // if (!(pddpf->dwFlags & DDPF_ALPHAPIXELS))
352 // return DDENUMRET_OK;
353
354 if (pddpf->dwRGBBitCount < 8)
355 return DDENUMRET_OK;
356
357 if (pddpf->dwRGBBitCount == 8 && !(pddpf->dwFlags & DDPF_PALETTEINDEXED8))
358 return DDENUMRET_OK;
359
360 if (pddpf->dwRGBBitCount > 8 && !(pddpf->dwFlags & DDPF_RGB))
361 return DDENUMRET_OK;
362
363 //
364 // keep the texture format that is nearest to the bitmap we have
365 //
366 if (FindData->ddpf.dwRGBBitCount == 0 ||
367 (pddpf->dwRGBBitCount >= FindData->bpp && pddpf->dwRGBBitCount <= FindData->ddpf.dwRGBBitCount) //&&
368 //(pddpf->dwAlphaBitDepth != 0 && pddpf->dwAlphaBitDepth > FindData->ddpf.dwAlphaBitDepth) // ALPHA BIT DEPTHS ARE REVERSED!!!!
369 )
370 {
371 FindData->ddpf = *pddpf;
372 }
373
374 return DDENUMRET_OK;
375 }
376
ChooseTextureFormat(LPDIRECT3DDEVICE3 Device,DWORD bpp,DDPIXELFORMAT * pddpf)377 void ChooseTextureFormat(LPDIRECT3DDEVICE3 Device, DWORD bpp, DDPIXELFORMAT *pddpf)
378 {
379 HRESULT hr;
380 FindTextureData FindData;
381 ZeroMemory(&FindData, sizeof(FindData));
382 FindData.bpp = bpp;
383 hr = Device->EnumTextureFormats(FindTextureCallback, (LPVOID)&FindData);
384 ASSERT(hr == S_OK);
385 *pddpf = FindData.ddpf;
386 }
387
Initialize()388 HRESULT CPaletteInfo::Initialize ()
389 {
390 m_spddpPalette = NULL;
391
392 //
393 // find the best texture format to use.
394 //
395 ChooseTextureFormat (g_pFramework->GetD3DDevice (), 8, &m_ddpfPixelFormat);
396
397 m_cshftR = GetShift (m_mskR = m_ddpfPixelFormat.dwRBitMask);
398 m_cshftG = GetShift (m_mskG = m_ddpfPixelFormat.dwGBitMask);
399 m_cshftB = GetShift (m_mskB = m_ddpfPixelFormat.dwBBitMask);
400
401 HRESULT hr;
402
403 D3DDEVICEDESC descHAL, descHEL;
404 descHAL.dwSize = descHEL.dwSize = sizeof (descHAL);
405 hr = g_pFramework->GetD3DDevice ()->GetCaps (&descHAL, &descHEL);
406 ASSERT (SUCCEEDED (hr));
407
408 if (!descHAL.dwFlags) {
409 m_bPow2 = (descHEL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0;
410 m_bSquare = (descHEL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0;
411 } else {
412 m_bPow2 = (descHAL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) != 0;
413 m_bSquare = (descHAL.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) != 0;
414 }
415
416 if (IsIndexed ())
417 {
418 hr = g_pFramework->GetDirectDraw ()->CreatePalette (DDPCAPS_8BIT | DDPCAPS_ALLOW256, m_rgpe, &m_spddpPalette, NULL);
419 ASSERT (SUCCEEDED (hr));
420 }
421
422 return S_OK;
423 }
424
Uninitialize()425 HRESULT CPaletteInfo::Uninitialize ()
426 {
427 m_spddpPalette = NULL; // smart pointer release
428
429 return S_OK;
430 }
431
SetPaletteEntries(PALETTEENTRY rgpe[256])432 void CPaletteInfo::SetPaletteEntries (PALETTEENTRY rgpe [256])
433 {
434 // okay, we don't really need to cache the palette values
435 // we could implement ReadPalette by individual Getentries calls...
436 memcpy (m_rgpe, rgpe, sizeof (m_rgpe));
437
438 if (m_spddpPalette != NULL)
439 {
440 HRESULT hr = m_spddpPalette->SetEntries (0, 0, 256, m_rgpe);
441 ASSERT (SUCCEEDED (hr));
442 }
443 }
444
GetPaletteEntries(PALETTEENTRY rgpe[256])445 void CPaletteInfo::GetPaletteEntries (PALETTEENTRY rgpe [256])
446 {
447 if (m_spddpPalette != NULL)
448 {
449 HRESULT hr = m_spddpPalette->GetEntries (0, 0, 256, m_rgpe);
450 ASSERT (SUCCEEDED (hr));
451 }
452 }
453
454 ////////////////////////////////////////////////////////////////
455 CPaletteInfo *CTexture::m_ppi;
456
Initialize()457 HRESULT CTextureSet::Initialize ()
458 {
459 HRESULT hr;
460
461 hr = m_pi.Initialize ();
462 ASSERT (SUCCEEDED (hr));
463
464 CTexture::m_ppi = &m_pi;
465
466 for (TEXTURE_SET::iterator iter = m_setTextures.begin ();
467 iter != m_setTextures.end ();
468 iter ++)
469 {
470 (*iter)->Allocate (&m_pi);
471 }
472
473 return hr;
474 }
475
Uninitialize()476 HRESULT CTextureSet::Uninitialize ()
477 {
478 for (TEXTURE_SET::iterator iter = m_setTextures.begin ();
479 iter != m_setTextures.end ();
480 iter ++)
481 {
482 (*iter)->Free ();
483 }
484
485 m_pi.Uninitialize ();
486
487 return S_OK;
488 }
489
CreateTexture(BYTE * rgbSource,ULONG dx,ULONG dy,ULONG ulPitch)490 CTexture *CTextureSet::CreateTexture (BYTE *rgbSource, ULONG dx, ULONG dy, ULONG ulPitch)
491 {
492 CTexture *pTexture = new CTexture;
493
494 pTexture->Initialize (rgbSource, dx, dy, ulPitch);
495 pTexture->Allocate (&m_pi);
496
497 m_setTextures.insert (pTexture);
498
499 return pTexture;
500 }
501
FreeTexture(CTexture * pTexture)502 void CTextureSet::FreeTexture (CTexture *pTexture)
503 {
504 m_setTextures.erase (pTexture);
505
506 delete pTexture;
507 }
508
DirtyTextures(void)509 void CTextureSet::DirtyTextures (void)
510 {
511 for (TEXTURE_SET::iterator iter = m_setTextures.begin ();
512 iter != m_setTextures.end ();
513 iter ++)
514 {
515 (*iter)->DirtyMemory ();
516 }
517 }
518
519
SetPaletteEntries(PALETTEENTRY rgpe[256])520 void CTextureSet::SetPaletteEntries (PALETTEENTRY rgpe [256])
521 {
522 m_pi.SetPaletteEntries (rgpe);
523
524 if (!m_pi.IsIndexed ())
525 {
526 DirtyTextures ();
527 }
528 }
529
GetPaletteEntries(PALETTEENTRY rgpe[256])530 void CTextureSet::GetPaletteEntries (PALETTEENTRY rgpe [256])
531 {
532 m_pi.GetPaletteEntries (rgpe);
533 }
534