443 lines
11 KiB
C++
443 lines
11 KiB
C++
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// BandiVideoLibrary 2.1
|
||
|
|
///
|
||
|
|
/// Copyright(C) 2008-2010 BandiSoft.com All rights reserved.
|
||
|
|
///
|
||
|
|
/// Visit http://www.bandisoft.com for more information.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
#include "stdafx.h"
|
||
|
|
|
||
|
|
#include "BandiVideoTexture_DX9.h"
|
||
|
|
|
||
|
|
static BOOL GetTextureFormat(LPDIRECT3D9 d3d9, D3DFORMAT &texture_fmt_d3d, BVL_PIXEL_FORMAT &texture_fmt_bvl, int &texture_pixel_size)
|
||
|
|
{
|
||
|
|
struct
|
||
|
|
{
|
||
|
|
D3DFORMAT d3d_fmt;
|
||
|
|
BVL_PIXEL_FORMAT bvl_fmt;
|
||
|
|
int pixel_size;
|
||
|
|
} fmt_list[] =
|
||
|
|
{
|
||
|
|
{ D3DFMT_X8R8G8B8, BVLPF_X8R8G8B8, 4},
|
||
|
|
{ D3DFMT_R8G8B8, BVLPF_R8G8B8, 3},
|
||
|
|
{ D3DFMT_R5G6B5, BVLPF_R5G6B5, 2},
|
||
|
|
{ D3DFMT_X1R5G5B5, BVLPF_R5G5B5, 2},
|
||
|
|
};
|
||
|
|
|
||
|
|
D3DDISPLAYMODE d3ddm;
|
||
|
|
HRESULT hr = d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
|
||
|
|
if(SUCCEEDED(hr))
|
||
|
|
{
|
||
|
|
int fmt_count = sizeof(fmt_list)/sizeof(fmt_list[0]);
|
||
|
|
for(int i = 0; i < fmt_count; i++ )
|
||
|
|
{
|
||
|
|
if(SUCCEEDED(d3d9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_TEXTURE, fmt_list[i].d3d_fmt)))
|
||
|
|
{
|
||
|
|
texture_fmt_d3d = fmt_list[i].d3d_fmt;
|
||
|
|
texture_fmt_bvl = fmt_list[i].bvl_fmt;
|
||
|
|
texture_pixel_size = fmt_list[i].pixel_size;
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
texture_fmt_d3d = D3DFMT_UNKNOWN;
|
||
|
|
texture_fmt_bvl = BVLPF_NULL;
|
||
|
|
texture_pixel_size = NULL;
|
||
|
|
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// CBandiVideoDevice_DX9 class
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
CBandiVideoDevice_DX9::CBandiVideoDevice_DX9()
|
||
|
|
{
|
||
|
|
// BV_DEVICE_DX9 structure
|
||
|
|
m_d3d9 = NULL;
|
||
|
|
m_d3d9_device = NULL;
|
||
|
|
m_hwnd_parent = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
CBandiVideoDevice_DX9::~CBandiVideoDevice_DX9()
|
||
|
|
{
|
||
|
|
Close();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Open Direct3D9 Device.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoDevice_DX9::Open(HWND hWnd)
|
||
|
|
{
|
||
|
|
HRESULT hr;
|
||
|
|
LPDIRECT3D9 d3d9 = NULL;
|
||
|
|
LPDIRECT3DDEVICE9 d3d9_device = NULL;
|
||
|
|
D3DDISPLAYMODE d3ddm;
|
||
|
|
D3DPRESENT_PARAMETERS d3dpp = {0};;
|
||
|
|
|
||
|
|
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
|
||
|
|
if(d3d9 == NULL)
|
||
|
|
{
|
||
|
|
ASSERT(0);
|
||
|
|
return E_FAIL;
|
||
|
|
}
|
||
|
|
|
||
|
|
hr = d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
|
||
|
|
if(FAILED(hr))
|
||
|
|
{
|
||
|
|
ASSERT(0);
|
||
|
|
return hr;
|
||
|
|
}
|
||
|
|
|
||
|
|
d3dpp.hDeviceWindow = hWnd;
|
||
|
|
d3dpp.Windowed = TRUE;
|
||
|
|
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||
|
|
d3dpp.BackBufferFormat = d3ddm.Format;
|
||
|
|
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
|
||
|
|
|
||
|
|
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
|
||
|
|
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3d9_device)))
|
||
|
|
{
|
||
|
|
ASSERT(0);
|
||
|
|
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
|
||
|
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3d9_device)))
|
||
|
|
{
|
||
|
|
ASSERT(0);
|
||
|
|
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
|
||
|
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3d9_device)))
|
||
|
|
{
|
||
|
|
ASSERT(0);
|
||
|
|
d3d9->Release();
|
||
|
|
return E_FAIL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
m_d3d9 = d3d9;
|
||
|
|
m_d3d9_device = d3d9_device;
|
||
|
|
m_hwnd_parent = hWnd;
|
||
|
|
|
||
|
|
return S_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Close Direct3D9 Device.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
void CBandiVideoDevice_DX9::Close()
|
||
|
|
{
|
||
|
|
if(m_d3d9_device)
|
||
|
|
{
|
||
|
|
m_d3d9_device->Release();
|
||
|
|
m_d3d9_device = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(m_d3d9)
|
||
|
|
{
|
||
|
|
m_d3d9->Release( );
|
||
|
|
m_d3d9 = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_hwnd_parent = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Resize the Direct3D9 viewport.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoDevice_DX9::Resize(INT width, INT height)
|
||
|
|
{
|
||
|
|
if(m_d3d9_device == NULL)
|
||
|
|
return E_FAIL;
|
||
|
|
|
||
|
|
width = max(1, width);
|
||
|
|
height = max(1, height);
|
||
|
|
|
||
|
|
// Create the viewport
|
||
|
|
D3DVIEWPORT9 vp = { 0, 0, width, height, 0.0f, 1.0f };
|
||
|
|
|
||
|
|
m_d3d9_device->SetViewport( &vp );
|
||
|
|
|
||
|
|
return S_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Begin a Direct3D9 frame.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoDevice_DX9::StartFrame()
|
||
|
|
{
|
||
|
|
if(m_d3d9_device == NULL)
|
||
|
|
return E_FAIL;
|
||
|
|
|
||
|
|
m_d3d9_device->Clear( 0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0 );
|
||
|
|
m_d3d9_device->BeginScene();
|
||
|
|
|
||
|
|
return S_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// End a Direct3D9 frame.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoDevice_DX9::EndFrame()
|
||
|
|
{
|
||
|
|
if(m_d3d9_device == NULL)
|
||
|
|
return E_FAIL;
|
||
|
|
|
||
|
|
m_d3d9_device->EndScene();
|
||
|
|
m_d3d9_device->Present(NULL, NULL, NULL, NULL);
|
||
|
|
|
||
|
|
return S_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/// D3DVERTEX structure
|
||
|
|
typedef struct _D3DVERTEX { // D3D Vertex
|
||
|
|
D3DVECTOR pos;
|
||
|
|
float rhw;
|
||
|
|
float tu, tv;
|
||
|
|
} D3DVERTEX;
|
||
|
|
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// CBandiVideoTexture_DX9 class
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
CBandiVideoTexture_DX9::CBandiVideoTexture_DX9(BV_DEVICE_DX9* device)
|
||
|
|
{
|
||
|
|
memcpy(&m_device, device, sizeof(BV_DEVICE_DX9));
|
||
|
|
|
||
|
|
m_texture = NULL;
|
||
|
|
m_vertex_buffer = NULL;
|
||
|
|
|
||
|
|
m_vid_width = m_vid_height = 0;
|
||
|
|
m_tex_width = m_tex_height = 0;
|
||
|
|
|
||
|
|
if(!GetTextureFormat(device->m_d3d9, m_fmt_d3d, m_fmt_bvl, m_pixel_size))
|
||
|
|
ASSERT(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
CBandiVideoTexture_DX9::~CBandiVideoTexture_DX9()
|
||
|
|
{
|
||
|
|
Close();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Open a Direct3D9 texture
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoTexture_DX9::Open(INT vid_width, INT vid_height)
|
||
|
|
{
|
||
|
|
HRESULT hr;
|
||
|
|
LPDIRECT3DTEXTURE9 texture = NULL;
|
||
|
|
LPDIRECT3DDEVICE9 d3d9_device = m_device.m_d3d9_device;
|
||
|
|
BOOL pow2 = TRUE;
|
||
|
|
|
||
|
|
D3DCAPS9 Caps;
|
||
|
|
d3d9_device->GetDeviceCaps(&Caps);
|
||
|
|
if(!!(Caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
|
||
|
|
{
|
||
|
|
pow2 = FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
int tex_width = CalcTexSize(vid_width, pow2);
|
||
|
|
int tex_height = CalcTexSize(vid_height, pow2);
|
||
|
|
|
||
|
|
// try to create a dynamic texture first
|
||
|
|
hr = d3d9_device->CreateTexture(tex_width, tex_height, 1,D3DUSAGE_DYNAMIC,
|
||
|
|
m_fmt_d3d, D3DPOOL_DEFAULT, &texture, 0);
|
||
|
|
if(FAILED(hr))
|
||
|
|
{
|
||
|
|
hr = d3d9_device->CreateTexture(tex_width, tex_height, 1, 0,
|
||
|
|
m_fmt_d3d, D3DPOOL_MANAGED, &texture, 0);
|
||
|
|
if(FAILED(hr))
|
||
|
|
{
|
||
|
|
Beep(1000, 1000);
|
||
|
|
ASSERT(0);
|
||
|
|
return hr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
D3DLOCKED_RECT locked_rect;
|
||
|
|
|
||
|
|
// Clear the texture to black.
|
||
|
|
if(SUCCEEDED(texture->LockRect(0, &locked_rect, NULL, NULL)))
|
||
|
|
{
|
||
|
|
// Clear the pixels.
|
||
|
|
BYTE* dest = (BYTE*) locked_rect.pBits;
|
||
|
|
int bytes = tex_width*m_pixel_size;
|
||
|
|
|
||
|
|
for(int y = 0 ; y < tex_height ; y++)
|
||
|
|
{
|
||
|
|
memset(dest, 0, bytes);
|
||
|
|
dest += locked_rect.Pitch;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Unlock the DirectX texture.
|
||
|
|
texture->UnlockRect(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
m_texture = texture;
|
||
|
|
|
||
|
|
m_vid_width = vid_width;
|
||
|
|
m_vid_height = vid_height;
|
||
|
|
m_tex_width = tex_width;
|
||
|
|
m_tex_height = tex_height;
|
||
|
|
|
||
|
|
return S_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Close a Direct3D9 texture
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
void CBandiVideoTexture_DX9::Close()
|
||
|
|
{
|
||
|
|
m_vid_width = m_vid_height = 0;
|
||
|
|
m_tex_width = m_tex_height = 0;
|
||
|
|
|
||
|
|
if(m_texture)
|
||
|
|
{
|
||
|
|
m_texture->Release();
|
||
|
|
m_texture = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Lock a Direct3D9 teture and return the buffer address and pitch
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
BYTE* CBandiVideoTexture_DX9::Lock(INT &pitch)
|
||
|
|
{
|
||
|
|
D3DLOCKED_RECT rc;
|
||
|
|
BYTE *buf;
|
||
|
|
|
||
|
|
m_texture->LockRect(0, &rc, NULL, 0);
|
||
|
|
buf = (BYTE*)rc.pBits;
|
||
|
|
pitch = rc.Pitch;
|
||
|
|
|
||
|
|
return buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Unlock a Direct3D9 texture.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
void CBandiVideoTexture_DX9::Unlock()
|
||
|
|
{
|
||
|
|
m_texture->UnlockRect(NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Draw a Direct3D9 texture.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoTexture_DX9::Draw(INT x, INT y, INT width, INT height)
|
||
|
|
{
|
||
|
|
HRESULT hr;
|
||
|
|
hr = m_device.m_d3d9_device->SetTexture(0, m_texture);
|
||
|
|
if(FAILED(hr)) return hr;
|
||
|
|
|
||
|
|
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||
|
|
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||
|
|
|
||
|
|
return SetVertices((float)x, (float)y, (float)width, (float)height);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Set the vertices.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
HRESULT CBandiVideoTexture_DX9::SetVertices(float scr_x, float scr_y, float scr_width, float scr_height)
|
||
|
|
{
|
||
|
|
D3DVERTEX vertices[4];
|
||
|
|
|
||
|
|
// Set vertices
|
||
|
|
vertices[0].pos.x = scr_x;
|
||
|
|
vertices[0].pos.y = scr_y;
|
||
|
|
vertices[0].tu = 0.0f;
|
||
|
|
vertices[0].tv = 0.0f;
|
||
|
|
|
||
|
|
vertices[1].pos.x = scr_x + scr_width;
|
||
|
|
vertices[1].pos.y = scr_y;
|
||
|
|
vertices[1].tu = 1.0f * ((float)m_vid_width / m_tex_width);
|
||
|
|
vertices[1].tv = 0.0f;
|
||
|
|
|
||
|
|
vertices[2].pos.x = scr_x;
|
||
|
|
vertices[2].pos.y = scr_y + scr_height;
|
||
|
|
vertices[2].tu = 0.0f;
|
||
|
|
vertices[2].tv = 1.0f * ((float)m_vid_height / m_tex_height);
|
||
|
|
|
||
|
|
vertices[3].pos.x = scr_x + scr_width;
|
||
|
|
vertices[3].pos.y = scr_y + scr_height;
|
||
|
|
vertices[3].tu = 1.0f * ((float)m_vid_width / m_tex_width);
|
||
|
|
vertices[3].tv = 1.0f * ((float)m_vid_height / m_tex_height);
|
||
|
|
|
||
|
|
|
||
|
|
vertices[0].pos.z = vertices[1].pos.z = vertices[2].pos.z = vertices[3].pos.z = 0.0f;
|
||
|
|
vertices[0].rhw = vertices[1].rhw = vertices[2].rhw = vertices[3].rhw = 1.0f;
|
||
|
|
|
||
|
|
// Draw the vertices.
|
||
|
|
m_device.m_d3d9_device->SetVertexShader(0);
|
||
|
|
m_device.m_d3d9_device->SetFVF(D3DFVF_VERTEX);
|
||
|
|
|
||
|
|
return m_device.m_d3d9_device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(vertices[0]));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
///
|
||
|
|
/// Calculate texture size.
|
||
|
|
///
|
||
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
int CBandiVideoTexture_DX9::CalcTexSize(int vid_size, BOOL pow2)
|
||
|
|
{
|
||
|
|
// Power-of-2 texture dimensions are required.
|
||
|
|
D3DCAPS9 caps;
|
||
|
|
m_device.m_d3d9_device->GetDeviceCaps(&caps);
|
||
|
|
if(pow2 && caps.TextureCaps & D3DPTEXTURECAPS_POW2)
|
||
|
|
{
|
||
|
|
int tex_size = 16;
|
||
|
|
while (tex_size < vid_size)
|
||
|
|
tex_size = tex_size<<1;
|
||
|
|
|
||
|
|
return tex_size;
|
||
|
|
}
|
||
|
|
|
||
|
|
return vid_size;
|
||
|
|
}
|