?? gameswf_render_handler_d3d.cpp
字號:
// gameswf_render_handler_d3d.cpp Paul Kelly & Bob Ives, 2006
// This source code has been donated to the Public Domain. Do
// whatever you want with it.
// A gameswf::render_handler that uses DX8 or DX9.
// Based on the xbox code by Thatcher Ulrich <http://tulrich.com> 2003
#include <windows.h>
#include <assert.h>
#include "gameswf.h"
#include "gameswf/gameswf_log.h"
#include "gameswf_types.h"
#include "base/image.h"
#include "base/container.h"
//#define _DX8
#if defined (_DX8)
# include <d3d8.h>
#else
# include <d3d9.h>
#endif
#if DIRECT3D_VERSION < 0x0900
# include <d3dx8tex.h>
# include <d3d8types.h>
typedef IDirect3D8 IDirect3D;
typedef IDirect3DDevice8 IDirect3DDevice;
typedef IDirect3DTexture8 IDirect3DTexture;
typedef IDirect3DBaseTexture8 IDirect3DBaseTexture;
typedef IDirect3DSurface8 IDirect3DSurface;
typedef IDirect3DVertexBuffer8 IDirect3DVertexBuffer;
typedef D3DVIEWPORT8 D3DVIEWPORT;
typedef BYTE tLock;
#else
# include <d3dx9tex.h>
# include <d3d9types.h>
typedef IDirect3D9 IDirect3D;
typedef IDirect3DDevice9 IDirect3DDevice;
typedef IDirect3DTexture9 IDirect3DTexture;
typedef IDirect3DBaseTexture9 IDirect3DBaseTexture;
typedef IDirect3DSurface9 IDirect3DSurface;
typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer;
typedef D3DVIEWPORT9 D3DVIEWPORT;
typedef void tLock;
#endif
#include <string.h>
#define INIT_SIZE_VERTEX_BUFFER 128
#define Z_DEPTH 1.0f
// A structure for our custom vertex type. We added texture coordinates
struct CUSTOMVERTEX
{
float x,y,z; // transformed position for the vertex
};
// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ)
struct CUSTOMVERTEX2
{
float x,y,z; // position
float tu, tv; // texture coordinates
};
#define D3DFVF_CUSTOMVERTEX2 (D3DFVF_XYZ|D3DFVF_TEX1)
static inline float clamp( float x,float min,float max ) {
union { float f; int hex; };
f = x - min;
hex &= ~hex>>31;
f += min - max;
hex &= hex>>31;
f += max;
return f;
}
// bitmap_info_d3d declaration
struct bitmap_info_d3d : public gameswf::bitmap_info
{
bitmap_info_d3d();
void convert_to_argb(image::rgba* im);
bitmap_info_d3d(image::rgb* im);
bitmap_info_d3d(image::rgba* im);
bitmap_info_d3d(int width, int height, Uint8* data);
};
struct render_handler_d3d : public gameswf::render_handler
{
// Some renderer state.
gameswf::matrix m_current_matrix;
gameswf::cxform m_current_cxform;
IDirect3DVertexBuffer* m_pVB; // Buffer to hold vertices
IDirect3DVertexBuffer* m_pVB2; // Buffer to hold vertices
DWORD m_nMaxVertices; // Max Vertices held in m_pVB
D3DVIEWPORT m_origVP;
static IDirect3DDevice* m_pd3dDevice; // Our rendering device
static D3DFORMAT m_FormatRGB;
static D3DFORMAT m_FormatRGBA;
static D3DFORMAT m_FormatA;
static D3DXMATRIX m_ModelViewMatrix;
static D3DXMATRIX m_ProjMatrix;
static array<IDirect3DBaseTexture*> m_d3d_textures;
void set_antialiased(bool enable)
{
// not supported
}
static void make_next_miplevel(int* width, int* height, Uint8* data)
// Utility. Mutates *width, *height and *data to create the
// next mip level.
{
assert(width);
assert(height);
assert(data);
int new_w = *width >> 1;
int new_h = *height >> 1;
if (new_w < 1) new_w = 1;
if (new_h < 1) new_h = 1;
if (new_w * 2 != *width || new_h * 2 != *height)
{
// Image can't be shrunk along (at least) one
// of its dimensions, so don't bother
// resampling. Technically we should, but
// it's pretty useless at this point. Just
// change the image dimensions and leave the
// existing pixels.
}
else
{
// Resample. Simple average 2x2 --> 1, in-place.
for (int j = 0; j < new_h; j++) {
Uint8* out = ((Uint8*) data) + j * new_w;
Uint8* in = ((Uint8*) data) + (j << 1) * *width;
for (int i = 0; i < new_w; i++) {
int a;
a = (*(in + 0) + *(in + 1) + *(in + 0 + *width) + *(in + 1 + *width));
*(out) = (Uint8) (a >> 2);
out++;
in += 2;
}
}
}
// Munge parameters to reflect the shrunken image.
*width = new_w;
*height = new_h;
}
struct fill_style
{
enum mode
{
INVALID,
COLOR,
BITMAP_WRAP,
BITMAP_CLAMP,
LINEAR_GRADIENT,
RADIAL_GRADIENT,
};
mode m_mode;
gameswf::rgba m_color;
const gameswf::bitmap_info* m_bitmap_info;
gameswf::matrix m_bitmap_matrix;
gameswf::cxform m_bitmap_color_transform;
bool m_has_nonzero_bitmap_additive_color;
fill_style()
:
m_mode(INVALID),
m_has_nonzero_bitmap_additive_color(false)
{
}
void apply(const gameswf::matrix& current_matrix) const
// Push our style into D3D.
{
assert(m_mode != INVALID);
if (m_mode == COLOR)
{
apply_color(m_color);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
}
else if (m_mode == BITMAP_WRAP
|| m_mode == BITMAP_CLAMP)
{
assert(m_bitmap_info != NULL);
apply_color(m_color);
if (m_bitmap_info == NULL)
{
assert(0);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
}
else
{
// Set up the texture for rendering.
// Do the modulate part of the color
// transform in the first pass. The
// additive part, if any, needs to
// happen in a second pass.
m_pd3dDevice->SetTexture(0, m_d3d_textures[m_bitmap_info->m_texture_id]);
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
if (m_mode == BITMAP_CLAMP)
{
#if DIRECT3D_VERSION >= 0x0900
m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
#else
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
#endif
}
else
{
assert(m_mode == BITMAP_WRAP);
#if DIRECT3D_VERSION >= 0x0900
m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
#else
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
#endif
}
// Set up the bitmap matrix for texgen.
float inv_width = 1.0f / m_bitmap_info->m_original_width;
float inv_height = 1.0f / m_bitmap_info->m_original_height;
gameswf::matrix m = m_bitmap_matrix;
gameswf::matrix m_cm_inv;
m_cm_inv.set_inverse(current_matrix);
m.concatenate(m_cm_inv);
D3DXMATRIXA16 mat;
D3DXMatrixIdentity(&mat);
mat._11 = m.m_[0][0] * inv_width; mat._12 = m.m_[1][0] * inv_height; mat._13 = 0.00f; mat._14 = 0.00f;
mat._21 = m.m_[0][1] * inv_width; mat._22 = m.m_[1][1] * inv_height; mat._23 = 0.00f; mat._24 = 0.00f;
mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 0.00f; mat._34 = 0.00f;
mat._41 = m.m_[0][2] * inv_width; mat._42 = m.m_[1][2] * inv_height; mat._43 = 0.00f; mat._44 = 1.00f;
m_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
}
}
}
bool needs_second_pass() const
// Return true if we need to do a second pass to make
// a valid color. This is for cxforms with additive
// parts.
{
if (m_mode == BITMAP_WRAP
|| m_mode == BITMAP_CLAMP)
{
return m_has_nonzero_bitmap_additive_color;
}
else
{
return false;
}
}
void apply_second_pass() const
// Set D3D state for a necessary second pass.
{
assert(needs_second_pass());
// Additive color.
apply_color(gameswf::rgba(
Uint8(m_bitmap_color_transform.m_[0][1]),
Uint8(m_bitmap_color_transform.m_[1][1]),
Uint8(m_bitmap_color_transform.m_[2][1]),
Uint8(m_bitmap_color_transform.m_[3][1])));
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE );
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE );
}
void cleanup_second_pass() const
{
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
}
void disable() { m_mode = INVALID; }
void set_color(gameswf::rgba color)
{
m_mode = COLOR;
m_color = color;
}
void set_bitmap(const gameswf::bitmap_info* bi, const gameswf::matrix& m, bitmap_wrap_mode wm, const gameswf::cxform& color_transform)
{
m_mode = (wm == WRAP_REPEAT) ? BITMAP_WRAP : BITMAP_CLAMP;
m_bitmap_info = bi;
m_bitmap_matrix = m;
m_bitmap_color_transform.m_[0][0] = clamp(color_transform.m_[0][0], 0, 1);
m_bitmap_color_transform.m_[1][0] = clamp(color_transform.m_[1][0], 0, 1);
m_bitmap_color_transform.m_[2][0] = clamp(color_transform.m_[2][0], 0, 1);
m_bitmap_color_transform.m_[3][0] = clamp(color_transform.m_[3][0], 0, 1);
m_bitmap_color_transform.m_[0][1] = clamp(color_transform.m_[0][1], -255.0f, 255.0f);
m_bitmap_color_transform.m_[1][1] = clamp(color_transform.m_[1][1], -255.0f, 255.0f);
m_bitmap_color_transform.m_[2][1] = clamp(color_transform.m_[2][1], -255.0f, 255.0f);
m_bitmap_color_transform.m_[3][1] = clamp(color_transform.m_[3][1], -255.0f, 255.0f);
m_color = gameswf::rgba(
Uint8(m_bitmap_color_transform.m_[0][0]*255.0f),
Uint8(m_bitmap_color_transform.m_[1][0]*255.0f),
Uint8(m_bitmap_color_transform.m_[2][0]*255.0f),
Uint8(m_bitmap_color_transform.m_[3][0]*255.0f));
if (m_bitmap_color_transform.m_[0][1] > 1.0f
|| m_bitmap_color_transform.m_[1][1] > 1.0f
|| m_bitmap_color_transform.m_[2][1] > 1.0f
|| m_bitmap_color_transform.m_[3][1] > 1.0f)
{
m_has_nonzero_bitmap_additive_color = true;
}
else
{
m_has_nonzero_bitmap_additive_color = false;
}
}
bool is_valid() const { return m_mode != INVALID; }
};
// Constructor.
render_handler_d3d(IDirect3DDevice* device)
: m_pVB(NULL)
, m_pVB2(NULL)
, m_nMaxVertices(INIT_SIZE_VERTEX_BUFFER)
{
HRESULT hr;
m_pd3dDevice = device;
m_pd3dDevice->AddRef();
hr = m_pd3dDevice->CreateVertexBuffer( m_nMaxVertices*sizeof(CUSTOMVERTEX)
, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB
#if DIRECT3D_VERSION >= 0x0900
, NULL
#endif
);
assert(hr==S_OK);
hr = m_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX2)
, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEX2, D3DPOOL_DEFAULT, &m_pVB2
#if DIRECT3D_VERSION >= 0x0900
, NULL
#endif
);
assert(hr==S_OK);
// Determine texture formats
IDirect3D* l_pD3D;
hr = m_pd3dDevice->GetDirect3D( &l_pD3D );
assert(hr==S_OK);
#if DIRECT3D_VERSION < 0x0900
D3DCAPS8 l_DeviceCaps;
#else
D3DCAPS9 l_DeviceCaps;
#endif
ZeroMemory( &l_DeviceCaps, sizeof(l_DeviceCaps) );
hr = m_pd3dDevice->GetDeviceCaps( &l_DeviceCaps );
assert(hr==S_OK);
D3DDISPLAYMODE l_DisplayMode;
hr = m_pd3dDevice->GetDisplayMode(
#if DIRECT3D_VERSION >= 0x0900
0,
#endif
&l_DisplayMode );
if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)))
m_FormatRGB = D3DFMT_DXT1;
else if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_R8G8B8)))
m_FormatRGB = D3DFMT_R8G8B8;
else
m_FormatRGB = D3DFMT_A8R8G8B8;
if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)))
m_FormatRGBA = D3DFMT_DXT5;
else
m_FormatRGBA = D3DFMT_A8R8G8B8;
if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8)))
m_FormatA = D3DFMT_A8;
else if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)))
m_FormatA = D3DFMT_A8L8;
else if (SUCCEEDED(l_pD3D->CheckDeviceFormat(l_DeviceCaps.AdapterOrdinal, l_DeviceCaps.DeviceType, l_DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8P8)))
m_FormatA = D3DFMT_A8P8;
else
m_FormatA = D3DFMT_A8R8G8B8;
}
~render_handler_d3d()
// Destructor.
{
for (int i = 0; i < m_d3d_textures.size(); i++)
{
if( m_d3d_textures[i] )
{
m_d3d_textures[i]->Release();
m_d3d_textures[i] = 0;
}
}
if (m_pVB)
{
m_pVB->Release();
m_pVB = 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -