Initial commit: ROW Client source code

Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,371 @@
//----------------------------------------------------------------------------
// File: AllocPresenter.cpp
//
// Desc: DirectShow sample code
// Implementation of user-provided allocator-presenter for VMR
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include "project.h"
#include <mmreg.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include "resrc1.h"
#include "D3DTextr.h"
#include "utils.h"
#ifndef __INITDDSTRUCT_DEFINED
#define __INITDDSTRUCT_DEFINED
template <typename T>
__inline void INITDDSTRUCT(T& dd)
{
ZeroMemory(&dd, sizeof(dd));
dd.dwSize = sizeof(dd);
}
#endif
//----------------------------------------------------------------------------
// CreateDefaultAllocatorPresenter
//
// creates user-provides allocator presenter
//
// Usually you have to actually override several functions of AllocatorPresenter;
// For the rest, QI IVMRImagePresenter and call default functions
//----------------------------------------------------------------------------
HRESULT
CMpegMovie::CreateDefaultAllocatorPresenter(
LPDIRECTDRAW7 lpDD,
LPDIRECTDRAWSURFACE7 lpPS
)
{
HRESULT hr = S_OK;
IVMRImagePresenterExclModeConfig* lpConfig = NULL;
__try {
// for exclusive mode, we do need AllocPresenterDDXclMode of IVMRSurfaceAllocator
CHECK_HR(hr = CoCreateInstance(CLSID_AllocPresenterDDXclMode, NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IVMRSurfaceAllocator),
(LPVOID*)&m_lpDefSA));
CHECK_HR(hr = m_lpDefSA->QueryInterface(__uuidof(IVMRImagePresenterExclModeConfig),
(LPVOID*)&lpConfig));
CHECK_HR(hr = lpConfig->SetRenderingPrefs(RenderPrefs_ForceOffscreen));
// this sets exclusive mode
CHECK_HR(hr = lpConfig->SetXlcModeDDObjAndPrimarySurface(lpDD, lpPS));
CHECK_HR(hr = m_lpDefSA->QueryInterface(__uuidof(IVMRImagePresenter),
(LPVOID*)&m_lpDefIP));
CHECK_HR(hr = m_lpDefSA->QueryInterface(__uuidof(IVMRWindowlessControl),
(LPVOID*)&m_lpDefWC));
CHECK_HR(hr = m_lpDefWC->SetVideoClippingWindow(m_hwndApp));
CHECK_HR(hr = m_lpDefSA->AdviseNotify(this));
}
__finally {
RELEASE(lpConfig);
if (FAILED(hr)) {
RELEASE(m_lpDefWC);
RELEASE(m_lpDefIP);
RELEASE(m_lpDefSA);
}
}
return hr;
}
//----------------------------------------------------------------------------
// NonDelegatingQueryInterface
//
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::NonDelegatingQueryInterface(
REFIID riid,
void** ppv
)
{
if (riid == __uuidof(IVMRSurfaceAllocator)) {
return GetInterface((IVMRSurfaceAllocator*)this, ppv);
}
else if (riid == __uuidof(IVMRImagePresenter)) {
return GetInterface((IVMRImagePresenter*)this, ppv);
}
return CUnknown::NonDelegatingQueryInterface(riid,ppv);
}
//////////////////////////////////////////////////////////////////////////////
//
// IVMRSurfaceAllocator-overriden functions
//
//////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// AllocateSurfaces
//
// call default AllocateSurface
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::AllocateSurface(
DWORD_PTR dwUserID,
VMRALLOCATIONINFO* lpAllocInfo,
DWORD* lpdwBuffer,
LPDIRECTDRAWSURFACE7* lplpSurface
)
{
HRESULT hr = m_lpDefSA->AllocateSurface(dwUserID, lpAllocInfo,
lpdwBuffer, lplpSurface);
if( SUCCEEDED(hr))
{
m_lpSurf = *lplpSurface;
}
return hr;
}
//----------------------------------------------------------------------------
// FreeSurfaces()
//
// Call default FreeSurface
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::FreeSurface(
DWORD_PTR dwUserID
)
{
HRESULT hr = m_lpDefSA->FreeSurface(dwUserID);
if( SUCCEEDED(hr))
{
m_lpSurf = NULL;
}
return hr;
}
//----------------------------------------------------------------------------
// PrepareSurface
//
// call default PrepareSurface
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::PrepareSurface(
DWORD_PTR dwUserID,
LPDIRECTDRAWSURFACE7 lplpSurface,
DWORD dwSurfaceFlags
)
{
return m_lpDefSA->PrepareSurface(dwUserID, lplpSurface, dwSurfaceFlags);
}
//----------------------------------------------------------------------------
// AdviseNotify
//
// call default AdviseNotify
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::AdviseNotify(
IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify
)
{
return m_lpDefSA->AdviseNotify(lpIVMRSurfAllocNotify);
}
//////////////////////////////////////////////////////////////////////////////
//
// IVMRSurfaceAllocatorNotify-overriden functions
//
//////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// AdviseSurfaceAllocator
//
// standard AdviseSurfaceAllocator
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::AdviseSurfaceAllocator(
DWORD_PTR dwUserID,
IVMRSurfaceAllocator* lpIVRMSurfaceAllocator
)
{
return m_lpDefSAN->AdviseSurfaceAllocator(dwUserID, lpIVRMSurfaceAllocator);
}
//----------------------------------------------------------------------------
// SetDDrawDevice
//
// standard SetDDrawDevice
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::SetDDrawDevice(LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor)
{
return m_lpDefSAN->SetDDrawDevice(lpDDrawDevice, hMonitor);
}
//----------------------------------------------------------------------------
// ChangeDDrawDevice
//
// standard ChangeDDrawDevice
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::ChangeDDrawDevice(LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor)
{
return m_lpDefSAN->ChangeDDrawDevice(lpDDrawDevice, hMonitor);
}
//----------------------------------------------------------------------------
// RestoreDDrawSurfaces
//
// standard RestoreDDrawSurfaces
//----------------------------------------------------------------------------
STDMETHODIMP CMpegMovie::RestoreDDrawSurfaces()
{
// Make sure that the menu is redrawn
if( m_AlphaBlt )
m_AlphaBlt->SetMenuRestoreFlag();
return m_lpDefSAN->RestoreDDrawSurfaces();
}
//----------------------------------------------------------------------------
// NotifyEvent
//
// standard NotifyEvent
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::NotifyEvent(LONG EventCode, LONG_PTR lp1, LONG_PTR lp2)
{
return m_lpDefSAN->NotifyEvent(EventCode, lp1, lp2);
}
//----------------------------------------------------------------------------
// SetBorderColor
//
// default SetBorderColor
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::SetBorderColor(
COLORREF clr
)
{
return m_lpDefSAN->SetBorderColor(clr);
}
//////////////////////////////////////////////////////////////////////////////
//
// IVMRImagePresenter overriden functions
// we perform all user customization here
//
//////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
// StartPresenting()
//
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::StartPresenting(DWORD_PTR dwUserID)
{
return m_lpDefIP->StartPresenting(dwUserID);
}
//----------------------------------------------------------------------------
// StopPresenting()
//
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::StopPresenting(DWORD_PTR dwUserID)
{
return m_lpDefIP->StopPresenting(dwUserID);
}
//----------------------------------------------------------------------------
// PresentImage
//
// Here all the fun happens. lpPresInfo contains surface with current video image
// Call m_AlphaBlt->AlphaBlt to perform all the necessary transformation
//----------------------------------------------------------------------------
STDMETHODIMP
CMpegMovie::PresentImage(
DWORD_PTR dwUserID,
VMRPRESENTATIONINFO* lpPresInfo
)
{
// clear the background
DDBLTFX ddFX;
INITDDSTRUCT(ddFX);
RECT rcS = {0, 0, 640, 480};
RECT rcD = {128, 96, 512, 384};
RECT rcDt ={128, 0, 512, 288};
m_lpDefWC->GetVideoPosition(&rcS, NULL);
if( g_ss.bShowTwist )
{
m_AlphaBlt->AlphaBlt(&rcDt, lpPresInfo->lpSurf, &rcS, 0xFF);
}
else
{
m_AlphaBlt->AlphaBlt(&rcD, lpPresInfo->lpSurf, &rcS, 0xFF);
}
m_lpSurf->Flip(NULL,0);
if( g_ss.bShowStatistics && m_Qp)
{
// call IQualProp functions here to get performance statistics
GetPerformance();
}
// Show the scene
m_pDDObject.GetFB()->Flip(NULL, /*DDFLIP_WAIT*/ 0);
return S_OK;
}
//----------------------------------------------------------------------------
// GetPerformance
//
// Calls IQualProp::get_AvgFrameRate
// every 25 frames (to not overload VMR with senseless calculations)
// and saves this value to g_ss, global SceneSettings structure
//
//----------------------------------------------------------------------------
void
CMpegMovie::GetPerformance()
{
static int nCounter = 0;
static int nAvgFrameRate = 0;
char szFrameRate[MAX_PATH];
nCounter++;
if( 25 == nCounter )
{
m_Qp->get_AvgFrameRate( &nAvgFrameRate);
nCounter = 0;
}
sprintf( szFrameRate, "FPS: %f ", (float)nAvgFrameRate/100.f);
lstrcpy(g_ss.achFPS, TEXT(szFrameRate));
return;
}

View File

@@ -0,0 +1,976 @@
//----------------------------------------------------------------------------
// File: BltAlpha.h
//
// Desc: DirectShow sample code
// Header file and class description for CAlphaBlt,
// texture surface to be used in PresentImage of the
// customized allocator-presenter
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#ifndef __INITDDSTRUCT_DEFINED
#define __INITDDSTRUCT_DEFINED
#include <math.h>
#include <d3dxmath.h>
#include "d3dtextr.h"
#include "d3dfont.h"
#include "utils.h"
#include "resrc1.h"
#include "d3dutil.h"
extern struct SceneSettings g_ss;
template <typename T>
__inline void INITDDSTRUCT(T& dd)
{
ZeroMemory(&dd, sizeof(dd));
dd.dwSize = sizeof(dd);
}
#endif
#ifndef __RELEASE_DEFINED
#define __RELEASE_DEFINED
template<typename T>
__inline void RELEASE( T* &p )
{
if( p ) {
p->Release();
p = NULL;
}
}
#endif
#ifndef CHECK_HR
#define CHECK_HR(expr) do { if (FAILED(expr)) __leave; } while(0);
#endif
#define COMPLVERTSIZE 640 // must be divisible by 4!!!
#define pi 3.1415926535f
//----------------------------------------------------------------------------
// CAlphaBlt
//
// Desc: texture surface to be used in PresentImage of the
// customized allocator-presenter
//----------------------------------------------------------------------------
class CAlphaBlt
{
private:
LPDIRECTDRAW7 m_pDD;
LPDIRECT3D7 m_pD3D;
LPDIRECT3DDEVICE7 m_pD3DDevice;
LPDIRECTDRAWSURFACE7 m_lpDDBackBuffer;
LPDIRECTDRAWSURFACE7 m_lpDDMirror;
LPDIRECTDRAWSURFACE7 m_lpDDM32;
LPDIRECTDRAWSURFACE7 m_lpDDM16;
DDSURFACEDESC2 m_ddsdM32;
DDSURFACEDESC2 m_ddsdM16;
bool m_fPowerOf2;
bool m_fSquare;
bool m_bNeedToRestoreMenu;
TextureContainer * m_ptxtrMenu;
CD3DFont * m_pFont;
typedef struct Vertex
{
float x, y, z, rhw;
D3DCOLOR clr;
float tu, tv;
} Vertex;
Vertex pVertices[4]; // primitive for rotating effect
Vertex pVComplex[COMPLVERTSIZE];// primitive for twisting effect
Vertex pVMenu[4]; // primitive for menu effect
//----------------------------------------------------------------------------
// CAlphaBlt::Rotate
//
// Desc: 3D transformation of pVertices that provide rotation around Z and Y
//
// Parameters:
// theta - angle of rotation around Z axis
// thetaY - angle of rotation around Y axis
// pVertices - array of (Vertex*) to be transformed
// nSize - number of vertices
// (cx2, cy2) - center of rotation
//----------------------------------------------------------------------------
void Rotate(float theta, float thetaY,
CAlphaBlt::Vertex * pVertices,
int nSize, float cx2, float cy2)
{
D3DXMATRIX mtrV;
D3DXMATRIX mtrRotZ;
D3DXMATRIX mtrRotY;
D3DXMATRIX mtrPrs;
D3DXMATRIX mtrRes;
float pi2 = 1.57079632675f; // pi/2.
// initialize mtrV
mtrV.m[0][0] = pVertices[0].x - cx2;
mtrV.m[1][0] = pVertices[0].y - cy2;
mtrV.m[2][0] = pVertices[0].z;
mtrV.m[3][0] = 0.f;
mtrV.m[0][1] = pVertices[1].x - cx2;
mtrV.m[1][1] = pVertices[1].y - cy2;
mtrV.m[2][1] = pVertices[1].z;
mtrV.m[3][1] = 0;
mtrV.m[0][2] = pVertices[2].x - cx2;
mtrV.m[1][2] = pVertices[2].y - cy2;
mtrV.m[2][2] = pVertices[2].z;
mtrV.m[3][2] = 0;
mtrV.m[0][3] = pVertices[3].x - cx2;
mtrV.m[1][3] = pVertices[3].y - cy2;
mtrV.m[2][3] = pVertices[3].z;
mtrV.m[3][3] = 0;
D3DXMatrixRotationZ( &mtrRotZ, theta);
D3DXMatrixRotationY( &mtrRotY, thetaY);
D3DXMatrixPerspectiveFov( &mtrPrs, pi2, 1.1f, 0.f, 1.f);
// mtrRotZ * mtrV
D3DXMatrixMultiply( &mtrRes, &mtrRotZ, &mtrV);
// mtrRotY * mtrRotZ * mtrV
D3DXMatrixMultiply( &mtrV, &mtrRotY, &mtrRes);
// mtrPrs * mtrRotY * mtrRotZ * mtrV
D3DXMatrixMultiply( &mtrRes, &mtrPrs, &mtrV);
// here, mtrRes has what we need; copy it back to pVertices
pVertices[0].x = mtrRes.m[0][0] + cx2;
pVertices[1].x = mtrRes.m[0][1] + cx2;
pVertices[2].x = mtrRes.m[0][2] + cx2;
pVertices[3].x = mtrRes.m[0][3] + cx2;
pVertices[0].y = mtrRes.m[1][0] + cy2;
pVertices[1].y = mtrRes.m[1][1] + cy2;
pVertices[2].y = mtrRes.m[1][2] + cy2;
pVertices[3].y = mtrRes.m[1][3] + cy2;
pVertices[0].z = mtrRes.m[2][0];
pVertices[1].z = mtrRes.m[2][1];
pVertices[2].z = mtrRes.m[2][2];
pVertices[3].z = mtrRes.m[2][3];
return;
}
//----------------------------------------------------------------------------
// IsSurfaceBlendable
//
// Checks the DD surface description and the given
// alpha value to determine if this surface is blendable.
//
//----------------------------------------------------------------------------
bool
IsSurfaceBlendable(
DDSURFACEDESC2& ddsd,
BYTE fAlpha
)
{
// Is the surface already a D3D texture ?
if (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
return true;
}
// OK we have to mirror the surface
return false;
}
//----------------------------------------------------------------------------
// MirrorSourceSurface
//
// The mirror surface cab be either 16 or 32 bit RGB depending
// upon the format of the source surface.
//
// Of course it should have the "texture" flag set and should be in VRAM.
// If we can't create the surface then the AlphaBlt should fail
//----------------------------------------------------------------------------
HRESULT MirrorSourceSurface(
LPDIRECTDRAWSURFACE7 lpDDS,
DDSURFACEDESC2& ddsd
)
{
HRESULT hr = DD_OK;
DWORD dwMirrorBitDepth = 0;
DDSURFACEDESC2 ddsdMirror={0};
//
// OK - is it suitable for our needs.
//
// Apply the following rules:
// if ddsd is a FOURCC surface the mirror should be 32 bit
// if ddsd is RGB then the mirror's bit depth should match
// that of ddsd.
//
// Also, the mirror must be large enough to actually hold
// the surface to be blended
//
m_lpDDMirror = NULL;
if (ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ||
ddsd.ddpfPixelFormat.dwRGBBitCount == 32) {
if (ddsd.dwWidth > m_ddsdM32.dwWidth ||
ddsd.dwHeight > m_ddsdM32.dwHeight) {
RELEASE(m_lpDDM32);
}
if (!m_lpDDM32) {
dwMirrorBitDepth = 32;
}
else {
m_lpDDMirror = m_lpDDM32;
ddsdMirror = m_ddsdM32;
}
}
else if (ddsd.ddpfPixelFormat.dwRGBBitCount == 16) {
if (ddsd.dwWidth > m_ddsdM16.dwWidth ||
ddsd.dwHeight > m_ddsdM16.dwHeight) {
RELEASE(m_lpDDM16);
}
if (!m_lpDDM16) {
dwMirrorBitDepth = 16;
}
else {
m_lpDDMirror = m_lpDDM16;
ddsdMirror = m_ddsdM16;
}
}
else {
// No support for RGB24 or RGB8!
return E_INVALIDARG;
}
if (!m_lpDDMirror) {
INITDDSTRUCT(ddsdMirror);
ddsdMirror.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsdMirror.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsdMirror.ddpfPixelFormat.dwRGBBitCount = dwMirrorBitDepth;
switch (dwMirrorBitDepth) {
case 16:
ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x0000F800;
ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x000007E0;
ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x0000001F;
break;
case 32:
ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x000000FF;
break;
}
ddsdMirror.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
ddsdMirror.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
if (m_fPowerOf2) {
for (ddsdMirror.dwWidth = 1;
ddsd.dwWidth > ddsdMirror.dwWidth;
ddsdMirror.dwWidth <<= 1);
for (ddsdMirror.dwHeight = 1;
ddsd.dwHeight > ddsdMirror.dwHeight;
ddsdMirror.dwHeight <<= 1);
}
else {
ddsdMirror.dwWidth = ddsd.dwWidth;
ddsdMirror.dwHeight = ddsd.dwHeight;
}
if (m_fSquare) {
if (ddsdMirror.dwHeight > ddsdMirror.dwWidth) {
ddsdMirror.dwWidth = ddsdMirror.dwHeight;
}
if (ddsdMirror.dwWidth > ddsdMirror.dwHeight) {
ddsdMirror.dwHeight = ddsdMirror.dwWidth;
}
}
__try {
// Attempt to create the surface with theses settings
CHECK_HR(hr = m_pDD->CreateSurface(&ddsdMirror, &m_lpDDMirror, NULL));
INITDDSTRUCT(ddsdMirror);
CHECK_HR(hr = m_lpDDMirror->GetSurfaceDesc(&ddsdMirror));
switch (dwMirrorBitDepth) {
case 16:
m_ddsdM16 = ddsdMirror;
m_lpDDM16 = m_lpDDMirror;
break;
case 32:
m_ddsdM32 = ddsdMirror;
m_lpDDM32 = m_lpDDMirror;
break;
}
} __finally {}
}
if (hr == DD_OK) {
__try {
RECT rc = {0, 0, ddsd.dwWidth, ddsd.dwHeight};
CHECK_HR(hr = m_lpDDMirror->Blt(&rc, lpDDS, &rc, DDBLT_WAIT, NULL));
ddsd = ddsdMirror;
} __finally {}
}
return hr;
}
public:
//----------------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------------
CAlphaBlt(LPDIRECTDRAWSURFACE7 lpDDSDst, HRESULT* phr) :
m_pDD(NULL),
m_pD3D(NULL),
m_pD3DDevice(NULL),
m_lpDDBackBuffer(NULL),
m_lpDDMirror(NULL),
m_lpDDM32(NULL),
m_lpDDM16(NULL),
m_ptxtrMenu( NULL),
m_pFont(NULL),
m_fPowerOf2(false),
m_fSquare(false),
m_bNeedToRestoreMenu(false)
{
ZeroMemory(&m_ddsdM32, sizeof(m_ddsdM32));
ZeroMemory(&m_ddsdM16, sizeof(m_ddsdM16));
HRESULT hr;
hr = lpDDSDst->GetDDInterface((LPVOID *)&m_pDD);
if (FAILED(hr)) {
m_pDD = NULL;
*phr = hr;
}
if (SUCCEEDED(hr)) {
hr = m_pDD->QueryInterface(IID_IDirect3D7, (LPVOID *)&m_pD3D);
if (FAILED(hr)) {
m_pD3D = NULL;
*phr = hr;
}
}
if (SUCCEEDED(hr)) {
hr = m_pD3D->CreateDevice(IID_IDirect3DHALDevice,
lpDDSDst,
&m_pD3DDevice);
if (FAILED(hr)) {
m_pD3DDevice = NULL;
*phr = hr;
}
else {
m_lpDDBackBuffer = lpDDSDst;
m_lpDDBackBuffer->AddRef();
}
}
if (SUCCEEDED(hr)) {
D3DDEVICEDESC7 ddDesc;
if (DD_OK == m_pD3DDevice->GetCaps(&ddDesc)) {
if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) {
m_fPowerOf2 = true;
}
if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
m_fSquare = true;
}
}
else {
*phr = hr;
}
}
// here, so far we have D3Device, let's Restore texture surface
// it actually loads the bitmap from the resource onto a texture surface
m_ptxtrMenu = new TextureContainer(
"IDB_MENU", 0, 0, IDB_MENU);
if( m_ptxtrMenu)
{
hr = m_ptxtrMenu->LoadImageData();
if( m_ptxtrMenu->m_hbmBitmap )
{
BITMAP bm;
GetObject( m_ptxtrMenu->m_hbmBitmap, sizeof(BITMAP), &bm );
m_ptxtrMenu->m_dwWidth = (DWORD)bm.bmWidth;
m_ptxtrMenu->m_dwHeight = (DWORD)bm.bmHeight;
m_ptxtrMenu->m_dwBPP = (DWORD)bm.bmBitsPixel;
}
hr = m_ptxtrMenu->Restore(m_pD3DDevice);
if( FAILED(hr))
{
delete m_ptxtrMenu;
m_ptxtrMenu = NULL;
}
}
// load the font
m_pFont = new CD3DFont( TEXT("Comic Sans MS"),18,0);
if( m_pFont )
{
m_pFont->InitDeviceObjects( m_pDD, m_pD3DDevice);
}
// setup menu primitive
pVMenu[0].x = 0.f;
pVMenu[0].y = 0.f;
pVMenu[0].z = 0.0f;
pVMenu[0].rhw = 2.0f;
pVMenu[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
pVMenu[1].x = 60.f;
pVMenu[1].y = 0.f;
pVMenu[1].z = 0.0f;
pVMenu[1].rhw = 2.0f;
pVMenu[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
pVMenu[2].x = 0.f;
pVMenu[2].y = 480.f;
pVMenu[2].z = 0.0f;
pVMenu[2].rhw = 2.0f;
pVMenu[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
pVMenu[3].x = 60.f;
pVMenu[3].y = 480.f;
pVMenu[3].z = 0.0f;
pVMenu[3].rhw = 2.0f;
pVMenu[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, 0xff);
//
// Setup the SRC info
//
pVMenu[0].tu = 0.f;
pVMenu[0].tv = 0.f;
pVMenu[1].tu = 1.f;
pVMenu[1].tv = 0.f;
pVMenu[2].tu = 0.f;
pVMenu[2].tv = 1.f;
pVMenu[3].tu = 1.f;
pVMenu[3].tv = 1.f;
}
//----------------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------------
~CAlphaBlt()
{
if( m_ptxtrMenu )
{
delete m_ptxtrMenu;
m_ptxtrMenu = NULL;
}
if( m_pFont )
{
delete m_pFont;
m_pFont = NULL;
}
RELEASE(m_lpDDBackBuffer);
RELEASE(m_lpDDM32);
RELEASE(m_lpDDM16);
RELEASE(m_pD3DDevice);
RELEASE(m_pD3D);
RELEASE(m_pDD);
}
//----------------------------------------------------------------------------
// GetMenuTexture
//
// returns pointer to texture's DD surface or NULL otherwise
//----------------------------------------------------------------------------
LPDIRECTDRAWSURFACE7 GetMenuTexture()
{
if( m_ptxtrMenu && m_ptxtrMenu->m_pddsSurface )
{
return (m_ptxtrMenu->m_pddsSurface);
}
return NULL;
}
//----------------------------------------------------------------------------
// SetMenuRestoreFlag
//
// sets m_bNeedToRestoreMenu = true; (called from CMpegMovie::RestoreDDRawSurfaces() )
//----------------------------------------------------------------------------
void SetMenuRestoreFlag()
{
m_bNeedToRestoreMenu = true;
}
//----------------------------------------------------------------------------
// GetFont
//----------------------------------------------------------------------------
CD3DFont * GetFont()
{
return m_pFont;
}
//----------------------------------------------------------------------------
// PrepareVerticesRotate
//
// This is the 'main' transformation function for foration effect.
// It generates rotation angles from 'time' variable that is just
// a static counter of images from CMpegMovie:PresentImage function
//
// Parameters:
// lpDst - destination rectangle
// lpSrc - source rectangle
// alpha - alpha level for the surface
// fWid - width of the surface obtained by CMpegMovie:PresentImage
// fHgt - height of the surface obtained by CMpegMovie:PresentImage
//----------------------------------------------------------------------------
void PrepareVerticesRotate( RECT* lpDst, RECT* lpSrc, BYTE alpha,
float fWid, float fHgt)
{
float RotRadZ = 0.f;
float RotRadY = 0.f;
//
// Setup the DST info
//
pVertices[0].x = (float)lpDst->left;
pVertices[0].y = (float)lpDst->top;
pVertices[0].z = 0.5f;
pVertices[0].rhw = 2.0f;
pVertices[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
pVertices[1].x = (float)lpDst->right;
pVertices[1].y = (float)lpDst->top;
pVertices[1].z = 0.5f;
pVertices[1].rhw = 2.0f;
pVertices[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
pVertices[2].x = (float)lpDst->left;
pVertices[2].y = (float)lpDst->bottom;
pVertices[2].z = 0.5f;
pVertices[2].rhw = 2.0f;
pVertices[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
pVertices[3].x = (float)lpDst->right;
pVertices[3].y = (float)lpDst->bottom;
pVertices[3].z = 0.5f;
pVertices[3].rhw = 2.0f;
pVertices[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
//
// Setup the SRC info
//
pVertices[0].tu = ((float)lpSrc->left) / fWid;
pVertices[0].tv = ((float)lpSrc->top) / fHgt;
pVertices[1].tu = ((float)lpSrc->right) / fWid;
pVertices[1].tv = ((float)lpSrc->top) / fHgt;
pVertices[2].tu = ((float)lpSrc->left) / fWid;
pVertices[2].tv = ((float)lpSrc->bottom) / fHgt;
pVertices[3].tu = ((float)lpSrc->right) / fWid;
pVertices[3].tv = ((float)lpSrc->bottom) / fHgt;
// g_ss.nGradZ is an angle in grades, so calculate radians
RotRadZ = (float) (g_ss.nGradZ++) * pi / 180.f;
if( !g_ss.bRotateZ)
{
g_ss.nGradZ--;
}
RotRadY = (float) (g_ss.nGradY++) * pi / 180.f;
if( !g_ss.bRotateY)
{
g_ss.nGradY--;
}
// to avoid stack overflow, limit counters withing 360 grades
if( g_ss.nGradZ > 360)
{
g_ss.nGradZ = 0;
}
if( g_ss.nGradY > 360)
{
g_ss.nGradY = 0;
}
// and finally rotate the primitive pVertices
// NOTE that rotation center is hardcoded for the case
// 640x480 display mode
Rotate(RotRadZ, RotRadY, pVertices, 4, 320.f, 240.f);
}
//----------------------------------------------------------------------------
// PrepareVerticesTwist
//
// This is the 'main' transformation function for "twist" effect.
// It generates transformation parameters 'time' variable that is just
// a static counter of images from CMpegMovie:PresentImage function
//
// Parameters:
// lpDst - destination rectangle
// lpSrc - source rectangle
// alpha - alpha level for the surface
// fWid - width of the surface obtained by CMpegMovie:PresentImage
// fHgt - height of the surface obtained by CMpegMovie:PresentImage
//
// Other: put your own effects here
// The effect I use is as following:
// (a) move picture down to create 'slipping' effect
// (b) srink lower part of the picture (parameter c applied to each verticle
// so that it would look like a wine glass stem (cosine is what we need)
// Shrinking coefficient depends on Y-coordinate of a verticle
// (c) twist lower part of the picture around Y axis, angle depends on
// Y-coordinate of a verticle
//----------------------------------------------------------------------------
void PrepareVerticesTwist( RECT* lpDst, RECT* lpSrc, BYTE alpha,
float fW, float fH)
{
CAlphaBlt::Vertex * V = pVComplex;
float W = (float)(lpDst->right - lpDst->left);
float H = (float)(lpDst->bottom - lpDst->top);
float sW = (float)(lpSrc->right - lpSrc->left)/fW;
float sH = (float)(lpSrc->bottom - lpSrc->top);
float Ht = 480 - H;
float c;
float radY = 0.f;
float radX = pi/4.f;
float x;
double costh;
double sinth;
D3DXMATRIX mtrPrs;
D3DXMATRIX mtrOrg;
D3DXMATRIX mtrRes;
int N = COMPLVERTSIZE/2;
g_ss.nDy = g_ss.nDy + 3;
if( g_ss.nDy > 480 )
{
g_ss.nDy = 0;
}
for( int i=0; i<COMPLVERTSIZE; i=i+2)
{
V[i ].x = (float)(lpDst->left);
V[i+1].x = (float)(lpDst->right);
V[i ].y = V[i+1].y = (float)(i * H/(N-1)) + g_ss.nDy;
V[i ].z = V[i+1].z = 0.5f;
V[i ].rhw = V[i+1].rhw = 2.f;
V[i ].clr = V[i+1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
V[i ].tu = ((float)lpSrc->left) / fW;
V[i+1].tu = ((float)lpSrc->right) / fW;
V[i ].tv = V[i+1].tv = (float)(lpSrc->top + sH * (float)i/(N-1.f)/2.f)/fH;
if( V[i].y >= H )
{
c = (float)( W * (1. + cos(pi * (480. - V[i].y)/Ht)) / 4.);
//c *= 0.25f;
V[i ].x += c;
V[i+1].x -= c;
radY = pi * ( V[i].y - H ) / 2.f / Ht;
costh = cos(radY);
sinth = sin(radY);
x = V[i].x - 320.f;
V[i].x = (float)(costh * x - sinth * V[i].z) + 320.f;
V[i].z = (float)(sinth * x + costh * V[i].z);
x = V[i+1].x - 320.f;
V[i+1].x = (float)(costh * x - sinth * V[i+1].z) + 320.f;
V[i+1].z = (float)(sinth * x + costh * V[i+1].z);
} // if
}// for i
// now let's implement projection
D3DXMatrixPerspectiveFov( &mtrPrs, pi/2.f, 1.1f, 0.f, 1.f);
for( i=0; i<COMPLVERTSIZE; i = i+4)
{
mtrOrg.m[0][0] = V[i].x;
mtrOrg.m[1][0] = V[i].y;
mtrOrg.m[2][0] = V[i].z;
mtrOrg.m[3][0] = 0.f;
mtrOrg.m[0][1] = V[i+1].x;
mtrOrg.m[1][1] = V[i+1].y;
mtrOrg.m[2][1] = V[i+1].z;
mtrOrg.m[3][1] = 0.f;
mtrOrg.m[0][2] = V[i+2].x;
mtrOrg.m[1][2] = V[i+2].y;
mtrOrg.m[2][2] = V[i+2].z;
mtrOrg.m[3][2] = 0.f;
mtrOrg.m[0][3] = V[i+3].x;
mtrOrg.m[1][3] = V[i+3].y;
mtrOrg.m[2][3] = V[i+3].z;
mtrOrg.m[3][3] = 0.f;
D3DXMatrixMultiply( &mtrRes, &mtrPrs, &mtrOrg);
V[i ].x = mtrRes.m[0][0];
V[i ].y = mtrRes.m[1][0];
V[i ].z = mtrRes.m[2][0];
V[i+1].x = mtrRes.m[0][1];
V[i+1].y = mtrRes.m[1][1];
V[i+1].z = mtrRes.m[2][1];
V[i+2].x = mtrRes.m[0][2];
V[i+2].y = mtrRes.m[1][2];
V[i+2].z = mtrRes.m[2][2];
V[i+3].x = mtrRes.m[0][3];
V[i+3].y = mtrRes.m[1][3];
V[i+3].z = mtrRes.m[2][3];
}// for
return;
}
//----------------------------------------------------------------------------
// AlphaBlt
//
// This function receives LPDIRECTDRAWSURFACE7 from ImagePresenter, calls
// transformation functions to provide visual effects, sets the scene and
// renders primitives
//
// Parameters:
// lpDst -- destination rectangle
// lpDDSSrc -- surface obtained by ImagePresenter
// lpSrc -- source rectangle
// bAlpha -- alpha value for the surface
//----------------------------------------------------------------------------
HRESULT
AlphaBlt(RECT* lpDst,
LPDIRECTDRAWSURFACE7 lpDDSSrc,
RECT* lpSrc,
BYTE bAlpha
)
{
HRESULT hr=S_OK;
DDSURFACEDESC2 ddsd;
int nVertSize = 0;
CAlphaBlt::Vertex * pV = NULL;
__try {
INITDDSTRUCT(ddsd);
CHECK_HR(hr = lpDDSSrc->GetSurfaceDesc(&ddsd));
if (!IsSurfaceBlendable(ddsd, bAlpha)) {
CHECK_HR(hr = MirrorSourceSurface(lpDDSSrc, ddsd));
lpDDSSrc = m_lpDDMirror;
}
float fWid = (float)ddsd.dwWidth;
float fHgt = (float)ddsd.dwHeight;
if( g_ss.bShowTwist )
{
nVertSize = COMPLVERTSIZE;
PrepareVerticesTwist(lpDst, lpSrc, bAlpha, fWid, fHgt);
pV = pVComplex;
}
else
{
nVertSize = 4;
PrepareVerticesRotate(lpDst, lpSrc, bAlpha, fWid, fHgt);
pV = pVertices;
}
BYTE alpha = bAlpha;
m_pD3DDevice->SetTexture(0, lpDDSSrc);
// if menu is defined, set it
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, TRUE);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
//
// Do the alpha BLT
//
CHECK_HR(hr = m_pD3DDevice->BeginScene());
CHECK_HR(hr = m_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,0.5,0));
CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
pV, nVertSize, D3DDP_WAIT));
// now, draw menu over the video
// if user switched modes, menu texture may be lost; then restore
if( m_bNeedToRestoreMenu )
{
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_ALL;
m_pDD->GetDisplayMode( &ddsd);
// if we try to restore surface in a different display mode, we will fail
// so make the check first
if( ddsd.dwWidth == SCRN_WIDTH &&
ddsd.dwHeight == SCRN_HEIGHT &&
ddsd.ddpfPixelFormat.dwRGBBitCount == SCRN_BITDEPTH )
{
hr = GetMenuTexture()->Restore();
if( FAILED(hr))
{
OutputDebugString("ERROR: Failed to restore menu texture");
}
else
{
// surface restored, but its image lost; reload
if( m_ptxtrMenu)
{
hr = m_ptxtrMenu->LoadImageData();
if( FAILED(hr))
{
OutputDebugString("Failed to load the image from resource\n");
}
if( m_ptxtrMenu->m_hbmBitmap )
{
BITMAP bm;
GetObject( m_ptxtrMenu->m_hbmBitmap, sizeof(BITMAP), &bm );
m_ptxtrMenu->m_dwWidth = (DWORD)bm.bmWidth;
m_ptxtrMenu->m_dwHeight = (DWORD)bm.bmHeight;
m_ptxtrMenu->m_dwBPP = (DWORD)bm.bmBitsPixel;
}
hr = m_ptxtrMenu->Restore(m_pD3DDevice);
if( FAILED(hr))
{
delete m_ptxtrMenu;
m_ptxtrMenu = NULL;
}
}
m_bNeedToRestoreMenu = false;
}
}
else
{
OutputDebugString("Failed to restore menu texture");
}
}
m_pD3DDevice->SetTexture(0, m_ptxtrMenu->m_pddsSurface);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
//
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
pVMenu, 4, D3DDP_WAIT));
m_pD3DDevice->SetTexture(0, NULL);
// and if necessary, draw the dext over the menu
if( g_ss.bShowHelp )
{
HRESULT hr = m_pFont->DrawText((float)g_ss.nXHelp, (float)g_ss.nYHelp,
RGBA_MAKE(0xFF, 0xFF, 0x00, 0xFF),
g_ss.achHelp );
}
if( g_ss.bShowStatistics )
{
m_pFont->DrawText( 420, 0,
RGBA_MAKE(0x00, 0xFF, 0x00, 0xFF),
g_ss.achFPS );
}
CHECK_HR(hr = m_pD3DDevice->EndScene());
} __finally {
m_pD3DDevice->SetTexture(0, NULL);
}
return hr;
}
//----------------------------------------------------------------------------
// TextureSquare
// true if texture is square
//----------------------------------------------------------------------------
bool TextureSquare() {
return m_fSquare;
}
//----------------------------------------------------------------------------
// TexturePower2
// true if texture size is of a power of 2
//----------------------------------------------------------------------------
bool TexturePower2() {
return m_fPowerOf2;
}
};

View File

@@ -0,0 +1,116 @@
//----------------------------------------------------------------------------
// File: DDrawSupport.cpp
//
// Desc: DirectShow sample code
// Implementation of DDrawObject that provides basic DDraw functionality
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include "project.h"
#include <d3d.h>
//----------------------------------------------------------------------------
// Initialize
//
// Initialize DDrawObject by getting to fullscreen exclusive mode and
// setting front and back buffer
//----------------------------------------------------------------------------
HRESULT
CDDrawObject::Initialize(HWND hWndApp)
{
HRESULT hr;
DDSURFACEDESC2 ddsd;
m_hwndApp = hWndApp;
hr = DirectDrawCreateEx(NULL, (LPVOID *)&m_pDDObject,
IID_IDirectDraw7, NULL);
if (FAILED(hr)) {
return hr;
}
// Get into fullscreen exclusive mode
hr = m_pDDObject->SetCooperativeLevel(hWndApp,
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN |
DDSCL_ALLOWREBOOT);
if (FAILED(hr)) {
Terminate();
return hr;
}
hr = m_pDDObject->SetDisplayMode(SCRN_WIDTH, SCRN_HEIGHT, SCRN_BITDEPTH,
0, DDSDM_STANDARDVGAMODE);
if (FAILED(hr)) {
Terminate();
return hr;
}
// Create the primary surface with 1 back buffer
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 2;
hr = m_pDDObject->CreateSurface(&ddsd, &m_pPrimary, NULL);
if (FAILED(hr)) {
Terminate();
return hr;
}
// Get a pointer to the back buffer
DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
hr = m_pPrimary->GetAttachedSurface(&ddscaps, &m_pBackBuff);
if (FAILED(hr)) {
Terminate();
return hr;
}
// Get the screen size and save it as a rect
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
hr = m_pPrimary->GetSurfaceDesc(&ddsd);
if (!(SUCCEEDED(hr) &&
(ddsd.dwFlags & DDSD_WIDTH) && (ddsd.dwFlags & DDSD_HEIGHT))) {
Terminate();
return hr;
}
SetRect(&m_RectScrn, 0, 0, ddsd.dwWidth, ddsd.dwHeight);
return S_OK;
}
//----------------------------------------------------------------------------
// Terminate
//
// return from exclusive mode
//----------------------------------------------------------------------------
HRESULT
CDDrawObject::Terminate()
{
if (m_pBackBuff) {
m_pBackBuff->Release();
m_pBackBuff = NULL;
}
if (m_pPrimary) {
m_pPrimary->Release();
m_pPrimary = NULL;
}
if (m_pDDObject) {
m_pDDObject->SetCooperativeLevel(m_hwndApp, DDSCL_NORMAL) ;
m_pDDObject->Release();
m_pDDObject = NULL;
}
return S_OK;
}

View File

@@ -0,0 +1,69 @@
//----------------------------------------------------------------------------
// File: DDrawSupport.h
//
// Desc: DirectShow sample code
// Prototype of DDrawObject that provides basic DDraw functionality
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#ifndef DDRAWSUPPORT_HEADER
#define DDRAWSUPPORT_HEADER
#ifndef __RELEASE_DEFINED
#define __RELEASE_DEFINED
template<typename T>
__inline void RELEASE( T* &p )
{
if( p ) {
p->Release();
p = NULL;
}
}
#endif
#ifndef CHECK_HR
#define CHECK_HR(expr) if (FAILED(expr)) {\
DbgLog((LOG_ERROR, 0, \
TEXT("FAILED: %s\nat Line:%d of %s"), \
TEXT(#expr), __LINE__, TEXT(__FILE__) ));__leave; } else
#endif
#define SCRN_WIDTH 640
#define SCRN_HEIGHT 480
#define SCRN_BITDEPTH 32
//----------------------------------------------------------------------------
// CDDrawObject
//
// Class provides basic DDraw functionality
//----------------------------------------------------------------------------
class CDDrawObject {
public:
CDDrawObject() :
m_hwndApp(NULL),
m_pDDObject(NULL),
m_pPrimary(NULL),
m_pBackBuff(NULL)
{
ZeroMemory(&m_RectScrn, sizeof(m_RectScrn));
}
HRESULT Initialize(HWND hwndApp);
HRESULT Terminate();
LPDIRECTDRAW7 GetDDObj() {return m_pDDObject;};
LPDIRECTDRAWSURFACE7 GetFB() {return m_pPrimary;};
LPDIRECTDRAWSURFACE7 GetBB() {return m_pBackBuff;};
private:
HWND m_hwndApp;
RECT m_RectScrn;
LPDIRECTDRAW7 m_pDDObject;
LPDIRECTDRAWSURFACE7 m_pPrimary;
LPDIRECTDRAWSURFACE7 m_pBackBuff;
};
#endif

View File

@@ -0,0 +1,35 @@
Windows XP DirectShow Sample -- VMRXCL
--------------------------------------
Description: This application shows capabilities of the new
video mixing renderer (VMR) that is the default video
renderer in Windows XP. In particular, it demonstrates
how to use the VMR in exclusive DirectDraw mode and
how to implement a user-provided (customized) Allocator-Presenter
for the VMR. Also, it contains useful utilities to manage
bitmaps (as textures) and TrueType fonts for text over video.
Usage:
Upon initialization, VMRXCL asks you to specify a video file.
The application switches to DirectDraw exclusive mode, after setting
the display mode to 640 x 480 x 32bpp. A bitmap-based menu on the
left side of the screen provides interactivity.
(From top to bottom, the menu items are:
- Show statistics
- Pause
- Run
- Rotate in XY plane
- Rotate in YX plane
- 'Twist' non-linear effect
- Exit
Right click over the menu button to activate its text hint.
Left click to hide text hints.
Troubleshooting:
Depending on the capabilities of your video driver, text may be disabled.
You may also experience glitches with bitmaps applied over the video.
NOTE: The speed of the 3D animation is directly related to the frame rate of
the video file being played.

View File

@@ -0,0 +1,561 @@
//----------------------------------------------------------------------------
// File: Utils.h
//
// Desc: DirectShow sample code
// External (global) utilities specific for VMRXcl app
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include "project.h"
#include "utils.h"
//-----------------------------------------------------------------------------------------
// Function: hresultNameLookup
// Purpose: returns a string value for the given hresult
// Arguments: HRESULT that needs verifying
// Returns: string
//-----------------------------------------------------------------------------------------*/
const char * hresultNameLookup(HRESULT hres)
{
switch(hres)
{
case VFW_E_CANNOT_RENDER:
return "VFW_E_CANNOT_RENDER";
break;
case VFW_E_INVALID_FILE_FORMAT:
return "VFW_E_INVALID_FILE_FORMAT";
break;
case VFW_E_NOT_FOUND:
return "VFW_E_NOT_FOUND";
break;
case VFW_E_NOT_IN_GRAPH:
return "VFW_E_NOT_IN_GRAPH";
break;
case VFW_E_UNKNOWN_FILE_TYPE:
return "VFW_E_UNKNOWN_FILE_TYPE";
break;
case VFW_E_UNSUPPORTED_STREAM:
return "VFW_E_UNSUPPORTED_STREAM";
break;
case VFW_E_CANNOT_CONNECT:
return "VFW_E_CANNOT_CONNECT";
break;
case VFW_E_CANNOT_LOAD_SOURCE_FILTER:
return "VFW_E_CANNOT_LOAD_SOURCE_FILTER";
break;
case VFW_S_PARTIAL_RENDER:
return "VFW_S_PARTIAL_RENDER";
break;
case VFW_S_VIDEO_NOT_RENDERED:
return "VFW_S_VIDEO_NOT_RENDERED";
break;
case VFW_S_AUDIO_NOT_RENDERED:
return "VFW_S_AUDIO_NOT_RENDERED";
break;
case VFW_S_DUPLICATE_NAME:
return "VFW_S_DUPLICATE_NAME";
break;
case VFW_S_MEDIA_TYPE_IGNORED:
return "VFW_S_MEDIA_TYPE_IGNORED";
break;
case E_INVALIDARG:
return "E_INVALIDARG";
break;
case DDERR_INCOMPATIBLEPRIMARY:
return "DDERR_INCOMPATIBLEPRIMARY";
break;
case DDERR_INVALIDCAPS:
return "DDERR_INVALIDCAPS";
break;
case DDERR_INVALIDOBJECT :
return "DDERR_INVALIDOBJECT";
break;
case DDERR_INVALIDPIXELFORMAT:
return "DDERR_INVALIDPIXELFORMAT";
break;
case DDERR_NOALPHAHW :
return "DDERR_NOALPHAHW";
break;
case DDERR_NOCOOPERATIVELEVELSET :
return "DDERR_NOCOOPERATIVELEVELSET";
break;
case DDERR_NODIRECTDRAWHW :
return "DDERR_NODIRECTDRAWHW";
break;
case DDERR_NOEMULATION :
return "DDERR_NOEMULATION";
break;
case VFW_E_BUFFERS_OUTSTANDING:
return "VFW_E_BUFFERS_OUTSTANDING";
break;
case DDERR_NOEXCLUSIVEMODE :
return "DDERR_NOEXCLUSIVEMODE ";
break;
case DDERR_NOFLIPHW:
return "DDERR_NOFLIPHW";
break;
case DDERR_NOMIPMAPHW:
return "DDERR_NOMIPMAPHW";
break;
case DDERR_NOOVERLAYHW :
return "DDERR_NOOVERLAYHW ";
break;
case E_OUTOFMEMORY:
return "E_OUTOFMEMORY";
break;
case VFW_E_NO_DISPLAY_PALETTE:
return "VFW_E_NO_DISPLAY_PALETTE";
break;
case VFW_E_NO_COLOR_KEY_FOUND:
return "VFW_E_NO_COLOR_KEY_FOUND";
break;
case VFW_E_PALETTE_SET:
return "VFW_E_PALETTE_SET";
break;
case DDERR_NOZBUFFERHW :
return "DDERR_NOZBUFFERHW ";
break;
case DDERR_OUTOFVIDEOMEMORY :
return "DDERR_OUTOFVIDEOMEMORY";
break;
case DDERR_PRIMARYSURFACEALREADYEXISTS:
return "DDERR_PRIMARYSURFACEALREADYEXISTS ";
break;
case DDERR_UNSUPPORTEDMODE:
return "DDERR_UNSUPPORTEDMODE";
break;
case VFW_E_NO_ADVISE_SET:
return "VFW_E_NO_ADVISE_SET";
break;
case S_OK:
return "S_OK";
break;
case S_FALSE:
return "S_FALSE";
break;
case VFW_S_CONNECTIONS_DEFERRED:
return "VFW_S_CONNECTIONS_DEFERRED";
break;
case 0x80040154:
return "Class not registered";
break;
case E_FAIL:
return "E_FAIL";
break;
case VFW_E_DVD_OPERATION_INHIBITED:
return "VFW_E_DVD_OPERATION_INHIBITED";
break;
case VFW_E_DVD_INVALIDDOMAIN:
return "VFW_E_DVD_INVALIDDOMAIN";
break;
case E_NOTIMPL:
return "E_NOTIMPL";
break;
case VFW_E_WRONG_STATE:
return "VFW_E_WRONG_STATE";
break;
case E_PROP_SET_UNSUPPORTED:
return "E_PROP_SET_UNSUPPORTED";
break;
case VFW_E_NO_PALETTE_AVAILABLE:
return "VFW_E_NO_PALETTE_AVAILABLE";
break;
case E_UNEXPECTED:
return "E_UNEXPECTED";
break;
case VFW_E_DVD_NO_BUTTON:
return "VFW_E_DVD_NO_BUTTON";
break;
case VFW_E_DVD_GRAPHNOTREADY:
return "VFW_E_DVD_GRAPHNOTREADY";
break;
case VFW_E_NOT_OVERLAY_CONNECTION:
return "VFW_E_NOT_OVERLAY_CONNECTION";
break;
case VFW_E_DVD_RENDERFAIL:
return "VFW_E_DVD_RENDERFAIL";
break;
case VFW_E_NOT_CONNECTED:
return "VFW_E_NOT_CONNECTED";
break;
case E_NOINTERFACE:
return "E_NOINTERFACE";
break;
case VFW_E_NO_COLOR_KEY_SET :
return "VFW_E_NO_COLOR_KEY_SET ";
break;
case VFW_E_NO_INTERFACE:
return "VFW_E_NO_INTERFACE";
break;
case 0x8004020c:
return "VFW_E_BUFFER_NOTSET";
break;
case 0x80040225:
return "VFW_E_NOT_PAUSED";
case 0x80070002:
return "System cannot find the file specified";
break;
case 0x80070003:
return "System cannot find the path specified";
break;
case VFW_E_DVD_DECNOTENOUGH:
return "VFW_E_DVD_DECNOTENOUGH";
break;
case VFW_E_ADVISE_ALREADY_SET:
return "VFW_E_ADVISE_ALREADY_SET";
break;
case VFW_E_DVD_CMD_CANCELLED:
return "VFW_E_DVD_CMD_CANCELLED";
break;
case VFW_E_DVD_MENU_DOES_NOT_EXIST:
return "VFW_E_DVD_MENU_DOES_NOT_EXIST";
break;
case VFW_E_DVD_WRONG_SPEED:
return "VFW_E_DVD_WRONG_SPEED";
break;
case VFW_S_DVD_NON_ONE_SEQUENTIAL:
return "VFW_S_DVD_NON_ONE_SEQUENTIAL";
break;
case E_POINTER:
return "E_POINTER";
break;
case VFW_E_DVD_NOT_IN_KARAOKE_MODE:
return "VFW_E_DVD_NOT_IN_KARAOKE_MODE";
break;
case VFW_E_DVD_INVALID_DISC:
return "VFW_E_DVD_INVALID_DISC";
break;
case VFW_E_DVD_STREAM_DISABLED:
return "VFW_E_DVD_STREAM_DISABLED";
break;
case VFW_E_NOT_STOPPED:
return "VFW_E_NOT_STOPPED";
break;
default:
return "Unrecognized";
break;
}
}
/*-----------------------------------------------------------------------------------------
| Function: MySleep
| Purpose: if the application is in automated mode, then sleep func is turned off
| Arguments: checks m_bAutomatedStatus to see if the func is in automation
| Returns: true if automated, false otherwist
\-----------------------------------------------------------------------------------------*/
bool MySleep(DWORD dwTime)
{
HANDLE hNeverHappensEvent;
hNeverHappensEvent = CreateEvent(NULL, FALSE, FALSE, "EVENTTHATNEVERHAPPENS");
WaitForSingleObject( hNeverHappensEvent, dwTime);
return false;
} // end of checkHResult method
void ReportDDrawSurfDesc( DDSURFACEDESC2 ddsd)
{
char szFlags[4096];
char szMsg[4096];
OutputDebugString("*** Surface description ***\n");
SurfaceDescHelper( ddsd.dwFlags, szFlags);
OutputDebugString(szFlags);
sprintf( szMsg, " dwWidth x dwHeight: %ld x %ld\n", ddsd.dwWidth, ddsd.dwHeight);
OutputDebugString(szMsg);
sprintf( szMsg, " lPitch: %ld\n", ddsd.lPitch);
OutputDebugString(szMsg);
OutputDebugString(" (dwLinearSize)\n");
sprintf( szMsg, " dwBackBufferCount: %ld\n", ddsd.dwBackBufferCount);
OutputDebugString(szMsg);
sprintf( szMsg, " dwMipMapCount: %ld\n", ddsd.dwMipMapCount);
OutputDebugString(szMsg);
OutputDebugString(" (dwRefreshRate)");
sprintf( szMsg, " dwAlphaBitDepth: %ld\n", (LONG)ddsd.dwAlphaBitDepth);
OutputDebugString(szMsg);
sprintf( szMsg, " lpSurface: %x\n", (LONG_PTR)(ddsd.lpSurface));
OutputDebugString(szMsg);
ReportPixelFormat( ddsd.ddpfPixelFormat );
ReportDDSCAPS2( ddsd.ddsCaps );
sprintf( szMsg, " dwTextureStage: %ld\n", ddsd.dwTextureStage);
OutputDebugString(szMsg);
OutputDebugString("***************************\n");
}
void ReportDDSCAPS2( DDSCAPS2 ddscaps )
{
char sz[4096];
strcpy( sz, " DDSCAPS2::dwCaps: ");
if( ddscaps.dwCaps & DDSCAPS_3DDEVICE ) strcat( sz, "DDSCAPS_3DDEVICE, ");
if( ddscaps.dwCaps & DDSCAPS_ALLOCONLOAD ) strcat( sz, "DDSCAPS_ALLOCONLOAD, ");
if( ddscaps.dwCaps & DDSCAPS_ALPHA ) strcat( sz, "DDSCAPS_ALPHA, ");
if( ddscaps.dwCaps & DDSCAPS_BACKBUFFER ) strcat( sz, "DDSCAPS_BACKBUFFER, ");
if( ddscaps.dwCaps & DDSCAPS_COMPLEX ) strcat( sz, "DDSCAPS_COMPLEX, ");
if( ddscaps.dwCaps & DDSCAPS_FLIP ) strcat( sz, "DDSCAPS_FLIP, ");
if( ddscaps.dwCaps & DDSCAPS_FRONTBUFFER ) strcat( sz, "DDSCAPS_FRONTBUFFER, ");
if( ddscaps.dwCaps & DDSCAPS_HWCODEC ) strcat( sz, "DDSCAPS_HWCODEC, ");
if( ddscaps.dwCaps & DDSCAPS_LIVEVIDEO ) strcat( sz, "DDSCAPS_LIVEVIDEO, ");
if( ddscaps.dwCaps & DDSCAPS_LOCALVIDMEM ) strcat( sz, "DDSCAPS_LOCALVIDMEM, ");
if( ddscaps.dwCaps & DDSCAPS_MIPMAP ) strcat( sz, "DDSCAPS_MIPMAP, ");
if( ddscaps.dwCaps & DDSCAPS_MODEX ) strcat( sz, "DDSCAPS_MODEX, ");
if( ddscaps.dwCaps & DDSCAPS_NONLOCALVIDMEM ) strcat( sz, "DDSCAPS_NONLOCALVIDMEM, ");
if( ddscaps.dwCaps & DDSCAPS_OFFSCREENPLAIN ) strcat( sz, "DDSCAPS_OFFSCREENPLAIN, ");
if( ddscaps.dwCaps & DDSCAPS_OPTIMIZED ) strcat( sz, "DDSCAPS_OPTIMIZED, ");
if( ddscaps.dwCaps & DDSCAPS_OVERLAY ) strcat( sz, "DDSCAPS_OVERLAY, ");
if( ddscaps.dwCaps & DDSCAPS_OWNDC ) strcat( sz, "DDSCAPS_OWNDC, ");
if( ddscaps.dwCaps & DDSCAPS_PALETTE ) strcat( sz, "DDSCAPS_PALETTE, ");
if( ddscaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) strcat( sz, "DDSCAPS_PRIMARYSURFACE, ");
if( ddscaps.dwCaps & DDSCAPS_STANDARDVGAMODE ) strcat( sz, "DDSCAPS_STANDARDVGAMODE, ");
if( ddscaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) strcat( sz, "DDSCAPS_SYSTEMMEMORY, ");
if( ddscaps.dwCaps & DDSCAPS_TEXTURE ) strcat( sz, "DDSCAPS_TEXTURE, ");
if( ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY ) strcat( sz, "DDSCAPS_VIDEOMEMORY, ");
if( ddscaps.dwCaps & DDSCAPS_VIDEOPORT ) strcat( sz, "DDSCAPS_VIDEOPORT, ");
if( ddscaps.dwCaps & DDSCAPS_VISIBLE ) strcat( sz, "DDSCAPS_VISIBLE, ");
if( ddscaps.dwCaps & DDSCAPS_WRITEONLY ) strcat( sz, "DDSCAPS_WRITEONLY, ");
if( ddscaps.dwCaps & DDSCAPS_ZBUFFER ) strcat( sz, "DDSCAPS_ZBUFFER, ");
strcat( sz, "\n");
OutputDebugString(sz);
strcpy( sz, " DDSCAPS2::dwCaps2: ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP ) strcat( sz, "DDSCAPS2_CUBEMAP, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) strcat( sz, "DDSCAPS2_CUBEMAP_POSITIVEX, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) strcat( sz, "DDSCAPS2_CUBEMAP_NEGATIVEX, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) strcat( sz, "DDSCAPS2_CUBEMAP_POSITIVEY, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) strcat( sz, "DDSCAPS2_CUBEMAP_NEGATIVEY, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) strcat( sz, "DDSCAPS2_CUBEMAP_POSITIVEZ, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) strcat( sz, "DDSCAPS2_CUBEMAP_NEGATIVEZ, ");
if( ddscaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES ) strcat( sz, "DDSCAPS2_CUBEMAP_ALLFACES, ");
if( ddscaps.dwCaps2 & DDSCAPS2_D3DTEXTUREMANAGE ) strcat( sz, "DDSCAPS2_D3DTEXTUREMANAGE, ");
if( ddscaps.dwCaps2 & DDSCAPS2_DONOTPERSIST ) strcat( sz, "DDSCAPS2_DONOTPERSIST, ");
if( ddscaps.dwCaps2 & DDSCAPS2_HARDWAREDEINTERLACE ) strcat( sz, "DDSCAPS2_HARDWAREDEINTERLACE, ");
if( ddscaps.dwCaps2 & DDSCAPS2_HINTANTIALIASING ) strcat( sz, "DDSCAPS2_HINTANTIALIASING, ");
if( ddscaps.dwCaps2 & DDSCAPS2_HINTDYNAMIC ) strcat( sz, "DDSCAPS2_HINTDYNAMIC, ");
if( ddscaps.dwCaps2 & DDSCAPS2_HINTSTATIC ) strcat( sz, "DDSCAPS2_HINTSTATIC, ");
if( ddscaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ) strcat( sz, "DDSCAPS2_MIPMAPSUBLEVEL, ");
if( ddscaps.dwCaps2 & DDSCAPS2_OPAQUE ) strcat( sz, "DDSCAPS2_OPAQUE, ");
if( ddscaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT ) strcat( sz, "DDSCAPS2_STEREOSURFACELEFT, ");
if( ddscaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE ) strcat( sz, "DDSCAPS2_TEXTUREMANAGE, ");
strcat( sz, "\n");
OutputDebugString(sz);
}
void ReportPixelFormat( DDPIXELFORMAT ddpf)
{
char szFlags[4096];
char szMsg[MAX_PATH];
PixelFormatHelper( ddpf.dwFlags, szFlags);
OutputDebugString(szFlags);
sprintf( szMsg, " dwFourCC: %ld\n", ddpf.dwFourCC);
OutputDebugString(szMsg);
sprintf( szMsg, " dwRGBBitCount: %ld\n", ddpf.dwRGBBitCount);
OutputDebugString(szMsg);
OutputDebugString(" (dwYUVBitCount, dwZBufferBitDepth, dwAlphaBitDepth, dwLuminanceBitCount, dwBumpBitCount)\n");
sprintf( szMsg, " dwRBitMask: %ld\n", ddpf.dwRBitMask);
OutputDebugString(szMsg);
OutputDebugString(" (dwYBitMask, dwStencilBitDepth, dwLuminanceBitMask, dwBumpDuBitMask)\n");
sprintf( szMsg, " dwGBitMask: %ld\n", ddpf.dwGBitMask);
OutputDebugString(szMsg);
OutputDebugString(" (dwUBitMask, dwZBitMask, dwBumpDvBitMask)\n");
sprintf( szMsg, " dwBBitMask: %ld\n", ddpf.dwBBitMask);
OutputDebugString(szMsg);
OutputDebugString(" (dwVBitMask, dwStencilBitMask, dwBumpLuminanceBitMask)\n");
sprintf( szMsg, " dwRGBAlphaBitMask: %ld\n", ddpf.dwRGBAlphaBitMask);
OutputDebugString(szMsg);
OutputDebugString(" (dwYUVAlphaBitMask, dwLuminanceAlphaBitMask, dwRGBZBitMask, dwYUVZBitMask)\n");
}
void SurfaceDescHelper( DWORD dwFlags, char * pszFlags )
{
if( !pszFlags )
{
return;
}
strcpy( pszFlags, " dwFlags: ");
if( dwFlags & DDSD_ALL )
strcat( pszFlags, "DDSD_ALL\n");
if( dwFlags & DDSD_ALPHABITDEPTH )
strcat( pszFlags, "DDSD_ALPHABITDEPTH\n");
if( dwFlags & DDSD_BACKBUFFERCOUNT )
strcat( pszFlags, "DDSD_BACKBUFFERCOUNT\n");
if( dwFlags & DDSD_CAPS )
strcat( pszFlags, "DDSD_CAPS\n");
if( dwFlags & DDSD_CKDESTBLT )
strcat( pszFlags, "DDSD_CKDESTBLT\n");
if( dwFlags & DDSD_CKDESTOVERLAY )
strcat( pszFlags, "DDSD_CKDESTOVERLAY\n");
if( dwFlags & DDSD_CKSRCBLT )
strcat( pszFlags, "DDSD_CKSRCBLT\n");
if( dwFlags & DDSD_CKSRCOVERLAY )
strcat( pszFlags, "DDSD_CKSRCOVERLAY\n");
if( dwFlags & DDSD_HEIGHT )
strcat( pszFlags, "DDSD_HEIGHT\n");
if( dwFlags & DDSD_LINEARSIZE )
strcat( pszFlags, "DDSD_LINEARSIZE\n");
if( dwFlags & DDSD_LPSURFACE )
strcat( pszFlags, "DDSD_LPSURFACE\n");
if( dwFlags & DDSD_MIPMAPCOUNT )
strcat( pszFlags, "DDSD_MIPMAPCOUNT\n");
if( dwFlags & DDSD_PITCH )
strcat( pszFlags, "DDSD_PITCH\n");
if( dwFlags & DDSD_PIXELFORMAT )
strcat( pszFlags, "DDSD_PIXELFORMAT\n");
if( dwFlags & DDSD_REFRESHRATE )
strcat( pszFlags, "DDSD_REFRESHRATE\n");
if( dwFlags & DDSD_TEXTURESTAGE )
strcat( pszFlags, "DDSD_TEXTURESTAGE\n");
if( dwFlags & DDSD_WIDTH )
strcat( pszFlags, "DDSD_WIDTH\n");
strcat(pszFlags, "\n");
}
void PixelFormatHelper( DWORD dwFlags, char * pszFlags)
{
if( !pszFlags )
{
return;
}
strcpy( pszFlags, " dwFlags: ");
if( dwFlags & DDPF_ALPHA )
strcat( pszFlags, "DDPF_ALPHA, ");
if( dwFlags & DDPF_ALPHAPIXELS )
strcat( pszFlags, "DDPF_ALPHAPIXELS, ");
if( dwFlags & DDPF_ALPHAPREMULT )
strcat( pszFlags, "DDPF_ALPHAPREMULT, ");
if( dwFlags & DDPF_BUMPLUMINANCE )
strcat( pszFlags, "DDPF_BUMPLUMINANCE, ");
if( dwFlags & DDPF_BUMPDUDV )
strcat( pszFlags, "DDPF_BUMPDUDV, ");
if( dwFlags & DDPF_COMPRESSED )
strcat( pszFlags, "DDPF_COMPRESSED, ");
if( dwFlags & DDPF_FOURCC )
strcat( pszFlags, "DDPF_FOURCC, ");
if( dwFlags & DDPF_LUMINANCE )
strcat( pszFlags, "DDPF_LUMINANCE, ");
if( dwFlags & DDPF_PALETTEINDEXED1 )
strcat( pszFlags, "DDPF_PALETTEINDEXED1, ");
if( dwFlags & DDPF_PALETTEINDEXED2 )
strcat( pszFlags, "DDPF_PALETTEINDEXED2, ");
if( dwFlags & DDPF_PALETTEINDEXED4 )
strcat( pszFlags, "DDPF_PALETTEINDEXED4, ");
if( dwFlags & DDPF_PALETTEINDEXED8 )
strcat( pszFlags, "DDPF_PALETTEINDEXED8, ");
if( dwFlags & DDPF_PALETTEINDEXEDTO8 )
strcat( pszFlags, "DDPF_PALETTEINDEXEDTO8, ");
if( dwFlags & DDPF_RGB )
strcat( pszFlags, "DDPF_RGB, ");
if( dwFlags & DDPF_RGBTOYUV )
strcat( pszFlags, "DDPF_RGBTOYUV, ");
if( dwFlags & DDPF_STENCILBUFFER )
strcat( pszFlags, "DDPF_STENCILBUFFER, ");
if( dwFlags & DDPF_YUV )
strcat( pszFlags, "DDPF_YUV, ");
if( dwFlags & DDPF_ZBUFFER )
strcat( pszFlags, "DDPF_ZBUFFER, ");
if( dwFlags & DDPF_ZPIXELS )
strcat( pszFlags, "DDPF_ZPIXELS, ");
strcat( pszFlags, "\n");
}
/*****************************Private*Routine******************************\
* VerifyVMR
*
\**************************************************************************/
BOOL VerifyVMR(void)
{
HRESULT hres;
CoInitialize(NULL);
// Verify that the VMR exists on this system
IBaseFilter* pBF = NULL;
hres = CoCreateInstance(CLSID_VideoMixingRenderer,
NULL,
CLSCTX_INPROC,
IID_IBaseFilter,
(LPVOID *)&pBF);
if(SUCCEEDED(hres))
{
pBF->Release();
CoUninitialize();
return TRUE;
}
else
{
MessageBox(hwndApp,
TEXT("This application requires the Video Mixing Renderer, which is present\r\n")
TEXT("only on Windows XP.\r\n\r\n")
TEXT("The Video Mixing Renderer (VMR) is also not enabled when viewing a \r\n")
TEXT("remote Windows XP machine through a Remote Desktop session.\r\n")
TEXT("You can run VMR-enabled applications only on your local machine.")
TEXT("\r\n\r\nThis sample will now exit."),
TEXT("Video Mixing Renderer capabilities are required"), MB_OK);
CoUninitialize();
return FALSE;
}
}

View File

@@ -0,0 +1,71 @@
//----------------------------------------------------------------------------
// File: Utils.h
//
// Desc: DirectShow sample code
// Prototypes for external (global) utilities
// specific for VMRXcl app
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
// global headers
#if !defined(UTILS_H)
#define UTILS_H
// helper function prototypes
DWORD MyMessage(char *sQuestion, char *sTitle);
const char * hresultNameLookup(HRESULT hres);
bool MySleep(DWORD dwTime = 2500);
void ReportPixelFormat( DDPIXELFORMAT ddpf);
void ReportDDSCAPS2( DDSCAPS2 ddscaps );
void ReportDDrawSurfDesc( DDSURFACEDESC2 ddsd);
void PixelFormatHelper( DWORD dwFlags, char * pszFlags);
void SurfaceDescHelper( DWORD dwFlags, char * pszFlags );
//----------------------------------------------------------------------------
// SceneSettings
//
// This structure defines demonstration settings
//----------------------------------------------------------------------------
struct SceneSettings
{
bool bRotateZ; // rotate around Z axis if true
int nGradZ; // angle of rotation around Z axis, in grades
// this is a 'time' variable for Z-rotation effect
bool bRotateY; // rotate around Y axis if true
int nGradY; // angle of rotation around Y axis, in grades
// this is a 'time' variable for Y-rotation effect
bool bShowStatistics; // show FPS in the upper right corner if true
bool bShowTwist; // show "twist" effect if true; THIS STATE OVERRIDES bRotateZ AND bRotateY
int nDy; // vertical offset for the twist effect
// this is a 'time' variable for "twist" effect
bool bShowHelp; // show text help hints if true (it is activated by right click on the control)
int nXHelp; // coordinates for text help hint
int nYHelp;
TCHAR achHelp[MAX_PATH]; // help hint text
TCHAR achFPS[MAX_PATH]; // string representation of FramesPerSecons
// (when bShowStatistics is on)
SceneSettings() // constructor: no effects by default
{
bRotateZ = false;
nGradZ = 0;
bRotateY = false;
nGradY = 0;
bShowStatistics = false;
bShowTwist = false;
nDy = 0;
bShowHelp = 0;
nXHelp = 0;
nYHelp = 0;
lstrcpy(achHelp, TEXT(""));
};
~SceneSettings()
{
};
};
#endif

View File

@@ -0,0 +1,196 @@
# Microsoft Developer Studio Project File - Name="VMRXcl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=VMRXcl - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "VMRXcl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "VMRXcl.mak" CFG="VMRXcl - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "VMRXcl - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "VMRXcl - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "VMRXcl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /O2 /I "..\..\BaseClasses" /I "..\..\..\DirectShow\BaseClasses" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D WINVER=0x501 /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" /d "WIN32"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 d3dx.lib ..\..\..\DirectShow\baseclasses\release\strmbase.lib strmiids.lib comctl32.lib winmm.lib gdi32.lib ddraw.lib comdlg32.lib /nologo /subsystem:windows /pdb:none /machine:I386
!ELSEIF "$(CFG)" == "VMRXcl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\..\..\DirectShow\BaseClasses" /D "DEBUG" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D WINVER=0x501 /YX"project.h" /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" /d "WIN32"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 d3dx.lib ..\..\..\DirectShow\baseclasses\debug\strmbasd.lib strmiids.lib comctl32.lib winmm.lib gdi32.lib ddraw.lib comdlg32.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcmtd" /pdbtype:sept
# SUBTRACT LINK32 /map
!ENDIF
# Begin Target
# Name "VMRXcl - Win32 Release"
# Name "VMRXcl - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\AllocPresenter.cpp
# End Source File
# Begin Source File
SOURCE=.\app.cpp
# End Source File
# Begin Source File
SOURCE=.\commands.cpp
# End Source File
# Begin Source File
SOURCE=.\d3dfont.cpp
# End Source File
# Begin Source File
SOURCE=.\d3dtextr.cpp
# End Source File
# Begin Source File
SOURCE=.\d3dutil.cpp
# End Source File
# Begin Source File
SOURCE=.\DDrawSupport.cpp
# End Source File
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# Begin Source File
SOURCE=.\Utils.cpp
# End Source File
# Begin Source File
SOURCE=.\vcdplyer.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\app.h
# End Source File
# Begin Source File
SOURCE=.\BltAlpha.h
# End Source File
# Begin Source File
SOURCE=.\d3dfont.h
# End Source File
# Begin Source File
SOURCE=.\d3dtextr.h
# End Source File
# Begin Source File
SOURCE=.\d3dutil.h
# End Source File
# Begin Source File
SOURCE=.\DDrawSupport.h
# End Source File
# Begin Source File
SOURCE=.\project.h
# End Source File
# Begin Source File
SOURCE=.\resource.h
# End Source File
# Begin Source File
SOURCE=.\Utils.h
# End Source File
# Begin Source File
SOURCE=.\vcdplyer.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\VMRXcl.ico
# End Source File
# Begin Source File
SOURCE=.\VMRXcl.rc
# End Source File
# Begin Source File
SOURCE=.\VMRxclMenu.bmp
# End Source File
# End Group
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "VMRXCL"=.\VMRXCL.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,173 @@
//Microsoft Developer Studio generated resource script.
//
#include "resrc1.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_ACCELERATOR ACCELERATORS DISCARDABLE
BEGIN
"S", IDM_MOVIE_STOP, VIRTKEY, CONTROL, NOINVERT
"P", IDM_MOVIE_PLAY, VIRTKEY, CONTROL, NOINVERT
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resrc1.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""resource.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_MENU BITMAP DISCARDABLE "VMRxclMenu.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "VMRXcl.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 8,1,0,0
PRODUCTVERSION 8,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "This sample requires Windows XP or greater.\0"
VALUE "CompanyName", "Microsoft\0"
VALUE "FileDescription", "VMR Exclusive Mode Application\0"
VALUE "FileVersion", "8.10\0"
VALUE "InternalName", "VMR XCL\0"
VALUE "LegalCopyright", "Copyright (c) 2000-2001 Microsoft Corporation\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "VMRXCL.EXE\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "DirectX 8.1 SDK\0"
VALUE "ProductVersion", "8.1\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDM_MOVIE_STOP "Stop"
IDM_MOVIE_PLAY "Play"
IDM_MOVIE_PAUSE "Pause"
END
STRINGTABLE DISCARDABLE
BEGIN
IDM_FULL_SCREEN "Full screen playback"
END
STRINGTABLE DISCARDABLE
BEGIN
STR_FILE_OPEN "Open a new movie to play"
STR_FILE_CLOSE "Close the movie"
STR_FILE_EXIT "Quit VMR Exclusive Mode Player"
END
STRINGTABLE DISCARDABLE
BEGIN
STR_FILE_FILTER "All Movies#*.mpg;*.avi;*.dat;*.mov#Mpeg Files (*.mpg)#*.mpg#Video CD Files (*.dat)#*.dat#QuickTime Files (*.mov)#*.mov#All Files (*.*)#*.*#"
STR_APP_TITLE "VMR Exclusive Mode Player"
STR_APP_TITLE_LOADED "VMR Exclusive Mode Player - %s"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -0,0 +1,811 @@
//----------------------------------------------------------------------------
// File: app.cpp
//
// Desc: DirectShow sample code
// Main module for customized video player in exclusive mode
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include "project.h"
#include <atlbase.h>
#include <atlconv.cpp>
#include <mmreg.h>
#include <commctrl.h>
#include <stdarg.h>
#include <stdio.h>
#include "utils.h"
/* -------------------------------------------------------------------------
** Global variables that are initialized at run time and then stay constant.
** -------------------------------------------------------------------------
*/
HINSTANCE g_hInst;
HICON hIconVideoCd;
HWND hwndApp;
HWND g_hwndToolbar;
CMpegMovie *pMpegMovie;
BOOL g_bPlay = FALSE;
/* -------------------------------------------------------------------------
** True Globals - these may change during execution of the program.
** -------------------------------------------------------------------------
*/
TCHAR g_achFileName[MAX_PATH];
DWORD g_State = VCD_NO_CD;
BOOL g_bFullScreen = FALSE;
struct SceneSettings g_ss;
const LONG g_Style = WS_POPUP | WS_CAPTION | WS_SYSMENU;
/* -------------------------------------------------------------------------
** Constants
** -------------------------------------------------------------------------
*/
const TCHAR szClassName[] = TEXT("VMRXCLPlayer_CLASS");
const TCHAR g_szNULL[] = TEXT("\0");
const TCHAR g_szEmpty[] = TEXT("");
typedef enum VMRXcl_menu
{
evxShowInfo = 0x0,
evxMoviePause,
evxMoviePlay,
evxMovieRotateZ,
evxMovieRotateY,
evxMovieTwist,
evxMovieOption4,
evxExit,
} VMRXcl_menu;
void SetFullScreenMode(BOOL bMode);
BOOL IsFullScreenMode();
extern BOOL VerifyVMR(void);
/******************************Public*Routine******************************\
* WinMain
*
*
* Windows recognizes this function by name as the initial entry point
* for the program. This function calls the application initialization
* routine, if no other instance of the program is running, and always
* calls the instance initialization routine. It then executes a message
* retrieval and dispatch loop that is the top-level control structure
* for the remainder of execution. The loop is terminated when a WM_QUIT
* message is received, at which time this function exits the application
* instance by returning the value passed by PostQuitMessage().
*
* If this function must abort before entering the message loop, it
* returns the conventional value NULL.
*
\**************************************************************************/
int PASCAL
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLineOld,
int nCmdShow
)
{
USES_CONVERSION;
int iRet=0;
LPTSTR lpCmdLine = A2T(lpCmdLineOld);
HRESULT hres = CoInitialize(NULL);
if (hres == S_FALSE) {
CoUninitialize();
}
if ( !hPrevInstance ) {
if ( !InitApplication( hInstance ) ) {
return FALSE;
}
}
/*
** Perform initializations that apply to a specific instance
*/
if ( !InitInstance( hInstance, nCmdShow ) ) {
return FALSE;
}
// Verify that the Video Mixing Renderer is present (requires Windows XP).
// Otherwise, this sample cannot continue.
if (!VerifyVMR())
return FALSE;
/* Look for options */
while (lpCmdLine && (*lpCmdLine == '-' || *lpCmdLine == '/')) {
if (lpCmdLine[1] == 'P') {
g_bPlay = TRUE;
lpCmdLine += 2;
} else {
break;
}
while (lpCmdLine[0] == ' ') {
lpCmdLine++;
}
}
SetFullScreenMode(g_bPlay);
// If the user selects a file, open it and start playing.
// Otherwise, just exit the app.
if (ProcessOpen(lpCmdLine, TRUE) == TRUE)
{
/*
** Acquire and dispatch messages until a WM_QUIT message is received.
*/
iRet = DoMainLoop();
}
QzUninitialize();
return iRet;
}
/*****************************Private*Routine******************************\
* DoMainLoop
*
* Process the main message loop
*
\**************************************************************************/
int
DoMainLoop(
void
)
{
MSG msg;
HANDLE ahObjects[8];;
int cObjects;
HACCEL haccel = LoadAccelerators(g_hInst, MAKEINTRESOURCE(IDR_ACCELERATOR));
//
// message loop lasts until we get a WM_QUIT message
// upon which we shall return from the function
//
for ( ;; ) {
if (pMpegMovie != NULL) {
cObjects = 1;
ahObjects[0] = pMpegMovie->GetMovieEventHandle();
}
else {
ahObjects[0] = NULL;
cObjects = 0;
}
if (ahObjects[0] == NULL) {
WaitMessage();
}
else {
//
// wait for any message sent or posted to this queue
// or for a graph notification
//
DWORD result;
result = MsgWaitForMultipleObjects(cObjects, ahObjects, FALSE,
INFINITE, QS_ALLINPUT);
if (result != (WAIT_OBJECT_0 + cObjects)) {
VideoCd_OnGraphNotify(result - WAIT_OBJECT_0);
continue;
}
}
//
// When here, we either have a message or no event handle
// has been created yet.
//
// read all of the messages in this next loop
// removing each message as we read it
//
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
switch( msg.message )
{
case WM_QUIT:
return (int) msg.wParam;
break;
}
if (!TranslateAccelerator(hwndApp, haccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
} // DoMainLoop
/*****************************Private*Routine******************************\
* InitApplication(HANDLE)
*
* This function is called at initialization time only if no other
* instances of the application are running. This function performs
* initialization tasks that can be done once for any number of running
* instances.
*
* In this case, we initialize a window class by filling out a data
* structure of type WNDCLASS and calling the Windows RegisterClass()
* function. Since all instances of this application use the same window
* class, we only need to do this when the first instance is initialized.
*
\**************************************************************************/
BOOL
InitApplication(
HINSTANCE hInstance
)
{
WNDCLASS wc;
/*
** Fill in window class structure with parameters that describe the
** main window.
*/
hIconVideoCd = LoadIcon( hInstance, MAKEINTRESOURCE(IDR_VIDEOCD_ICON) );
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = VideoCdWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = hIconVideoCd;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)NULL; // (COLOR_BTNFACE + 1);
wc.lpszMenuName = MAKEINTRESOURCE( IDR_MAIN_MENU);
wc.lpszClassName = szClassName;
/*
** Register the window class and return success/failure code.
*/
return RegisterClass( &wc );
}
/*****************************Private*Routine******************************\
* InitInstance
*
*
* This function is called at initialization time for every instance of
* this application. This function performs initialization tasks that
* cannot be shared by multiple instances.
*
* In this case, we save the instance handle in a static variable and
* create and display the main program window.
*
\**************************************************************************/
BOOL
InitInstance(
HINSTANCE hInstance,
int nCmdShow
)
{
HWND hwnd;
/*
** Save the instance handle in static variable, which will be used in
** many subsequence calls from this application to Windows.
*/
g_hInst = hInstance;
/*
** Create a hidden window for this application instance.
*/
hwnd = CreateWindow( szClassName, IdStr(STR_APP_TITLE), g_Style,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL );
/*
** If window could not be created, return "failure"
*/
if ( NULL == hwnd ) {
return FALSE;
}
hwndApp = hwnd;
/*
** Keep the main window invisible, since all we need to do is
* display a FileOpen dialog box.
*/
return TRUE;
}
/*****************************Private*Routine******************************\
* GetMoviePosition
*
* Place the movie in the centre of the client window. We do not stretch the
* the movie yet !
*
\**************************************************************************/
void
GetMoviePosition(
HWND hwnd,
long* xPos,
long* yPos,
long* pcx,
long* pcy
)
{
RECT rc = {0, 0, 400, 300};
GetClientRect(hwnd, &rc);
*xPos = rc.left;
*yPos = rc.top;
*pcx = rc.right - rc.left;
*pcy = rc.bottom - rc.top;
}
/******************************Public*Routine******************************\
* RepositionMovie
*
\**************************************************************************/
void
RepositionMovie(HWND hwnd)
{
if (pMpegMovie) {
IVMRWindowlessControl* lpDefWC = pMpegMovie->GetWLC();
if (lpDefWC) {
LONG w, h;
lpDefWC->GetNativeVideoSize(&w, &h, NULL, NULL);
RECT rc = {(640-w)/2, (480-h)/2, (640+w)/2, (480+h)/2};
lpDefWC->SetVideoPosition(NULL, &rc);
}
}
}
/*****************************Private*Routine******************************\
* VideoCd_OnMove
*
\**************************************************************************/
void
VideoCd_OnMove(
HWND hwnd,
int x,
int y
)
{
if (pMpegMovie) {
if (pMpegMovie->GetStateMovie() != State_Running) {
RepositionMovie(hwnd);
}
}
}
/******************************Public*Routine******************************\
* VideoCdWndProc
*
\**************************************************************************/
LRESULT CALLBACK
VideoCdWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
switch ( message ) {
HANDLE_MSG( hwnd, WM_CREATE, VideoCd_OnCreate );
HANDLE_MSG( hwnd, WM_PAINT, VideoCd_OnPaint );
HANDLE_MSG( hwnd, WM_CLOSE, VideoCd_OnClose );
HANDLE_MSG( hwnd, WM_DESTROY, VideoCd_OnDestroy );
HANDLE_MSG( hwnd, WM_SIZE, VideoCd_OnSize );
HANDLE_MSG( hwnd, WM_KEYUP, VideoCd_OnKeyUp);
HANDLE_MSG( hwnd, WM_MOVE, VideoCd_OnMove );
case WM_LBUTTONUP:
{
VideoCd_OnClick(hwnd, wParam, lParam);
}
break;
case WM_RBUTTONUP:
{
VideoCd_OnClickHold(hwnd, wParam, lParam);
}
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0L;
}
/*****************************Private*Routine******************************\
* VideoCd_OnCreate
*
\**************************************************************************/
BOOL
VideoCd_OnCreate(
HWND hwnd,
LPCREATESTRUCT lpCreateStruct
)
{
return TRUE;
}
/*****************************Private*Routine******************************\
* VideoCd_OnKeyUp
*
\**************************************************************************/
void
VideoCd_OnKeyUp(
HWND hwnd,
UINT vk,
BOOL fDown,
int cRepeat,
UINT flags
)
{
// Catch escape sequences to stop fullscreen mode
if (vk == VK_ESCAPE) {
if (pMpegMovie) {
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
}
}
/*****************************Private*Routine******************************\
* VideoCd_OnClick
*
\**************************************************************************/
void
VideoCd_OnClick(
HWND hwnd,
WPARAM pParam,
LPARAM lParam)
{
int xPos;
int yPos;
int nMenuItem = -1;
xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);
g_ss.bShowHelp = false;
g_ss.nXHelp = 0;
g_ss.nYHelp = 0;
lstrcpy( g_ss.achHelp, TEXT(""));
if( xPos >= 3 && xPos <= 55 )
{
nMenuItem = (yPos -6)/53;
if( nMenuItem == 8 )
{
nMenuItem = -1;
}
}
switch( nMenuItem)
{
case evxMovieRotateZ:
g_ss.bShowTwist = false;
g_ss.nDy = 0;
g_ss.bRotateZ = !(g_ss.bRotateZ);
break;
case evxMovieRotateY:
g_ss.bShowTwist = false;
g_ss.nDy = 0;
g_ss.bRotateY = !(g_ss.bRotateY);
break;
case evxMovieTwist:
g_ss.bShowTwist = !(g_ss.bShowTwist);
break;
case evxExit:
if (pMpegMovie)
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
break;
case evxMoviePause:
if( pMpegMovie )
{
pMpegMovie->PauseMovie();
}
break;
case evxMoviePlay:
if( pMpegMovie )
{
pMpegMovie->PlayMovie();
}
break;
case evxShowInfo:
g_ss.bShowStatistics = !(g_ss.bShowStatistics);
break;
}// switch
}
/*****************************Private*Routine******************************\
* VideoCd_OnClickHold
*
\**************************************************************************/
void
VideoCd_OnClickHold(
HWND hwnd,
WPARAM pParam,
LPARAM lParam)
{
int xPos;
int yPos;
int nMenuItem = -1;
OutputDebugString("*** Event is captured\n");
xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);
g_ss.bShowHelp = false;
g_ss.nXHelp = 0;
g_ss.nYHelp = 0;
lstrcpy( g_ss.achHelp, TEXT(""));
if( xPos >= 3 && xPos <= 55 )
{
nMenuItem = (yPos -6)/53;
g_ss.bShowHelp = true;
if( nMenuItem == 8 )
{
nMenuItem = -1;
g_ss.bShowHelp = false;
}
}
if( g_ss.bShowHelp )
{
OutputDebugString("*** WILL show help\n");
}
else
{
OutputDebugString("*** WILL NOT show help\n");
}
switch( nMenuItem)
{
case evxMovieRotateZ:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Rotate around Z axis "));
break;
case evxMovieRotateY:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Rotate around Y axis "));
break;
case evxMovieTwist:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Non-linear transformation "));
break;
case evxExit:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Exit application "));
break;
case evxMoviePause:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Pause "));
break;
case evxMoviePlay:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Play "));
break;
case evxShowInfo:
g_ss.nXHelp = 70;
g_ss.nYHelp = yPos;
lstrcpy( g_ss.achHelp, TEXT("Show statistics "));
break;
}// switch
}
/*****************************Private*Routine******************************\
* VideoCd_OnPaint
*
\**************************************************************************/
void
VideoCd_OnPaint(
HWND hwnd
)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rc2;
/*
** Draw a frame around the movie playback area.
*/
hdc = BeginPaint( hwnd, &ps );
GetClientRect(hwnd, &rc2);
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1));
EndPaint( hwnd, &ps );
}
/******************************Public*Routine******************************\
* VideoCd_OnDestroy
*
\**************************************************************************/
void
VideoCd_OnDestroy(
HWND hwnd
)
{
PostQuitMessage( 0 );
}
/******************************Public*Routine******************************\
* VideoCd_OnClose
*
\**************************************************************************/
void
VideoCd_OnClose(
HWND hwnd
)
{
if (pMpegMovie) {
pMpegMovie->StopMovie();
pMpegMovie->CloseMovie();
delete pMpegMovie;
pMpegMovie = NULL;
}
DestroyWindow( hwnd );
}
/******************************Public*Routine******************************\
* VideoCd_OnSize
*
\**************************************************************************/
void
VideoCd_OnSize(
HWND hwnd,
UINT state,
int dx,
int dy
)
{
RepositionMovie(hwnd);
}
/*****************************Private*Routine******************************\
* VideoCd_OnGraphNotify
*
* This is where we get any notifications from the filter graph.
*
\**************************************************************************/
void
VideoCd_OnGraphNotify(
int stream
)
{
long lEventCode;
lEventCode = pMpegMovie->GetMovieEventCode();
switch (lEventCode) {
case EC_FULLSCREEN_LOST:
break;
case EC_COMPLETE:
// when movie is complete, reposition it to the start position
pMpegMovie->SeekToPosition(0L,FALSE);
break;
case EC_USERABORT:
case EC_ERRORABORT:
break;
}
}
/******************************Public*Routine******************************\
* IdStr
*
* Loads the given string resource ID into the passed storage.
*
\**************************************************************************/
LPCTSTR
IdStr(
int idResource
)
{
static TCHAR chBuffer[ STR_MAX_STRING_LEN ];
if (LoadString(g_hInst, idResource, chBuffer, STR_MAX_STRING_LEN) == 0) {
return g_szEmpty;
}
return chBuffer;
}
/******************************Public*Routine******************************\
* SetFullScreenMode
*
\**************************************************************************/
void
SetFullScreenMode(BOOL bMode)
{
g_bFullScreen = bMode;
static HMENU hMenu;
static LONG lStyle;
static int xs, ys, cxs, cys;
HDC hdcScreen = GetDC(NULL);
int cx = GetDeviceCaps(hdcScreen,HORZRES);
int cy = GetDeviceCaps(hdcScreen,VERTRES);
ReleaseDC(NULL, hdcScreen);
if (bMode) {
hMenu = GetMenu(hwndApp);
lStyle = GetWindowStyle(hwndApp);
WINDOWPLACEMENT wp;
GetWindowPlacement(hwndApp, &wp);
xs = wp.rcNormalPosition.left;
ys = wp.rcNormalPosition.top;
cxs = wp.rcNormalPosition.right - xs;
cys = wp.rcNormalPosition.bottom - ys;
ShowWindow(g_hwndToolbar, SW_HIDE);
SetMenu(hwndApp, NULL);
SetWindowLong(hwndApp, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE);
SetWindowPos(hwndApp, HWND_TOP, 0, 0, cx, cy, SWP_NOACTIVATE);
ShowCursor(FALSE);
}
else {
ShowCursor(TRUE);
ShowWindow(g_hwndToolbar, SW_SHOW);
SetMenu(hwndApp, hMenu);
SetWindowLong(hwndApp, GWL_STYLE, lStyle);
SetWindowPos(hwndApp, HWND_TOP, xs, ys, cxs, cys, SWP_NOACTIVATE);
}
}
/******************************Public*Routine******************************\
* IsFullScreenMode()
*
\**************************************************************************/
BOOL
IsFullScreenMode()
{
return g_bFullScreen;
}

View File

@@ -0,0 +1,342 @@
//----------------------------------------------------------------------------
// File: app.h
//
// Desc: DirectShow sample code
// Header file for customized video player application
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
/* -------------------------------------------------------------------------
** Functions prototypes
** -------------------------------------------------------------------------
*/
int
DoMainLoop(
void
);
BOOL
InitApplication(
HINSTANCE hInstance
);
BOOL
InitInstance(
HINSTANCE hInstance,
int nCmdShow
);
void
UpdateMpegMovieRect(
void
);
void
GetAdjustedClientRect(
RECT *prc
);
BOOL
DrawStats(
HDC hdc
);
void
CalcMovieRect(
LPRECT lprc
);
LPCTSTR
IdStr(
int idResource
);
void
UpdateSystemColors(
void
);
/* -------------------------------------------------------------------------
** Message crackers
** -------------------------------------------------------------------------
*/
#define HANDLE_WM_USER(hwnd, wParam, lParam, fn) \
((fn)(hwnd, wParam, lParam), 0L)
#ifndef HANDLE_WM_NOTIFY
#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \
(fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam))
#endif
/* -------------------------------------------------------------------------
** VideoCd window class prototypes
** -------------------------------------------------------------------------
*/
extern "C" LRESULT CALLBACK
VideoCdWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
);
void
VideoCd_OnClose(
HWND hwnd
);
BOOL
VideoCd_OnQueryEndSession(
HWND hwnd
);
void
VideoCd_OnDestroy(
HWND hwnd
);
void
VideoCd_OnClick(
HWND hwnd,
WPARAM pParam,
LPARAM lParam);
void
VideoCd_OnClickHold(
HWND hwnd,
WPARAM pParam,
LPARAM lParam);
void
VideoCd_OnCommand(
HWND hwnd,
int id,
HWND hwndCtl,
UINT codeNotify
);
void
VideoCd_OnPaint(
HWND hwnd
);
void
VideoCd_OnTimer(
HWND hwnd,
UINT id
);
BOOL
VideoCd_OnCreate(
HWND hwnd,
LPCREATESTRUCT lpCreateStruct
);
void
VideoCd_OnSize(
HWND hwnd,
UINT state,
int cx,
int cy
);
void
VideoCd_OnKeyUp(
HWND hwnd,
UINT vk,
BOOL fDown,
int cRepeat,
UINT flags
);
void
VideoCd_OnHScroll(
HWND hwnd,
HWND hwndCtl,
UINT code,
int pos
);
void
VideoCd_OnUser(
HWND hwnd,
WPARAM wParam,
LPARAM lParam
);
void
VideoCd_OnSysColorChange(
HWND hwnd
);
void
VideoCd_OnMenuSelect(
HWND hwnd,
HMENU hmenu,
int item,
HMENU hmenuPopup,
UINT flags
);
void
VideoCd_OnInitMenuPopup(
HWND hwnd,
HMENU hMenu,
UINT item,
BOOL fSystemMenu
);
#ifdef WM_NOTIFY
LRESULT
VideoCd_OnNotify(
HWND hwnd,
int idFrom,
NMHDR FAR* pnmhdr
);
#endif
void
VideoCd_OnGraphNotify(
int stream
);
void
VideoCd_OnDropFiles(
HWND hwnd,
HDROP hdrop);
void
SetPlayButtonsEnableState(
void
);
/* -------------------------------------------------------------------------
** Command processing functions
** -------------------------------------------------------------------------
*/
BOOL
VcdPlayerSetLog(
void
);
BOOL
VcdPlayerSetPerfLogFile(
void
);
BOOL
VcdPlayerOpenCmd(
void
);
BOOL
VcdPlayerCloseCmd(
void
);
BOOL
VcdPlayerPlayCmd(
void
);
BOOL
VcdPlayerStopCmd(
void
);
BOOL
VcdPlayerPauseCmd(
void
);
BOOL
VcdPlayerPauseCmd(
void
);
void
VcdPlayerSeekCmd(
REFTIME rtSeekBy
);
BOOL
ProcessOpen(
TCHAR *achFileName,
BOOL bPlay = FALSE
);
/* -------------------------------------------------------------------------
** Recent filename stuff
** -------------------------------------------------------------------------
*/
typedef TCHAR RECENTFILES[MAX_PATH];
#define MAX_RECENT_FILES 5
#define ID_RECENT_FILE_BASE 500
int
GetRecentFiles(
int LastCount
);
int
SetRecentFiles(
TCHAR *FileName,
int iCount
);
/* -------------------------------------------------------------------------
** Global Variables
** -------------------------------------------------------------------------
*/
extern int cxMovie;
extern int cyMovie;
extern HWND hwndApp;
extern int cx;
extern int cy;
extern int xOffset;
extern int yOffset;
extern DWORD g_State;
extern TCHAR g_szPerfLog[];
extern int g_TimeFormat;
/* -------------------------------------------------------------------------
** Constants
** -------------------------------------------------------------------------
*/
#define LEFT_MARGIN 0
/* -------------------------------------------------------------------------
** Player states: these are bit flags
** -------------------------------------------------------------------------
*/
#define VCD_PLAYING 0x0001
#define VCD_STOPPED 0x0002
#define VCD_PAUSED 0x0004
#define VCD_SKIP_F 0x0008
#define VCD_SKIP_B 0x0010
#define VCD_FF 0x0020
#define VCD_RW 0x0040
#define VCD_SEEKING (VCD_FF | VCD_RW)
#define VCD_LOADED 0x0080
#define VCD_NO_CD 0x0100
#define VCD_DATA_CD_LOADED 0x0200
#define VCD_EDITING 0x0400
#define VCD_PAUSED_AND_MOVED 0x0800
#define VCD_PLAY_PENDING 0x1000
#define VCD_WAS_PLAYING 0x2000
#define VCD_IN_USE 0x4000

View File

@@ -0,0 +1,143 @@
//----------------------------------------------------------------------------
// File: commands.cpp
//
// Desc: DirectShow sample code
// Processes commands from the user.
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include "project.h"
#include <mmreg.h>
#include <commctrl.h>
#include <stdio.h>
#include <io.h>
#include "resrc1.h"
// Function prototypes
void RepositionMovie(HWND hwnd);
bool FindMediaFile(TCHAR * achFileName, TCHAR * achFoundFile);
// External data
extern TCHAR g_achFileName[];
extern CMpegMovie * pMpegMovie;
//----------------------------------------------------------------------------
// ProcessOpen
//
// Creates instance of CMpegMovie and plays it. Called from user UI functions.
//
// Parameters:
// achFileName - path to the file to play
// bPlay - start demonstration if true
//----------------------------------------------------------------------------
BOOL
ProcessOpen(
TCHAR *achFileName,
BOOL bPlay
)
{
TCHAR achFoundFile[MAX_PATH];
if( !FindMediaFile(achFileName, achFoundFile) )
{
InvalidateRect( hwndApp, NULL, FALSE );
UpdateWindow( hwndApp );
return false;
}
lstrcpy(g_achFileName, achFoundFile);
pMpegMovie = new CMpegMovie(hwndApp);
if (pMpegMovie) {
HRESULT hr = pMpegMovie->OpenMovie(g_achFileName);
if (SUCCEEDED(hr)) {
TCHAR achTmp[MAX_PATH];
wsprintf(achTmp, IdStr(STR_APP_TITLE_LOADED), g_achFileName );
g_State = (VCD_LOADED | VCD_STOPPED);
RepositionMovie(hwndApp);
InvalidateRect(hwndApp, NULL, TRUE);
if (bPlay) {
pMpegMovie->PlayMovie();
}
}
else {
MessageBox(hwndApp,
TEXT("Failed to open the movie; "),
IdStr(STR_APP_TITLE), MB_OK );
pMpegMovie->CloseMovie();
delete pMpegMovie;
pMpegMovie = NULL;
}
}
InvalidateRect( hwndApp, NULL, FALSE );
UpdateWindow( hwndApp );
return TRUE;
}
//----------------------------------------------------------------------------
// FindMediaFile
//
// Provides FileOpen dialog to select media file or processes command line
//
// Parameters:
// achFileName - command line
// achFoundFile - path to the file to play
//
// Return: true if success
//----------------------------------------------------------------------------
bool FindMediaFile(TCHAR * achFileName, TCHAR * achFoundFile)
{
long lFindRes;
struct _finddata_t fileinfo;
lFindRes = _findfirst( achFileName, &fileinfo );
if( -1 != lFindRes )
{
lstrcpy(achFoundFile, achFileName);
return true;
}
OPENFILENAME ofn;
TCHAR szBuffer[MAX_PATH];
lstrcpy(szBuffer, TEXT(""));
static char szFilter[] = "Video Files (.MOV, .AVI, .MPG, .VOB, .QT)\0*.AVI;*.MOV;*.MPG;*.VOB;*.QT\0" \
"All Files (*.*)\0*.*\0\0";
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.lpstrFile = szBuffer;
ofn.nMaxFile = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = "VMRXCL: Select a video file to play...";
ofn.Flags = OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "mov";
ofn.lCustData = 0L;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (GetOpenFileName (&ofn)) // user specified a file
{
lstrcpy(achFoundFile, ofn.lpstrFile);
return true;
}// if
return false;
}

View File

@@ -0,0 +1,411 @@
//-----------------------------------------------------------------------------
// File: D3DFont.cpp
//
// Desc: Texture-based font class
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <streams.h>
#include <stdio.h>
#include <tchar.h>
#include <ddraw.h>
#define D3D_OVERLOADS
#include <d3d.h>
#include "D3DFont.h"
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color,
FLOAT tu, FLOAT tv )
{
FONT2DVERTEX v;
v.p.x = p.x;
v.p.y = p.y;
v.p.z = p.z;
v.p.w = p.w;
v.color = color;
v.tu = tu;
v.tv = tv;
return v;
}
//-----------------------------------------------------------------------------
// Name: CD3DFont()
// Desc: Font class constructor
//-----------------------------------------------------------------------------
CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags )
{
_tcscpy( m_strFontName, strFontName );
m_dwFontHeight = dwHeight;
m_dwFontFlags = dwFlags;
m_pd3dDevice = NULL;
m_pTexture = NULL;
ZeroMemory(&m_VB, sizeof(m_VB));
m_dwSavedStateBlock = 0L;
m_dwDrawTextStateBlock = 0L;
}
//-----------------------------------------------------------------------------
// Name: ~CD3DFont()
// Desc: Font class destructor
//-----------------------------------------------------------------------------
CD3DFont::~CD3DFont()
{
InvalidateDeviceObjects();
DeleteDeviceObjects();
}
//-----------------------------------------------------------------------------
// Name: InitDeviceObjects()
// Desc: Initializes device-dependent objects, including the vertex buffer used
// for rendering text and the texture map which stores the font image.
//-----------------------------------------------------------------------------
HRESULT CD3DFont::InitDeviceObjects(
LPDIRECTDRAW7 pDD,
LPDIRECT3DDEVICE7 pd3dDevice
)
{
HRESULT hr;
// Keep a local copy of the device
m_pd3dDevice = pd3dDevice;
// Establish the font and texture size
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Large fonts need larger textures
if( m_dwFontHeight > 40 )
m_dwTexWidth = m_dwTexHeight = 1024;
else if( m_dwFontHeight > 20 )
m_dwTexWidth = m_dwTexHeight = 512;
else
m_dwTexWidth = m_dwTexHeight = 256;
// If requested texture is too big, use a smaller texture and smaller font,
// and scale up when rendering.
D3DDEVICEDESC7 d3dCaps;
m_pd3dDevice->GetCaps( &d3dCaps );
if( m_dwTexWidth > d3dCaps.dwMaxTextureWidth )
{
m_fTextScale = (FLOAT)d3dCaps.dwMaxTextureWidth / (FLOAT)m_dwTexWidth;
m_dwTexWidth = m_dwTexHeight = d3dCaps.dwMaxTextureWidth;
}
DDSURFACEDESC2 ddsd;
INITDDSTRUCT(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTSTATIC;
ddsd.dwWidth = m_dwTexWidth;
ddsd.dwHeight = m_dwTexHeight;
ddsd.ddpfPixelFormat.dwFourCC = BI_RGB;
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xF000;
ddsd.ddpfPixelFormat.dwRBitMask = 0x0F00;
ddsd.ddpfPixelFormat.dwGBitMask = 0x00F0;
ddsd.ddpfPixelFormat.dwBBitMask = 0x000F;
// Create a new texture for the font
hr = pDD->CreateSurface(&ddsd, &m_pTexture, NULL);
if( FAILED(hr) )
return hr;
// Prepare to create a bitmap
DWORD* pBitmapBits;
BITMAPINFO bmi;
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
// Create a DC and a bitmap for the font
HDC hDC = CreateCompatibleDC( NULL );
HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
(VOID**)&pBitmapBits, NULL, 0 );
SetMapMode( hDC, MM_TEXT );
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
// antialiased font, but this is not guaranteed.
INT nHeight = -MulDiv( m_dwFontHeight,
(INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
DWORD dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL;
DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE;
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic,
FALSE, FALSE, DEFAULT_CHARSET, OUT_STRING_PRECIS,
CLIP_STROKE_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, m_strFontName );
if( NULL==hFont )
return E_FAIL;
SelectObject( hDC, hbmBitmap );
SelectObject( hDC, hFont );
// Set text properties
SetTextColor( hDC, RGB(255,255,255) );
SetBkColor( hDC, 0x00000000 );
SetTextAlign( hDC, TA_TOP );
// Loop through all printable character and output them to the bitmap..
// Meanwhile, keep track of the corresponding tex coords for each character.
DWORD x = 0;
DWORD y = 0;
TCHAR str[2] = _T("x");
SIZE size;
for( TCHAR c=32; c<127; c++ )
{
str[0] = c;
GetTextExtentPoint32( hDC, str, 1, &size );
if( (DWORD)(x+size.cx+1) > m_dwTexWidth )
{
x = 0;
y += size.cy+1;
}
ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL );
m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth;
m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight;
m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight;
x += size.cx+1;
}
// Lock the surface and write the alpha values for the set pixels
m_pTexture->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL);
WORD* pDst16 = (WORD*)ddsd.lpSurface;
BYTE bAlpha; // 4-bit measure of pixel intensity
for( y=0; y < m_dwTexHeight; y++ )
{
for( x=0; x < m_dwTexWidth; x++ )
{
bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
if (bAlpha > 0)
{
*pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff);
}
else
{
*pDst16++ = 0x0000;
}
}
}
// Done updating texture, so clean up used objects
m_pTexture->Unlock(NULL);
DeleteObject( hbmBitmap );
DeleteDC( hDC );
DeleteObject( hFont );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DFont::RestoreDeviceObjects()
{
// Create vertex buffer for the letters
ZeroMemory(&m_VB, sizeof(m_VB));
// Create the state blocks for rendering text
m_pd3dDevice->SetTexture(0, m_pTexture);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, 0x08);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATEREQUAL);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_POINT);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_NONE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0 );
m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
m_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CD3DFont::InvalidateDeviceObjects()
{
ZeroMemory(&m_VB, sizeof(m_VB));
// Delete the state blocks
if( m_pd3dDevice )
{
if (m_dwSavedStateBlock)
m_pd3dDevice->DeleteStateBlock(m_dwSavedStateBlock);
if (m_dwDrawTextStateBlock)
m_pd3dDevice->DeleteStateBlock(m_dwDrawTextStateBlock);
}
m_dwSavedStateBlock = 0L;
m_dwDrawTextStateBlock = 0L;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DeleteDeviceObjects()
{
RELEASE(m_pTexture);
m_pd3dDevice = NULL;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: GetTextExtent()
// Desc: Get the dimensions of a text string
//-----------------------------------------------------------------------------
HRESULT CD3DFont::GetTextExtent( TCHAR* strText, SIZE* pSize )
{
if( NULL==strText || NULL==pSize )
return E_FAIL;
FLOAT fRowWidth = 0.0f;
FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
FLOAT fWidth = 0.0f;
FLOAT fHeight = fRowHeight;
while( *strText )
{
TCHAR c = *strText++;
if( c == _T('\n') )
{
fRowWidth = 0.0f;
fHeight += fRowHeight;
}
if( c < _T(' ') )
continue;
FLOAT tx1 = m_fTexCoords[c-32][0];
FLOAT tx2 = m_fTexCoords[c-32][2];
fRowWidth += (tx2-tx1)*m_dwTexWidth;
if( fRowWidth > fWidth )
fWidth = fRowWidth;
}
pSize->cx = (int)fWidth;
pSize->cy = (int)fHeight;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DrawText()
// Desc: Draws 2D text
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
TCHAR* strText, DWORD dwFlags )
{
if( m_pd3dDevice == NULL )
return E_FAIL;
// Setup renderstate
RestoreDeviceObjects();
// Set filter states
if( dwFlags & D3DFONT_FILTERED )
{
m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
}
FLOAT fStartX = sx;
// Fill vertex buffer
FONT2DVERTEX* pVertices = NULL;
DWORD dwNumTriangles = 0;
pVertices = &m_VB[0];
while( *strText )
{
TCHAR c = *strText++;
if( c == _T('\n') )
{
sx = fStartX;
sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
}
if( c < _T(' ') )
continue;
FLOAT tx1 = m_fTexCoords[c-32][0];
FLOAT ty1 = m_fTexCoords[c-32][1];
FLOAT tx2 = m_fTexCoords[c-32][2];
FLOAT ty2 = m_fTexCoords[c-32][3];
FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale;
FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.5f,2.0f), dwColor, tx1, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.5f,2.0f), dwColor, tx2, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.5f,2.0f), dwColor, tx1, ty1 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.5f,2.0f), dwColor, tx2, ty1 );
dwNumTriangles += 2;
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
&m_VB[0], dwNumTriangles*2, D3DDP_WAIT);
pVertices = &m_VB[0];
dwNumTriangles = 0L;
sx += w;
}
return S_OK;
}

View File

@@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// File: D3DFont.h
//
// Desc: Texture-based font class
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#ifndef D3DFONT_H
#define D3DFONT_H
#include <tchar.h>
#include <ddraw.h>
#include <d3dxmath.h>
#define D3D_OVERLOADS
#include <d3d.h>
// Font creation flags
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
// Font rendering flags
#define D3DFONT_CENTERED 0x0001
#define D3DFONT_TWOSIDED 0x0002
#define D3DFONT_FILTERED 0x0004
#ifndef __INITDDSTRUCT_DEFINED
#define __INITDDSTRUCT_DEFINED
template <typename T>
__inline void INITDDSTRUCT(T& dd)
{
ZeroMemory(&dd, sizeof(dd));
dd.dwSize = sizeof(dd);
}
#endif
#ifndef __RELEASE_DEFINED
#define __RELEASE_DEFINED
template<typename T>
__inline void RELEASE( T* &p )
{
if( p ) {
p->Release();
p = NULL;
}
}
#endif
#define MAX_NUM_VERTICES 50*6
//-----------------------------------------------------------------------------
// Custom vertex types for rendering text
//-----------------------------------------------------------------------------
struct FONT2DVERTEX {
D3DXVECTOR4 p;
DWORD color;
FLOAT tu, tv;
};
//-----------------------------------------------------------------------------
// Name: class CD3DFont
// Desc: Texture-based font class for doing text in a 3D scene.
//-----------------------------------------------------------------------------
class CD3DFont
{
TCHAR m_strFontName[80]; // Font properties
DWORD m_dwFontHeight;
DWORD m_dwFontFlags;
LPDIRECT3DDEVICE7 m_pd3dDevice; // A D3DDevice used for rendering
LPDIRECTDRAWSURFACE7 m_pTexture; // The d3d texture for this font
FONT2DVERTEX m_VB[MAX_NUM_VERTICES]; // VertexBuffer for rendering text
DWORD m_dwTexWidth; // Texture dimensions
DWORD m_dwTexHeight;
FLOAT m_fTextScale;
FLOAT m_fTexCoords[128-32][4];
// Stateblocks for setting and restoring render states
DWORD m_dwSavedStateBlock;
DWORD m_dwDrawTextStateBlock;
public:
// 2D and 3D text drawing functions
HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor,
TCHAR* strText, DWORD dwFlags=0L );
// Function to get extent of text
HRESULT GetTextExtent( TCHAR* strText, SIZE* pSize );
// Initializing and destroying device-dependent objects
HRESULT InitDeviceObjects(LPDIRECTDRAW7 pDD, LPDIRECT3DDEVICE7 pd3dDevice);
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();
// Constructor / destructor
CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L );
~CD3DFont();
};
#endif

View File

@@ -0,0 +1,836 @@
//-----------------------------------------------------------------------------
// File: D3DTextr.cpp
//
// Desc: Functions to manage textures, including creating (loading from a
// file), restoring lost surfaces, invalidating, and destroying.
//
// Note: the implementation of these functions maintains an internal list
// of loaded textures. After creation, individual textures are referenced
// via their ASCII names.
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#include "project.h"
#include <tchar.h>
#include "D3DTextr.h"
#include "D3DUtil.h"
#include <stdio.h>
#ifndef _T
#define _T TEXT
#endif
//-----------------------------------------------------------------------------
// Macros, function prototypes and static variable
//-----------------------------------------------------------------------------
static TCHAR g_strTexturePath[512] = _T(""); // Path for files
// Local list of textures
static TextureContainer* g_ptcTextureList = NULL;
//-----------------------------------------------------------------------------
// Name: CD3DTextureManager
// Desc: Class used to automatically construct and destruct the static
// texture engine class.
//-----------------------------------------------------------------------------
class CD3DTextureManager
{
public:
CD3DTextureManager() {}
~CD3DTextureManager() { if( g_ptcTextureList ) delete g_ptcTextureList; }
};
// Global instance
CD3DTextureManager g_StaticTextureEngine;
//-----------------------------------------------------------------------------
// Name: struct TEXTURESEARCHINFO
// Desc: Structure used to search for texture formats
//-----------------------------------------------------------------------------
struct TEXTURESEARCHINFO
{
DWORD dwDesiredBPP; // Input for texture format search
BOOL bUseAlpha;
BOOL bUsePalette;
BOOL bFoundGoodFormat;
DDPIXELFORMAT* pddpf; // Output of texture format search
};
//-----------------------------------------------------------------------------
// Name: TextureSearchCallback()
// Desc: Enumeration callback routine to find a best-matching texture format.
// The param data is the DDPIXELFORMAT of the best-so-far matching
// texture. Note: the desired BPP is passed in the dwSize field, and the
// default BPP is passed in the dwFlags field.
//-----------------------------------------------------------------------------
static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf,
VOID* param )
{
if( NULL==pddpf || NULL==param )
return DDENUMRET_OK;
TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param;
// Skip any unusual modes
if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )
return DDENUMRET_OK;
// Check for palettized formats
if( ptsi->bUsePalette )
{
if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) )
return DDENUMRET_OK;
// Accept the first 8-bit palettized format we get
memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
ptsi->bFoundGoodFormat = TRUE;
return DDENUMRET_CANCEL;
}
// Else, skip any paletized formats (all modes under 16bpp)
if( pddpf->dwRGBBitCount < 16 )
return DDENUMRET_OK;
// Skip any FourCC formats
if( pddpf->dwFourCC != 0 )
return DDENUMRET_OK;
// Skip any ARGB 4444 formats (which are best used for pre-authored
// content designed speciafically for an ARGB 4444 format).
if( pddpf->dwRGBAlphaBitMask == 0x0000f000 )
return DDENUMRET_OK;
// Make sure current alpha format agrees with requested format type
if( (ptsi->bUseAlpha==TRUE) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) )
return DDENUMRET_OK;
if( (ptsi->bUseAlpha==FALSE) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) )
return DDENUMRET_OK;
// Check if we found a good match
if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP )
{
memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
ptsi->bFoundGoodFormat = TRUE;
return DDENUMRET_CANCEL;
}
return DDENUMRET_OK;
}
//-----------------------------------------------------------------------------
// Name: FindTexture()
// Desc: Searches the internal list of textures for a texture specified by
// its name. Returns the structure associated with that texture.
//-----------------------------------------------------------------------------
static TextureContainer* FindTexture( TCHAR* strTextureName )
{
TextureContainer* ptcTexture = g_ptcTextureList;
while( ptcTexture )
{
if( !lstrcmpi( strTextureName, ptcTexture->m_strName ) )
return ptcTexture;
ptcTexture = ptcTexture->m_pNext;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Name: TextureContainer()
// Desc: Constructor for a texture object
//-----------------------------------------------------------------------------
TextureContainer::TextureContainer( TCHAR* strName, DWORD dwStage,
DWORD dwFlags, UINT uintRes /*= NULL */ )
{
lstrcpy( m_strName, strName );
m_dwWidth = 0;
m_dwHeight = 0;
m_dwStage = dwStage;
m_dwBPP = 0;
m_dwFlags = dwFlags;
m_bHasAlpha = 0;
m_nRes = uintRes;
m_pddsSurface = NULL;
m_hbmBitmap = NULL;
m_pRGBAData = NULL;
// Add the texture to the head of the global texture list
m_pNext = g_ptcTextureList;
g_ptcTextureList = this;
}
//-----------------------------------------------------------------------------
// Name: ~TextureContainer()
// Desc: Destructs the contents of the texture container
//-----------------------------------------------------------------------------
TextureContainer::~TextureContainer()
{
SAFE_RELEASE( m_pddsSurface );
SAFE_DELETE( m_pRGBAData );
DeleteObject( m_hbmBitmap );
// Remove the texture container from the global list
if( g_ptcTextureList == this )
g_ptcTextureList = m_pNext;
else
{
for( TextureContainer* ptc=g_ptcTextureList; ptc; ptc=ptc->m_pNext )
if( ptc->m_pNext == this )
ptc->m_pNext = m_pNext;
}
}
//-----------------------------------------------------------------------------
// Name: LoadImageData()
// Desc: Loads the texture map's image data
//-----------------------------------------------------------------------------
HRESULT TextureContainer::LoadImageData()
{
TCHAR* strExtension;
TCHAR strPathname[256];
HFILE file;
char szAnsiName[256];
// Check the executable's resource. If it's there, we're done!
if( m_nRes )
{
m_hbmBitmap = (HBITMAP)LoadImage(g_hInst, MAKEINTRESOURCE(m_nRes),
IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if( m_hbmBitmap )
{
return S_OK;
}
}
m_hbmBitmap = (HBITMAP)LoadImage(g_hInst, m_strName,
IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if( m_hbmBitmap )
return S_OK;
// First check if the file exists in the global texture path
lstrcpy( strPathname, g_strTexturePath );
lstrcat( strPathname, m_strName );
wsprintfA(szAnsiName, "%ls", strPathname);
if( NULL == ( file = _lopen(szAnsiName, OF_READ) ) )
{
// Then check if the file exists in the DirectX SDK media path
lstrcpy( strPathname, D3DUtil_GetDXSDKMediaPath() );
lstrcat( strPathname, m_strName );
wsprintfA(szAnsiName, "%ls", strPathname);
if( NULL == ( file = _lopen(szAnsiName, OF_READ) ) )
return DDERR_NOTFOUND;
}
_lclose( file );
// Get the filename extension
if( NULL == ( strExtension = _tcsrchr( m_strName, _T('.') ) ) )
return DDERR_UNSUPPORTED;
// Load bitmap files
if( !lstrcmpi( strExtension, _T(".bmp") ) )
return LoadBitmapFile( strPathname );
// Can add code here to check for other file formats before failing
return DDERR_UNSUPPORTED;
}
//-----------------------------------------------------------------------------
// Name: LoadBitmapFile()
// Desc: Loads data from a .bmp file, and stores it in a bitmap structure.
//-----------------------------------------------------------------------------
HRESULT TextureContainer::LoadBitmapFile( TCHAR* strPathname )
{
// Try to load the bitmap as a file
m_hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION );
if( m_hbmBitmap )
return S_OK;
return DDERR_NOTFOUND;
}
//-----------------------------------------------------------------------------
// Name: Restore()
// Desc: Rebuilds the texture surface using the new device.
//-----------------------------------------------------------------------------
HRESULT TextureContainer::Restore( LPDIRECT3DDEVICE7 pd3dDevice )
{
// Release any previously created objects
SAFE_RELEASE( m_pddsSurface );
// Check params
if( NULL == pd3dDevice )
return DDERR_INVALIDPARAMS;
// Get the device caps
D3DDEVICEDESC7 ddDesc;
if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) )
return E_FAIL;
// Setup the new surface desc
DDSURFACEDESC2 ddsd;
D3DUtil_InitSurfaceDesc( ddsd );
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|
DDSD_PIXELFORMAT /* |DDSD_TEXTURESTAGE */;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
ddsd.dwTextureStage = m_dwStage;
ddsd.dwWidth = m_dwWidth;
ddsd.dwHeight = m_dwHeight;
// Turn on texture management for hardware devices
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
// Adjust width and height to be powers of 2, if the device requires it
if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
{
for( ddsd.dwWidth=1; m_dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 );
for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 );
}
// Limit max texture sizes, if the driver can't handle large textures
DWORD dwMaxWidth = ddDesc.dwMaxTextureWidth;
DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight;
ddsd.dwWidth = min( ddsd.dwWidth, ( dwMaxWidth ? dwMaxWidth : 256 ) );
ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) );
// Make the texture square, if the driver requires it
if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
{
if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth;
else ddsd.dwWidth = ddsd.dwHeight;
}
// Setup the structure to be used for texture enumration.
TEXTURESEARCHINFO tsi;
tsi.bFoundGoodFormat = FALSE;
tsi.pddpf = &ddsd.ddpfPixelFormat;
tsi.dwDesiredBPP = m_dwBPP;
tsi.bUsePalette = ( m_dwBPP <= 8 );
tsi.bUseAlpha = m_bHasAlpha;
if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL )
tsi.dwDesiredBPP = 16;
else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
tsi.dwDesiredBPP = 32;
if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
{
if( tsi.bUsePalette )
{
if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
{
tsi.bUseAlpha = TRUE;
tsi.bUsePalette = TRUE;
}
else
{
tsi.bUseAlpha = TRUE;
tsi.bUsePalette = FALSE;
}
}
}
OutputDebugString("Restore: calling EnumTextureFormats\n");
// Enumerate the texture formats, and find the closest device-supported
// texture pixel format
pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
// If we couldn't find a format, let's try a default format
if( FALSE == tsi.bFoundGoodFormat )
{
tsi.bUsePalette = FALSE;
tsi.dwDesiredBPP = 16;
pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
// If we still fail, we cannot create this texture
if( FALSE == tsi.bFoundGoodFormat )
return E_FAIL;
}
// Get the DirectDraw interface for creating surfaces
LPDIRECTDRAW7 pDD;
LPDIRECTDRAWSURFACE7 pddsRender;
OutputDebugString("Restore: calling GetRenderTarget\n");
pd3dDevice->GetRenderTarget( &pddsRender );
pddsRender->GetDDInterface( (VOID**)&pDD );
pddsRender->Release();
// Create a new surface for the texture
OutputDebugString("Restore: calling CreateSurface\n");
HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL );
// Done with DDraw
pDD->Release();
if( FAILED(hr) )
return hr;
// For bitmap-based textures, copy the bitmap image.
OutputDebugString("Restore: calling CopyBitmapToSurface\n");
if( m_hbmBitmap )
return CopyBitmapToSurface();
if( m_pRGBAData )
return CopyRGBADataToSurface();
// At this point, code can be added to handle other file formats (such as
// .dds files, .jpg files, etc.).
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CopyBitmapToSurface()
// Desc: Copies the image of a bitmap into a surface
//-----------------------------------------------------------------------------
HRESULT TextureContainer::CopyBitmapToSurface()
{
// Get a DDraw object to create a temporary surface
LPDIRECTDRAW7 pDD;
m_pddsSurface->GetDDInterface( (VOID**)&pDD );
// Get the bitmap structure (to extract width, height, and bpp)
BITMAP bm;
GetObject( m_hbmBitmap, sizeof(BITMAP), &bm );
// Setup the new surface desc
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
m_pddsSurface->GetSurfaceDesc( &ddsd );
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
DDSD_TEXTURESTAGE;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
ddsd.ddsCaps.dwCaps2 = 0L;
ddsd.dwWidth = bm.bmWidth;
ddsd.dwHeight = bm.bmHeight;
// Create a new surface for the texture
LPDIRECTDRAWSURFACE7 pddsTempSurface;
HRESULT hr;
if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
{
pDD->Release();
return hr;
}
// Get a DC for the bitmap
HDC hdcBitmap = CreateCompatibleDC( NULL );
if( NULL == hdcBitmap )
{
pddsTempSurface->Release();
pDD->Release();
return hr;
}
SelectObject( hdcBitmap, m_hbmBitmap );
// Handle palettized textures. Need to attach a palette
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 )
{
LPDIRECTDRAWPALETTE pPalette;
DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256;
DWORD pe[256];
UINT wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe );
// Create the color table
for( WORD i=0; i<wNumColors; i++ )
{
pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) );
// Handle textures with transparent pixels
if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
{
// Set alpha for opaque pixels
if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK )
{
if( pe[i] != 0x00000000 )
pe[i] |= 0xff000000;
}
else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
{
if( pe[i] != 0x00ffffff )
pe[i] |= 0xff000000;
}
}
}
// Add DDPCAPS_ALPHA flag for textures with transparent pixels
if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
dwPaletteFlags |= DDPCAPS_ALPHA;
// Create & attach a palette
pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL );
pddsTempSurface->SetPalette( pPalette );
m_pddsSurface->SetPalette( pPalette );
SAFE_RELEASE( pPalette );
}
// Copy the bitmap image to the surface.
HDC hdcSurface;
if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) )
{
BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0,
SRCCOPY );
pddsTempSurface->ReleaseDC( hdcSurface );
}
DeleteDC( hdcBitmap );
// Copy the temp surface to the real texture surface
m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
// Done with the temp surface
pddsTempSurface->Release();
// For textures with real alpha (not palettized), set transparent bits
if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask )
{
if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
{
// Lock the texture surface
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) ==
DDERR_WASSTILLDRAWING );
DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask |
ddsd.ddpfPixelFormat.dwGBitMask |
ddsd.ddpfPixelFormat.dwBBitMask );
DWORD dwColorkey = 0x00000000; // Colorkey on black
if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
dwColorkey = dwRGBMask; // Colorkey on white
// Add an opaque alpha value to each non-colorkeyed pixel
for( DWORD y=0; y<ddsd.dwHeight; y++ )
{
WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
for( DWORD x=0; x<ddsd.dwWidth; x++ )
{
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
{
if( ( *p16 &= dwRGBMask ) != dwColorkey )
*p16 |= dwAlphaMask;
p16++;
}
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
{
if( ( *p32 &= dwRGBMask ) != dwColorkey )
*p32 |= dwAlphaMask;
p32++;
}
}
}
m_pddsSurface->Unlock( NULL );
}
}
pDD->Release();
return S_OK;;
}
//-----------------------------------------------------------------------------
// Name: CopyRGBADataToSurface()
// Desc: Invalidates the current texture objects and rebuilds new ones
// using the new device.
//-----------------------------------------------------------------------------
HRESULT TextureContainer::CopyRGBADataToSurface()
{
// Get a DDraw object to create a temporary surface
LPDIRECTDRAW7 pDD;
m_pddsSurface->GetDDInterface( (VOID**)&pDD );
// Setup the new surface desc
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
m_pddsSurface->GetSurfaceDesc( &ddsd );
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
DDSD_TEXTURESTAGE;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
ddsd.ddsCaps.dwCaps2 = 0L;
ddsd.dwWidth = m_dwWidth;
ddsd.dwHeight = m_dwHeight;
// Create a new surface for the texture
LPDIRECTDRAWSURFACE7 pddsTempSurface;
HRESULT hr;
if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
{
pDD->Release();
return NULL;
}
while( pddsTempSurface->Lock( NULL, &ddsd, 0, 0 ) == DDERR_WASSTILLDRAWING );
DWORD lPitch = ddsd.lPitch;
BYTE* pBytes = (BYTE*)ddsd.lpSurface;
DWORD dwRMask = ddsd.ddpfPixelFormat.dwRBitMask;
DWORD dwGMask = ddsd.ddpfPixelFormat.dwGBitMask;
DWORD dwBMask = ddsd.ddpfPixelFormat.dwBBitMask;
DWORD dwAMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
DWORD dwRShiftL = 8, dwRShiftR = 0;
DWORD dwGShiftL = 8, dwGShiftR = 0;
DWORD dwBShiftL = 8, dwBShiftR = 0;
DWORD dwAShiftL = 8, dwAShiftR = 0;
DWORD dwMask;
for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
for( ; dwMask; dwMask>>=1 ) dwRShiftL--;
for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
for( ; dwMask; dwMask>>=1 ) dwGShiftL--;
for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
for( ; dwMask; dwMask>>=1 ) dwBShiftL--;
for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
for( ; dwMask; dwMask>>=1 ) dwAShiftL--;
for( DWORD y=0; y<ddsd.dwHeight; y++ )
{
DWORD* pDstData32 = (DWORD*)pBytes;
WORD* pDstData16 = (WORD*)pBytes;
for( DWORD x=0; x<ddsd.dwWidth; x++ )
{
DWORD dwPixel = m_pRGBAData[y*ddsd.dwWidth+x];
BYTE r = (BYTE)((dwPixel>>24)&0x000000ff);
BYTE g = (BYTE)((dwPixel>>16)&0x000000ff);
BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff);
BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff);
DWORD dr = ((r>>(dwRShiftL))<<dwRShiftR)&dwRMask;
DWORD dg = ((g>>(dwGShiftL))<<dwGShiftR)&dwGMask;
DWORD db = ((b>>(dwBShiftL))<<dwBShiftR)&dwBMask;
DWORD da = ((a>>(dwAShiftL))<<dwAShiftR)&dwAMask;
if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
pDstData32[x] = (DWORD)(dr+dg+db+da);
else
pDstData16[x] = (WORD)(dr+dg+db+da);
}
pBytes += ddsd.lPitch;
}
pddsTempSurface->Unlock(0);
// Copy the temp surface to the real texture surface
m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
// Done with the temp objects
pddsTempSurface->Release();
pDD->Release();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_SetTexturePath()
// Desc: Enumeration callback routine to find a best-matching texture format.
//-----------------------------------------------------------------------------
VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath )
{
if( NULL == strTexturePath )
strTexturePath = _T("");
lstrcpy( g_strTexturePath, strTexturePath );
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_CreateTextureFromFile()
// Desc: Is passed a filename and creates a local Bitmap from that file.
// The texture can not be used until it is restored, however.
//-----------------------------------------------------------------------------
HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage,
DWORD dwFlags )
{
// Check parameters
if( NULL == strName )
return E_INVALIDARG;
// Check first to see if the texture is already loaded
if( NULL != FindTexture( strName ) )
return S_OK;
// Allocate and add the texture to the linked list of textures;
TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
dwFlags );
if( NULL == ptcTexture )
return E_OUTOFMEMORY;
// Create a bitmap and load the texture file into it,
if( FAILED( ptcTexture->LoadImageData() ) )
{
delete ptcTexture;
return E_FAIL;
}
// Save the image's dimensions
if( ptcTexture->m_hbmBitmap )
{
BITMAP bm;
GetObject( ptcTexture->m_hbmBitmap, sizeof(BITMAP), &bm );
ptcTexture->m_dwWidth = (DWORD)bm.bmWidth;
ptcTexture->m_dwHeight = (DWORD)bm.bmHeight;
ptcTexture->m_dwBPP = (DWORD)bm.bmBitsPixel;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_CreateEmptyTexture()
// Desc: Creates an empty texture.
//-----------------------------------------------------------------------------
HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
DWORD dwHeight, DWORD dwStage,
DWORD dwFlags )
{
// Check parameters
if( NULL == strName )
return E_INVALIDARG;
// Check first to see if the texture is already loaded
if( NULL != FindTexture( strName ) )
return E_FAIL;
// Allocate and add the texture to the linked list of textures;
TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
dwFlags );
if( NULL == ptcTexture )
return E_OUTOFMEMORY;
// Save dimensions
ptcTexture->m_dwWidth = dwWidth;
ptcTexture->m_dwHeight = dwHeight;
ptcTexture->m_dwBPP = 16;
if( ptcTexture->m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
ptcTexture->m_dwBPP = 32;
// Save alpha usage flag
if( dwFlags & D3DTEXTR_CREATEWITHALPHA )
ptcTexture->m_bHasAlpha = TRUE;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_Restore()
// Desc: Invalidates the current texture objects and rebuilds new ones
// using the new device.
//-----------------------------------------------------------------------------
HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice )
{
TextureContainer* ptcTexture = FindTexture( strName );
if( NULL == ptcTexture )
return DDERR_NOTFOUND;
// Restore the texture (this recreates the new surface for this device).
return ptcTexture->Restore( pd3dDevice );
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_RestoreAllTextures()
// Desc: This function is called when a mode is changed. It updates all
// texture objects to be valid with the new device.
//-----------------------------------------------------------------------------
HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice )
{
TextureContainer* ptcTexture = g_ptcTextureList;
while( ptcTexture )
{
D3DTextr_Restore( ptcTexture->m_strName, pd3dDevice );
ptcTexture = ptcTexture->m_pNext;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_Invalidate()
// Desc: Used to bump a texture out of (video) memory, this function
// actually destroys the d3dtexture and ddsurface of the texture
//-----------------------------------------------------------------------------
HRESULT D3DTextr_Invalidate( TCHAR* strName )
{
TextureContainer* ptcTexture = FindTexture( strName );
if( NULL == ptcTexture )
return DDERR_NOTFOUND;
SAFE_RELEASE( ptcTexture->m_pddsSurface );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_InvalidateAllTextures()
// Desc: This function is called when a mode is changed. It invalidates
// all texture objects so their device can be safely released.
//-----------------------------------------------------------------------------
HRESULT D3DTextr_InvalidateAllTextures()
{
TextureContainer* ptcTexture = g_ptcTextureList;
while( ptcTexture )
{
SAFE_RELEASE( ptcTexture->m_pddsSurface );
ptcTexture = ptcTexture->m_pNext;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_DestroyTexture()
// Desc: Frees the resources for the specified texture container
//-----------------------------------------------------------------------------
HRESULT D3DTextr_DestroyTexture( TCHAR* strName )
{
TextureContainer* ptcTexture = FindTexture( strName );
SAFE_DELETE( ptcTexture );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DTextr_GetSurface()
// Desc: Returns a pointer to a d3dSurface from the name of the texture
//-----------------------------------------------------------------------------
LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName )
{
TextureContainer* ptcTexture = FindTexture( strName );
return ptcTexture ? ptcTexture->m_pddsSurface : NULL;
}

View File

@@ -0,0 +1,88 @@
//-----------------------------------------------------------------------------
// File: D3DTextr.h
//
// Desc: Functions to manage textures, including creating (loading from a
// file), restoring lost surfaces, invalidating, and destroying.
//
// Note: the implementation of these functions maintains an internal list
// of loaded textures. After creation, individual textures are referenced
// via their ASCII names.
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#ifndef D3DTEXTR_H
#define D3DTEXTR_H
#include <ddraw.h>
#include <d3d.h>
//-----------------------------------------------------------------------------
// Access functions for loaded textures. Note: these functions search
// an internal list of the textures, and use the texture associated with the
// ASCII name.
//-----------------------------------------------------------------------------
LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName );
//-----------------------------------------------------------------------------
// Texture invalidation and restoration functions
//-----------------------------------------------------------------------------
HRESULT D3DTextr_Invalidate( TCHAR* strName );
HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice );
HRESULT D3DTextr_InvalidateAllTextures();
HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice );
//-----------------------------------------------------------------------------
// Texture creation and deletion functions
//-----------------------------------------------------------------------------
#define D3DTEXTR_TRANSPARENTWHITE 0x00000001
#define D3DTEXTR_TRANSPARENTBLACK 0x00000002
#define D3DTEXTR_32BITSPERPIXEL 0x00000004
#define D3DTEXTR_16BITSPERPIXEL 0x00000008
#define D3DTEXTR_CREATEWITHALPHA 0x00000010
HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage=0L,
DWORD dwFlags=0L );
HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
DWORD dwHeight, DWORD dwStage,
DWORD dwFlags );
HRESULT D3DTextr_DestroyTexture( TCHAR* strName );
VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath );
//-----------------------------------------------------------------------------
// Name: TextureContainer
// Desc: Linked list structure to hold info per texture
//-----------------------------------------------------------------------------
struct TextureContainer
{
TextureContainer* m_pNext; // Linked list ptr
TCHAR m_strName[MAX_PATH]; // Name of texture (doubles as image filename)
DWORD m_dwWidth;
DWORD m_dwHeight;
DWORD m_dwStage; // Texture stage (for multitexture devices)
DWORD m_dwBPP;
DWORD m_dwFlags;
BOOL m_bHasAlpha;
UINT m_nRes;
LPDIRECTDRAWSURFACE7 m_pddsSurface; // Surface of the texture
HBITMAP m_hbmBitmap; // Bitmap containing texture image
DWORD* m_pRGBAData;
public:
HRESULT LoadImageData();
HRESULT LoadBitmapFile( TCHAR* strPathname );
HRESULT Restore( LPDIRECT3DDEVICE7 pd3dDevice );
HRESULT CopyBitmapToSurface();
HRESULT CopyRGBADataToSurface();
TextureContainer( TCHAR* strName, DWORD dwStage, DWORD dwFlags, UINT nRes = NULL );
~TextureContainer();
};
#endif // D3DTEXTR_H

View File

@@ -0,0 +1,302 @@
//-----------------------------------------------------------------------------
// File: D3DUtil.cpp
//
// Desc: Shortcut macros and functions for using DX objects
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#include <streams.h>
#define D3D_OVERLOADS
#include <math.h>
#include "D3DUtil.h"
#ifndef _T
#define _T TEXT
#endif
//-----------------------------------------------------------------------------
// Name: D3DUtil_GetDXSDKMediaPath()
// Desc: Returns the DirectX SDK media path, as stored in the system registry
// during the SDK install.
//-----------------------------------------------------------------------------
const TCHAR* D3DUtil_GetDXSDKMediaPath()
{
static TCHAR strNull[2] = _T("");
static TCHAR strPath[512];
HKEY key;
DWORD type, size = 512;
// Open the appropriate registry key
LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
_T("Software\\Microsoft\\DirectX"),
0, KEY_READ, &key );
if( ERROR_SUCCESS != result )
return strNull;
result = RegQueryValueEx( key, _T("DX81SDK Samples Path"), NULL,
&type, (BYTE*)strPath, &size );
RegCloseKey( key );
if( ERROR_SUCCESS != result )
{
result = RegQueryValueEx( key, _T("DX8SDK Samples Path"), NULL,
&type, (BYTE*)strPath, &size );
RegCloseKey( key );
if( ERROR_SUCCESS != result )
{
result = RegQueryValueEx( key, _T("DXSDK Samples Path"), NULL,
&type, (BYTE*)strPath, &size );
RegCloseKey( key );
if( ERROR_SUCCESS != result )
return strNull;
}
}
lstrcat( strPath, _T("\\D3DIM\\Media\\") );
return strPath;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitSurfaceDesc()
// Desc: Helper function called to build a DDSURFACEDESC2 structure,
// typically before calling CreateSurface() or GetSurfaceDesc()
//-----------------------------------------------------------------------------
VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
DWORD dwCaps )
{
ZeroMemory( &ddsd, sizeof(ddsd) );
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = dwFlags;
ddsd.ddsCaps.dwCaps = dwCaps;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitMaterial()
// Desc: Helper function called to build a D3DMATERIAL7 structure
//-----------------------------------------------------------------------------
VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b,
FLOAT a )
{
ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) );
mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_InitLight()
// Desc: Initializes a D3DLIGHT7 structure
//-----------------------------------------------------------------------------
VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
FLOAT x, FLOAT y, FLOAT z )
{
ZeroMemory( &light, sizeof(D3DLIGHT7) );
light.dltType = ltType;
light.dcvDiffuse.r = 1.0f;
light.dcvDiffuse.g = 1.0f;
light.dcvDiffuse.b = 1.0f;
light.dcvSpecular = light.dcvDiffuse;
light.dvPosition.x = light.dvDirection.x = x;
light.dvPosition.y = light.dvDirection.y = y;
light.dvPosition.z = light.dvDirection.z = z;
light.dvAttenuation0 = 1.0f;
light.dvRange = D3DLIGHT_RANGE_MAX;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetViewMatrix()
// Desc: Given an eye point, a lookat point, and an up vector, this
// function builds a 4x4 view matrix.
//-----------------------------------------------------------------------------
HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
{
// Get the z basis vector, which points straight ahead. This is the
// difference from the eyepoint to the lookat point.
D3DVECTOR vView = vAt - vFrom;
FLOAT fLength = Magnitude( vView );
if( fLength < 1e-6f )
return E_INVALIDARG;
// Normalize the z basis vector
vView /= fLength;
// Get the dot product, and calculate the projection of the z basis
// vector onto the up vector. The projection is the y basis vector.
FLOAT fDotProduct = DotProduct( vWorldUp, vView );
D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
// If this vector has near-zero length because the input specified a
// bogus up vector, let's try a default up vector
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
{
vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
// If we still have near-zero length, resort to a different axis.
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
{
vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
return E_INVALIDARG;
}
}
// Normalize the y basis vector
vUp /= fLength;
// The x basis vector is found simply with the cross product of the y
// and z basis vectors
D3DVECTOR vRight = CrossProduct( vUp, vView );
// Start building the matrix. The first three rows contains the basis
// vectors used to rotate the view to point at the lookat point
D3DUtil_SetIdentityMatrix( mat );
mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x;
mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y;
mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z;
// Do the translation values (rotations are still about the eyepoint)
mat._41 = - DotProduct( vFrom, vRight );
mat._42 = - DotProduct( vFrom, vUp );
mat._43 = - DotProduct( vFrom, vView );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetProjectionMatrix()
// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
// from the field-of-view (fov, in y), aspect ratio, near plane (D),
// and far plane (F). Note that the projection matrix is normalized for
// element [3][4] to be 1.0. This is performed so that W-based range fog
// will work correctly.
//-----------------------------------------------------------------------------
HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
FLOAT fNearPlane, FLOAT fFarPlane )
{
if( fabs(fFarPlane-fNearPlane) < 0.01f )
return E_INVALIDARG;
if( fabs(sin(fFOV/2)) < 0.01f )
return E_INVALIDARG;
FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) );
FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) );
FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
ZeroMemory( &mat, sizeof(D3DMATRIX) );
mat._11 = w;
mat._22 = h;
mat._33 = Q;
mat._34 = 1.0f;
mat._43 = -Q*fNearPlane;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateXMatrix()
// Desc: Create Rotation matrix about X axis
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
{
D3DUtil_SetIdentityMatrix( mat );
mat._22 = cosf( fRads );
mat._23 = sinf( fRads );
mat._32 = -sinf( fRads );
mat._33 = cosf( fRads );
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateYMatrix()
// Desc: Create Rotation matrix about Y axis
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
{
D3DUtil_SetIdentityMatrix( mat );
mat._11 = cosf( fRads );
mat._13 = -sinf( fRads );
mat._31 = sinf( fRads );
mat._33 = cosf( fRads );
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotateZMatrix()
// Desc: Create Rotation matrix about Z axis
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
{
D3DUtil_SetIdentityMatrix( mat );
mat._11 = cosf( fRads );
mat._12 = sinf( fRads );
mat._21 = -sinf( fRads );
mat._22 = cosf( fRads );
}
//-----------------------------------------------------------------------------
// Name: D3DUtil_SetRotationMatrix
// Desc: Create a Rotation matrix about vector direction
//-----------------------------------------------------------------------------
VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
{
FLOAT fCos = cosf( fRads );
FLOAT fSin = sinf( fRads );
D3DVECTOR v = Normalize( vDir );
mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
mat._14 = mat._24 = mat._34 = 0.0f;
mat._41 = mat._42 = mat._43 = 0.0f;
mat._44 = 1.0f;
}
//-----------------------------------------------------------------------------
// Name: _DbgOut()
// Desc: Outputs a message to the debug stream
//-----------------------------------------------------------------------------
HRESULT _DbgOut( CHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
{
TCHAR buffer[256];
wsprintf( buffer, _T("%hs(%ld): "), strFile, dwLine );
OutputDebugString( buffer );
OutputDebugString( strMsg );
if( hr )
{
wsprintf( buffer, _T("(hr=%08lx)\n"), hr );
OutputDebugString( buffer );
}
OutputDebugString( _T("\n") );
return hr;
}

View File

@@ -0,0 +1,84 @@
//-----------------------------------------------------------------------------
// File: D3DUtil.h
//
// Desc: Helper functions and typing shortcuts for Direct3D programming.
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
#ifndef D3DUTIL_H
#define D3DUTIL_H
#include <ddraw.h>
#include <d3d.h>
//-----------------------------------------------------------------------------
// Miscellaneous helper functions
//-----------------------------------------------------------------------------
const TCHAR* D3DUtil_GetDXSDKMediaPath();
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
//-----------------------------------------------------------------------------
// Shortcut functions for creating and using DX structures
//-----------------------------------------------------------------------------
VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC7& ddDevDesc );
VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0,
DWORD dwCaps=0 );
VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r=0.0f, FLOAT g=0.0f,
FLOAT b=0.0f, FLOAT a=1.0f );
VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f );
//-----------------------------------------------------------------------------
// D3D Matrix functions. For performance reasons, some functions are inline.
//-----------------------------------------------------------------------------
HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
D3DVECTOR& vAt, D3DVECTOR& vUp );
HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f,
FLOAT fAspect = 1.0f,
FLOAT fNearPlane = 1.0f,
FLOAT fFarPlane = 1000.0f );
inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
{
m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
m._11 = m._22 = m._33 = m._44 = 1.0f;
}
inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty,
FLOAT tz )
{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; }
inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v )
{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); }
inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy,
FLOAT sz )
{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; }
inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v )
{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); }
VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads );
VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads );
VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads );
VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir,
FLOAT fRads );
//-----------------------------------------------------------------------------
// Debug printing support
//-----------------------------------------------------------------------------
HRESULT _DbgOut( CHAR*, DWORD, HRESULT, TCHAR* );
#if defined(DEBUG) | defined(_DEBUG)
#define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str )
#define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str )
#else
#define DEBUG_MSG(str) (0L)
#define DEBUG_ERR(hr,str) (hr)
#endif
#endif // D3DUTIL_H

View File

@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------
// File: project.h
//
// Desc: DirectShow sample code
// Master header file that includes all the other header files
// used by the project.
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include <streams.h>
#include <commdlg.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <process.h>
#include <time.h>
#include <objbase.h>
#include <ddraw.h>
#include <atlbase.h>
#include <atlconv.cpp>
#include <mmreg.h>
#include <commctrl.h>
#include <strmif.h>
#include <combase.h>
#include <stdarg.h>
#include <stdio.h>
#include <uuids.h>
#include "app.h"
#include "vcdplyer.h"
#include "ddrawsupport.h"
#include "resource.h"
#include "utils.h"
#ifndef __RELEASE_DEFINED
#define __RELEASE_DEFINED
template<typename T>
__inline void RELEASE( T* &p )
{
if( p ) {
p->Release();
p = NULL;
}
}
#endif
#ifndef CHECK_HR
#define CHECK_HR(expr) if (FAILED(expr)) {\
OutputDebugString( hresultNameLookup(expr)+"\n");\
DbgLog((LOG_ERROR, 0, \
TEXT("FAILED: %s\nat Line:%d of %s"), \
TEXT(#expr), __LINE__, TEXT(__FILE__) ));__leave; } else
#endif

View File

@@ -0,0 +1,62 @@
// Copyright (c) 1995 - 2001 Microsoft Corporation. All Rights Reserved.
//
// These are indexes used by the toolbar.
//
#define IDC_ADEFAULT2 4013
#define IDC_STATIC -1
#define STR_MAX_STRING_LEN 256
#define IDX_SEPARATOR -1
#define IDX_1 0
#define IDX_2 1
#define IDX_3 2
#define IDX_4 3
#define IDX_5 4
#define IDX_6 5
#define IDX_7 6
#define IDX_8 7
#define IDX_9 8
#define IDX_10 9
#define IDX_11 10
#define DEFAULT_TBAR_SIZE 6
#define NUMBER_OF_BITMAPS 11
#define ID_TOOLBAR 9
#define ID_TRACKBAR 10
#define IDR_MAIN_MENU 101
#define IDR_TOOLBAR 102
#define IDR_VIDEOCD_ICON 103
#define IDR_ACCELERATOR 104
#define IDM_FILE_OPEN 40001
#define IDM_FILE_CLOSE 40002
#define IDM_FILE_EXIT 40003
// Toolbar commands
#define IDM_MOVIE_STOP 40010
#define IDM_MOVIE_PLAY 40011
#define IDM_MOVIE_PAUSE 40013
#define IDM_FULL_SCREEN 40019
#define IDM_MOVIE_ALIGN 40020
#define MENU_STRING_BASE 1000
// File
#define STR_FILE_OPEN IDM_FILE_OPEN + MENU_STRING_BASE
#define STR_FILE_CLOSE IDM_FILE_CLOSE + MENU_STRING_BASE
#define STR_FILE_EXIT IDM_FILE_EXIT + MENU_STRING_BASE
// System Menu
#define STR_SYSMENU_RESTORE 1800
#define STR_SYSMENU_MOVE 1801
#define STR_SYSMENU_MINIMIZE 1802
#define STR_SYSMENU_CLOSE 1803
#define STR_SYSMENU_MAXIMIZE 1804
#define STR_SYSMENU_TASK_LIST 1805
#define STR_FILE_FILTER 2000
#define STR_APP_TITLE 2001
#define STR_APP_TITLE_LOADED 2002

View File

@@ -0,0 +1,18 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by VMRXcl.rc
//
#define IDB_MENU 102
#define IDI_ICON1 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,504 @@
//----------------------------------------------------------------------------
// File: vcdplyer.cpp
//
// Desc: DirectShow sample code
// Implementation of CMpegMovie, a customized video player
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include "project.h"
#include <mmreg.h>
#include <commctrl.h>
#include <stdarg.h>
#include <stdio.h>
#define MY_USER_ID 0x1234ACDE
//----------------------------------------------------------------------------
// CMpegMovie
//
// Constructors and destructors
//
//----------------------------------------------------------------------------
CMpegMovie::CMpegMovie(HWND hwndApplication)
: CUnknown(NAME("Allocator Presenter"), NULL),
m_hwndApp(hwndApplication),
m_MediaEvent(NULL),
m_Mode(MOVIE_NOTOPENED),
m_pBF(NULL),
m_Fg(NULL),
m_Gb(NULL),
m_Mc(NULL),
m_Ms(NULL),
m_Me(NULL),
m_Qp(NULL),
m_lpDefSAN(NULL),
m_iDuration(-1),
m_TimeFormat(TIME_FORMAT_MEDIA_TIME),
m_lpDefWC(NULL),
m_lpDefIP(NULL),
m_lpDefSA(NULL),
m_AlphaBlt(NULL)
{
AddRef();
}
CMpegMovie::~CMpegMovie() {
;
}
//----------------------------------------------------------------------------
// SetRenderingMode
//
// Set rendering mode of VMR (Windowless, Windowed, Renderless)
//----------------------------------------------------------------------------
HRESULT
SetRenderingMode(
IBaseFilter* pBaseFilter,
VMRMode mode
)
{
IVMRFilterConfig* pConfig;
HRESULT hr = pBaseFilter->QueryInterface(__uuidof(IVMRFilterConfig),
(LPVOID *)&pConfig);
if( SUCCEEDED( hr )) {
pConfig->SetRenderingMode( mode );
pConfig->Release();
}
return hr;
}
HRESULT CMpegMovie::AllocateAlphaBlt(void)
{
HRESULT hRes=S_OK;
m_AlphaBlt = new CAlphaBlt(m_pDDObject.GetBB(), &hRes);
return hRes;
}
//----------------------------------------------------------------------------
// AddVideoMixingRendererToFG()
//
// creates and adds VMR to the graph
//----------------------------------------------------------------------------
HRESULT
CMpegMovie::AddVideoMixingRendererToFG()
{
HRESULT hRes = S_OK;
m_AlphaBlt = NULL;
__try {
CHECK_HR(hRes = m_pDDObject.Initialize(m_hwndApp));
CHECK_HR(hRes = CoCreateInstance(CLSID_VideoMixingRenderer,
NULL, CLSCTX_INPROC,IID_IBaseFilter,
(LPVOID *)&m_pBF));
CHECK_HR(hRes = m_Fg->AddFilter(m_pBF, L"Video Mixing Renderer"));
CHECK_HR(hRes = SetRenderingMode(m_pBF, VMRMode_Renderless));
CHECK_HR(hRes = m_pBF->QueryInterface(__uuidof(IVMRSurfaceAllocatorNotify),
(LPVOID *)&m_lpDefSAN));
hRes = AllocateAlphaBlt();
if (FAILED(hRes)) {
__leave;
}
CHECK_HR(hRes = CreateDefaultAllocatorPresenter(m_pDDObject.GetDDObj(),
m_pDDObject.GetBB()));
CHECK_HR(hRes = m_lpDefSAN->AdviseSurfaceAllocator(MY_USER_ID, this));
}
__finally {
if (FAILED(hRes)) {
delete m_AlphaBlt;
m_AlphaBlt= NULL;
m_pDDObject.Terminate();
}
}
return hRes;
}
//----------------------------------------------------------------------------
// OpenMovie
//
// creates the graph, adds VMR, QIs relevant interfaces and renders the file
//----------------------------------------------------------------------------
HRESULT
CMpegMovie::OpenMovie(
TCHAR *lpFileName
)
{
IUnknown *pUnk = NULL;
HRESULT hres = S_OK;
WCHAR FileName[MAX_PATH];
#ifdef UNICODE
lstrcpy(FileName, lpFileName);
#else
// wsprintfA((char*)FileName, "%hs", lpFileName);
MultiByteToWideChar(CP_ACP,0,(const char*) lpFileName, -1, FileName, MAX_PATH);
#endif
__try {
CHECK_HR(hres = CoCreateInstance(CLSID_FilterGraph,
NULL, CLSCTX_INPROC,
IID_IUnknown, (LPVOID *)&pUnk));
m_Mode = MOVIE_OPENED;
CHECK_HR(hres = pUnk->QueryInterface(IID_IFilterGraph, (LPVOID *)&m_Fg));
CHECK_HR(hres = AddVideoMixingRendererToFG());
CHECK_HR(hres = pUnk->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb));
CHECK_HR(hres = m_Gb->RenderFile(FileName, NULL));
CHECK_HR(hres = pUnk->QueryInterface(IID_IMediaControl, (LPVOID *)&m_Mc));
CHECK_HR(hres = m_pBF->QueryInterface(IID_IQualProp, (LPVOID*)&m_Qp));
//
// Not being able to get the IMediaEvent interface does
// necessarly mean that we can't play the graph.
//
HRESULT hr = pUnk->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_Me);
GetMovieEventHandle();
pUnk->QueryInterface(IID_IMediaSeeking, (LPVOID *)&m_Ms);
}
__finally {
if (FAILED(hres)) {
RELEASE(m_Ms);
RELEASE(m_Me);
RELEASE(m_Mc);
RELEASE(m_Gb);
RELEASE(m_Fg);
m_pDDObject.Terminate();
}
RELEASE(pUnk);
}
return hres;
}
//----------------------------------------------------------------------------
// CloseMovie
//
// Releases client-provided allocator-presenter, exits sxclusive mode
//----------------------------------------------------------------------------
DWORD
CMpegMovie::CloseMovie(
)
{
m_Mode = MOVIE_NOTOPENED;
RELEASE(m_Qp);
RELEASE(m_Mc);
RELEASE(m_Me);
RELEASE(m_Ms);
RELEASE(m_Gb);
RELEASE(m_Fg);
if (m_lpDefSAN) {
m_lpDefSAN->AdviseSurfaceAllocator(0, NULL);
m_lpDefSAN->Release();
}
RELEASE(m_pBF);
RELEASE(m_lpDefWC);
RELEASE(m_lpDefSA);
RELEASE(m_lpDefIP);
delete m_AlphaBlt;
m_pDDObject.Terminate();
return 0L;
}
//----------------------------------------------------------------------------
// RepaintVideo
//----------------------------------------------------------------------------
BOOL
CMpegMovie::RepaintVideo(
HWND hwnd,
HDC hdc
)
{
BOOL bRet = FALSE;
if (m_lpDefWC) {
bRet = (m_lpDefWC->RepaintVideo(hwnd, hdc) == S_OK);
}
return bRet;
}
//----------------------------------------------------------------------------
// PutMoviePosition
//----------------------------------------------------------------------------
BOOL
CMpegMovie::PutMoviePosition(
LONG x,
LONG y,
LONG cx,
LONG cy
)
{
HRESULT hr;
BOOL bRet = FALSE;
if (m_lpDefWC) {
RECT rc;
SetRect(&rc, x, y, x + cx, y + cy);
hr = m_lpDefWC->SetVideoPosition(NULL, &rc);
bRet = (hr == S_OK);
}
return bRet;
}
//----------------------------------------------------------------------------
// PlayMovie
//
// Just runs IMediaControl
//
//----------------------------------------------------------------------------
BOOL
CMpegMovie::PlayMovie(
)
{
REFTIME rt;
REFTIME rtAbs;
REFTIME rtDur;
rt = GetCurrentPosition();
rtDur = GetDuration();
//
// If we are near the end of the movie seek to the start, otherwise
// stay where we are.
//
rtAbs = rt - rtDur;
if (rtAbs < (REFTIME)0) {
rtAbs = -rtAbs;
}
if (rtAbs <= (REFTIME)1) {
SeekToPosition((REFTIME)0,FALSE);
}
//
// Change mode after setting m_Mode but before starting the graph
//
m_Mode = MOVIE_PLAYING;
HRESULT hr = m_Mc->Run();
return TRUE;
}
//----------------------------------------------------------------------------
// PauseMovie
//
//
//----------------------------------------------------------------------------
BOOL
CMpegMovie::PauseMovie(
)
{
m_Mode = MOVIE_PAUSED;
m_Mc->Pause();
return TRUE;
}
//----------------------------------------------------------------------------
// GetStateMovie
//
// returns state of the media control (running, paused, or stopped)
//----------------------------------------------------------------------------
OAFilterState
CMpegMovie::GetStateMovie(
)
{
OAFilterState State=0;
if (m_Mc)
m_Mc->GetState(INFINITE,&State);
return State;
}
//----------------------------------------------------------------------------
// StopMovie
//
//----------------------------------------------------------------------------
BOOL
CMpegMovie::StopMovie(
)
{
m_Mode = MOVIE_STOPPED;
m_Mc->Stop();
return TRUE;
}
//----------------------------------------------------------------------------
// GetMediaEventHandle
//
// Returns the IMediaEvent event handle for the filter graph iff the
// filter graph exists.
//
//----------------------------------------------------------------------------
HANDLE
CMpegMovie::GetMovieEventHandle(
)
{
HRESULT hr = S_OK;
if (m_Me != NULL) {
if ( m_MediaEvent == NULL) {
hr = m_Me->GetEventHandle((OAEVENT *)&m_MediaEvent);
}
}
else {
m_MediaEvent = NULL;
}
return m_MediaEvent;
}
//----------------------------------------------------------------------------
// GetMovieEventCode
//
// Retrieves notification events from the graph through IMediaEvent interface
//----------------------------------------------------------------------------
long
CMpegMovie::GetMovieEventCode()
{
HRESULT hr;
long lEventCode;
LONG_PTR lParam1, lParam2;
if (m_Me != NULL) {
hr = m_Me->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
if (SUCCEEDED(hr)) {
return lEventCode;
}
}
return 0L;
}
//----------------------------------------------------------------------------
// GetDuration
//
// Returns the duration of the current movie
// NOTE that time format may vary with different media types
//
//----------------------------------------------------------------------------
REFTIME
CMpegMovie::GetDuration()
{
HRESULT hr;
LONGLONG Duration;
// Should we seek using IMediaSelection
if (m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME) {
hr = m_Ms->GetDuration(&Duration);
if (SUCCEEDED(hr)) {
return double(Duration);
}
} else if (m_Ms != NULL) {
hr = m_Ms->GetDuration(&Duration);
if (SUCCEEDED(hr)) {
return double(Duration) / UNITS;
}
}
return 0;
}
//----------------------------------------------------------------------------
// GetCurrentPosition
//
// Returns the duration of the current movie
// NOTE that time format may vary with different media types
//
//----------------------------------------------------------------------------
REFTIME
CMpegMovie::GetCurrentPosition()
{
REFTIME rt = (REFTIME)0;
HRESULT hr;
LONGLONG Position;
// Should we return a media position
if (m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME) {
hr = m_Ms->GetPositions(&Position, NULL);
if (SUCCEEDED(hr)) {
return double(Position);
}
} else if (m_Ms != NULL) {
hr = m_Ms->GetPositions(&Position, NULL);
if (SUCCEEDED(hr)) {
return double(Position) / UNITS;
}
}
return rt;
}
//----------------------------------------------------------------------------
// SeekToPosition
//
// NOTE that time format may vary with different media types
//
//----------------------------------------------------------------------------
BOOL
CMpegMovie::SeekToPosition(
REFTIME rt,
BOOL bFlushData
)
{
HRESULT hr=S_OK;
LONGLONG llTime =
LONGLONG(m_TimeFormat == TIME_FORMAT_MEDIA_TIME ? rt * double(UNITS) : rt);
if (m_Ms != NULL) {
FILTER_STATE fs;
m_Mc->GetState(100, (OAFilterState *)&fs);
hr = m_Ms->SetPositions(&llTime, AM_SEEKING_AbsolutePositioning, NULL, 0);
// This gets new data through to the renderers
if (fs == State_Stopped && bFlushData){
m_Mc->Pause();
hr = m_Mc->GetState(INFINITE, (OAFilterState *)&fs);
m_Mc->Stop();
}
if (SUCCEEDED(hr)) {
return TRUE;
}
}
return FALSE;
}

View File

@@ -0,0 +1,138 @@
//----------------------------------------------------------------------------
// File: vcdplyer.h
//
// Desc: DirectShow sample code
// Prototype for CMpegMovie, a customized video player
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
#include <ddraw.h>
#define D3D_OVERLOADS
#include <d3d.h>
#include "DDrawSupport.h"
#include "BltAlpha.h"
#include "d3dtextr.h"
/* -------------------------------------------------------------------------
** CMpegMovie - a movie playback class.
** -------------------------------------------------------------------------
*/
enum EMpegMovieMode { MOVIE_NOTOPENED = 0x00,
MOVIE_OPENED = 0x01,
MOVIE_PLAYING = 0x02,
MOVIE_STOPPED = 0x03,
MOVIE_PAUSED = 0x04 };
//----------------------------------------------------------------------------\
// CMpegMovie
//
// A customized video player for exclusive DDraw mode. In fact, it is a
// user-provided Allocator-Presenter for VMR
//----------------------------------------------------------------------------
class CMpegMovie :
public CUnknown,
public IVMRSurfaceAllocator,
public IVMRImagePresenter,
public IVMRSurfaceAllocatorNotify
{
private:
// Our state variable - records whether we are opened, playing etc.
EMpegMovieMode m_Mode;
HANDLE m_MediaEvent;
HWND m_hwndApp;
int m_iDuration;
GUID m_TimeFormat;
CDDrawObject m_pDDObject;
CAlphaBlt* m_AlphaBlt;
LPDIRECTDRAWSURFACE7 m_lpSurf;
IBaseFilter* m_pBF; // ptr to the VMR
IFilterGraph* m_Fg;
IGraphBuilder* m_Gb;
IMediaControl* m_Mc;
IMediaSeeking* m_Ms;
IMediaEvent* m_Me;
IQualProp* m_Qp;
IVMRSurfaceAllocator* m_lpDefSA;
IVMRImagePresenter* m_lpDefIP;
IVMRWindowlessControl* m_lpDefWC;
IVMRSurfaceAllocatorNotify* m_lpDefSAN;
HRESULT CreateDefaultAllocatorPresenter(LPDIRECTDRAW7 lpDD, LPDIRECTDRAWSURFACE7 lpPS);
HRESULT AddVideoMixingRendererToFG();
HRESULT OnSetDDrawDevice(LPDIRECTDRAW7 pDD, HMONITOR hMon);
HRESULT AllocateAlphaBlt(void);
public:
CMpegMovie(HWND hwndApplication);
~CMpegMovie();
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID, void**);
// IVMRSurfaceAllocator
STDMETHODIMP AllocateSurface(DWORD_PTR dwUserID,
VMRALLOCATIONINFO* lpAllocInfo,
DWORD* lpdwActualBackBuffers,
LPDIRECTDRAWSURFACE7* lplpSurface);
STDMETHODIMP FreeSurface(DWORD_PTR dwUserID);
STDMETHODIMP PrepareSurface(DWORD_PTR dwUserID,
LPDIRECTDRAWSURFACE7 lplpSurface,
DWORD dwSurfaceFlags);
STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify);
// IVMRSurfaceAllocatorNotify
STDMETHODIMP AdviseSurfaceAllocator(DWORD_PTR dwUserID,
IVMRSurfaceAllocator* lpIVRMSurfaceAllocator);
STDMETHODIMP SetDDrawDevice(LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor);
STDMETHODIMP ChangeDDrawDevice(LPDIRECTDRAW7 lpDDrawDevice,HMONITOR hMonitor);
STDMETHODIMP RestoreDDrawSurfaces();
STDMETHODIMP NotifyEvent(LONG EventCode, LONG_PTR lp1, LONG_PTR lp2);
STDMETHODIMP SetBorderColor(COLORREF clr);
// IVMRImagePresenter
STDMETHODIMP StartPresenting(DWORD_PTR dwUserID);
STDMETHODIMP StopPresenting(DWORD_PTR dwUserID);
STDMETHODIMP PresentImage(DWORD_PTR dwUserID,
VMRPRESENTATIONINFO* lpPresInfo);
HRESULT OpenMovie(TCHAR *lpFileName);
DWORD CloseMovie();
BOOL PlayMovie();
BOOL PauseMovie();
BOOL StopMovie();
OAFilterState GetStateMovie();
HANDLE GetMovieEventHandle();
long GetMovieEventCode();
BOOL PutMoviePosition(LONG x, LONG y, LONG cx, LONG cy);
REFTIME GetDuration();
REFTIME GetCurrentPosition();
BOOL SeekToPosition(REFTIME rt,BOOL bFlushData);
BOOL RepaintVideo(HWND hwnd, HDC hdc);
void DisplayModeChanged() {
if (m_lpDefWC) {
m_lpDefWC->DisplayModeChanged();
}
}
IVMRWindowlessControl* GetWLC() {
return m_lpDefWC;
}
void GetPerformance( void);
};