dsrc isn't necessary for this repo
[client-tools.git] / src / external / 3rd / application / DXTex / dxtexdoc.cpp
blob48677065435220fc87e702c150d4251cd45ca936
1 // dxtexDoc.cpp : implementation of the CDxtexDoc class
2 //
4 #include "stdafx.h"
5 #include "dxtex.h"
6 #include "dxtexDoc.h"
7 #include "dialogs.h"
8 #include "dds.h"
10 #ifdef _DEBUG
11 #define new DEBUG_NEW
12 #undef THIS_FILE
13 static char THIS_FILE[] = __FILE__;
14 #endif
16 // Helper function that tells whether the given D3DFMT has a working alpha channel
17 BOOL FormatContainsAlpha( D3DFORMAT fmt )
19 switch( fmt )
21 case D3DFMT_A8R8G8B8:
22 case D3DFMT_A1R5G5B5:
23 case D3DFMT_A4R4G4B4:
24 case D3DFMT_A8R3G3B2:
25 case D3DFMT_DXT1:
26 case D3DFMT_DXT3:
27 case D3DFMT_DXT5:
28 case D3DFMT_A2R10G10B10:
29 case D3DFMT_A16B16G16R16:
30 return TRUE;
31 default:
32 return FALSE;
36 /////////////////////////////////////////////////////////////////////////////
37 // CDxtexDoc
39 IMPLEMENT_DYNCREATE(CDxtexDoc, CDocument)
41 BEGIN_MESSAGE_MAP(CDxtexDoc, CDocument)
42 //{{AFX_MSG_MAP(CDxtexDoc)
43 ON_COMMAND(ID_FILE_OPENALPHA, OnFileOpenAlpha)
44 ON_COMMAND(ID_FORMAT_GENERATEMIPMAPS, OnGenerateMipMaps)
45 ON_COMMAND(ID_FORMAT_CHANGECUBEMAPFACES, OnFormatChangeCubeMapFaces)
46 ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHA, OnUpdateFileOpenAlpha)
47 ON_UPDATE_COMMAND_UI(ID_FORMAT_GENERATEMIPMAPS, OnUpdateFormatGenerateMipmaps)
48 ON_UPDATE_COMMAND_UI(ID_FORMAT_CHANGECUBEMAPFACES, OnUpdateFormatChangeCubeMapFaces)
49 ON_COMMAND(ID_FORMAT_MAKEINTOVOLUMEMAP, OnFormatMakeIntoVolumeMap)
50 ON_UPDATE_COMMAND_UI(ID_FORMAT_MAKEINTOVOLUMEMAP, OnUpdateFormatMakeIntoVolumeMap)
51 ON_COMMAND(ID_FORMAT_CHANGESURFACEFMT, OnFormatChangeSurfaceFmt)
52 ON_COMMAND(ID_FORMAT_RESIZE, OnFormatResize)
53 ON_UPDATE_COMMAND_UI(ID_FORMAT_RESIZE, OnUpdateFormatResize)
54 ON_COMMAND(ID_FORMAT_GENERATESPECULARLOOKUP, OnFormatGeneratespecularlookup)
55 ON_UPDATE_COMMAND_UI(ID_FORMAT_GENERATESPECULARLOOKUP, OnUpdateFormatGeneratespecularlookup)
56 //}}AFX_MSG_MAP
57 END_MESSAGE_MAP()
59 /////////////////////////////////////////////////////////////////////////////
60 // CDxtexDoc diagnostics
62 #ifdef _DEBUG
63 void CDxtexDoc::AssertValid() const
65 CDocument::AssertValid();
68 void CDxtexDoc::Dump(CDumpContext& dc) const
70 CDocument::Dump(dc);
72 #endif //_DEBUG
74 /////////////////////////////////////////////////////////////////////////////
75 // CDxtexDoc construction/destruction
77 CDxtexDoc::CDxtexDoc()
79 m_ptexOrig = NULL;
80 m_ptexNew = NULL;
81 m_dwWidth = 0;
82 m_dwHeight = 0;
83 m_dwDepth = 0;
84 m_numMips = 0;
85 m_dwCubeMapFlags = 0;
86 m_bTitleModsChanged = FALSE;
90 CDxtexDoc::~CDxtexDoc()
92 ReleasePpo(&m_ptexOrig);
93 ReleasePpo(&m_ptexNew);
97 BOOL CDxtexDoc::OnNewDocument()
99 HRESULT hr;
100 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
102 if (!CDocument::OnNewDocument())
103 return FALSE;
105 CNewTextureDlg dlg;
107 if (IDCANCEL == dlg.DoModal())
108 return FALSE;
110 m_dwWidth = dlg.m_dwWidth;
111 m_dwHeight = dlg.m_dwHeight;
112 m_numMips = dlg.m_numMips;
114 if (dlg.m_iTexType == 0)
116 LPDIRECT3DTEXTURE9 pmiptex;
117 hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips,
118 0, dlg.m_fmt, D3DPOOL_MANAGED, &pmiptex, NULL);
119 if (FAILED(hr))
121 AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
122 return FALSE;
124 m_ptexOrig = pmiptex;
127 else if (dlg.m_iTexType == 1)
129 // Cube Map
130 LPDIRECT3DCUBETEXTURE9 pcubetex;
131 m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES;
132 hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips,
133 0, dlg.m_fmt, D3DPOOL_MANAGED, &pcubetex, NULL);
134 if (FAILED(hr))
136 AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
137 return FALSE;
139 m_ptexOrig = pcubetex;
141 else
143 LPDIRECT3DVOLUMETEXTURE9 pvoltex;
144 m_dwDepth = dlg.m_dwDepth;
145 hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips,
146 0, dlg.m_fmt, D3DPOOL_SYSTEMMEM, &pvoltex, NULL);
147 if (FAILED(hr))
149 AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
150 return FALSE;
152 m_ptexOrig = pvoltex;
155 return TRUE;
159 BOOL CDxtexDoc::OnOpenDocument(LPCTSTR lpszPathName)
161 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
162 D3DXIMAGE_INFO imageinfo;
163 D3DXIMAGE_INFO imageinfo2;
165 if( FAILED( D3DXGetImageInfoFromFile( lpszPathName, &imageinfo ) ) )
167 AfxMessageBox(ID_ERROR_COULDNTLOADFILE);
168 return FALSE;
171 switch( imageinfo.ResourceType )
173 case D3DRTYPE_TEXTURE:
174 if( FAILED( D3DXCreateTextureFromFileEx( pd3ddev, lpszPathName,
175 imageinfo.Width, imageinfo.Height, imageinfo.MipLevels, 0,
176 imageinfo.Format, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0,
177 &imageinfo2, NULL, (LPDIRECT3DTEXTURE9*)&m_ptexOrig ) ) )
179 AfxMessageBox(ID_ERROR_COULDNTLOADFILE);
180 return FALSE;
182 m_dwWidth = imageinfo2.Width;
183 m_dwHeight = imageinfo2.Height;
184 m_dwDepth = 0;
185 m_numMips = imageinfo2.MipLevels;
187 if( imageinfo.ImageFileFormat == D3DXIFF_BMP )
189 // Look for "foo_a.bmp" for alpha channel
190 CString strPath = lpszPathName;
191 int i = strPath.ReverseFind('.');
192 HRESULT hr;
193 strPath = strPath.Left(i) + "_a.bmp";
194 CFileStatus status;
195 if (CFile::GetStatus(strPath, status))
197 // Make sure there's an alpha channel to load alpha image into
198 if (FAILED(EnsureAlpha(&m_ptexOrig)))
199 return FALSE;
201 LPDIRECT3DSURFACE9 psurf;
203 hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(0, &psurf);
204 if (FAILED(hr))
205 return FALSE;
207 hr = LoadAlphaIntoSurface(strPath, psurf);
208 ReleasePpo(&psurf);
209 if (FAILED(hr))
210 return FALSE;
214 break;
216 case D3DRTYPE_VOLUMETEXTURE:
217 if( FAILED( D3DXCreateVolumeTextureFromFileEx( pd3ddev, lpszPathName,
218 imageinfo.Width, imageinfo.Height, imageinfo.Depth, imageinfo.MipLevels,
219 0, imageinfo.Format, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE,
220 0, &imageinfo2, NULL, (LPDIRECT3DVOLUMETEXTURE9*)&m_ptexOrig ) ) )
222 AfxMessageBox(ID_ERROR_COULDNTLOADFILE);
223 return FALSE;
225 m_dwWidth = imageinfo2.Width;
226 m_dwHeight = imageinfo2.Height;
227 m_dwDepth = imageinfo2.Depth;
228 m_numMips = imageinfo2.MipLevels;
229 break;
231 case D3DRTYPE_CUBETEXTURE:
232 if( FAILED( D3DXCreateCubeTextureFromFileEx( pd3ddev, lpszPathName,
233 imageinfo.Width, imageinfo.MipLevels, 0, imageinfo.Format,
234 D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE,
235 0, &imageinfo2, NULL, (LPDIRECT3DCUBETEXTURE9*)&m_ptexOrig ) ) )
237 AfxMessageBox(ID_ERROR_COULDNTLOADFILE);
238 return FALSE;
240 m_dwWidth = imageinfo2.Width;
241 m_dwHeight = imageinfo2.Height;
242 m_dwDepth = 0;
243 m_numMips = imageinfo2.MipLevels;
244 m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES;
245 break;
247 default:
248 AfxMessageBox(ID_ERROR_COULDNTLOADFILE);
249 return FALSE;
252 return TRUE;
256 BOOL CDxtexDoc::OnSaveDocument(LPCTSTR lpszPathName)
258 LPDIRECT3DBASETEXTURE9 ptex;
259 ptex = (m_ptexNew == NULL ? m_ptexOrig : m_ptexNew);
261 if( FAILED( D3DXSaveTextureToFile( lpszPathName, D3DXIFF_DDS, ptex, NULL ) ) )
263 AfxMessageBox(ID_ERROR_COULDNTSAVEFILE);
264 return FALSE;
267 SetModifiedFlag(FALSE);
269 return TRUE;
275 D3DFORMAT CDxtexDoc::GetFormat(LPDIRECT3DBASETEXTURE9 ptex)
277 LPDIRECT3DTEXTURE9 pmiptex = NULL;
278 LPDIRECT3DCUBETEXTURE9 pcubetex = NULL;
279 LPDIRECT3DVOLUMETEXTURE9 pvoltex = NULL;
280 D3DFORMAT fmt;
282 if (IsVolumeMap())
283 pvoltex = (LPDIRECT3DVOLUMETEXTURE9)ptex;
284 else if (IsCubeMap())
285 pcubetex = (LPDIRECT3DCUBETEXTURE9)ptex;
286 else
287 pmiptex = (LPDIRECT3DTEXTURE9)ptex;
289 if (pvoltex != NULL)
291 D3DVOLUME_DESC vd;
292 pvoltex->GetLevelDesc(0, &vd);
293 fmt = vd.Format;
295 else if (pcubetex != NULL)
297 D3DSURFACE_DESC sd;
298 pcubetex->GetLevelDesc(0, &sd);
299 fmt = sd.Format;
301 else
303 D3DSURFACE_DESC sd;
304 pmiptex->GetLevelDesc(0, &sd);
305 fmt = sd.Format;
307 return fmt;
312 // If *pptex's current format has less than 4 bits of alpha, change
313 // it to a similar format that has at least 4 bits of alpha.
314 HRESULT CDxtexDoc::EnsureAlpha(LPDIRECT3DBASETEXTURE9* pptex)
316 HRESULT hr;
317 D3DFORMAT fmtCur = GetFormat(*pptex);
318 D3DFORMAT fmtNew = D3DFMT_UNKNOWN;
319 LPDIRECT3DBASETEXTURE9 ptex = NULL;
321 switch (fmtCur)
323 case D3DFMT_R8G8B8:
324 fmtNew = D3DFMT_A8R8G8B8;
325 break;
326 default:
327 break;
330 if( fmtNew != D3DFMT_UNKNOWN )
332 if (FAILED(hr = ChangeFormat(m_ptexOrig, fmtNew, &ptex)))
333 return hr;
334 ReleasePpo(&m_ptexOrig);
335 m_ptexOrig = ptex;
338 return S_OK;
344 /////////////////////////////////////////////////////////////////////////////
345 // CDxtexDoc commands
347 HRESULT CDxtexDoc::LoadAlphaBmp(CString& strPath)
349 HRESULT hr;
350 LPDIRECT3DTEXTURE9 pmiptex;
351 LPDIRECT3DSURFACE9 psurf;
353 if (IsCubeMap())
354 return E_FAIL;
356 pmiptex = (LPDIRECT3DTEXTURE9)m_ptexOrig;
357 hr = pmiptex->GetSurfaceLevel(0, &psurf);
358 if (FAILED(hr))
359 return hr;
361 hr = LoadAlphaIntoSurface(strPath, psurf);
362 ReleasePpo(&psurf);
363 if (FAILED(hr))
364 return hr;
366 UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
367 return S_OK;
373 HRESULT CDxtexDoc::ChangeFormat(LPDIRECT3DBASETEXTURE9 ptexCur, D3DFORMAT fmtTo,
374 LPDIRECT3DBASETEXTURE9* pptexNew)
376 HRESULT hr;
377 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
378 LPDIRECT3DTEXTURE9 pmiptex;
379 LPDIRECT3DCUBETEXTURE9 pcubetex;
380 LPDIRECT3DVOLUMETEXTURE9 pvoltex;
381 D3DFORMAT fmtFrom;
382 LPDIRECT3DTEXTURE9 pmiptexNew;
383 LPDIRECT3DCUBETEXTURE9 pcubetexNew;
384 LPDIRECT3DVOLUMETEXTURE9 pvoltexNew;
386 if (IsVolumeMap())
388 pvoltex = (LPDIRECT3DVOLUMETEXTURE9)ptexCur;
389 D3DVOLUME_DESC vd;
390 pvoltex->GetLevelDesc(0, &vd);
391 fmtFrom = vd.Format;
393 else if (IsCubeMap())
395 pcubetex = (LPDIRECT3DCUBETEXTURE9)ptexCur;
396 D3DSURFACE_DESC sd;
397 pcubetex->GetLevelDesc(0, &sd);
398 fmtFrom = sd.Format;
400 else
402 pmiptex = (LPDIRECT3DTEXTURE9)ptexCur;
403 D3DSURFACE_DESC sd;
404 pmiptex->GetLevelDesc(0, &sd);
405 fmtFrom = sd.Format;
408 if (fmtFrom == D3DFMT_DXT2 || fmtFrom == D3DFMT_DXT4)
410 if (fmtTo == D3DFMT_DXT1)
412 AfxMessageBox(ID_ERROR_PREMULTTODXT1);
414 else if (fmtTo != D3DFMT_DXT2 && fmtTo != D3DFMT_DXT4)
416 AfxMessageBox(ID_ERROR_PREMULTALPHA);
417 return S_OK;
421 if (IsVolumeMap())
423 hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips,
424 0, fmtTo, D3DPOOL_SYSTEMMEM, &pvoltexNew, NULL);
425 if (FAILED(hr))
426 return hr;
427 *pptexNew = pvoltexNew;
428 if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, ptexCur, *pptexNew)))
429 return hr;
431 else if (IsCubeMap())
433 hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips,
434 0, fmtTo, D3DPOOL_MANAGED, &pcubetexNew, NULL);
435 if (FAILED(hr))
436 return hr;
437 *pptexNew = pcubetexNew;
438 if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_X, ptexCur, *pptexNew)))
439 return hr;
440 if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_X, ptexCur, *pptexNew)))
441 return hr;
442 if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_Y, ptexCur, *pptexNew)))
443 return hr;
444 if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_Y, ptexCur, *pptexNew)))
445 return hr;
446 if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_Z, ptexCur, *pptexNew)))
447 return hr;
448 if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_Z, ptexCur, *pptexNew)))
449 return hr;
451 else
453 if ((fmtTo == D3DFMT_DXT1 || fmtTo == D3DFMT_DXT2 ||
454 fmtTo == D3DFMT_DXT3 || fmtTo == D3DFMT_DXT4 ||
455 fmtTo == D3DFMT_DXT5) && (m_dwWidth % 4 != 0 || m_dwHeight % 4 != 0))
457 AfxMessageBox(ID_ERROR_NEEDMULTOF4);
458 return E_FAIL;
461 hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips,
462 0, fmtTo, D3DPOOL_MANAGED, &pmiptexNew, NULL);
463 if (FAILED(hr))
464 return hr;
465 *pptexNew = pmiptexNew;
466 if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, ptexCur, *pptexNew)))
467 return hr;
469 return S_OK;
475 HRESULT CDxtexDoc::Compress(D3DFORMAT fmtTo, BOOL bSwitchView)
477 HRESULT hr;
478 LPDIRECT3DBASETEXTURE9 ptexNew = NULL;
480 if (FAILED(hr = ChangeFormat(m_ptexOrig, fmtTo, &ptexNew)))
481 return hr;
483 ReleasePpo(&m_ptexNew);
484 m_ptexNew = ptexNew;
486 SetModifiedFlag();
487 m_bTitleModsChanged = TRUE; // force title bar update
488 if (bSwitchView)
490 if( AfxGetMainWnd() != NULL )
491 AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_VIEW_COMPRESSED, 0);
494 return S_OK;
500 void CDxtexDoc::OnGenerateMipMaps()
502 GenerateMipMaps();
508 void CDxtexDoc::GenerateMipMaps()
510 LONG lwTempH;
511 LONG lwTempW;
512 LONG lwPowsW;
513 LONG lwPowsH;
514 LPDIRECT3DTEXTURE9 pddsNew = NULL;
515 D3DFORMAT fmt;
516 HRESULT hr;
517 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
518 LPDIRECT3DTEXTURE9 pmiptex = NULL;
519 LPDIRECT3DCUBETEXTURE9 pcubetex = NULL;
520 LPDIRECT3DVOLUMETEXTURE9 pvoltex = NULL;
521 LPDIRECT3DTEXTURE9 pmiptexNew = NULL;
522 LPDIRECT3DCUBETEXTURE9 pcubetexNew = NULL;
523 LPDIRECT3DVOLUMETEXTURE9 pvoltexNew = NULL;
524 LPDIRECT3DSURFACE9 psurfSrc;
525 LPDIRECT3DSURFACE9 psurfDest;
526 LPDIRECT3DVOLUME9 pvolSrc;
527 LPDIRECT3DVOLUME9 pvolDest;
529 if (IsVolumeMap())
530 pvoltex = (LPDIRECT3DVOLUMETEXTURE9)m_ptexOrig;
531 else if (IsCubeMap())
532 pcubetex = (LPDIRECT3DCUBETEXTURE9)m_ptexOrig;
533 else
534 pmiptex = (LPDIRECT3DTEXTURE9)m_ptexOrig;
536 if (pvoltex != NULL)
538 D3DVOLUME_DESC vd;
539 pvoltex->GetLevelDesc(0, &vd);
540 fmt = vd.Format;
542 else if (pcubetex != NULL)
544 D3DSURFACE_DESC sd;
545 pcubetex->GetLevelDesc(0, &sd);
546 fmt = sd.Format;
548 else
550 D3DSURFACE_DESC sd;
551 pmiptex->GetLevelDesc(0, &sd);
552 fmt = sd.Format;
555 lwTempW = m_dwWidth;
556 lwTempH = m_dwHeight;
557 lwPowsW = 0;
558 lwPowsH = 0;
559 while (lwTempW > 0)
561 lwPowsW++;
562 lwTempW = lwTempW / 2;
564 while (lwTempH > 0)
566 lwPowsH++;
567 lwTempH = lwTempH / 2;
569 m_numMips = lwPowsW > lwPowsH ? lwPowsW : lwPowsH;
571 // Create destination mipmap surface - same format as source
572 if (pvoltex != NULL)
574 if (FAILED(hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth,
575 m_numMips, 0, fmt, D3DPOOL_SYSTEMMEM, &pvoltexNew, NULL)))
577 goto LFail;
579 hr = pvoltex->GetVolumeLevel(0, &pvolSrc);
580 hr = pvoltexNew->GetVolumeLevel(0, &pvolDest);
581 hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL, pvolSrc, NULL, NULL,
582 D3DX_FILTER_TRIANGLE, 0);
583 ReleasePpo(&pvolSrc);
584 ReleasePpo(&pvolDest);
585 hr = D3DXFilterVolumeTexture(pvoltexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
587 else if (pmiptex != NULL)
589 if (FAILED(hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips,
590 0, fmt, D3DPOOL_MANAGED, &pmiptexNew, NULL)))
592 goto LFail;
594 hr = pmiptex->GetSurfaceLevel(0, &psurfSrc);
595 hr = pmiptexNew->GetSurfaceLevel(0, &psurfDest);
596 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
597 D3DX_FILTER_TRIANGLE, 0);
598 ReleasePpo(&psurfSrc);
599 ReleasePpo(&psurfDest);
600 hr = D3DXFilterTexture(pmiptexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
602 else
604 if (FAILED(hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips,
605 0, fmt, D3DPOOL_MANAGED, &pcubetexNew, NULL)))
607 goto LFail;
609 hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &psurfSrc);
610 hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &psurfDest);
611 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
612 D3DX_FILTER_TRIANGLE, 0);
613 ReleasePpo(&psurfSrc);
614 ReleasePpo(&psurfDest);
615 hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_X, 0, &psurfSrc);
616 hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_X, 0, &psurfDest);
617 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
618 D3DX_FILTER_TRIANGLE, 0);
619 ReleasePpo(&psurfSrc);
620 ReleasePpo(&psurfDest);
621 hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &psurfSrc);
622 hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &psurfDest);
623 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
624 D3DX_FILTER_TRIANGLE, 0);
625 ReleasePpo(&psurfSrc);
626 ReleasePpo(&psurfDest);
627 hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Y, 0, &psurfSrc);
628 hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Y, 0, &psurfDest);
629 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
630 D3DX_FILTER_TRIANGLE, 0);
631 ReleasePpo(&psurfSrc);
632 ReleasePpo(&psurfDest);
633 hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Z, 0, &psurfSrc);
634 hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Z, 0, &psurfDest);
635 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
636 D3DX_FILTER_TRIANGLE, 0);
637 ReleasePpo(&psurfSrc);
638 ReleasePpo(&psurfDest);
639 hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Z, 0, &psurfSrc);
640 hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Z, 0, &psurfDest);
641 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
642 D3DX_FILTER_TRIANGLE, 0);
643 ReleasePpo(&psurfSrc);
644 ReleasePpo(&psurfDest);
645 hr = D3DXFilterCubeTexture(pcubetexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
648 ReleasePpo(&m_ptexOrig);
649 if (pvoltexNew != NULL)
650 m_ptexOrig = pvoltexNew;
651 else if (pcubetexNew != NULL)
652 m_ptexOrig = pcubetexNew;
653 else
654 m_ptexOrig = pmiptexNew;
656 if (m_ptexNew != NULL)
658 // Rather than filtering down the (probably-compressed) m_ptexNew
659 // top level, compress each mip level from the (probably-uncompressed)
660 // m_ptexOrig levels.
661 if (pvoltexNew != NULL)
663 D3DVOLUME_DESC vd;
664 ((LPDIRECT3DVOLUMETEXTURE9)m_ptexNew)->GetLevelDesc(0, &vd);
665 fmt = vd.Format;
667 else if (pcubetexNew != NULL)
669 D3DSURFACE_DESC sd;
670 ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd);
671 fmt = sd.Format;
673 else
675 D3DSURFACE_DESC sd;
676 ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd);
677 fmt = sd.Format;
679 Compress(fmt, FALSE);
682 m_bTitleModsChanged = TRUE; // Generate title bar update
683 UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
684 SetModifiedFlag();
685 return;
687 LFail:
688 ReleasePpo(&pddsNew);
692 void CDxtexDoc::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
694 CDocument::SetPathName(lpszPathName, bAddToMRU);
696 TCHAR* pszLeaf = strrchr(lpszPathName, '\\');
697 if( pszLeaf )
699 pszLeaf++;
700 TCHAR* pszExtension = strrchr(lpszPathName, '.');
701 if( pszExtension && lstrcmpi(pszExtension, ".dds") != 0)
703 lstrcpy(pszExtension, "");
704 SetModifiedFlag(TRUE);
705 SetTitle(pszLeaf);
706 m_strPathName.Empty();
711 DWORD CDxtexDoc::NumMips(VOID)
713 return m_numMips;
717 void CDxtexDoc::OnFileOpenAlpha()
719 HRESULT hr;
720 CString fileName;
721 LPDIRECT3DTEXTURE9 pmiptex;
723 if (IsCubeMap() || IsVolumeMap())
724 return;
726 // Premultiplied-alpha files don't support this feature:
727 D3DSURFACE_DESC sd;
728 ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetLevelDesc(0, &sd);
729 if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
731 AfxMessageBox(ID_ERROR_PREMULTALPHA);
732 return;
735 // Check if the original has alpha
736 if( !FormatContainsAlpha(sd.Format) )
738 // If it doesn't then see if the new does
739 if (m_ptexNew != NULL)
741 ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd);
742 if( !FormatContainsAlpha(sd.Format) )
744 AfxMessageBox(ID_ERROR_NEEDALPHA);
745 return;
747 else
749 ReleasePpo(&m_ptexOrig);
750 m_ptexOrig = m_ptexNew;
751 m_ptexNew = NULL;
752 if( AfxGetMainWnd() != NULL )
753 AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_VIEW_ORIGINAL, 0);
756 else
758 AfxMessageBox(ID_ERROR_NEEDALPHA);
759 return;
763 pmiptex = (LPDIRECT3DTEXTURE9)m_ptexOrig;
765 if (!PromptForBmp(&fileName))
766 return;
768 LPDIRECT3DSURFACE9 psurf;
769 if (FAILED(hr = pmiptex->GetSurfaceLevel(0, &psurf)))
770 return;
772 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurf)))
773 return;
774 if (m_numMips > 1)
775 OnGenerateMipMaps();
776 else if (m_ptexNew != NULL)
778 ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd);
779 Compress(sd.Format, FALSE);
781 UpdateAllViews(NULL, 1);
785 HRESULT CDxtexDoc::LoadAlphaIntoSurface(CString& strPath, LPDIRECT3DSURFACE9 psurf)
787 HRESULT hr;
788 D3DSURFACE_DESC sd;
789 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
790 LPDIRECT3DTEXTURE9 ptexAlpha;
791 LPDIRECT3DSURFACE9 psurfAlpha;
792 LPDIRECT3DSURFACE9 psurfTarget;
794 psurf->GetDesc(&sd);
796 // Load the alpha BMP into psurfAlpha, a new A8R8G8B8 surface
797 hr = D3DXCreateTextureFromFileEx(pd3ddev, strPath, sd.Width, sd.Height, 1, 0,
798 D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE,
799 D3DX_FILTER_TRIANGLE, 0, NULL, NULL, &ptexAlpha);
800 hr = ptexAlpha->GetSurfaceLevel(0, &psurfAlpha);
802 // Copy the target surface into an A8R8G8B8 surface
803 hr = pd3ddev->CreateOffscreenPlainSurface(sd.Width, sd.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &psurfTarget, NULL);
804 hr = D3DXLoadSurfaceFromSurface(psurfTarget, NULL, NULL, psurf, NULL, NULL,
805 D3DX_FILTER_TRIANGLE, 0);
807 // Fill in the alpha channels of psurfTarget based on the blue channel of psurfAlpha
808 D3DLOCKED_RECT lrSrc;
809 D3DLOCKED_RECT lrDest;
811 hr = psurfAlpha->LockRect(&lrSrc, NULL, D3DLOCK_READONLY);
812 hr = psurfTarget->LockRect(&lrDest, NULL, 0);
814 DWORD xp;
815 DWORD yp;
816 DWORD* pdwRowSrc = (DWORD*)lrSrc.pBits;
817 DWORD* pdwRowDest = (DWORD*)lrDest.pBits;
818 DWORD* pdwSrc;
819 DWORD* pdwDest;
820 DWORD dwAlpha;
821 LONG dataBytesPerRow = 4 * sd.Width;
823 for (yp = 0; yp < sd.Height; yp++)
825 pdwSrc = pdwRowSrc;
826 pdwDest = pdwRowDest;
827 for (xp = 0; xp < sd.Width; xp++)
829 dwAlpha = *pdwSrc << 24;
830 *pdwDest &= 0x00ffffff;
831 *pdwDest |= dwAlpha;
833 pdwSrc++;
834 pdwDest++;
836 pdwRowSrc += lrSrc.Pitch / 4;
837 pdwRowDest += lrDest.Pitch / 4;
840 psurfAlpha->UnlockRect();
841 psurfTarget->UnlockRect();
843 // Copy psurfTarget back into real surface
844 hr = D3DXLoadSurfaceFromSurface(psurf, NULL, NULL, psurfTarget, NULL, NULL,
845 D3DX_FILTER_TRIANGLE, 0);
847 // Release allocated interfaces
848 ReleasePpo(&psurfTarget);
849 ReleasePpo(&psurfAlpha);
850 ReleasePpo(&ptexAlpha);
852 return S_OK;
856 BOOL CDxtexDoc::PromptForBmp(CString* pstrPath)
858 CFileDialog dlgFile(TRUE);
860 CString title;
861 VERIFY(title.LoadString(AFX_IDS_OPENFILE));
863 CString strFilter;
864 CString strDefault;
866 strFilter += "Image Files (*.dds, *.bmp, *.tga, *.jpg, *.png, *.dib)";
867 strFilter += (TCHAR)'\0'; // next string please
868 strFilter += _T("*.dds;*.bmp;*.tga;*.jpg;*.png;*.dib");
869 strFilter += (TCHAR)'\0'; // last string
870 dlgFile.m_ofn.nMaxCustFilter++;
872 // append the "*.*" all files filter
873 CString allFilter;
874 VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
875 strFilter += allFilter;
876 strFilter += (TCHAR)'\0'; // next string please
877 strFilter += _T("*.*");
878 strFilter += (TCHAR)'\0'; // last string
879 dlgFile.m_ofn.nMaxCustFilter++;
881 dlgFile.m_ofn.lpstrFilter = strFilter;
882 dlgFile.m_ofn.lpstrTitle = title;
883 dlgFile.m_ofn.lpstrFile = pstrPath->GetBuffer(_MAX_PATH);
885 INT_PTR nResult = dlgFile.DoModal();
886 pstrPath->ReleaseBuffer();
887 if (nResult != IDOK)
888 return FALSE;
889 return TRUE;
893 void CDxtexDoc::OpenSubsurface(D3DCUBEMAP_FACES FaceType, LONG lwMip, LONG lwSlice)
895 HRESULT hr;
896 CString fileName;
897 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
898 LPDIRECT3DTEXTURE9 ptex = NULL;
899 LPDIRECT3DSURFACE9 psurfOrig = NULL;
900 LPDIRECT3DSURFACE9 psurfNew = NULL;
902 if (!PromptForBmp(&fileName))
903 return;
905 if (IsVolumeMap())
907 hr = D3DXCreateTextureFromFile(pd3ddev, fileName, &ptex);
908 hr = ptex->GetSurfaceLevel(0, &psurfOrig);
910 else if (IsCubeMap())
912 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetCubeMapSurface(FaceType, lwMip, &psurfOrig);
913 if (m_ptexNew != NULL)
914 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetCubeMapSurface(FaceType, lwMip, &psurfNew);
915 hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_FILTER_TRIANGLE, 0, NULL);
917 else
919 hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(lwMip, &psurfOrig);
920 if (m_ptexNew != NULL)
921 hr = ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetSurfaceLevel(lwMip, &psurfNew);
922 hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_FILTER_TRIANGLE, 0, NULL);
925 // Look for "foo_a.bmp" for alpha channel
926 int i = fileName.ReverseFind('.');
927 fileName = fileName.Left(i) + "_a.bmp";
928 CFileStatus status;
929 if (CFile::GetStatus(fileName, status))
931 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
932 return;
935 if (IsVolumeMap())
937 LPDIRECT3DVOLUME9 pvol;
938 hr = ((LPDIRECT3DVOLUMETEXTURE9)m_ptexOrig)->GetVolumeLevel(lwMip, &pvol);
939 hr = LoadVolumeSliceFromSurface(pvol, lwSlice, psurfOrig);
940 ReleasePpo(&pvol);
941 if (m_ptexNew)
943 hr = ((LPDIRECT3DVOLUMETEXTURE9)m_ptexNew)->GetVolumeLevel(lwMip, &pvol);
944 hr = LoadVolumeSliceFromSurface(pvol, lwSlice, psurfOrig);
945 ReleasePpo(&pvol);
948 else if (psurfNew != NULL)
950 hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
953 ReleasePpo(&psurfOrig);
954 ReleasePpo(&psurfNew);
955 ReleasePpo(&ptex);
957 SetModifiedFlag(TRUE);
958 UpdateAllViews(NULL, 1);
962 void CDxtexDoc::OpenAlphaSubsurface(D3DCUBEMAP_FACES FaceType, LONG lwMip, LONG lwSlice)
964 HRESULT hr;
965 CString fileName;
966 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
967 LPDIRECT3DTEXTURE9 ptexOrig = NULL;
968 LPDIRECT3DTEXTURE9 ptexNew = NULL;
969 LPDIRECT3DSURFACE9 psurfOrig = NULL;
970 LPDIRECT3DSURFACE9 psurfNew = NULL;
971 LPDIRECT3DVOLUME9 pvolOrig = NULL;
972 LPDIRECT3DVOLUME9 pvolNew = NULL;
973 D3DSURFACE_DESC sd;
974 DWORD dwWidth = m_dwWidth;
975 DWORD dwHeight = m_dwHeight;
977 if (IsVolumeMap())
979 for (int i = 0; i < lwMip; i++)
981 dwWidth /= 2;
982 dwHeight /= 2;
984 hr = pd3ddev->CreateTexture(dwWidth, dwHeight, 1,
985 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &ptexOrig, NULL);
986 hr = ptexOrig->GetSurfaceLevel(0, &psurfOrig);
987 hr = ((LPDIRECT3DVOLUMETEXTURE9)m_ptexOrig)->GetVolumeLevel(lwMip, &pvolOrig);
988 hr = LoadSurfaceFromVolumeSlice(pvolOrig, lwSlice, psurfOrig);
989 if (m_ptexNew != NULL)
991 hr = pd3ddev->CreateTexture(dwWidth, dwHeight, 1,
992 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &ptexNew, NULL);
993 hr = ptexNew->GetSurfaceLevel(0, &psurfOrig);
994 hr = ((LPDIRECT3DVOLUMETEXTURE9)m_ptexOrig)->GetVolumeLevel(lwMip, &pvolNew);
995 hr = LoadSurfaceFromVolumeSlice(pvolNew, lwSlice, psurfOrig);
998 else if (IsCubeMap())
1000 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetCubeMapSurface(FaceType, lwMip, &psurfOrig);
1001 ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetLevelDesc(lwMip, &sd);
1002 if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
1004 AfxMessageBox(ID_ERROR_PREMULTALPHA);
1005 return;
1007 if (m_ptexNew != NULL)
1009 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetCubeMapSurface(FaceType, lwMip, &psurfNew);
1010 ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetLevelDesc(lwMip, &sd);
1011 if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
1013 AfxMessageBox(ID_ERROR_PREMULTALPHA);
1014 return;
1018 else
1020 BOOL bAlphaFound = FALSE;
1021 hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(lwMip, &psurfOrig);
1022 ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetLevelDesc(lwMip, &sd);
1023 if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
1025 AfxMessageBox(ID_ERROR_PREMULTALPHA);
1026 return;
1029 // Check if the original has alpha
1030 if( FormatContainsAlpha(sd.Format) )
1032 bAlphaFound = TRUE;
1035 if (m_ptexNew != NULL)
1037 hr = ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetSurfaceLevel(lwMip, &psurfNew);
1038 ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(lwMip, &sd);
1039 if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
1041 AfxMessageBox(ID_ERROR_PREMULTALPHA);
1042 return;
1044 // Check if the new has alpha
1045 if( FormatContainsAlpha(sd.Format) )
1047 bAlphaFound = TRUE;
1051 if( bAlphaFound == FALSE )
1053 AfxMessageBox(ID_ERROR_NEEDALPHA);
1054 return;
1058 if (!PromptForBmp(&fileName))
1059 return;
1061 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
1062 return;
1064 if (psurfNew != NULL)
1066 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfNew)))
1067 return;
1070 if (pvolOrig != NULL)
1072 hr = LoadVolumeSliceFromSurface(pvolOrig, lwSlice, psurfOrig);
1074 if (pvolNew != NULL)
1076 hr = LoadVolumeSliceFromSurface(pvolNew, lwSlice, psurfNew);
1079 ReleasePpo(&psurfOrig);
1080 ReleasePpo(&psurfNew);
1081 ReleasePpo(&ptexOrig);
1082 ReleasePpo(&ptexNew);
1083 ReleasePpo(&pvolOrig);
1084 ReleasePpo(&pvolNew);
1086 SetModifiedFlag(TRUE);
1087 UpdateAllViews(NULL, 1);
1091 void CDxtexDoc::OnFormatChangeCubeMapFaces()
1093 HRESULT hr;
1094 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
1095 D3DSURFACE_DESC sd;
1096 LPDIRECT3DCUBETEXTURE9 ptexCube;
1097 DWORD iLevel;
1098 LPDIRECT3DSURFACE9 psurfSrc;
1099 LPDIRECT3DSURFACE9 psurfDest;
1101 CCubeMapDlg cubeMapDlg;
1102 if (IDCANCEL == cubeMapDlg.DoModal())
1103 return;
1105 // Change m_ptexOrig into a cubemap
1106 ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetLevelDesc(0, &sd);
1107 hr = D3DXCreateCubeTexture(pd3ddev, m_dwWidth, m_numMips, 0, sd.Format, D3DPOOL_MANAGED, &ptexCube);
1108 for (iLevel = 0; iLevel < m_numMips; iLevel++)
1110 hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(iLevel, &psurfSrc);
1111 hr = ptexCube->GetCubeMapSurface((D3DCUBEMAP_FACES)cubeMapDlg.m_iFace, iLevel, &psurfDest);
1112 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL,
1113 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1114 ReleasePpo(&psurfSrc);
1115 ReleasePpo(&psurfDest);
1117 ReleasePpo(&m_ptexOrig);
1118 m_ptexOrig = ptexCube;
1120 // Change m_ptexNew into a cubemap too
1121 if (m_ptexNew != NULL)
1123 ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd);
1124 hr = D3DXCreateCubeTexture(pd3ddev, m_dwWidth, m_numMips, 0, sd.Format, D3DPOOL_MANAGED, &ptexCube);
1125 for (iLevel = 0; iLevel < m_numMips; iLevel++)
1127 hr = ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetSurfaceLevel(iLevel, &psurfSrc);
1128 hr = ptexCube->GetCubeMapSurface((D3DCUBEMAP_FACES)cubeMapDlg.m_iFace, iLevel, &psurfDest);
1129 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL,
1130 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1131 ReleasePpo(&psurfSrc);
1132 ReleasePpo(&psurfDest);
1134 ReleasePpo(&m_ptexNew);
1135 m_ptexNew = ptexCube;
1137 m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES;
1138 SetModifiedFlag();
1139 UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
1143 void CDxtexDoc::OnFormatMakeIntoVolumeMap()
1145 HRESULT hr;
1146 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
1147 D3DSURFACE_DESC sd;
1148 LPDIRECT3DVOLUMETEXTURE9 ptexVolume;
1149 DWORD iLevel;
1150 LPDIRECT3DSURFACE9 psurfSrc;
1151 LPDIRECT3DVOLUME9 pvolumeDest;
1152 UINT numLayers;
1154 CVolumeMapDlg volumeMapDlg;
1155 if (IDCANCEL == volumeMapDlg.DoModal())
1156 return;
1158 numLayers = (1 << volumeMapDlg.m_powLayers) * 2;
1160 // Change m_ptexOrig into a volumemap
1161 ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetLevelDesc(0, &sd);
1162 hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, numLayers,
1163 m_numMips, 0, sd.Format, D3DPOOL_SYSTEMMEM, &ptexVolume, NULL);
1164 if (FAILED(hr))
1165 return;
1166 for (iLevel = 0; iLevel < m_numMips; iLevel++)
1168 hr = ((LPDIRECT3DTEXTURE9)m_ptexOrig)->GetSurfaceLevel(iLevel, &psurfSrc);
1169 hr = ptexVolume->GetVolumeLevel(iLevel, &pvolumeDest);
1170 hr = LoadVolumeSliceFromSurface(pvolumeDest, 0, psurfSrc);
1171 ReleasePpo(&psurfSrc);
1172 ReleasePpo(&pvolumeDest);
1174 ReleasePpo(&m_ptexOrig);
1175 m_ptexOrig = ptexVolume;
1177 // Change m_ptexNew into a volumemap too
1178 if (m_ptexNew != NULL)
1180 ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetLevelDesc(0, &sd);
1181 hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, numLayers,
1182 m_numMips, 0, sd.Format, D3DPOOL_SYSTEMMEM, &ptexVolume, NULL);
1183 if (FAILED(hr))
1184 return;
1185 for (iLevel = 0; iLevel < m_numMips; iLevel++)
1187 hr = ((LPDIRECT3DTEXTURE9)m_ptexNew)->GetSurfaceLevel(iLevel, &psurfSrc);
1188 hr = ptexVolume->GetVolumeLevel(iLevel, &pvolumeDest);
1189 hr = LoadVolumeSliceFromSurface(pvolumeDest, 0, psurfSrc);
1190 ReleasePpo(&psurfSrc);
1191 ReleasePpo(&pvolumeDest);
1193 ReleasePpo(&m_ptexNew);
1194 m_ptexNew = ptexVolume;
1196 m_dwDepth = numLayers;
1197 SetModifiedFlag();
1198 UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
1202 HRESULT CDxtexDoc::LoadVolumeSliceFromSurface(LPDIRECT3DVOLUME9 pVolume, UINT iSlice, LPDIRECT3DSURFACE9 psurf)
1204 HRESULT hr;
1205 D3DSURFACE_DESC sd;
1206 D3DVOLUME_DESC vd;
1207 D3DLOCKED_RECT lr;
1208 D3DBOX boxSrc;
1209 D3DBOX boxDest;
1211 psurf->GetDesc(&sd);
1212 pVolume->GetDesc(&vd);
1214 boxSrc.Left = 0;
1215 boxSrc.Right = sd.Width;
1216 boxSrc.Top = 0;
1217 boxSrc.Bottom = sd.Height;
1218 boxSrc.Front = 0;
1219 boxSrc.Back = 1;
1221 boxDest.Left = 0;
1222 boxDest.Right = vd.Width;
1223 boxDest.Top = 0;
1224 boxDest.Bottom = vd.Height;
1225 boxDest.Front = iSlice;
1226 boxDest.Back = iSlice + 1;
1228 hr = psurf->LockRect(&lr, NULL, 0);
1229 if (FAILED(hr))
1230 return hr;
1232 hr = D3DXLoadVolumeFromMemory(pVolume, NULL, &boxDest, lr.pBits, sd.Format, lr.Pitch,
1233 0, NULL, &boxSrc, D3DX_FILTER_TRIANGLE, 0);
1235 psurf->UnlockRect();
1237 return hr;
1241 HRESULT CDxtexDoc::LoadSurfaceFromVolumeSlice(LPDIRECT3DVOLUME9 pVolume, UINT iSlice, LPDIRECT3DSURFACE9 psurf)
1243 HRESULT hr;
1244 D3DVOLUME_DESC vd;
1245 D3DLOCKED_BOX lb;
1246 D3DBOX box;
1247 RECT rc;
1249 pVolume->GetDesc(&vd);
1251 box.Left = 0;
1252 box.Right = vd.Width;
1253 box.Top = 0;
1254 box.Bottom = vd.Height;
1255 box.Front = iSlice;
1256 box.Back = iSlice + 1;
1258 rc.left = 0;
1259 rc.right = vd.Width;
1260 rc.top = 0;
1261 rc.bottom = vd.Height;
1263 hr = pVolume->LockBox(&lb, &box, 0);
1264 if (FAILED(hr))
1265 return hr;
1267 hr = D3DXLoadSurfaceFromMemory(psurf, NULL, NULL, lb.pBits, vd.Format, lb.RowPitch,
1268 NULL, &rc, D3DX_FILTER_TRIANGLE, 0);
1270 pVolume->UnlockBox();
1272 return hr;
1276 HRESULT CDxtexDoc::BltAllLevels(D3DCUBEMAP_FACES FaceType,
1277 LPDIRECT3DBASETEXTURE9 ptexSrc, LPDIRECT3DBASETEXTURE9 ptexDest)
1279 HRESULT hr;
1280 LPDIRECT3DTEXTURE9 pmiptexSrc;
1281 LPDIRECT3DTEXTURE9 pmiptexDest;
1282 LPDIRECT3DCUBETEXTURE9 pcubetexSrc;
1283 LPDIRECT3DCUBETEXTURE9 pcubetexDest;
1284 LPDIRECT3DVOLUMETEXTURE9 pvoltexSrc;
1285 LPDIRECT3DVOLUMETEXTURE9 pvoltexDest;
1286 DWORD iLevel;
1288 if (IsVolumeMap())
1290 pvoltexSrc = (LPDIRECT3DVOLUMETEXTURE9)ptexSrc;
1291 pvoltexDest = (LPDIRECT3DVOLUMETEXTURE9)ptexDest;
1293 else if (IsCubeMap())
1295 pcubetexSrc = (LPDIRECT3DCUBETEXTURE9)ptexSrc;
1296 pcubetexDest = (LPDIRECT3DCUBETEXTURE9)ptexDest;
1298 else
1300 pmiptexSrc = (LPDIRECT3DTEXTURE9)ptexSrc;
1301 pmiptexDest = (LPDIRECT3DTEXTURE9)ptexDest;
1304 for (iLevel = 0; iLevel < m_numMips; iLevel++)
1306 if (IsVolumeMap())
1308 LPDIRECT3DVOLUME9 pvolSrc = NULL;
1309 LPDIRECT3DVOLUME9 pvolDest = NULL;
1310 hr = pvoltexSrc->GetVolumeLevel(iLevel, &pvolSrc);
1311 hr = pvoltexDest->GetVolumeLevel(iLevel, &pvolDest);
1312 hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL,
1313 pvolSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1314 ReleasePpo(&pvolSrc);
1315 ReleasePpo(&pvolDest);
1317 else if (IsCubeMap())
1319 LPDIRECT3DSURFACE9 psurfSrc = NULL;
1320 LPDIRECT3DSURFACE9 psurfDest = NULL;
1321 hr = pcubetexSrc->GetCubeMapSurface(FaceType, iLevel, &psurfSrc);
1322 hr = pcubetexDest->GetCubeMapSurface(FaceType, iLevel, &psurfDest);
1323 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL,
1324 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1325 ReleasePpo(&psurfSrc);
1326 ReleasePpo(&psurfDest);
1328 else
1330 LPDIRECT3DSURFACE9 psurfSrc = NULL;
1331 LPDIRECT3DSURFACE9 psurfDest = NULL;
1332 hr = pmiptexSrc->GetSurfaceLevel(iLevel, &psurfSrc);
1333 hr = pmiptexDest->GetSurfaceLevel(iLevel, &psurfDest);
1334 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL,
1335 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1336 ReleasePpo(&psurfSrc);
1337 ReleasePpo(&psurfDest);
1341 return S_OK;
1345 HRESULT CDxtexDoc::Resize(DWORD dwWidthNew, DWORD dwHeightNew)
1347 HRESULT hr;
1348 LPDIRECT3DTEXTURE9 pmiptexNew;
1349 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
1351 hr = pd3ddev->CreateTexture(dwWidthNew, dwHeightNew, m_numMips,
1352 0, GetFormat(m_ptexOrig), D3DPOOL_MANAGED, &pmiptexNew, NULL);
1353 if (FAILED(hr))
1354 return hr;
1355 if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, m_ptexOrig, pmiptexNew)))
1356 return hr;
1357 ReleasePpo(&m_ptexOrig);
1358 m_ptexOrig = pmiptexNew;
1360 if( m_ptexNew != NULL )
1362 hr = pd3ddev->CreateTexture(dwWidthNew, dwHeightNew, m_numMips,
1363 0, GetFormat(m_ptexOrig), D3DPOOL_MANAGED, &pmiptexNew, NULL);
1364 if (FAILED(hr))
1365 return hr;
1366 if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, m_ptexNew, pmiptexNew)))
1367 return hr;
1368 ReleasePpo(&m_ptexNew);
1369 m_ptexNew = pmiptexNew;
1372 m_dwWidth = dwWidthNew;
1373 m_dwHeight = dwHeightNew;
1374 SetModifiedFlag(TRUE);
1375 UpdateAllViews(NULL, 4);
1377 return S_OK;
1381 void CDxtexDoc::OpenCubeFace(D3DCUBEMAP_FACES FaceType)
1383 HRESULT hr;
1384 CString fileName;
1385 LPDIRECT3DSURFACE9 psurfOrig = NULL;
1386 LPDIRECT3DSURFACE9 psurfNew = NULL;
1388 if (!IsCubeMap())
1389 return;
1391 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetCubeMapSurface(FaceType, 0, &psurfOrig);
1392 if (m_ptexNew != NULL)
1393 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetCubeMapSurface(FaceType, 0, &psurfNew);
1395 if (!PromptForBmp(&fileName))
1396 return;
1398 hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_FILTER_TRIANGLE, 0, NULL);
1400 // Look for "foo_a.bmp" for alpha channel
1401 int i = fileName.ReverseFind('.');
1402 fileName = fileName.Left(i) + "_a.bmp";
1403 CFileStatus status;
1404 if (CFile::GetStatus(fileName, status))
1406 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
1407 return;
1410 if (m_numMips > 1)
1412 hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE9)m_ptexOrig, NULL, 0, D3DX_FILTER_TRIANGLE);
1416 if (psurfNew != NULL)
1418 hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1420 if (m_numMips > 1)
1422 hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE9)m_ptexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
1426 ReleasePpo(&psurfOrig);
1427 ReleasePpo(&psurfNew);
1429 SetModifiedFlag(TRUE);
1430 UpdateAllViews(NULL, 1);
1434 void CDxtexDoc::OpenAlphaCubeFace(D3DCUBEMAP_FACES FaceType)
1436 HRESULT hr;
1437 CString fileName;
1438 LPDIRECT3DSURFACE9 psurfOrig = NULL;
1439 LPDIRECT3DSURFACE9 psurfNew = NULL;
1440 D3DSURFACE_DESC sd;
1442 if (!IsCubeMap())
1443 return;
1445 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetCubeMapSurface(FaceType, 0, &psurfOrig);
1446 ((LPDIRECT3DCUBETEXTURE9)m_ptexOrig)->GetLevelDesc(0, &sd);
1447 if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
1449 AfxMessageBox(ID_ERROR_PREMULTALPHA);
1450 return;
1452 if (m_ptexNew != NULL)
1454 hr = ((LPDIRECT3DCUBETEXTURE9)m_ptexNew)->GetCubeMapSurface(FaceType, 0, &psurfNew);
1457 if (!PromptForBmp(&fileName))
1458 return;
1460 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
1461 return;
1463 if (psurfNew != NULL)
1465 if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfNew)))
1466 return;
1469 if (m_numMips > 1)
1471 hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE9)m_ptexOrig, NULL, 0, D3DX_FILTER_TRIANGLE);
1475 if (psurfNew != NULL)
1477 hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
1479 if (m_numMips > 1)
1481 hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE9)m_ptexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
1485 ReleasePpo(&psurfOrig);
1486 ReleasePpo(&psurfNew);
1488 SetModifiedFlag(TRUE);
1489 UpdateAllViews(NULL, 1);
1493 DWORD CDxtexDoc::DwDepthAt(LONG lwMip)
1495 DWORD dwDepth = m_dwDepth;
1496 while (lwMip > 0 && dwDepth > 1)
1498 dwDepth /= 2;
1499 lwMip--;
1501 return dwDepth;
1505 void CDxtexDoc::OnFormatChangeSurfaceFmt()
1507 CChangeFmtDlg changeFmtDlg;
1508 LPDIRECT3DBASETEXTURE9 ptex;
1510 ptex = (m_ptexNew == NULL ? m_ptexOrig : m_ptexNew);
1512 if (IsVolumeMap())
1514 D3DVOLUME_DESC vd;
1515 ((LPDIRECT3DVOLUMETEXTURE9)ptex)->GetLevelDesc(0, &vd);
1516 changeFmtDlg.m_fmt = vd.Format;
1518 else if (IsCubeMap())
1520 D3DSURFACE_DESC sd;
1521 ((LPDIRECT3DCUBETEXTURE9)ptex)->GetLevelDesc(0, &sd);
1522 changeFmtDlg.m_fmt = sd.Format;
1524 else
1526 D3DSURFACE_DESC sd;
1527 ((LPDIRECT3DTEXTURE9)ptex)->GetLevelDesc(0, &sd);
1528 changeFmtDlg.m_fmt = sd.Format;
1531 changeFmtDlg.m_bVolume = IsVolumeMap();
1533 if (IDCANCEL == changeFmtDlg.DoModal())
1534 return;
1536 Compress(changeFmtDlg.m_fmt, TRUE);
1540 void CDxtexDoc::OnUpdateFileOpenAlpha(CCmdUI* pCmdUI)
1542 pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap());
1546 void CDxtexDoc::OnUpdateFormatGenerateMipmaps(CCmdUI* pCmdUI)
1548 pCmdUI->Enable(m_numMips <= 1);
1552 void CDxtexDoc::OnUpdateFormatChangeCubeMapFaces(CCmdUI* pCmdUI)
1554 pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap());
1558 void CDxtexDoc::OnUpdateFormatMakeIntoVolumeMap(CCmdUI* pCmdUI)
1560 pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap());
1564 void CDxtexDoc::OnFormatResize()
1566 CResizeDialog resizeDialog;
1568 resizeDialog.m_oldWidth.Format("%d", m_dwWidth);
1569 resizeDialog.m_oldHeight.Format("%d", m_dwHeight);
1570 resizeDialog.m_newWidth = m_dwWidth;
1571 resizeDialog.m_newHeight = m_dwHeight;
1572 resizeDialog.m_oldWidth.Format("%d", m_dwWidth);
1573 if( IDOK == resizeDialog.DoModal() )
1574 Resize(resizeDialog.m_newWidth, resizeDialog.m_newHeight);
1578 void CDxtexDoc::OnUpdateFormatResize(CCmdUI* pCmdUI)
1580 pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap());
1583 struct GenerateSpecularLookupData
1585 float power;
1588 VOID WINAPI SpecularColorFill(D3DXVECTOR4* pOut, const D3DXVECTOR2* pTexCoord, const D3DXVECTOR2* pTexelSize, LPVOID pData)
1590 float d = pTexCoord->x;
1591 float s = static_cast<float>(pow(pTexCoord->y, reinterpret_cast<GenerateSpecularLookupData*>(pData)->power));
1593 if (pTexCoord->x < pTexelSize->x)
1594 s = 0.0f;
1596 pOut->x = d;
1597 pOut->y = d;
1598 pOut->z = d;
1599 pOut->w = s;
1602 void CDxtexDoc::OnFormatGeneratespecularlookup()
1604 if (IsVolumeMap())
1605 return;
1606 if (IsCubeMap())
1607 return;
1609 CSpecularPowerDialog specularPowerDialog;
1610 if( IDOK == specularPowerDialog.DoModal() )
1612 GenerateSpecularLookupData specularLookupData;
1613 specularLookupData.power = static_cast<float>(atof(specularPowerDialog.m_specularPower));
1615 // TODO: Add your command handler code here
1616 HRESULT hresult = D3DXFillTexture((LPDIRECT3DTEXTURE9)m_ptexOrig, SpecularColorFill, &specularLookupData);
1618 SetModifiedFlag(TRUE);
1619 UpdateAllViews(NULL, 4);
1623 void CDxtexDoc::OnUpdateFormatGeneratespecularlookup(CCmdUI* pCmdUI)
1625 // TODO: Add your command update UI handler code here
1626 pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap());