dsrc isn't necessary for this repo
[client-tools.git] / src / external / 3rd / application / DXTex / dxtexview.cpp
blob623169cf3822844aacc6e438d3245221e0fbb1da
1 // dxtexView.cpp : implementation of the CDxtexView class
2 //
4 #include "stdafx.h"
5 #include "dxtex.h"
6 #include "dxtexDoc.h"
7 #include "dxtexView.h"
9 #ifdef _DEBUG
10 #define new DEBUG_NEW
11 #undef THIS_FILE
12 static char THIS_FILE[] = __FILE__;
13 #endif
15 // Our custom vertex type
16 struct CUSTOMVERTEX
18 FLOAT x, y, z;
19 FLOAT rhw;
20 DWORD color;
21 FLOAT tu, tv; // The texture coordinates
24 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
27 IMPLEMENT_DYNCREATE(CDxtexView, CScrollView)
29 BEGIN_MESSAGE_MAP(CDxtexView, CScrollView)
30 //{{AFX_MSG_MAP(CDxtexView)
31 ON_WM_LBUTTONUP()
32 ON_COMMAND(ID_FILE_OPENSUBSURFACE, OnFileOpenSubsurface)
33 ON_COMMAND(ID_FILE_OPENALPHASUBSURFACE, OnFileOpenAlphaSubsurface)
34 ON_COMMAND(ID_FILE_OPENFACE, OnFileOpenFace)
35 ON_COMMAND(ID_FILE_OPENALPHAFACE, OnFileOpenAlphaFace)
36 ON_COMMAND(ID_VIEW_ORIGINAL, OnViewOriginal)
37 ON_COMMAND(ID_VIEW_COMPRESSED, OnViewCompressed)
38 ON_COMMAND(ID_VIEW_SMALLERMIPLEVEL, OnViewSmallerMipLevel)
39 ON_COMMAND(ID_VIEW_LARGERMIPLEVEL, OnViewLargerMipLevel)
40 ON_COMMAND(ID_VIEW_ALPHACHANNEL, OnViewAlphaChannel)
41 ON_COMMAND(ID_VIEW_RGBONLY, OnViewRgbOnly)
42 ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomIn)
43 ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomOut)
44 ON_COMMAND(ID_VIEW_CHANGEBACKGROUNDCOLOR, OnViewChangeBackgroundColor)
45 ON_COMMAND(ID_VIEW_NEGX, OnViewNegX)
46 ON_COMMAND(ID_VIEW_POSX, OnViewPosX)
47 ON_COMMAND(ID_VIEW_NEGY, OnViewNegY)
48 ON_COMMAND(ID_VIEW_POSY, OnViewPosY)
49 ON_COMMAND(ID_VIEW_NEGZ, OnViewNegZ)
50 ON_COMMAND(ID_VIEW_POSZ, OnViewPosZ)
51 ON_COMMAND(ID_VIEW_HIGHERVOLUMESLICE, OnViewHigherVolumeSlice)
52 ON_COMMAND(ID_VIEW_LOWERVOLUMESLICE, OnViewLowerVolumeSlice)
53 ON_UPDATE_COMMAND_UI(ID_FILE_OPENSUBSURFACE, OnUpdateFileOpenSubsurface)
54 ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHASUBSURFACE, OnUpdateFileOpenAlphaSubsurface)
55 ON_UPDATE_COMMAND_UI(ID_FILE_OPENFACE, OnUpdateFileOpenFace)
56 ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHAFACE, OnUpdateFileOpenAlphaFace)
57 ON_UPDATE_COMMAND_UI(ID_VIEW_ORIGINAL, OnUpdateViewOriginal)
58 ON_UPDATE_COMMAND_UI(ID_VIEW_COMPRESSED, OnUpdateViewCompressed)
59 ON_UPDATE_COMMAND_UI(ID_VIEW_ALPHACHANNEL, OnUpdateViewAlphaChannel)
60 ON_UPDATE_COMMAND_UI(ID_VIEW_RGBONLY, OnUpdateViewRgbOnly)
61 ON_UPDATE_COMMAND_UI(ID_VIEW_LARGERMIPLEVEL, OnUpdateViewLargerMipLevel)
62 ON_UPDATE_COMMAND_UI(ID_VIEW_SMALLERMIPLEVEL, OnUpdateViewSmallerMipLevel)
63 ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMIN, OnUpdateViewZoomIn)
64 ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMOUT, OnUpdateViewZoomOut)
65 ON_UPDATE_COMMAND_UI(ID_VIEW_NEGX, OnUpdateViewNegX)
66 ON_UPDATE_COMMAND_UI(ID_VIEW_POSX, OnUpdateViewPosX)
67 ON_UPDATE_COMMAND_UI(ID_VIEW_NEGY, OnUpdateViewNegY)
68 ON_UPDATE_COMMAND_UI(ID_VIEW_POSY, OnUpdateViewPosY)
69 ON_UPDATE_COMMAND_UI(ID_VIEW_NEGZ, OnUpdateViewNegZ)
70 ON_UPDATE_COMMAND_UI(ID_VIEW_POSZ, OnUpdateViewPosZ)
71 ON_UPDATE_COMMAND_UI(ID_VIEW_HIGHERVOLUMESLICE, OnUpdateViewHigherVolumeSlice)
72 ON_UPDATE_COMMAND_UI(ID_VIEW_LOWERVOLUMESLICE, OnUpdateViewLowerVolumeSlice)
73 //}}AFX_MSG_MAP
74 END_MESSAGE_MAP()
76 static UINT GetSurfaceSize(D3DSURFACE_DESC* pDesc)
78 switch( pDesc->Format )
80 case D3DFMT_A16B16G16R16:
81 return pDesc->Width * pDesc->Height * 8;
83 case D3DFMT_A8R8G8B8:
84 case D3DFMT_X8R8G8B8:
85 case D3DFMT_A2R10G10B10:
86 return pDesc->Width * pDesc->Height * 4;
88 case D3DFMT_R8G8B8:
89 return pDesc->Width * pDesc->Height * 3;
91 case D3DFMT_A1R5G5B5:
92 case D3DFMT_X1R5G5B5:
93 case D3DFMT_A4R4G4B4:
94 case D3DFMT_X4R4G4B4:
95 case D3DFMT_R5G6B5:
96 return pDesc->Width * pDesc->Height * 2;
98 case D3DFMT_R3G3B2:
99 return pDesc->Width * pDesc->Height * 1;
101 case D3DFMT_DXT1:
102 return pDesc->Width * pDesc->Height / 2;
104 case D3DFMT_DXT2:
105 case D3DFMT_DXT3:
106 case D3DFMT_DXT4:
107 case D3DFMT_DXT5:
108 return pDesc->Width * pDesc->Height * 1;
110 default:
111 return 0;
115 static UINT GetVolumeSize(D3DVOLUME_DESC* pDesc)
117 switch( pDesc->Format )
119 case D3DFMT_A16B16G16R16:
120 return pDesc->Width * pDesc->Height * pDesc->Depth * 8;
122 case D3DFMT_A8R8G8B8:
123 case D3DFMT_X8R8G8B8:
124 case D3DFMT_A2R10G10B10:
125 return pDesc->Width * pDesc->Height * pDesc->Depth * 4;
127 case D3DFMT_R8G8B8:
128 return pDesc->Width * pDesc->Height * pDesc->Depth * 3;
130 case D3DFMT_A1R5G5B5:
131 case D3DFMT_X1R5G5B5:
132 case D3DFMT_A4R4G4B4:
133 case D3DFMT_X4R4G4B4:
134 case D3DFMT_R5G6B5:
135 return pDesc->Width * pDesc->Height * pDesc->Depth * 2;
137 case D3DFMT_R3G3B2:
138 return pDesc->Width * pDesc->Height * pDesc->Depth * 1;
140 case D3DFMT_DXT1:
141 return pDesc->Width * pDesc->Height * pDesc->Depth / 2;
143 case D3DFMT_DXT2:
144 case D3DFMT_DXT3:
145 case D3DFMT_DXT4:
146 case D3DFMT_DXT5:
147 return pDesc->Width * pDesc->Height * pDesc->Depth * 1;
149 default:
150 return 0;
155 CDxtexView::CDxtexView()
157 m_pVB = NULL;
158 m_ptexCur = NULL;
159 m_pSwapChain = NULL;
160 m_lwMipCur = 0;
161 m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD;
162 m_lwSliceCur = -1;
163 m_fZoom = 1.0f;
164 m_bViewOrig = TRUE;
165 m_bRgbOnly = TRUE;
166 m_bViewAlpha = FALSE;
170 CDxtexView::~CDxtexView()
172 ReleasePpo(&m_pVB);
173 ReleasePpo(&m_ptexCur);
174 ReleasePpo(&m_pSwapChain);
178 // Note: repaints don't require re-rendering, just recopy from back buffer to view's DC
179 void CDxtexView::OnDraw(CDC* pDC)
181 CDxtexDoc* pDoc = GetDocument();
182 ASSERT_VALID(pDoc);
184 HRESULT hr;
185 CRect rcSrc;
186 CRect rcDest;
188 rcSrc = m_rcSrc;
189 rcDest = m_rcDest;
191 rcDest.OffsetRect(pDC->GetViewportOrg());
193 // REVIEW: only update dirty region?
194 if (m_pSwapChain != NULL)
196 if( PDxtexApp()->HandlePossibleLostDevice() )
198 hr = m_pSwapChain->Present(&rcSrc, &rcDest, GetSafeHwnd(), NULL, 0);
199 if( hr == D3DERR_DEVICELOST )
201 PDxtexApp()->DeviceIsLost();
202 Invalidate();
209 #ifdef _DEBUG
210 void CDxtexView::AssertValid() const
212 CScrollView::AssertValid();
216 void CDxtexView::Dump(CDumpContext& dc) const
218 CScrollView::Dump(dc);
222 CDxtexDoc* CDxtexView::GetDocument() // non-debug version is inline
224 ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDxtexDoc)));
225 return (CDxtexDoc*)m_pDocument;
227 #endif //_DEBUG
230 void CDxtexView::OnLButtonUp(UINT nFlags, CPoint point)
232 // Button click means toggle compressed / uncompressed view
233 if (m_bViewOrig)
234 OnViewCompressed();
235 else
236 OnViewOriginal();
238 CScrollView::OnLButtonUp(nFlags, point);
242 void CDxtexView::OnInitialUpdate()
244 #ifdef _WIN64
245 SetClassLongPtr(GetSafeHwnd(), GCLP_HBRBACKGROUND, (LONG_PTR)CreateSolidBrush(RGB(100, 100, 120)));
246 #else
247 SetClassLong(GetSafeHwnd(), GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(100, 100, 120)));
248 #endif
250 if (GetDocument()->IsCubeMap())
251 m_CubeFaceCur = D3DCUBEMAP_FACE_POSITIVE_X;
252 else
253 m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD;
254 if (GetDocument()->IsVolumeMap())
255 m_lwSliceCur = 0;
256 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
257 UpdateDevice();
258 CreateVertexBuffer();
259 RenderScene();
261 SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
262 ResizeParentToFit();
264 CScrollView::OnInitialUpdate();
266 m_bTitleModsChanged = TRUE; // force title bar update
270 VOID CDxtexView::GetImageInfo(CString& strInfo)
272 LPDIRECT3DBASETEXTURE9 ptex;
273 D3DSURFACE_DESC sd;
274 D3DVOLUME_DESC vd;
275 D3DFORMAT fmt;
276 DWORD dwWidth;
277 DWORD dwHeight;
278 DWORD dwDepth;
279 CString strFormat;
280 TCHAR sz[100];
281 DWORD dwBytes = 0;
282 UINT iLevel;
284 if (m_bViewOrig)
285 ptex = GetDocument()->PtexOrig();
286 else
287 ptex = GetDocument()->PtexNew();
289 if (GetDocument()->IsVolumeMap())
291 ((LPDIRECT3DVOLUMETEXTURE9)ptex)->GetLevelDesc(0, &vd);
292 fmt = vd.Format;
293 dwWidth = vd.Width;
294 dwHeight = vd.Height;
295 dwDepth = vd.Depth;
297 else if (!GetDocument()->IsCubeMap())
299 ((LPDIRECT3DTEXTURE9)ptex)->GetLevelDesc(0, &sd);
300 fmt = sd.Format;
301 dwWidth = sd.Width;
302 dwHeight = sd.Height;
303 dwDepth = 0;
305 else
307 ((LPDIRECT3DCUBETEXTURE9)ptex)->GetLevelDesc(0, &sd);
308 fmt = sd.Format;
309 dwWidth = sd.Width;
310 dwHeight = sd.Height;
311 dwDepth = 0;
314 strFormat = FormatName(fmt);
316 // Count bytes in main surface chain
317 if (GetDocument()->IsVolumeMap())
319 for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++)
321 ((LPDIRECT3DVOLUMETEXTURE9)ptex)->GetLevelDesc(iLevel, &vd);
322 dwBytes += GetVolumeSize(&vd);
325 else if (!GetDocument()->IsCubeMap())
327 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_FORCE_DWORD, ptex);
329 else
331 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_X, ptex);
332 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_X, ptex);
333 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Y, ptex);
334 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Y, ptex);
335 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Z, ptex);
336 dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Z, ptex);
339 if (dwDepth == 0)
340 wsprintf(sz, "%d x %d, %s, %d bytes", dwWidth, dwHeight, (LPCTSTR)strFormat, dwBytes);
341 else
342 wsprintf(sz, "%d x %d x %d, %s, %d bytes", dwWidth, dwHeight, dwDepth, (LPCTSTR)strFormat, dwBytes);
343 strInfo = sz;
347 DWORD CDxtexView::NumBytesInSurfaces(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE9 ptex)
349 DWORD dwBytes = 0;
350 LPDIRECT3DTEXTURE9 pmiptex = NULL;
351 LPDIRECT3DCUBETEXTURE9 pcubetex = NULL;
352 D3DSURFACE_DESC sd;
353 DWORD iLevel;
355 if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
356 pmiptex = (LPDIRECT3DTEXTURE9)ptex;
357 else
358 pcubetex = (LPDIRECT3DCUBETEXTURE9)ptex;
360 for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++)
362 if (pmiptex != NULL)
363 pmiptex->GetLevelDesc(iLevel, &sd);
364 else
365 pcubetex->GetLevelDesc(iLevel, &sd);
366 dwBytes += GetSurfaceSize(&sd);
369 return dwBytes;
373 HRESULT CDxtexView::UpdateDevice(VOID)
375 HRESULT hr;
376 LPDIRECT3D9 pd3d = PDxtexApp()->Pd3d();
377 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
378 D3DDISPLAYMODE dispMode;
379 D3DPRESENT_PARAMETERS presentParams;
381 pd3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode);
383 ReleasePpo(&m_pSwapChain);
384 ZeroMemory(&presentParams, sizeof(presentParams));
385 presentParams.Windowed = TRUE;
386 presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
387 presentParams.BackBufferWidth = m_rcSrc.Width();
388 presentParams.BackBufferHeight = m_rcSrc.Height();
389 presentParams.BackBufferFormat = dispMode.Format;
391 if (FAILED(hr = pd3ddev->CreateAdditionalSwapChain(&presentParams, &m_pSwapChain)))
392 return hr;
394 COLORREF crBkgd;
395 crBkgd = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255));
396 m_dwClearColor = D3DCOLOR_RGBA(GetRValue(crBkgd), GetGValue(crBkgd), GetBValue(crBkgd), 255);
398 return S_OK;
401 HRESULT CDxtexView::InvalidateDeviceObjects(VOID)
403 ReleasePpo( &m_pSwapChain );
404 return S_OK;
407 HRESULT CDxtexView::RestoreDeviceObjects(VOID)
409 UpdateDevice();
410 RenderScene();
411 Invalidate();
412 return S_OK;
415 HRESULT CDxtexView::CreateVertexBuffer(VOID)
417 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
419 // Create the the vertex buffer
420 if( FAILED( pd3ddev->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX),
421 0 /* Usage */, D3DFVF_CUSTOMVERTEX,
422 D3DPOOL_MANAGED, &m_pVB, NULL ) ) )
424 return E_FAIL;
427 return S_OK;
431 HRESULT CDxtexView::RenderScene(VOID)
433 CWaitCursor waitCursor;
434 HRESULT hr;
435 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
437 LPDIRECT3DSURFACE9 psurf;
439 if (m_pSwapChain == NULL)
440 return E_FAIL;
442 // Vertices for our quad
443 CUSTOMVERTEX vertexArray[] =
445 // x, y, z, rhw, color
446 { 0.0f, 0.0f, 0.5f, 1.0f, 0xffffffff, 0.0, 0.0, },
447 { (FLOAT)m_rcSrc.right, 0.0f, 0.5f, 1.0f, 0xffffffff, 1.0, 0.0, },
448 { (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, },
450 { (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, },
451 { 0.0f, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 0.0, 1.0, },
452 { 0.0f, 0.0f, 0.5f, 1.0f, 0xffffffff, 0.0, 0.0, },
455 // Copy the global vertex data into the vertex buffer
456 VOID* pVertices;
457 if( FAILED( m_pVB->Lock( 0, sizeof(vertexArray), (void**)&pVertices, 0 ) ) )
458 return E_FAIL;
459 memcpy( pVertices, vertexArray, sizeof(vertexArray) );
460 m_pVB->Unlock();
462 hr = m_pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &psurf);
464 hr = pd3ddev->SetRenderTarget(0, psurf);
466 ReleasePpo(&psurf);
468 hr = pd3ddev->Clear(0, NULL, D3DCLEAR_TARGET, m_dwClearColor, 0.0f, 0);
470 hr = pd3ddev->BeginScene();
472 // If the texture uses premultiplied alpha, the source blend should be D3DBLEND_ONE
473 // since RGB is already at the level we want. With nonpremultiplied alpha, the
474 // source blend should be D3DBLEND_SRCALPHA.
475 D3DSURFACE_DESC sd;
476 m_ptexCur->GetLevelDesc(0, &sd);
477 if (!m_bViewAlpha && (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4))
479 if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)))
480 return hr;
482 else
484 if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)))
485 return hr;
487 hr = pd3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
488 hr = pd3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, m_bRgbOnly ? FALSE : TRUE);
490 pd3ddev->SetTexture(0, m_ptexCur);
491 pd3ddev->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) );
492 pd3ddev->SetFVF( D3DFVF_CUSTOMVERTEX );
493 pd3ddev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
494 pd3ddev->SetTexture(0, NULL);
496 hr = pd3ddev->EndScene();
498 return S_OK;
502 void CDxtexView::OnViewOriginal()
504 if (GetDocument()->PtexOrig() == NULL)
505 return;
506 BuildViewSurface(TRUE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
507 RenderScene();
508 m_bTitleModsChanged = TRUE; // force title bar update
509 InvalidateRect(&m_rcDest, FALSE); // force redraw of this view
513 void CDxtexView::OnViewCompressed()
515 if (GetDocument()->PtexNew() == NULL)
516 return;
517 BuildViewSurface(FALSE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
518 RenderScene();
519 m_bTitleModsChanged = TRUE; // force title bar update
520 InvalidateRect(&m_rcDest, FALSE); // force redraw of this view
524 void CDxtexView::OnUpdateViewOriginal(CCmdUI* pCmdUI)
526 if (GetDocument()->PtexOrig() == NULL)
528 pCmdUI->Enable(FALSE);
529 pCmdUI->SetCheck(0);
531 else
533 pCmdUI->Enable(TRUE);
534 pCmdUI->SetCheck(m_bViewOrig);
539 void CDxtexView::OnUpdateViewCompressed(CCmdUI* pCmdUI)
541 if (GetDocument()->PtexNew() == NULL)
543 pCmdUI->Enable(FALSE);
544 pCmdUI->SetCheck(0);
546 else
548 pCmdUI->Enable(TRUE);
549 pCmdUI->SetCheck(!m_bViewOrig);
554 void CDxtexView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
556 m_bTitleModsChanged = TRUE; // force title bar update
557 if (lHint == 1)
559 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
560 RenderScene();
562 else if (lHint == 2)
564 UpdateDevice();
565 RenderScene();
567 else if (lHint == 3)
569 RenderScene();
571 else if( lHint == 4)
573 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
574 UpdateDevice();
575 RenderScene();
576 SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
577 ResizeParentToFit();
580 CScrollView::OnUpdate(pSender, lHint, pHint);
584 void CDxtexView::OnViewSmallerMipLevel()
586 m_lwMipCur++;
587 if (m_lwSliceCur > 0)
588 m_lwSliceCur /= 2;
589 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
590 UpdateDevice();
591 RenderScene();
592 m_bTitleModsChanged = TRUE; // force title bar update
593 SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
594 Invalidate(); // force redraw of this view
598 void CDxtexView::OnViewLargerMipLevel()
600 m_lwMipCur--;
601 if (m_lwSliceCur > 0)
602 m_lwSliceCur *= 2;
603 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
604 UpdateDevice();
605 RenderScene();
606 m_bTitleModsChanged = TRUE; // force title bar update
607 SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
608 Invalidate(); // force redraw of this view
612 void CDxtexView::OnViewAlphaChannel(VOID)
614 m_bRgbOnly = false;
615 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, !m_bViewAlpha);
616 RenderScene();
617 Invalidate(); // force redraw of this view
618 m_bTitleModsChanged = TRUE; // force title bar update
622 void CDxtexView::OnUpdateViewAlphaChannel(CCmdUI* pCmdUI)
624 pCmdUI->SetCheck(m_bViewAlpha);
627 void CDxtexView::OnViewRgbOnly(VOID)
629 m_bRgbOnly = !m_bRgbOnly;
630 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, false);
631 RenderScene();
632 Invalidate(); // force redraw of this view
633 m_bTitleModsChanged = TRUE; // force title bar update
637 void CDxtexView::OnUpdateViewRgbOnly(CCmdUI* pCmdUI)
639 pCmdUI->Enable(TRUE);
640 pCmdUI->SetCheck(m_bRgbOnly);
644 void CDxtexView::OnUpdateViewLargerMipLevel(CCmdUI* pCmdUI)
646 if (m_lwMipCur > 0)
647 pCmdUI->Enable(TRUE);
648 else
649 pCmdUI->Enable(FALSE);
653 void CDxtexView::OnUpdateViewSmallerMipLevel(CCmdUI* pCmdUI)
655 if (m_lwMipCur < (LONG)GetDocument()->NumMips() - 1)
656 pCmdUI->Enable(TRUE);
657 else
658 pCmdUI->Enable(FALSE);
662 void CDxtexView::OnViewZoomIn()
664 if (m_fZoom < 8.0f)
665 m_fZoom *= 2.0f;
666 m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom);
667 m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom);
668 SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
669 m_bTitleModsChanged = TRUE; // force title bar update
670 Invalidate(); // force redraw of this view
674 void CDxtexView::OnViewZoomOut()
676 if (m_fZoom > 0.125f)
677 m_fZoom /= 2.0f;
678 m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom);
679 m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom);
680 SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height()));
681 m_bTitleModsChanged = TRUE; // force title bar update
682 Invalidate(); // force redraw of this view
686 void CDxtexView::OnUpdateViewZoomIn(CCmdUI* pCmdUI)
688 pCmdUI->Enable(m_fZoom < 8.0f);
692 void CDxtexView::OnUpdateViewZoomOut(CCmdUI* pCmdUI)
694 pCmdUI->Enable(m_fZoom > 0.125f);
698 CString CDxtexView::GetStrTitleMods(VOID)
700 CString strTitleMods;
701 strTitleMods = "(";
703 // Append alpha, if in alpha mode
704 if (m_bViewAlpha)
705 strTitleMods += "Alpha, ";
707 // Show format
708 LPDIRECT3DBASETEXTURE9 ptex;
709 CString strFormat;
710 D3DFORMAT fmt;
712 if (m_bViewOrig)
713 ptex = GetDocument()->PtexOrig();
714 else
715 ptex = GetDocument()->PtexNew();
717 if (GetDocument()->IsVolumeMap())
719 D3DVOLUME_DESC vd;
720 ((LPDIRECT3DVOLUMETEXTURE9)ptex)->GetLevelDesc(0, &vd);
721 fmt = vd.Format;
723 else if (!GetDocument()->IsCubeMap())
725 D3DSURFACE_DESC sd;
726 ((LPDIRECT3DTEXTURE9)ptex)->GetLevelDesc(0, &sd);
727 fmt = sd.Format;
729 else
731 D3DSURFACE_DESC sd;
732 ((LPDIRECT3DCUBETEXTURE9)ptex)->GetLevelDesc(0, &sd);
733 fmt = sd.Format;
736 strTitleMods += FormatName(fmt);
737 strTitleMods += TEXT(", ");
739 // Append cube map info, if a cube map
740 switch (m_CubeFaceCur)
742 case D3DCUBEMAP_FACE_NEGATIVE_X:
743 strTitleMods += "Negative X, ";
744 break;
745 case D3DCUBEMAP_FACE_POSITIVE_X:
746 strTitleMods += "Positive X, ";
747 break;
748 case D3DCUBEMAP_FACE_NEGATIVE_Y:
749 strTitleMods += "Negative Y, ";
750 break;
751 case D3DCUBEMAP_FACE_POSITIVE_Y:
752 strTitleMods += "Positive Y, ";
753 break;
754 case D3DCUBEMAP_FACE_NEGATIVE_Z:
755 strTitleMods += "Negative Z, ";
756 break;
757 case D3DCUBEMAP_FACE_POSITIVE_Z:
758 strTitleMods += "Positive Z, ";
759 break;
762 if (m_lwSliceCur >= 0)
764 CString strSlice;
765 strSlice.Format("Slice %d of %d, ", m_lwSliceCur + 1, GetDocument()->DwDepthAt(m_lwMipCur));
766 strTitleMods += strSlice;
769 // Append mip info, if multiple mip levels
770 DWORD dwNumMips = GetDocument()->NumMips();
771 if (dwNumMips > 1)
773 CString strMipInfo;
774 strMipInfo.Format("Mip %d of %d, ", m_lwMipCur + 1, dwNumMips);
775 strTitleMods += strMipInfo;
778 // Append view magnification
779 CString strView;
780 strView.Format("%d", (LONG)(100 * m_fZoom));
781 strTitleMods += strView + "%";
783 strTitleMods += ")";
784 return strTitleMods;
788 CString CDxtexView::FormatName(D3DFORMAT fmt)
790 CString str;
791 switch (fmt)
793 case D3DFMT_A8R8G8B8:
794 str = TEXT("A8R8G8B8");
795 break;
796 case D3DFMT_A1R5G5B5:
797 str = TEXT("A1R5G5B5");
798 break;
799 case D3DFMT_A4R4G4B4:
800 str = TEXT("A4R4G4B4");
801 break;
802 case D3DFMT_R8G8B8:
803 str = TEXT("R8G8B8");
804 break;
805 case D3DFMT_R5G6B5:
806 str = TEXT("R5G6B5");
807 break;
808 case D3DFMT_X8R8G8B8:
809 str = TEXT("X8R8G8B8");
810 break;
811 case D3DFMT_X1R5G5B5:
812 str = TEXT("X1R5G5B5");
813 break;
814 case D3DFMT_R3G3B2:
815 str = TEXT("R3G3B2");
816 break;
817 case D3DFMT_A8R3G3B2:
818 str = TEXT("A8R3G3B2");
819 break;
820 case D3DFMT_X4R4G4B4:
821 str = TEXT("X4R4G4B4");
822 break;
823 case D3DFMT_DXT1:
824 str = TEXT("DXT1");
825 break;
826 case D3DFMT_DXT2:
827 str = TEXT("DXT2");
828 break;
829 case D3DFMT_DXT3:
830 str = TEXT("DXT3");
831 break;
832 case D3DFMT_DXT4:
833 str = TEXT("DXT4");
834 break;
835 case D3DFMT_DXT5:
836 str = TEXT("DXT5");
837 break;
838 case D3DFMT_A2R10G10B10:
839 str = TEXT("A2R10G10B10");
840 break;
841 case D3DFMT_A16B16G16R16:
842 str = TEXT("A16B16G16R16");
843 break;
844 default:
845 str = TEXT("unknown fmt");
846 break;
848 return str;
851 void CDxtexView::OnViewChangeBackgroundColor()
853 CHOOSECOLOR cc;
854 COLORREF crArray[16];
856 ZeroMemory(&cc, sizeof(cc));
857 cc.lStructSize = sizeof(cc);
858 cc.hwndOwner = GetSafeHwnd();
859 cc.rgbResult = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255));
860 cc.lpCustColors = crArray;
861 cc.Flags = CC_RGBINIT | CC_ANYCOLOR | CC_FULLOPEN;
863 if (ChooseColor(&cc))
865 PDxtexApp()->WriteProfileInt("Settings", "Background Color", cc.rgbResult);
867 // Update all views of all documents of our one doc template
868 POSITION posTemp = PDxtexApp()->GetFirstDocTemplatePosition();
869 CDocTemplate* pDocTemplate = PDxtexApp()->GetNextDocTemplate(posTemp);
870 CDocument* pdoc;
871 POSITION pos = pDocTemplate->GetFirstDocPosition();
872 while (pos != NULL)
874 pdoc = pDocTemplate->GetNextDoc(pos);
875 pdoc->UpdateAllViews(NULL, 2);
881 void CDxtexView::OnFileOpenSubsurface()
883 GetDocument()->OpenSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur);
887 void CDxtexView::OnUpdateFileOpenSubsurface(CCmdUI* pCmdUI)
889 pCmdUI->Enable(TRUE);
893 void CDxtexView::OnFileOpenAlphaSubsurface()
895 GetDocument()->OpenAlphaSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur);
899 void CDxtexView::OnUpdateFileOpenAlphaSubsurface(CCmdUI* pCmdUI)
901 pCmdUI->Enable(TRUE);
905 HRESULT CDxtexView::BuildViewSurface(BOOL bOrig, D3DCUBEMAP_FACES FaceType, LONG lwSlice, LONG lwMip, BOOL bViewAlpha)
907 HRESULT hr;
908 LPDIRECT3DDEVICE9 pd3ddev = PDxtexApp()->Pd3ddev();
909 LPDIRECT3DBASETEXTURE9 ptex;
910 BOOL bIsCubeMap = GetDocument()->IsCubeMap();
911 BOOL bIsVolumeMap = GetDocument()->IsVolumeMap();
912 D3DSURFACE_DESC sd;
913 D3DVOLUME_DESC vd;
915 ReleasePpo(&m_ptexCur);
917 if (bIsVolumeMap && lwSlice == -1)
918 lwSlice = 0;
920 if (bIsCubeMap && FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
921 FaceType = D3DCUBEMAP_FACE_POSITIVE_X;
923 m_bViewOrig = bOrig;
924 m_bViewAlpha = bViewAlpha;
925 m_lwSliceCur = lwSlice;
926 m_lwMipCur = lwMip;
927 m_CubeFaceCur = FaceType;
929 if (bOrig)
930 ptex = GetDocument()->PtexOrig();
931 else
932 ptex = GetDocument()->PtexNew();
934 if (bIsVolumeMap)
936 ((LPDIRECT3DVOLUMETEXTURE9)ptex)->GetLevelDesc(m_lwMipCur, &vd);
937 sd.Width = vd.Width;
938 sd.Height = vd.Height;
940 else if (!bIsCubeMap)
942 ((LPDIRECT3DTEXTURE9)ptex)->GetLevelDesc(m_lwMipCur, &sd);
944 else
946 ((LPDIRECT3DCUBETEXTURE9)ptex)->GetLevelDesc(m_lwMipCur, &sd);
949 hr = pd3ddev->CreateTexture(sd.Width, sd.Height, 1,
950 0 /* Usage */, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_ptexCur, NULL);
951 if (FAILED(hr))
952 return hr;
954 m_rcSrc.SetRect(0, 0, sd.Width, sd.Height);
955 m_rcDest.SetRect(0, 0, (INT)(sd.Width * m_fZoom), (INT)(sd.Height * m_fZoom));
957 LPDIRECT3DSURFACE9 psurfSrc = NULL;
958 LPDIRECT3DSURFACE9 psurfDest = NULL;
960 hr = m_ptexCur->GetSurfaceLevel(0, &psurfDest);
962 if (bIsVolumeMap)
964 LPDIRECT3DVOLUME9 pvolSrc;
965 hr = ((LPDIRECT3DVOLUMETEXTURE9)ptex)->GetVolumeLevel(m_lwMipCur, &pvolSrc);
966 hr = LoadSurfaceFromVolumeSlice(pvolSrc, m_lwSliceCur, psurfDest);
967 ReleasePpo(&pvolSrc);
969 else if (!bIsCubeMap)
971 hr = ((LPDIRECT3DTEXTURE9)ptex)->GetSurfaceLevel(m_lwMipCur, &psurfSrc);
972 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
973 D3DX_FILTER_TRIANGLE, 0);
975 else
977 hr = ((LPDIRECT3DCUBETEXTURE9)ptex)->GetCubeMapSurface(FaceType, m_lwMipCur, &psurfSrc);
978 hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL,
979 D3DX_FILTER_TRIANGLE, 0);
983 if (bViewAlpha)
985 // Move alpha channels into RGB (and set alpha to 0xff)
986 D3DLOCKED_RECT lr;
988 hr = psurfDest->LockRect(&lr, NULL, 0);
990 DWORD xp;
991 DWORD yp;
992 DWORD* pdwRow = (DWORD*)lr.pBits;
993 DWORD* pdw;
994 DWORD dwAlpha;
995 LONG dataBytesPerRow = 4 * sd.Width;
997 for (yp = 0; yp < sd.Height; yp++)
999 pdw = pdwRow;
1000 for (xp = 0; xp < sd.Width; xp++)
1002 dwAlpha = *pdw >> 24;
1003 *pdw = 0xff000000 | (dwAlpha << 16) | (dwAlpha << 8) | (dwAlpha);
1004 pdw++;
1006 pdwRow += lr.Pitch / 4;
1008 psurfDest->UnlockRect();
1011 ReleasePpo(&psurfSrc);
1012 ReleasePpo(&psurfDest);
1014 return S_OK;
1018 HRESULT CDxtexView::LoadSurfaceFromVolumeSlice(LPDIRECT3DVOLUME9 pVolume, UINT iSlice, LPDIRECT3DSURFACE9 psurf)
1020 HRESULT hr;
1021 D3DVOLUME_DESC vd;
1022 D3DLOCKED_BOX lb;
1023 D3DBOX box;
1024 RECT rc;
1026 pVolume->GetDesc(&vd);
1028 box.Left = 0;
1029 box.Right = vd.Width;
1030 box.Top = 0;
1031 box.Bottom = vd.Height;
1032 box.Front = iSlice;
1033 box.Back = iSlice + 1;
1035 rc.left = 0;
1036 rc.right = vd.Width;
1037 rc.top = 0;
1038 rc.bottom = vd.Height;
1040 hr = pVolume->LockBox(&lb, &box, 0);
1041 if (FAILED(hr))
1042 return hr;
1044 hr = D3DXLoadSurfaceFromMemory(psurf, NULL, NULL, lb.pBits, vd.Format, lb.RowPitch,
1045 NULL, &rc, D3DX_FILTER_TRIANGLE, 0);
1047 pVolume->UnlockBox();
1049 return hr;
1053 void CDxtexView::OnViewNegX()
1055 BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1056 m_bTitleModsChanged = TRUE; // force title bar update
1057 RenderScene();
1058 Invalidate(); // force redraw of this view
1062 void CDxtexView::OnUpdateViewNegX(CCmdUI* pCmdUI)
1064 BOOL bEnable = GetDocument()->IsCubeMap();
1065 pCmdUI->Enable(bEnable);
1066 pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_X);
1070 void CDxtexView::OnViewPosX()
1072 BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1073 m_bTitleModsChanged = TRUE; // force title bar update
1074 RenderScene();
1075 Invalidate(); // force redraw of this view
1079 void CDxtexView::OnUpdateViewPosX(CCmdUI* pCmdUI)
1081 BOOL bEnable = GetDocument()->IsCubeMap();
1082 pCmdUI->Enable(bEnable);
1083 pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_X);
1087 void CDxtexView::OnViewNegY()
1089 BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1090 m_bTitleModsChanged = TRUE; // force title bar update
1091 RenderScene();
1092 Invalidate(); // force redraw of this view
1096 void CDxtexView::OnUpdateViewNegY(CCmdUI* pCmdUI)
1098 BOOL bEnable = GetDocument()->IsCubeMap();
1099 pCmdUI->Enable(bEnable);
1100 pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Y);
1104 void CDxtexView::OnViewPosY()
1106 BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1107 m_bTitleModsChanged = TRUE; // force title bar update
1108 RenderScene();
1109 Invalidate(); // force redraw of this view
1113 void CDxtexView::OnUpdateViewPosY(CCmdUI* pCmdUI)
1115 BOOL bEnable = GetDocument()->IsCubeMap();
1116 pCmdUI->Enable(bEnable);
1117 pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Y);
1121 void CDxtexView::OnViewNegZ()
1123 BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1124 m_bTitleModsChanged = TRUE; // force title bar update
1125 RenderScene();
1126 Invalidate(); // force redraw of this view
1130 void CDxtexView::OnUpdateViewNegZ(CCmdUI* pCmdUI)
1132 BOOL bEnable = GetDocument()->IsCubeMap();
1133 pCmdUI->Enable(bEnable);
1134 pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Z);
1138 void CDxtexView::OnViewPosZ()
1140 BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1141 m_bTitleModsChanged = TRUE; // force title bar update
1142 RenderScene();
1143 Invalidate(); // force redraw of this view
1147 void CDxtexView::OnUpdateViewPosZ(CCmdUI* pCmdUI)
1149 BOOL bEnable = GetDocument()->IsCubeMap();
1150 pCmdUI->Enable(bEnable);
1151 pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Z);
1154 void CDxtexView::OnFileOpenFace()
1156 GetDocument()->OpenCubeFace(m_CubeFaceCur);
1159 void CDxtexView::OnUpdateFileOpenFace(CCmdUI* pCmdUI)
1161 BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD);
1162 pCmdUI->Enable(bEnable);
1165 void CDxtexView::OnFileOpenAlphaFace()
1167 GetDocument()->OpenAlphaCubeFace(m_CubeFaceCur);
1170 void CDxtexView::OnUpdateFileOpenAlphaFace(CCmdUI* pCmdUI)
1172 BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD);
1173 pCmdUI->Enable(bEnable);
1176 void CDxtexView::OnViewHigherVolumeSlice()
1178 m_lwSliceCur++;
1179 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1180 UpdateDevice();
1181 RenderScene();
1182 m_bTitleModsChanged = TRUE; // force title bar update
1183 Invalidate(); // force redraw of this view
1186 void CDxtexView::OnUpdateViewHigherVolumeSlice(CCmdUI* pCmdUI)
1188 pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur < (LONG)GetDocument()->DwDepthAt(m_lwMipCur) - 1);
1191 void CDxtexView::OnViewLowerVolumeSlice()
1193 m_lwSliceCur--;
1194 BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha);
1195 UpdateDevice();
1196 RenderScene();
1197 m_bTitleModsChanged = TRUE; // force title bar update
1198 Invalidate(); // force redraw of this view
1201 void CDxtexView::OnUpdateViewLowerVolumeSlice(CCmdUI* pCmdUI)
1203 pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur > 0);