Add Turntable.cpp to SCons build.

Set native eol-style on recently added files.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6252 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Soren Jorvang
2010-10-03 08:20:24 +00:00
parent c6fa5804de
commit 4b5b9ad05c
98 changed files with 18965 additions and 18964 deletions
File diff suppressed because it is too large Load Diff
@@ -1,165 +1,165 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _D3DBASE_H
#define _D3DBASE_H
#include <vector>
#include <set>
#include <d3dx9.h>
#include "Common.h"
namespace DX9
{
namespace D3D
{
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
// From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
// Magic FourCC's to unlock undocumented D3D9 features:
// Z texture formats
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
#define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z')))
#define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4')))
#define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6')))
// Depth buffer resolve:
#define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
#define RESZ_CODE 0x7fa05000
// Null render target to do Z-only shadow maps: (probably not useful for Dolphin)
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
bool IsATIDevice();
HRESULT Init();
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
void Close();
void Shutdown();
// Direct access to the device.
extern LPDIRECT3DDEVICE9 dev;
extern bool bFrameInProgress;
void Reset();
bool BeginFrame();
void EndFrame();
void Present();
bool CanUseINTZ();
int GetBackBufferWidth();
int GetBackBufferHeight();
LPDIRECT3DSURFACE9 GetBackBufferSurface();
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface();
LPDIRECT3DVERTEXBUFFER9 GetquadVB();
LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl();
const D3DCAPS9 &GetCaps();
const char *PixelShaderVersionString();
const char *VertexShaderVersionString();
void ShowD3DError(HRESULT err);
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
void RefreshRenderState(D3DRENDERSTATETYPE State);
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value);
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type);
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type);
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshVertexDeclaration();
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
void RefreshVertexShader();
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
void RefreshPixelShader();
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
void ApplyCachedState();
// Utility functions for vendor specific hacks. So far, just the one.
void EnableAlphaToCoverage();
struct Resolution
{
char name[32];
int xres;
int yres;
std::set<D3DFORMAT> bitdepths;
std::set<int> refreshes;
};
struct AALevel
{
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
strncpy(name, n, 32);
name[31] = '\0';
ms_setting = m;
qual_setting = q;
}
char name[32];
D3DMULTISAMPLE_TYPE ms_setting;
int qual_setting;
};
struct Adapter
{
D3DADAPTER_IDENTIFIER9 ident;
std::vector<Resolution> resolutions;
std::vector<AALevel> aa_levels;
bool supports_alpha_to_coverage;
// Magic render targets, see the top of this file.
bool supports_intz;
bool supports_rawz;
bool supports_resz;
bool supports_null;
};
const Adapter &GetAdapter(int i);
const Adapter &GetCurAdapter();
int GetNumAdapters();
} // namespace
// Used to not require the SDK and runtime versions to match:
// Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the
// compiler's SDK an actually unnecessary requirement.
// Add any d3dx9 functions which you want to use here and load them in LoadD3DX9()
typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*);
typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*);
extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA;
extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA;
extern D3DXCOMPILESHADERTYPE PD3DXCompileShader;
}
#endif
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _D3DBASE_H
#define _D3DBASE_H
#include <vector>
#include <set>
#include <d3dx9.h>
#include "Common.h"
namespace DX9
{
namespace D3D
{
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
// From http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards.pdf
// Magic FourCC's to unlock undocumented D3D9 features:
// Z texture formats
#define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
#define FOURCC_RAWZ ((D3DFORMAT)(MAKEFOURCC('R','A','W','Z')))
#define FOURCC_DF24 ((D3DFORMAT)(MAKEFOURCC('D','F','2','4')))
#define FOURCC_DF16 ((D3DFORMAT)(MAKEFOURCC('D','F','1','6')))
// Depth buffer resolve:
#define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
#define RESZ_CODE 0x7fa05000
// Null render target to do Z-only shadow maps: (probably not useful for Dolphin)
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
bool IsATIDevice();
HRESULT Init();
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
void Close();
void Shutdown();
// Direct access to the device.
extern LPDIRECT3DDEVICE9 dev;
extern bool bFrameInProgress;
void Reset();
bool BeginFrame();
void EndFrame();
void Present();
bool CanUseINTZ();
int GetBackBufferWidth();
int GetBackBufferHeight();
LPDIRECT3DSURFACE9 GetBackBufferSurface();
LPDIRECT3DSURFACE9 GetBackBufferDepthSurface();
LPDIRECT3DVERTEXBUFFER9 GetquadVB();
LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl();
const D3DCAPS9 &GetCaps();
const char *PixelShaderVersionString();
const char *VertexShaderVersionString();
void ShowD3DError(HRESULT err);
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
void RefreshRenderState(D3DRENDERSTATETYPE State);
void ChangeRenderState(D3DRENDERSTATETYPE State, DWORD Value);
void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void RefreshTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type);
void ChangeTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type);
void ChangeSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
void RefreshVertexDeclaration();
void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl);
void RefreshVertexShader();
void SetVertexShader(LPDIRECT3DVERTEXSHADER9 shader);
void RefreshPixelShader();
void SetPixelShader(LPDIRECT3DPIXELSHADER9 shader);
void ApplyCachedState();
// Utility functions for vendor specific hacks. So far, just the one.
void EnableAlphaToCoverage();
struct Resolution
{
char name[32];
int xres;
int yres;
std::set<D3DFORMAT> bitdepths;
std::set<int> refreshes;
};
struct AALevel
{
AALevel(const char *n, D3DMULTISAMPLE_TYPE m, int q) {
strncpy(name, n, 32);
name[31] = '\0';
ms_setting = m;
qual_setting = q;
}
char name[32];
D3DMULTISAMPLE_TYPE ms_setting;
int qual_setting;
};
struct Adapter
{
D3DADAPTER_IDENTIFIER9 ident;
std::vector<Resolution> resolutions;
std::vector<AALevel> aa_levels;
bool supports_alpha_to_coverage;
// Magic render targets, see the top of this file.
bool supports_intz;
bool supports_rawz;
bool supports_resz;
bool supports_null;
};
const Adapter &GetAdapter(int i);
const Adapter &GetCurAdapter();
int GetNumAdapters();
} // namespace
// Used to not require the SDK and runtime versions to match:
// Linking with d3dx9.lib makes the most recent d3dx9_xx.dll of the
// compiler's SDK an actually unnecessary requirement.
// Add any d3dx9 functions which you want to use here and load them in LoadD3DX9()
typedef HRESULT (WINAPI* D3DXSAVESURFACETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
typedef HRESULT (WINAPI* D3DXSAVETEXTURETOFILEATYPE)(LPCSTR, D3DXIMAGE_FILEFORMAT, LPDIRECT3DBASETEXTURE9, CONST PALETTEENTRY*);
typedef HRESULT (WINAPI* D3DXCOMPILESHADERTYPE)(LPCSTR, UINT, CONST D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*);
extern D3DXSAVESURFACETOFILEATYPE PD3DXSaveSurfaceToFileA;
extern D3DXSAVETEXTURETOFILEATYPE PD3DXSaveTextureToFileA;
extern D3DXCOMPILESHADERTYPE PD3DXCompileShader;
}
#endif
@@ -1,150 +1,150 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include <string>
#include "VideoConfig.h"
#include "DX9_D3DShader.h"
namespace DX9
{
namespace D3D
{
// Bytecode->shader.
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
{
LPDIRECT3DVERTEXSHADER9 v_shader;
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
if (FAILED(hr))
v_shader = 0;
return v_shader;
}
// Code->bytecode.
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
{
//try to compile
LPD3DXBUFFER shaderBuffer = 0;
LPD3DXBUFFER errorBuffer = 0;
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
0, &shaderBuffer, &errorBuffer, 0);
if (FAILED(hr))
{
//compilation error
if (g_ActiveConfig.bShowShaderErrors) {
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
}
*bytecode = 0;
*bytecodelen = 0;
}
else if (SUCCEEDED(hr))
{
*bytecodelen = shaderBuffer->GetBufferSize();
*bytecode = new u8[*bytecodelen];
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return SUCCEEDED(hr) ? true : false;
}
// Bytecode->shader.
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
{
LPDIRECT3DPIXELSHADER9 p_shader;
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
if (FAILED(hr))
p_shader = 0;
return p_shader;
}
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
{
LPD3DXBUFFER shaderBuffer = 0;
LPD3DXBUFFER errorBuffer = 0;
// Someone:
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
// in a dependency chain that is too complex for the target shader model (ps_2_0) to handle."
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(),
0, &shaderBuffer, &errorBuffer, 0);
if (FAILED(hr))
{
if (g_ActiveConfig.bShowShaderErrors) {
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
}
*bytecode = 0;
*bytecodelen = 0;
}
else if (SUCCEEDED(hr))
{
*bytecodelen = shaderBuffer->GetBufferSize();
*bytecode = new u8[*bytecodelen];
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return SUCCEEDED(hr) ? true : false;
}
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) {
u8 *bytecode;
int bytecodelen;
if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) {
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
delete [] bytecode;
return v_shader;
} else {
return 0;
}
}
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) {
u8 *bytecode;
int bytecodelen;
if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) {
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
delete [] bytecode;
return p_shader;
} else {
return 0;
}
}
} // namespace
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include <string>
#include "VideoConfig.h"
#include "DX9_D3DShader.h"
namespace DX9
{
namespace D3D
{
// Bytecode->shader.
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len)
{
LPDIRECT3DVERTEXSHADER9 v_shader;
HRESULT hr = D3D::dev->CreateVertexShader((DWORD *)bytecode, &v_shader);
if (FAILED(hr))
v_shader = 0;
return v_shader;
}
// Code->bytecode.
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
{
//try to compile
LPD3DXBUFFER shaderBuffer = 0;
LPD3DXBUFFER errorBuffer = 0;
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::VertexShaderVersionString(),
0, &shaderBuffer, &errorBuffer, 0);
if (FAILED(hr))
{
//compilation error
if (g_ActiveConfig.bShowShaderErrors) {
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
MessageBoxA(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
}
*bytecode = 0;
*bytecodelen = 0;
}
else if (SUCCEEDED(hr))
{
*bytecodelen = shaderBuffer->GetBufferSize();
*bytecode = new u8[*bytecodelen];
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return SUCCEEDED(hr) ? true : false;
}
// Bytecode->shader.
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len)
{
LPDIRECT3DPIXELSHADER9 p_shader;
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)bytecode, &p_shader);
if (FAILED(hr))
p_shader = 0;
return p_shader;
}
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen)
{
LPD3DXBUFFER shaderBuffer = 0;
LPD3DXBUFFER errorBuffer = 0;
// Someone:
// For some reason, I had this kind of errors : "Shader uses texture addressing operations
// in a dependency chain that is too complex for the target shader model (ps_2_0) to handle."
HRESULT hr = PD3DXCompileShader(code, len, 0, 0, "main", D3D::PixelShaderVersionString(),
0, &shaderBuffer, &errorBuffer, 0);
if (FAILED(hr))
{
if (g_ActiveConfig.bShowShaderErrors) {
std::string hello = (char*)errorBuffer->GetBufferPointer();
hello += "\n\n";
hello += code;
MessageBoxA(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
}
*bytecode = 0;
*bytecodelen = 0;
}
else if (SUCCEEDED(hr))
{
*bytecodelen = shaderBuffer->GetBufferSize();
*bytecode = new u8[*bytecodelen];
memcpy(*bytecode, shaderBuffer->GetBufferPointer(), *bytecodelen);
}
//cleanup
if (shaderBuffer)
shaderBuffer->Release();
if (errorBuffer)
errorBuffer->Release();
return SUCCEEDED(hr) ? true : false;
}
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len) {
u8 *bytecode;
int bytecodelen;
if (CompileVertexShader(code, len, &bytecode, &bytecodelen)) {
LPDIRECT3DVERTEXSHADER9 v_shader = CreateVertexShaderFromByteCode(bytecode, len);
delete [] bytecode;
return v_shader;
} else {
return 0;
}
}
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len) {
u8 *bytecode;
int bytecodelen;
if (CompilePixelShader(code, len, &bytecode, &bytecodelen)) {
LPDIRECT3DPIXELSHADER9 p_shader = CreatePixelShaderFromByteCode(bytecode, len);
delete [] bytecode;
return p_shader;
} else {
return 0;
}
}
} // namespace
}
@@ -1,39 +1,39 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "DX9_D3DBase.h"
namespace DX9
{
namespace D3D
{
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
// The returned bytecode buffers should be delete[]-d.
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
// Utility functions
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len);
}
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "DX9_D3DBase.h"
namespace DX9
{
namespace D3D
{
LPDIRECT3DVERTEXSHADER9 CreateVertexShaderFromByteCode(const u8 *bytecode, int len);
LPDIRECT3DPIXELSHADER9 CreatePixelShaderFromByteCode(const u8 *bytecode, int len);
// The returned bytecode buffers should be delete[]-d.
bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodelen);
// Utility functions
LPDIRECT3DVERTEXSHADER9 CompileAndCreateVertexShader(const char *code, int len);
LPDIRECT3DPIXELSHADER9 CompileAndCreatePixelShader(const char *code, int len);
}
}
@@ -1,275 +1,275 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h"
namespace DX9
{
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
{
u32* pBuffer = (u32*)buffer;
LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic, sorry :)
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
bool bExpand = false;
if (fmt == D3DFMT_A8P8) {
fmt = D3DFMT_A8L8;
bExpand = true;
}
HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps?
if (levels > 0)
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (FAILED(hr))
return 0;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0);
switch (fmt)
{
case D3DFMT_L8:
case D3DFMT_A8:
case D3DFMT_A4L4:
{
const u8 *pIn = buffer;
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width);
pIn += pitch;
}
}
break;
case D3DFMT_R5G6B5:
{
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
break;
case D3DFMT_A8L8:
{
if (bExpand) { // I8
const u8 *pIn = buffer;
// TODO(XK): Find a better way that does not involve either unpacking
// or downsampling (i.e. A4L4)
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
for(int i = 0; i < width * 2; i += 2) {
pBits[i] = pIn[i / 2];
pBits[i + 1] = pIn[i / 2];
}
pIn += pitch;
}
} else { // IA8
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
}
break;
case D3DFMT_A8R8G8B8:
{
if(pitch * 4 == Lock.Pitch && !swap_r_b)
{
memcpy(Lock.pBits,buffer,Lock.Pitch*height);
}
else
{
u32* pIn = pBuffer;
if (!swap_r_b) {
for (int y = 0; y < height; y++)
{
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4);
pIn += pitch;
}
} else {
for (int y = 0; y < height; y++)
{
u8 *pIn8 = (u8 *)pIn;
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
for (int x = 0; x < width * 4; x += 4) {
pBits[x + 0] = pIn8[x + 2];
pBits[x + 1] = pIn8[x + 1];
pBits[x + 2] = pIn8[x + 0];
pBits[x + 3] = pIn8[x + 3];
}
pIn += pitch;
}
}
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
break;
default:
PanicAlert("D3D: Invalid texture format %i", fmt);
}
pTexture->UnlockRect(level);
return pTexture;
}
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
{
LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic, sorry :)
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
bool bExpand = false;
HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps?
if (!isPow2)
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (FAILED(hr))
return 0;
return pTexture;
}
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
{
u32* pBuffer = (u32*)buffer;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0);
u32* pIn = pBuffer;
bool bExpand = false;
if (fmt == D3DFMT_A8P8) {
fmt = D3DFMT_A8L8;
bExpand = true;
}
switch (fmt)
{
case D3DFMT_A8R8G8B8:
if(pitch * 4 == Lock.Pitch && !swap_r_b)
{
memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
}
else if (!swap_r_b)
{
for (int y = 0; y < height; y++)
{
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4);
pIn += pitch;
}
}
else
{
for (int y = 0; y < height; y++)
{
u8 *pIn8 = (u8 *)pIn;
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
for (int x = 0; x < width * 4; x += 4)
{
pBits[x + 0] = pIn8[x + 2];
pBits[x + 1] = pIn8[x + 1];
pBits[x + 2] = pIn8[x + 0];
pBits[x + 3] = pIn8[x + 3];
}
pIn += pitch;
}
}
break;
case D3DFMT_L8:
case D3DFMT_A8:
case D3DFMT_A4L4:
{
const u8 *pIn = buffer;
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width);
pIn += pitch;
}
}
break;
case D3DFMT_R5G6B5:
{
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
break;
case D3DFMT_A8L8:
{
if (bExpand) { // I8
const u8 *pIn = buffer;
// TODO(XK): Find a better way that does not involve either unpacking
// or downsampling (i.e. A4L4)
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
for(int i = 0; i < width * 2; i += 2) {
pBits[i] = pIn[i / 2];
pBits[i + 1] = pIn[i / 2];
}
pIn += pitch;
}
} else { // IA8
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
break;
}
pTexture->UnlockRect(level);
}
} // namespace
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h"
namespace DX9
{
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
{
u32* pBuffer = (u32*)buffer;
LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic, sorry :)
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
bool bExpand = false;
if (fmt == D3DFMT_A8P8) {
fmt = D3DFMT_A8L8;
bExpand = true;
}
HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps?
if (levels > 0)
hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (FAILED(hr))
return 0;
int level = 0;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0);
switch (fmt)
{
case D3DFMT_L8:
case D3DFMT_A8:
case D3DFMT_A4L4:
{
const u8 *pIn = buffer;
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width);
pIn += pitch;
}
}
break;
case D3DFMT_R5G6B5:
{
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
break;
case D3DFMT_A8L8:
{
if (bExpand) { // I8
const u8 *pIn = buffer;
// TODO(XK): Find a better way that does not involve either unpacking
// or downsampling (i.e. A4L4)
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
for(int i = 0; i < width * 2; i += 2) {
pBits[i] = pIn[i / 2];
pBits[i + 1] = pIn[i / 2];
}
pIn += pitch;
}
} else { // IA8
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
}
break;
case D3DFMT_A8R8G8B8:
{
if(pitch * 4 == Lock.Pitch && !swap_r_b)
{
memcpy(Lock.pBits,buffer,Lock.Pitch*height);
}
else
{
u32* pIn = pBuffer;
if (!swap_r_b) {
for (int y = 0; y < height; y++)
{
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4);
pIn += pitch;
}
} else {
for (int y = 0; y < height; y++)
{
u8 *pIn8 = (u8 *)pIn;
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
for (int x = 0; x < width * 4; x += 4) {
pBits[x + 0] = pIn8[x + 2];
pBits[x + 1] = pIn8[x + 1];
pBits[x + 2] = pIn8[x + 0];
pBits[x + 3] = pIn8[x + 3];
}
pIn += pitch;
}
}
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
break;
default:
PanicAlert("D3D: Invalid texture format %i", fmt);
}
pTexture->UnlockRect(level);
return pTexture;
}
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
{
LPDIRECT3DTEXTURE9 pTexture;
// crazy bitmagic, sorry :)
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
bool bExpand = false;
HRESULT hr;
// TODO(ector): Allow mipmaps for non-pow textures on newer cards?
// TODO(ector): Use the game-specified mipmaps?
if (!isPow2)
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
else
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
if (FAILED(hr))
return 0;
return pTexture;
}
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
{
u32* pBuffer = (u32*)buffer;
D3DLOCKED_RECT Lock;
pTexture->LockRect(level, &Lock, NULL, 0);
u32* pIn = pBuffer;
bool bExpand = false;
if (fmt == D3DFMT_A8P8) {
fmt = D3DFMT_A8L8;
bExpand = true;
}
switch (fmt)
{
case D3DFMT_A8R8G8B8:
if(pitch * 4 == Lock.Pitch && !swap_r_b)
{
memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
}
else if (!swap_r_b)
{
for (int y = 0; y < height; y++)
{
u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 4);
pIn += pitch;
}
}
else
{
for (int y = 0; y < height; y++)
{
u8 *pIn8 = (u8 *)pIn;
u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
for (int x = 0; x < width * 4; x += 4)
{
pBits[x + 0] = pIn8[x + 2];
pBits[x + 1] = pIn8[x + 1];
pBits[x + 2] = pIn8[x + 0];
pBits[x + 3] = pIn8[x + 3];
}
pIn += pitch;
}
}
break;
case D3DFMT_L8:
case D3DFMT_A8:
case D3DFMT_A4L4:
{
const u8 *pIn = buffer;
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width);
pIn += pitch;
}
}
break;
case D3DFMT_R5G6B5:
{
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
break;
case D3DFMT_A8L8:
{
if (bExpand) { // I8
const u8 *pIn = buffer;
// TODO(XK): Find a better way that does not involve either unpacking
// or downsampling (i.e. A4L4)
for (int y = 0; y < height; y++)
{
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
for(int i = 0; i < width * 2; i += 2) {
pBits[i] = pIn[i / 2];
pBits[i + 1] = pIn[i / 2];
}
pIn += pitch;
}
} else { // IA8
const u16 *pIn = (u16*)buffer;
for (int y = 0; y < height; y++)
{
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
memcpy(pBits, pIn, width * 2);
pIn += pitch;
}
}
}
break;
case D3DFMT_DXT1:
memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
break;
}
pTexture->UnlockRect(level);
}
} // namespace
}
@@ -1,34 +1,34 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "DX9_D3DBase.h"
namespace DX9
{
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);
}
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "DX9_D3DBase.h"
namespace DX9
{
namespace D3D
{
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt = D3DFMT_A8R8G8B8, bool swap_r_b = false, int levels = 1);
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level = 0);
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height);
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height);
LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt);
}
}
@@ -1,447 +1,447 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "StringUtil.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DUtil.h"
#include "DX9_Render.h"
namespace DX9
{
namespace D3D
{
CD3DFont font;
#define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX {
float x,y,z;
float rhw;
u32 color;
float tu, tv;
};
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv)
{
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
return v;
}
CD3DFont::CD3DFont()
{
m_pTexture = NULL;
m_pVB = NULL;
}
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
int CD3DFont::Init()
{
// Create vertex buffer for the letters
HRESULT hr;
if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL)))
{
return hr;
}
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Prepare to create a bitmap
int *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.
// We definitely don't want to get it cleartype'd, anyway.
int m_dwFontHeight = 24;
int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72);
int dwBold = FW_NORMAL; ///FW_BOLD
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, _T("Tahoma"));
if (NULL == hFont)
return E_FAIL;
HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap);
HGDIOBJ hOldFont = SelectObject(hDC, hFont);
// Set text properties
SetTextColor(hDC, 0xFFFFFF);
SetBkColor (hDC, 0);
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.
int x = 0, y = 0;
char str[2] = "\0";
for (int c = 0; c < 127 - 32; c++)
{
str[0] = c + 32;
SIZE size;
GetTextExtentPoint32A(hDC, str, 1, &size);
if ((int)(x+size.cx+1) > m_dwTexWidth)
{
x = 0;
y += size.cy + 1;
}
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
x += size.cx + 3; //3 to work around annoying ij conflict (part of the j ends up with the i)
}
// Create a new texture for the font
hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC,
D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL);
if (FAILED(hr))
{
PanicAlert("Failed to create font texture");
return hr;
}
// Lock the surface and write the alpha values for the set pixels
D3DLOCKED_RECT d3dlr;
m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD);
int bAlpha; // 4-bit measure of pixel intensity
for (y = 0; y < m_dwTexHeight; y++)
{
u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch);
for (x = 0; x < m_dwTexWidth; x++)
{
bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4);
pDst16[x] = (bAlpha << 12) | 0x0fff;
}
}
// Done updating texture, so clean up used objects
m_pTexture->UnlockRect(0);
SelectObject(hDC, hOldbmBitmap);
DeleteObject(hbmBitmap);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
return S_OK;
}
int CD3DFont::Shutdown()
{
m_pVB->Release();
m_pVB = NULL;
m_pTexture->Release();
m_pTexture = NULL;
return S_OK;
}
const int RS[6][2] =
{
{D3DRS_ALPHABLENDENABLE, TRUE},
{D3DRS_SRCBLEND, D3DBLEND_SRCALPHA},
{D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA},
{D3DRS_CULLMODE, D3DCULL_NONE},
{D3DRS_ZENABLE, FALSE},
{D3DRS_FOGENABLE, FALSE},
};
const int TS[6][2] =
{
{D3DTSS_COLOROP, D3DTOP_MODULATE},
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
};
static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
void RestoreShaders()
{
D3D::SetTexture(0, 0);
D3D::RefreshVertexDeclaration();
D3D::RefreshPixelShader();
D3D::RefreshVertexShader();
}
void RestoreRenderStates()
{
RestoreShaders();
for (int i = 0; i < 6; i++)
{
D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]);
D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]));
}
}
void CD3DFont::SetRenderStates()
{
D3D::SetTexture(0, m_pTexture);
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++)
{
D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]);
D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
}
}
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center)
{
if (!m_pVB)
return 0;
SetRenderStates();
dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
float vpWidth = 1;
float vpHeight = 1;
float sx = x*vpWidth-0.5f;
float sy = y*vpHeight-0.5f;
float fStartX = sx;
float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight);
// Fill vertex buffer
FONT2DVERTEX* pVertices;
int dwNumTriangles = 0L;
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
const char *oldstrText=strText;
//First, let's measure the text
float tw=0;
float mx=0;
float maxx=0;
while (*strText)
{
char c = *strText++;
if (c == ('\n'))
mx = 0;
if (c < (' '))
continue;
float tx1 = m_fTexCoords[c-32][0];
float tx2 = m_fTexCoords[c-32][2];
float w = (tx2-tx1)*m_dwTexWidth;
w *= (fXScale*vpHeight)*invLineHeight;
mx += w + spacing*fXScale*vpWidth;
if (mx > maxx) maxx = mx;
}
float offset = -maxx/2;
strText = oldstrText;
//Then let's draw it
if (center)
{
sx+=offset;
fStartX+=offset;
}
float wScale = (fXScale*vpHeight)*invLineHeight;
float hScale = (fYScale*vpHeight)*invLineHeight;
while (*strText)
{
char c = *strText++;
if (c == ('\n'))
{
sx = fStartX;
sy += fYScale*vpHeight;
}
if (c < (' '))
continue;
c-=32;
float tx1 = m_fTexCoords[c][0];
float ty1 = m_fTexCoords[c][1];
float tx2 = m_fTexCoords[c][2];
float ty2 = m_fTexCoords[c][3];
float w = (tx2-tx1)*m_dwTexWidth;
float h = (ty2-ty1)*m_dwTexHeight;
w *= wScale;
h *= hScale;
FONT2DVERTEX v[6];
v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
v[4] = v[2];
v[5] = v[1];
memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX));
pVertices+=6;
dwNumTriangles += 2;
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
{
// Unlock, render, and relock the vertex buffer
m_pVB->Unlock();
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
dwNumTriangles = 0;
}
sx += w + spacing*fXScale*vpWidth;
}
// Unlock and render the vertex buffer
m_pVB->Unlock();
if (dwNumTriangles > 0)
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
RestoreRenderStates();
return S_OK;
}
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
{
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
};
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(NULL);
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
void drawShadedTexQuad(IDirect3DTexture9 *texture,
const RECT *rSource,
int SourceWidth,
int SourceHeight,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
float dw = 1.0f /(float) DestWidth;
float dh = 1.0f /(float) DestHeight;
float u1=((float)rSource->left) * sw;
float u2=((float)rSource->right) * sw;
float v1=((float)rSource->top) * sh;
float v2=((float)rSource->bottom) * sh;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);
D3D::SetTexture(0, texture);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
const MathUtil::Rectangle<float> *rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float> *rDest,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
float dw = 1.0f /(float) DestWidth;
float dh = 1.0f /(float) DestHeight;
float u1= rSource->left * sw;
float u2= rSource->right * sw;
float v1= rSource->top * sh;
float v2= rSource->bottom * sh;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
{ rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);
D3D::SetTexture(0, texture);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
{
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
{-1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, -1.0f, z, 1.0f, Color},
{-1.0f, -1.0f, z, 1.0f, Color}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
} // namespace
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "StringUtil.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DUtil.h"
#include "DX9_Render.h"
namespace DX9
{
namespace D3D
{
CD3DFont font;
#define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX {
float x,y,z;
float rhw;
u32 color;
float tu, tv;
};
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, float tv)
{
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
return v;
}
CD3DFont::CD3DFont()
{
m_pTexture = NULL;
m_pVB = NULL;
}
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
int CD3DFont::Init()
{
// Create vertex buffer for the letters
HRESULT hr;
if (FAILED(hr = dev->CreateVertexBuffer(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVB, NULL)))
{
return hr;
}
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Prepare to create a bitmap
int *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.
// We definitely don't want to get it cleartype'd, anyway.
int m_dwFontHeight = 24;
int nHeight = -MulDiv(m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72);
int dwBold = FW_NORMAL; ///FW_BOLD
HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0,
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, _T("Tahoma"));
if (NULL == hFont)
return E_FAIL;
HGDIOBJ hOldbmBitmap = SelectObject(hDC, hbmBitmap);
HGDIOBJ hOldFont = SelectObject(hDC, hFont);
// Set text properties
SetTextColor(hDC, 0xFFFFFF);
SetBkColor (hDC, 0);
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.
int x = 0, y = 0;
char str[2] = "\0";
for (int c = 0; c < 127 - 32; c++)
{
str[0] = c + 32;
SIZE size;
GetTextExtentPoint32A(hDC, str, 1, &size);
if ((int)(x+size.cx+1) > m_dwTexWidth)
{
x = 0;
y += size.cy + 1;
}
ExtTextOutA(hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL);
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
x += size.cx + 3; //3 to work around annoying ij conflict (part of the j ends up with the i)
}
// Create a new texture for the font
hr = dev->CreateTexture(m_dwTexWidth, m_dwTexHeight, 1, D3DUSAGE_DYNAMIC,
D3DFMT_A4R4G4B4, D3DPOOL_DEFAULT, &m_pTexture, NULL);
if (FAILED(hr))
{
PanicAlert("Failed to create font texture");
return hr;
}
// Lock the surface and write the alpha values for the set pixels
D3DLOCKED_RECT d3dlr;
m_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD);
int bAlpha; // 4-bit measure of pixel intensity
for (y = 0; y < m_dwTexHeight; y++)
{
u16 *pDst16 = (u16*)((u8 *)d3dlr.pBits + y * d3dlr.Pitch);
for (x = 0; x < m_dwTexWidth; x++)
{
bAlpha = ((pBitmapBits[m_dwTexWidth * y + x] & 0xff) >> 4);
pDst16[x] = (bAlpha << 12) | 0x0fff;
}
}
// Done updating texture, so clean up used objects
m_pTexture->UnlockRect(0);
SelectObject(hDC, hOldbmBitmap);
DeleteObject(hbmBitmap);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
return S_OK;
}
int CD3DFont::Shutdown()
{
m_pVB->Release();
m_pVB = NULL;
m_pTexture->Release();
m_pTexture = NULL;
return S_OK;
}
const int RS[6][2] =
{
{D3DRS_ALPHABLENDENABLE, TRUE},
{D3DRS_SRCBLEND, D3DBLEND_SRCALPHA},
{D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA},
{D3DRS_CULLMODE, D3DCULL_NONE},
{D3DRS_ZENABLE, FALSE},
{D3DRS_FOGENABLE, FALSE},
};
const int TS[6][2] =
{
{D3DTSS_COLOROP, D3DTOP_MODULATE},
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
};
static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
void RestoreShaders()
{
D3D::SetTexture(0, 0);
D3D::RefreshVertexDeclaration();
D3D::RefreshPixelShader();
D3D::RefreshVertexShader();
}
void RestoreRenderStates()
{
RestoreShaders();
for (int i = 0; i < 6; i++)
{
D3D::RefreshRenderState((_D3DRENDERSTATETYPE)RS[i][0]);
D3D::RefreshTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]));
}
}
void CD3DFont::SetRenderStates()
{
D3D::SetTexture(0, m_pTexture);
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetFVF(D3DFVF_FONT2DVERTEX);
for (int i = 0; i < 6; i++)
{
D3D::ChangeRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS[i][1]);
D3D::ChangeTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
}
}
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center)
{
if (!m_pVB)
return 0;
SetRenderStates();
dev->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX));
float vpWidth = 1;
float vpHeight = 1;
float sx = x*vpWidth-0.5f;
float sy = y*vpHeight-0.5f;
float fStartX = sx;
float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight);
// Fill vertex buffer
FONT2DVERTEX* pVertices;
int dwNumTriangles = 0L;
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
const char *oldstrText=strText;
//First, let's measure the text
float tw=0;
float mx=0;
float maxx=0;
while (*strText)
{
char c = *strText++;
if (c == ('\n'))
mx = 0;
if (c < (' '))
continue;
float tx1 = m_fTexCoords[c-32][0];
float tx2 = m_fTexCoords[c-32][2];
float w = (tx2-tx1)*m_dwTexWidth;
w *= (fXScale*vpHeight)*invLineHeight;
mx += w + spacing*fXScale*vpWidth;
if (mx > maxx) maxx = mx;
}
float offset = -maxx/2;
strText = oldstrText;
//Then let's draw it
if (center)
{
sx+=offset;
fStartX+=offset;
}
float wScale = (fXScale*vpHeight)*invLineHeight;
float hScale = (fYScale*vpHeight)*invLineHeight;
while (*strText)
{
char c = *strText++;
if (c == ('\n'))
{
sx = fStartX;
sy += fYScale*vpHeight;
}
if (c < (' '))
continue;
c-=32;
float tx1 = m_fTexCoords[c][0];
float ty1 = m_fTexCoords[c][1];
float tx2 = m_fTexCoords[c][2];
float ty2 = m_fTexCoords[c][3];
float w = (tx2-tx1)*m_dwTexWidth;
float h = (ty2-ty1)*m_dwTexHeight;
w *= wScale;
h *= hScale;
FONT2DVERTEX v[6];
v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
v[4] = v[2];
v[5] = v[1];
memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX));
pVertices+=6;
dwNumTriangles += 2;
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
{
// Unlock, render, and relock the vertex buffer
m_pVB->Unlock();
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
dwNumTriangles = 0;
}
sx += w + spacing*fXScale*vpWidth;
}
// Unlock and render the vertex buffer
m_pVB->Unlock();
if (dwNumTriangles > 0)
dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles);
RestoreRenderStates();
return S_OK;
}
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
{
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
};
dev->SetPixelShader(0);
dev->SetVertexShader(0);
dev->SetVertexDeclaration(NULL);
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
void drawShadedTexQuad(IDirect3DTexture9 *texture,
const RECT *rSource,
int SourceWidth,
int SourceHeight,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
float dw = 1.0f /(float) DestWidth;
float dh = 1.0f /(float) DestHeight;
float u1=((float)rSource->left) * sw;
float u2=((float)rSource->right) * sw;
float v1=((float)rSource->top) * sh;
float v2=((float)rSource->bottom) * sh;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
{ 1.0f - dw, 1.0f + dh, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);
D3D::SetTexture(0, texture);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
const MathUtil::Rectangle<float> *rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float> *rDest,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
float dw = 1.0f /(float) DestWidth;
float dh = 1.0f /(float) DestHeight;
float u1= rSource->left * sw;
float u2= rSource->right * sw;
float v1= rSource->top * sh;
float v2= rSource->bottom * sh;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2},
{ rDest->left - dw , rDest->bottom + dh, 1.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
{ rDest->right - dw , rDest->top + dh, 1.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
{ rDest->right - dw , rDest->bottom + dh, 1.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);
D3D::SetTexture(0, texture);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
{
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
{-1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, -1.0f, z, 1.0f, Color},
{-1.0f, -1.0f, z, 1.0f, Color}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);
dev->SetFVF(D3DFVF_XYZW | D3DFVF_DIFFUSE);
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
RestoreShaders();
}
} // namespace
}
@@ -1,88 +1,88 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "DX9_D3DBase.h"
#include <math.h>
#include <MathUtil.h>
namespace DX9
{
namespace D3D
{
// Font creation flags
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
// Font rendering flags
#define D3DFONT_CENTERED 0x0001
//a cut-down variant of the DXSDK CD3DFont class
class CD3DFont
{
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
//int m_dwTexWidth; // Texture dimensions
//int m_dwTexHeight;
float m_fTextScale;
float m_fTexCoords[128-32][4];
public:
CD3DFont();
// 2D (no longer 3D) text drawing function
// Initializing and destroying device-dependent objects
void SetRenderStates();
int Init();
int Shutdown();
int DrawTextScaled( float x, float y,
float fXScale, float fYScale,
float spacing, u32 dwColor,
const char* strText, bool center=true );
// Constructor / destructor
//~CD3DFont();
};
extern CD3DFont font;
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1);
void drawShadedTexQuad(IDirect3DTexture9 *texture,
const RECT *rSource,
int SourceWidth,
int SourceHeight,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader);
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
const MathUtil::Rectangle<float> *rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float> *rDest,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader);
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader);
void SaveRenderStates();
void RestoreRenderStates();
}
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "DX9_D3DBase.h"
#include <math.h>
#include <MathUtil.h>
namespace DX9
{
namespace D3D
{
// Font creation flags
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
// Font rendering flags
#define D3DFONT_CENTERED 0x0001
//a cut-down variant of the DXSDK CD3DFont class
class CD3DFont
{
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
//int m_dwTexWidth; // Texture dimensions
//int m_dwTexHeight;
float m_fTextScale;
float m_fTexCoords[128-32][4];
public:
CD3DFont();
// 2D (no longer 3D) text drawing function
// Initializing and destroying device-dependent objects
void SetRenderStates();
int Init();
int Shutdown();
int DrawTextScaled( float x, float y,
float fXScale, float fYScale,
float spacing, u32 dwColor,
const char* strText, bool center=true );
// Constructor / destructor
//~CD3DFont();
};
extern CD3DFont font;
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1);
void drawShadedTexQuad(IDirect3DTexture9 *texture,
const RECT *rSource,
int SourceWidth,
int SourceHeight,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader);
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
const MathUtil::Rectangle<float> *rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float> *rDest,
int DestWidth,
int DestHeight,
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader);
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader);
void SaveRenderStates();
void RestoreRenderStates();
}
}
@@ -1,285 +1,285 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h"
#include "DX9_Render.h"
#include "DX9_FramebufferManager.h"
#include "VideoConfig.h"
#include "DX9_PixelShaderCache.h"
#include "DX9_VertexShaderCache.h"
#include "DX9_TextureConverter.h"
#include "../Main.h"
#undef CHECK
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
namespace DX9
{
XFBSource FramebufferManager::m_realXFBSource;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_color_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_colorRead_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depth_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depthRead_texture;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_surface;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_surface;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_ReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_ReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_OffScreenReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_OffScreenReadBuffer;
D3DFORMAT FramebufferManager::s_efb_color_surface_Format;
D3DFORMAT FramebufferManager::s_efb_depth_surface_Format;
D3DFORMAT FramebufferManager::s_efb_depth_ReadBuffer_Format;
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
{
return s_efb_color_surface;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
{
return s_efb_depth_surface;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
{
return s_efb_color_OffScreenReadBuffer;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
{
return s_efb_depth_OffScreenReadBuffer;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
{
return s_efb_color_ReadBuffer;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
{
return s_efb_depth_ReadBuffer;
}
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat()
{
return s_efb_depth_surface_Format;
}
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat()
{
return s_efb_depth_ReadBuffer_Format;
}
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat()
{
return s_efb_color_surface_Format;
}
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
{
return s_efb_color_texture;
}
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc)
{
return s_efb_depth_texture;
}
FramebufferManager::FramebufferManager()
{
s_efb_color_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL;
LPDIRECT3DSURFACE9 s_efb_color_surface = NULL;
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL;
D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
m_realXFBSource.texture = NULL;
// Simplest possible setup to start with.
int target_width = Renderer::GetFullTargetWidth();
int target_height = Renderer::GetFullTargetHeight();
s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
// Get the framebuffer texture
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
if(s_efb_color_texture)
{
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
}
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL);
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
if(s_efb_colorRead_texture)
{
s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
}
// Create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL);
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
// Select a Z-buffer format with hardware support
D3DFORMAT *DepthTexFormats = new D3DFORMAT[5];
DepthTexFormats[0] = FOURCC_INTZ;
DepthTexFormats[1] = FOURCC_DF24;
DepthTexFormats[2] = FOURCC_RAWZ;
DepthTexFormats[3] = FOURCC_DF16;
DepthTexFormats[4] = D3DFMT_D24X8;
for(int i = 0; i < 5; i++)
{
s_efb_depth_surface_Format = DepthTexFormats[i];
// Create the framebuffer depth texture
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
if (!FAILED(hr))
break;
}
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
// Get the Surface
if(s_efb_depth_texture)
{
s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
}
// Create a 4x4 pixel texture to work as a buffer for peeking
if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8)
{
DepthTexFormats[0] = D3DFMT_A8R8G8B8;
}
else
{
DepthTexFormats[0] = D3DFMT_R32F;
}
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
for(int i = 0; i < 2; i++)
{
s_efb_depth_ReadBuffer_Format = DepthTexFormats[i];
// Get the framebuffer Depth texture
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format,
D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL);
if (!FAILED(hr))
break;
}
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
if(s_efb_depthRead_texture)
{
s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
}
// Create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL);
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
delete [] DepthTexFormats;
}
FramebufferManager::~FramebufferManager()
{
SAFE_RELEASE(s_efb_depth_surface);
SAFE_RELEASE(s_efb_color_surface);
SAFE_RELEASE(s_efb_color_ReadBuffer);
SAFE_RELEASE(s_efb_depth_ReadBuffer);
SAFE_RELEASE(s_efb_color_OffScreenReadBuffer);
SAFE_RELEASE(s_efb_depth_OffScreenReadBuffer);
SAFE_RELEASE(s_efb_color_texture);
SAFE_RELEASE(s_efb_colorRead_texture);
SAFE_RELEASE(s_efb_depth_texture);
SAFE_RELEASE(s_efb_depthRead_texture);
if (m_realXFBSource.texture)
m_realXFBSource.texture->Release();
m_realXFBSource.texture = NULL;
}
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
// TODO:
//u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
//if (!xfb_in_ram)
//{
// WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
// return;
//}
//TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
//TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
}
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
return NULL;
// TODO:
//xfbCount = 1;
//m_realXFBSource.texWidth = fbWidth;
//m_realXFBSource.texHeight = fbHeight;
//m_realXFBSource.srcAddr = xfbAddr;
//m_realXFBSource.srcWidth = fbWidth;
//m_realXFBSource.srcHeight = fbHeight;
//if (!m_realXFBSource.texture)
//{
// D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
// D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
//}
//// Decode YUYV data from GameCube RAM
//TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
//m_overlappingXFBArray[0] = &m_realXFBSource;
//return &m_overlappingXFBArray[0];
}
XFBSourceBase *FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{
XFBSource* const xfbs = new XFBSource;
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &xfbs->texture, NULL);
return xfbs;
}
XFBSource::~XFBSource()
{
texture->Release();
}
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
{
}
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h"
#include "DX9_Render.h"
#include "DX9_FramebufferManager.h"
#include "VideoConfig.h"
#include "DX9_PixelShaderCache.h"
#include "DX9_VertexShaderCache.h"
#include "DX9_TextureConverter.h"
#include "../Main.h"
#undef CHECK
#define CHECK(hr, Message, ...) if (FAILED(hr)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
namespace DX9
{
XFBSource FramebufferManager::m_realXFBSource;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_color_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_colorRead_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depth_texture;
LPDIRECT3DTEXTURE9 FramebufferManager::s_efb_depthRead_texture;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_surface;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_surface;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_ReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_ReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_color_OffScreenReadBuffer;
LPDIRECT3DSURFACE9 FramebufferManager::s_efb_depth_OffScreenReadBuffer;
D3DFORMAT FramebufferManager::s_efb_color_surface_Format;
D3DFORMAT FramebufferManager::s_efb_depth_surface_Format;
D3DFORMAT FramebufferManager::s_efb_depth_ReadBuffer_Format;
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
{
return s_efb_color_surface;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
{
return s_efb_depth_surface;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
{
return s_efb_color_OffScreenReadBuffer;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
{
return s_efb_depth_OffScreenReadBuffer;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
{
return s_efb_color_ReadBuffer;
}
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
{
return s_efb_depth_ReadBuffer;
}
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat()
{
return s_efb_depth_surface_Format;
}
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat()
{
return s_efb_depth_ReadBuffer_Format;
}
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat()
{
return s_efb_color_surface_Format;
}
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
{
return s_efb_color_texture;
}
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc)
{
return s_efb_depth_texture;
}
FramebufferManager::FramebufferManager()
{
s_efb_color_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL;
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL;
LPDIRECT3DSURFACE9 s_efb_color_surface = NULL;
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL;
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL;
D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
m_realXFBSource.texture = NULL;
// Simplest possible setup to start with.
int target_width = Renderer::GetFullTargetWidth();
int target_height = Renderer::GetFullTargetHeight();
s_efb_color_surface_Format = D3DFMT_A8R8G8B8;
// Get the framebuffer texture
HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &s_efb_color_texture, NULL);
if(s_efb_color_texture)
{
hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface);
}
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL);
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
if(s_efb_colorRead_texture)
{
s_efb_colorRead_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer);
}
// Create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL);
CHECK(hr, "Create offscreen color surface (hr=%#x)", hr);
// Select a Z-buffer format with hardware support
D3DFORMAT *DepthTexFormats = new D3DFORMAT[5];
DepthTexFormats[0] = FOURCC_INTZ;
DepthTexFormats[1] = FOURCC_DF24;
DepthTexFormats[2] = FOURCC_RAWZ;
DepthTexFormats[3] = FOURCC_DF16;
DepthTexFormats[4] = D3DFMT_D24X8;
for(int i = 0; i < 5; i++)
{
s_efb_depth_surface_Format = DepthTexFormats[i];
// Create the framebuffer depth texture
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format,
D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL);
if (!FAILED(hr))
break;
}
CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
// Get the Surface
if(s_efb_depth_texture)
{
s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface);
}
// Create a 4x4 pixel texture to work as a buffer for peeking
if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8)
{
DepthTexFormats[0] = D3DFMT_A8R8G8B8;
}
else
{
DepthTexFormats[0] = D3DFMT_R32F;
}
DepthTexFormats[1] = D3DFMT_A8R8G8B8;
for(int i = 0; i < 2; i++)
{
s_efb_depth_ReadBuffer_Format = DepthTexFormats[i];
// Get the framebuffer Depth texture
hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format,
D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL);
if (!FAILED(hr))
break;
}
CHECK(hr, "Create depth read texture (hr=%#x)", hr);
if(s_efb_depthRead_texture)
{
s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer);
}
// Create an offscreen surface that we can lock to retrieve the data
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL);
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
delete [] DepthTexFormats;
}
FramebufferManager::~FramebufferManager()
{
SAFE_RELEASE(s_efb_depth_surface);
SAFE_RELEASE(s_efb_color_surface);
SAFE_RELEASE(s_efb_color_ReadBuffer);
SAFE_RELEASE(s_efb_depth_ReadBuffer);
SAFE_RELEASE(s_efb_color_OffScreenReadBuffer);
SAFE_RELEASE(s_efb_depth_OffScreenReadBuffer);
SAFE_RELEASE(s_efb_color_texture);
SAFE_RELEASE(s_efb_colorRead_texture);
SAFE_RELEASE(s_efb_depth_texture);
SAFE_RELEASE(s_efb_depthRead_texture);
if (m_realXFBSource.texture)
m_realXFBSource.texture->Release();
m_realXFBSource.texture = NULL;
}
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
// TODO:
//u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
//if (!xfb_in_ram)
//{
// WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
// return;
//}
//TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
//TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
}
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
return NULL;
// TODO:
//xfbCount = 1;
//m_realXFBSource.texWidth = fbWidth;
//m_realXFBSource.texHeight = fbHeight;
//m_realXFBSource.srcAddr = xfbAddr;
//m_realXFBSource.srcWidth = fbWidth;
//m_realXFBSource.srcHeight = fbHeight;
//if (!m_realXFBSource.texture)
//{
// D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
// D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
//}
//// Decode YUYV data from GameCube RAM
//TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
//m_overlappingXFBArray[0] = &m_realXFBSource;
//return &m_overlappingXFBArray[0];
}
XFBSourceBase *FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
{
XFBSource* const xfbs = new XFBSource;
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
D3DPOOL_DEFAULT, &xfbs->texture, NULL);
return xfbs;
}
XFBSource::~XFBSource()
{
texture->Release();
}
void XFBSource::CopyEFB(const TargetRectangle& efbSource)
{
}
}
@@ -1,130 +1,130 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _FRAMEBUFFERMANAGER_D3D_H_
#define _FRAMEBUFFERMANAGER_D3D_H_
#include <list>
#include "DX9_D3DBase.h"
#include "../FramebufferManager.h"
// On the GameCube, the game sends a request for the graphics processor to
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
// called the XFB (External Framebuffer). The size and location of the XFB is
// decided at the time of the copy, and the format is always YUYV. The video
// interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV.
//
// There are two ways for Dolphin to emulate this:
//
// Real XFB mode:
//
// Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen.
//
// Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited.
//
// Virtual XFB mode:
//
// When a request is made to copy the EFB to an XFB, Dolphin
// will remember the RAM location and size of the XFB in a Virtual XFB list.
// The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available.
//
// Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// possible but uncommon), the Virtual XFB will not capture this information.
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize.
namespace DX9
{
const int MAX_VIRTUAL_XFB = 8;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return !((aLower >= bUpper) || (bLower >= aUpper));
}
struct XFBSource : public XFBSourceBase
{
XFBSource() : texture(NULL) {}
~XFBSource();
void CopyEFB(const TargetRectangle& efbSource);
LPDIRECT3DTEXTURE9 texture;
};
class FramebufferManager : public ::FramebufferManagerBase
{
public:
FramebufferManager();
~FramebufferManager();
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
XFBSourceBase *CreateXFBSource(unsigned int target_width, unsigned int target_height);
static LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
static D3DFORMAT GetEFBDepthRTSurfaceFormat();
static D3DFORMAT GetEFBColorRTSurfaceFormat();
static D3DFORMAT GetEFBDepthReadSurfaceFormat();
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
private:
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static XFBSource m_realXFBSource; // Only used in Real XFB mode
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
};
}
#endif
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _FRAMEBUFFERMANAGER_D3D_H_
#define _FRAMEBUFFERMANAGER_D3D_H_
#include <list>
#include "DX9_D3DBase.h"
#include "../FramebufferManager.h"
// On the GameCube, the game sends a request for the graphics processor to
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
// called the XFB (External Framebuffer). The size and location of the XFB is
// decided at the time of the copy, and the format is always YUYV. The video
// interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV.
//
// There are two ways for Dolphin to emulate this:
//
// Real XFB mode:
//
// Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen.
//
// Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited.
//
// Virtual XFB mode:
//
// When a request is made to copy the EFB to an XFB, Dolphin
// will remember the RAM location and size of the XFB in a Virtual XFB list.
// The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available.
//
// Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// possible but uncommon), the Virtual XFB will not capture this information.
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize.
namespace DX9
{
const int MAX_VIRTUAL_XFB = 8;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return !((aLower >= bUpper) || (bLower >= aUpper));
}
struct XFBSource : public XFBSourceBase
{
XFBSource() : texture(NULL) {}
~XFBSource();
void CopyEFB(const TargetRectangle& efbSource);
LPDIRECT3DTEXTURE9 texture;
};
class FramebufferManager : public ::FramebufferManagerBase
{
public:
FramebufferManager();
~FramebufferManager();
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
XFBSourceBase *CreateXFBSource(unsigned int target_width, unsigned int target_height);
static LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
static LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
static LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
static LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
static D3DFORMAT GetEFBDepthRTSurfaceFormat();
static D3DFORMAT GetEFBColorRTSurfaceFormat();
static D3DFORMAT GetEFBDepthReadSurfaceFormat();
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
private:
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
const XFBSource** getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
static XFBSource m_realXFBSource; // Only used in Real XFB mode
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
};
}
#endif
@@ -1,178 +1,178 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h"
#include "Profiler.h"
#include "x64Emitter.h"
#include "ABI.h"
#include "MemoryUtil.h"
#include "VertexShaderGen.h"
#include "CPMemory.h"
#include "DX9_VertexManager.h"
namespace DX9
{
class D3DVertexFormat : public NativeVertexFormat
{
LPDIRECT3DVERTEXDECLARATION9 d3d_decl;
public:
D3DVertexFormat();
~D3DVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers() const;
};
NativeVertexFormat *VertexManager::CreateNativeVertexFormat()
{
return new D3DVertexFormat();
}
D3DVertexFormat::D3DVertexFormat() : d3d_decl(NULL)
{
}
D3DVertexFormat::~D3DVertexFormat()
{
if (d3d_decl)
{
d3d_decl->Release();
d3d_decl = NULL;
}
}
D3DDECLTYPE VarToD3D(VarType t, int size)
{
if (t < 0 || t > 4) {
PanicAlert("VarToD3D: Invalid VarType %i", t);
}
static const D3DDECLTYPE lookup1[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1,
};
static const D3DDECLTYPE lookup2[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2,
};
static const D3DDECLTYPE lookup3[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3,
};
// Sadly, D3D9 has no SBYTE4N. D3D10 does, though.
static const D3DDECLTYPE lookup4[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4,
};
D3DDECLTYPE retval = D3DDECLTYPE_UNUSED;
switch (size) {
case 1: retval = lookup1[t]; break;
case 2: retval = lookup2[t]; break;
case 3: retval = lookup3[t]; break;
case 4: retval = lookup4[t]; break;
default: PanicAlert("VarToD3D: size wrong (%i)", size); break;
}
if (retval == D3DDECLTYPE_UNUSED) {
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
}
return retval;
}
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{
vertex_stride = _vtx_decl.stride;
D3DVERTEXELEMENT9 *elems = new D3DVERTEXELEMENT9[32];
memset(elems, 0, sizeof(D3DVERTEXELEMENT9) * 32);
// There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream.
// Same for method.
// So, here we go. First position:
int elem_idx = 0;
elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3.
elems[elem_idx].Type = D3DDECLTYPE_FLOAT3;
elems[elem_idx].Usage = D3DDECLUSAGE_POSITION;
++elem_idx;
for (int i = 0; i < 3; i++)
{
if (_vtx_decl.normal_offset[i] > 0)
{
elems[elem_idx].Offset = _vtx_decl.normal_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL;
elems[elem_idx].UsageIndex = i;
++elem_idx;
}
}
for (int i = 0; i < 2; i++)
{
if (_vtx_decl.color_offset[i] > 0)
{
elems[elem_idx].Offset = _vtx_decl.color_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4);
elems[elem_idx].Usage = D3DDECLUSAGE_COLOR;
elems[elem_idx].UsageIndex = i;
++elem_idx;
}
}
for (int i = 0; i < 8; i++)
{
if (_vtx_decl.texcoord_offset[i] > 0)
{
elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD;
elems[elem_idx].UsageIndex = i;
++elem_idx;
}
}
if (_vtx_decl.posmtx_offset != -1)
{
elems[elem_idx].Offset = _vtx_decl.posmtx_offset;
elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES;
elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR;
elems[elem_idx].UsageIndex = 0;
++elem_idx;
}
// End marker
elems[elem_idx].Stream = 0xff;
elems[elem_idx].Type = D3DDECLTYPE_UNUSED;
++elem_idx;
if (FAILED(D3D::dev->CreateVertexDeclaration(elems, &d3d_decl)))
{
PanicAlert("Failed to create D3D vertex declaration!");
return;
}
delete [] elems;
}
void D3DVertexFormat::SetupVertexPointers() const
{
if (d3d_decl)
D3D::SetVertexDeclaration(d3d_decl);
else
ERROR_LOG(VIDEO, "invalid d3d decl");
}
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DX9_D3DBase.h"
#include "Profiler.h"
#include "x64Emitter.h"
#include "ABI.h"
#include "MemoryUtil.h"
#include "VertexShaderGen.h"
#include "CPMemory.h"
#include "DX9_VertexManager.h"
namespace DX9
{
class D3DVertexFormat : public NativeVertexFormat
{
LPDIRECT3DVERTEXDECLARATION9 d3d_decl;
public:
D3DVertexFormat();
~D3DVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers() const;
};
NativeVertexFormat *VertexManager::CreateNativeVertexFormat()
{
return new D3DVertexFormat();
}
D3DVertexFormat::D3DVertexFormat() : d3d_decl(NULL)
{
}
D3DVertexFormat::~D3DVertexFormat()
{
if (d3d_decl)
{
d3d_decl->Release();
d3d_decl = NULL;
}
}
D3DDECLTYPE VarToD3D(VarType t, int size)
{
if (t < 0 || t > 4) {
PanicAlert("VarToD3D: Invalid VarType %i", t);
}
static const D3DDECLTYPE lookup1[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT1,
};
static const D3DDECLTYPE lookup2[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_FLOAT2,
};
static const D3DDECLTYPE lookup3[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_UNUSED, D3DDECLTYPE_FLOAT3,
};
// Sadly, D3D9 has no SBYTE4N. D3D10 does, though.
static const D3DDECLTYPE lookup4[5] = {
D3DDECLTYPE_UNUSED, D3DDECLTYPE_UBYTE4N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_FLOAT4,
};
D3DDECLTYPE retval = D3DDECLTYPE_UNUSED;
switch (size) {
case 1: retval = lookup1[t]; break;
case 2: retval = lookup2[t]; break;
case 3: retval = lookup3[t]; break;
case 4: retval = lookup4[t]; break;
default: PanicAlert("VarToD3D: size wrong (%i)", size); break;
}
if (retval == D3DDECLTYPE_UNUSED) {
PanicAlert("VarToD3D: Invalid type/size combo %i , %i", (int)t, size);
}
return retval;
}
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{
vertex_stride = _vtx_decl.stride;
D3DVERTEXELEMENT9 *elems = new D3DVERTEXELEMENT9[32];
memset(elems, 0, sizeof(D3DVERTEXELEMENT9) * 32);
// There's only one stream and it's 0, so the above memset takes care of that - no need to set Stream.
// Same for method.
// So, here we go. First position:
int elem_idx = 0;
elems[elem_idx].Offset = 0; // Positions are always first, at position 0. Always float3.
elems[elem_idx].Type = D3DDECLTYPE_FLOAT3;
elems[elem_idx].Usage = D3DDECLUSAGE_POSITION;
++elem_idx;
for (int i = 0; i < 3; i++)
{
if (_vtx_decl.normal_offset[i] > 0)
{
elems[elem_idx].Offset = _vtx_decl.normal_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
elems[elem_idx].Usage = D3DDECLUSAGE_NORMAL;
elems[elem_idx].UsageIndex = i;
++elem_idx;
}
}
for (int i = 0; i < 2; i++)
{
if (_vtx_decl.color_offset[i] > 0)
{
elems[elem_idx].Offset = _vtx_decl.color_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.color_gl_type, 4);
elems[elem_idx].Usage = D3DDECLUSAGE_COLOR;
elems[elem_idx].UsageIndex = i;
++elem_idx;
}
}
for (int i = 0; i < 8; i++)
{
if (_vtx_decl.texcoord_offset[i] > 0)
{
elems[elem_idx].Offset = _vtx_decl.texcoord_offset[i];
elems[elem_idx].Type = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
elems[elem_idx].Usage = D3DDECLUSAGE_TEXCOORD;
elems[elem_idx].UsageIndex = i;
++elem_idx;
}
}
if (_vtx_decl.posmtx_offset != -1)
{
elems[elem_idx].Offset = _vtx_decl.posmtx_offset;
elems[elem_idx].Usage = D3DDECLUSAGE_BLENDINDICES;
elems[elem_idx].Type = D3DDECLTYPE_D3DCOLOR;
elems[elem_idx].UsageIndex = 0;
++elem_idx;
}
// End marker
elems[elem_idx].Stream = 0xff;
elems[elem_idx].Type = D3DDECLTYPE_UNUSED;
++elem_idx;
if (FAILED(D3D::dev->CreateVertexDeclaration(elems, &d3d_decl)))
{
PanicAlert("Failed to create D3D vertex declaration!");
return;
}
delete [] elems;
}
void D3DVertexFormat::SetupVertexPointers() const
{
if (d3d_decl)
D3D::SetVertexDeclaration(d3d_decl);
else
ERROR_LOG(VIDEO, "invalid d3d decl");
}
}
@@ -1,392 +1,392 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <map>
#include <set>
#include "Common.h"
#include "Hash.h"
#include "FileUtil.h"
#include "LinearDiskCache.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DShader.h"
#include "Statistics.h"
#include "VideoConfig.h"
#include "PixelShaderGen.h"
#include "PixelShaderManager.h"
#include "DX9_PixelShaderCache.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
#include "ImageWrite.h"
#include "../Main.h"
//#include "Debugger/Debugger.h"
namespace DX9
{
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
static LinearDiskCache g_ps_disk_cache;
static std::set<u32> unique_shaders;
#define MAX_SSAA_SHADERS 3
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
{
return s_ColorMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
}
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode)
{
return s_DepthMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
}
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode)
{
return s_ColorCopyProgram[SSAAMode % MAX_SSAA_SHADERS];
}
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
{
return s_ClearProgram;
}
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
float f[4] = { f1, f2, f3, f4 };
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
}
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
{
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
}
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
D3D::dev->SetPixelShaderConstantF(const_number, f, count);
}
class PixelShaderCacheInserter : public LinearDiskCacheReader {
public:
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
{
PIXELSHADERUID uid;
if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
return;
}
memcpy(&uid, key, key_size);
PixelShaderCache::InsertByteCode(uid, value, value_size, false);
}
};
PixelShaderCache::PixelShaderCache()
{
//program used for clear screen
char pprog[3072];
sprintf(pprog, "void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float4 incol0 : COLOR0){\n"
"ocol0 = incol0;\n"
"}\n");
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Used for Copy/resolve the color buffer
//1 Sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float2 uv0 : TEXCOORD0){\n"
"ocol0 = tex2D(samp0,uv0);\n"
"}\n");
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 Samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n"
"ocol0 = tex2D(samp0,uv0.xy);\n"
"}\n");
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 Samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n"
"ocol0 = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25;\n"
"}\n");
s_ColorCopyProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Color conversion Programs
//1 sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = tex2D(samp0,uv0);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n"
"float4 texcol = tex2D(samp0,uv0.xy);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n"
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_ColorMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Depth copy programs
//1 sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = tex2D(samp0,uv0);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 sample SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n"
"float4 texcol = tex2D(samp0,uv0.xy);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 sample SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n"
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_DepthMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
Clear();
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
SETSTAT(stats.numPixelShadersCreated, 0);
SETSTAT(stats.numPixelShadersAlive, 0);
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
PixelShaderCacheInserter inserter;
int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
}
// ONLY to be used during shutdown.
void PixelShaderCache::Clear()
{
PSCache::iterator iter = PixelShaders.begin();
for (; iter != PixelShaders.end(); ++iter)
iter->second.Destroy();
PixelShaders.clear();
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
}
PixelShaderCache::~PixelShaderCache()
{
for(int i = 0;i < MAX_SSAA_SHADERS; i++)
{
if (s_ColorMatrixProgram[i]) s_ColorMatrixProgram[i]->Release();
s_ColorMatrixProgram[i] = NULL;
if (s_ColorCopyProgram[i]) s_ColorCopyProgram[i]->Release();
s_ColorCopyProgram[i] = NULL;
if (s_DepthMatrixProgram[i]) s_DepthMatrixProgram[i]->Release();
s_DepthMatrixProgram[i] = NULL;
}
if (s_ClearProgram) s_ClearProgram->Release();
s_ClearProgram = NULL;
Clear();
g_ps_disk_cache.Sync();
g_ps_disk_cache.Close();
unique_shaders.clear();
}
bool PixelShaderCache::SetShader(bool dstAlpha)
{
PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlpha);
// Is the shader already set?
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
{
PSCache::const_iterator iter = PixelShaders.find(uid);
if (iter != PixelShaders.end() && iter->second.shader)
return true; // Sure, we're done.
else
return false; // ?? something is wrong.
}
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
// Is the shader already in the cache?
PSCache::iterator iter;
iter = PixelShaders.find(uid);
if (iter != PixelShaders.end())
{
iter->second.frameCount = frameCount;
const PSCacheEntry &entry = iter->second;
last_entry = &entry;
if (entry.shader)
{
D3D::SetPixelShader(entry.shader);
return true;
}
else
return false;
}
// OK, need to generate and compile it.
const char *code = GeneratePixelShaderCode(dstAlpha, API_D3D9);
u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
unique_shaders.insert(code_hash);
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code);
}
#endif
u8 *bytecode = 0;
int bytecodelen = 0;
if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
if (g_ActiveConfig.bShowShaderErrors)
{
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code);
}
return false;
}
// Here we have the UID and the byte code. Insert it into the disk cache.
g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
g_ps_disk_cache.Sync();
// And insert it into the shader cache.
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode;
return result;
}
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
// Make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid];
if (!shader) {
// INCSTAT(stats.numPixelShadersFailed);
return false;
}
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
if (activate)
{
D3D::SetPixelShader(shader);
}
return true;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string PixelShaderCache::GetCurrentShaderCode()
{
if (last_entry)
return last_entry->code;
else
return "(no shader)\n";
}
#endif
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <map>
#include <set>
#include "Common.h"
#include "Hash.h"
#include "FileUtil.h"
#include "LinearDiskCache.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DShader.h"
#include "Statistics.h"
#include "VideoConfig.h"
#include "PixelShaderGen.h"
#include "PixelShaderManager.h"
#include "DX9_PixelShaderCache.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
#include "ImageWrite.h"
#include "../Main.h"
//#include "Debugger/Debugger.h"
namespace DX9
{
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
static LinearDiskCache g_ps_disk_cache;
static std::set<u32> unique_shaders;
#define MAX_SSAA_SHADERS 3
static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_DepthMatrixProgram[MAX_SSAA_SHADERS];
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
{
return s_ColorMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
}
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetDepthMatrixProgram(int SSAAMode)
{
return s_DepthMatrixProgram[SSAAMode % MAX_SSAA_SHADERS];
}
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram(int SSAAMode)
{
return s_ColorCopyProgram[SSAAMode % MAX_SSAA_SHADERS];
}
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
{
return s_ClearProgram;
}
void PixelShaderCache::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
float f[4] = { f1, f2, f3, f4 };
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
}
void PixelShaderCache::SetPSConstant4fv(unsigned int const_number, const float *f)
{
D3D::dev->SetPixelShaderConstantF(const_number, f, 1);
}
void PixelShaderCache::SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
D3D::dev->SetPixelShaderConstantF(const_number, f, count);
}
class PixelShaderCacheInserter : public LinearDiskCacheReader {
public:
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
{
PIXELSHADERUID uid;
if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in pixel shader cache");
return;
}
memcpy(&uid, key, key_size);
PixelShaderCache::InsertByteCode(uid, value, value_size, false);
}
};
PixelShaderCache::PixelShaderCache()
{
//program used for clear screen
char pprog[3072];
sprintf(pprog, "void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float4 incol0 : COLOR0){\n"
"ocol0 = incol0;\n"
"}\n");
s_ClearProgram = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Used for Copy/resolve the color buffer
//1 Sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float2 uv0 : TEXCOORD0){\n"
"ocol0 = tex2D(samp0,uv0);\n"
"}\n");
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 Samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n"
"ocol0 = tex2D(samp0,uv0.xy);\n"
"}\n");
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 Samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n"
"ocol0 = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25;\n"
"}\n");
s_ColorCopyProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Color conversion Programs
//1 sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = tex2D(samp0,uv0);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n"
"float4 texcol = tex2D(samp0,uv0.xy);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 samples SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n"
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_ColorMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//Depth copy programs
//1 sample
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float2 uv0 : TEXCOORD0){\n"
"float4 texcol = tex2D(samp0,uv0);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//1 sample SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1){\n"
"float4 texcol = tex2D(samp0,uv0.xy);\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
//4 sample SSAA
sprintf(pprog, "uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c%d);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 uv0 : TEXCOORD0,\n"
"in float4 uv1 : TEXCOORD1,\n"
"in float4 uv2 : TEXCOORD2,\n"
"in float4 uv3 : TEXCOORD3){\n"
"float4 texcol = (tex2D(samp0,uv1.xy) + tex2D(samp0,uv1.wz) + tex2D(samp0,uv2.xy) + tex2D(samp0,uv2.wz))*0.25f;\n"
"float4 EncodedDepth = frac((texcol.r * (16777215.0f/16777216.0f)) * float4(1.0f,255.0f,255.0f*255.0f,255.0f*255.0f*255.0f));\n"
"texcol = float4((EncodedDepth.rgb * (16777216.0f/16777215.0f)),1.0f);\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
"}\n",C_COLORMATRIX);
s_DepthMatrixProgram[2] = D3D::CompileAndCreatePixelShader(pprog, (int)strlen(pprog));
Clear();
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
SETSTAT(stats.numPixelShadersCreated, 0);
SETSTAT(stats.numPixelShadersAlive, 0);
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
PixelShaderCacheInserter inserter;
int read_items = g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
}
// ONLY to be used during shutdown.
void PixelShaderCache::Clear()
{
PSCache::iterator iter = PixelShaders.begin();
for (; iter != PixelShaders.end(); ++iter)
iter->second.Destroy();
PixelShaders.clear();
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
}
PixelShaderCache::~PixelShaderCache()
{
for(int i = 0;i < MAX_SSAA_SHADERS; i++)
{
if (s_ColorMatrixProgram[i]) s_ColorMatrixProgram[i]->Release();
s_ColorMatrixProgram[i] = NULL;
if (s_ColorCopyProgram[i]) s_ColorCopyProgram[i]->Release();
s_ColorCopyProgram[i] = NULL;
if (s_DepthMatrixProgram[i]) s_DepthMatrixProgram[i]->Release();
s_DepthMatrixProgram[i] = NULL;
}
if (s_ClearProgram) s_ClearProgram->Release();
s_ClearProgram = NULL;
Clear();
g_ps_disk_cache.Sync();
g_ps_disk_cache.Close();
unique_shaders.clear();
}
bool PixelShaderCache::SetShader(bool dstAlpha)
{
PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlpha);
// Is the shader already set?
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
{
PSCache::const_iterator iter = PixelShaders.find(uid);
if (iter != PixelShaders.end() && iter->second.shader)
return true; // Sure, we're done.
else
return false; // ?? something is wrong.
}
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
// Is the shader already in the cache?
PSCache::iterator iter;
iter = PixelShaders.find(uid);
if (iter != PixelShaders.end())
{
iter->second.frameCount = frameCount;
const PSCacheEntry &entry = iter->second;
last_entry = &entry;
if (entry.shader)
{
D3D::SetPixelShader(entry.shader);
return true;
}
else
return false;
}
// OK, need to generate and compile it.
const char *code = GeneratePixelShaderCode(dstAlpha, API_D3D9);
u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
unique_shaders.insert(code_hash);
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code);
}
#endif
u8 *bytecode = 0;
int bytecodelen = 0;
if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
if (g_ActiveConfig.bShowShaderErrors)
{
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code);
}
return false;
}
// Here we have the UID and the byte code. Insert it into the disk cache.
g_ps_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
g_ps_disk_cache.Sync();
// And insert it into the shader cache.
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode;
return result;
}
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
LPDIRECT3DPIXELSHADER9 shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
// Make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid];
if (!shader) {
// INCSTAT(stats.numPixelShadersFailed);
return false;
}
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
if (activate)
{
D3D::SetPixelShader(shader);
}
return true;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string PixelShaderCache::GetCurrentShaderCode()
{
if (last_entry)
return last_entry->code;
else
return "(no shader)\n";
}
#endif
}
@@ -1,89 +1,89 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _PIXELSHADERCACHE_H
#define _PIXELSHADERCACHE_H
#include "Common.h"
#include "LinearDiskCache.h"
#include "DX9_D3DBase.h"
#include <map>
#include "PixelShaderGen.h"
#include "VertexShaderGen.h"
#include "../PixelShaderCache.h"
namespace DX9
{
typedef u32 tevhash;
tevhash GetCurrentTEV();
class PixelShaderCache : public ::PixelShaderCacheBase
{
private:
struct PSCacheEntry
{
LPDIRECT3DPIXELSHADER9 shader;
bool owns_shader;
int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string code;
#endif
PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {}
void Destroy()
{
if (shader && owns_shader)
shader->Release();
shader = NULL;
}
};
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
static PSCache PixelShaders;
static const PSCacheEntry *last_entry;
static void Clear();
public:
PixelShaderCache();
~PixelShaderCache();
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetPSConstant4fv(unsigned int const_number, const float* f);
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
bool SetShader(bool dstAlpha);
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
#if defined(_DEBUG) || defined(DEBUGFAST)
static std::string GetCurrentShaderCode();
#endif
static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram);
};
}
#endif // _PIXELSHADERCACHE_H
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _PIXELSHADERCACHE_H
#define _PIXELSHADERCACHE_H
#include "Common.h"
#include "LinearDiskCache.h"
#include "DX9_D3DBase.h"
#include <map>
#include "PixelShaderGen.h"
#include "VertexShaderGen.h"
#include "../PixelShaderCache.h"
namespace DX9
{
typedef u32 tevhash;
tevhash GetCurrentTEV();
class PixelShaderCache : public ::PixelShaderCacheBase
{
private:
struct PSCacheEntry
{
LPDIRECT3DPIXELSHADER9 shader;
bool owns_shader;
int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string code;
#endif
PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {}
void Destroy()
{
if (shader && owns_shader)
shader->Release();
shader = NULL;
}
};
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
static PSCache PixelShaders;
static const PSCacheEntry *last_entry;
static void Clear();
public:
PixelShaderCache();
~PixelShaderCache();
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetPSConstant4fv(unsigned int const_number, const float* f);
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f);
bool SetShader(bool dstAlpha);
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode);
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
#if defined(_DEBUG) || defined(DEBUGFAST)
static std::string GetCurrentShaderCode();
#endif
static LPDIRECT3DPIXELSHADER9 CompileCgShader(const char *pstrprogram);
};
}
#endif // _PIXELSHADERCACHE_H
File diff suppressed because it is too large Load Diff
@@ -1,58 +1,58 @@
#pragma once
#include "MathUtil.h"
#include "VideoCommon.h"
#include "Renderer.h"
#include "pluginspecs_video.h"
namespace DX9
{
class Renderer : public ::RendererBase
{
public:
Renderer();
~Renderer();
void ResetAPIState();
void RestoreAPIState();
static void SetupDeviceObjects();
static void TeardownDeviceObjects();
void SetColorMask();
void SetBlendMode(bool forceUpdate);
bool SetScissorRect();
void SetGenerationMode();
void SetDepthMode();
void SetLogicOpMode();
void SetSamplerState(int stage,int texindex);
void SetDitherMode();
void SetLineWidth();
u32 AccessEFB(EFBAccessType type, int x, int y);
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
void UpdateViewport();
// virtual funcs used by RendererBase::Swap
void PrepareXFBCopy(const TargetRectangle &dst_rect);
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
void EndFrame();
void Present();
bool CheckForResize();
void GetBackBufferSize(int* w, int* h);
void RecreateFramebufferManger();
void BeginFrame();
void Swap(u32, FieldType, u32, u32, const EFBRectangle&);
private:
static bool IS_AMD;
};
}
#pragma once
#include "MathUtil.h"
#include "VideoCommon.h"
#include "Renderer.h"
#include "pluginspecs_video.h"
namespace DX9
{
class Renderer : public ::RendererBase
{
public:
Renderer();
~Renderer();
void ResetAPIState();
void RestoreAPIState();
static void SetupDeviceObjects();
static void TeardownDeviceObjects();
void SetColorMask();
void SetBlendMode(bool forceUpdate);
bool SetScissorRect();
void SetGenerationMode();
void SetDepthMode();
void SetLogicOpMode();
void SetSamplerState(int stage,int texindex);
void SetDitherMode();
void SetLineWidth();
u32 AccessEFB(EFBAccessType type, int x, int y);
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
void UpdateViewport();
// virtual funcs used by RendererBase::Swap
void PrepareXFBCopy(const TargetRectangle &dst_rect);
void Draw(const XFBSourceBase* xfbSource, const TargetRectangle& sourceRc,
const MathUtil::Rectangle<float>& drawRc, const EFBRectangle& rc);
void EndFrame();
void Present();
bool CheckForResize();
void GetBackBufferSize(int* w, int* h);
void RecreateFramebufferManger();
void BeginFrame();
void Swap(u32, FieldType, u32, u32, const EFBRectangle&);
private:
static bool IS_AMD;
};
}
@@ -1,207 +1,207 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include "Statistics.h"
#include "MemoryUtil.h"
#include "Hash.h"
#include "CommonPaths.h"
#include "FileUtil.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h"
#include "DX9_D3DUtil.h"
#include "DX9_FramebufferManager.h"
#include "DX9_PixelShaderCache.h"
#include "PixelShaderManager.h"
#include "VertexShaderManager.h"
#include "DX9_VertexShaderCache.h"
#include "VideoConfig.h"
#include "DX9_Render.h"
#include "TextureDecoder.h"
#include "DX9_TextureCache.h"
#include "HiresTextures.h"
#include "DX9_TextureConverter.h"
#include "../Main.h"
//#include "debugger/debugger.h"
namespace DX9
{
TextureCache::TCacheEntry::TCacheEntry(LPDIRECT3DTEXTURE9 _texture)
: texture(_texture), isDynamic(false)
{
}
TextureCache::TCacheEntry::~TCacheEntry()
{
texture->Release();
}
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level)
{
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
}
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
{
LPDIRECT3DSURFACE9 Rendersurf = NULL;
texture->GetSurfaceLevel(0, &Rendersurf);
D3D::dev->SetDepthStencilSurface(NULL);
D3D::dev->SetRenderTarget(0, Rendersurf);
D3DVIEWPORT9 vp;
// Stretch picture with increased internal resolution
vp.X = 0;
vp.Y = 0;
vp.Width = Scaledw;
vp.Height = Scaledh;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
D3D::dev->SetViewport(&vp);
RECT destrect;
destrect.bottom = Scaledh;
destrect.left = 0;
destrect.right = Scaledw;
destrect.top = 0;
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
RECT sourcerect;
sourcerect.bottom = targetSource.bottom;
sourcerect.left = targetSource.left;
sourcerect.right = targetSource.right;
sourcerect.top = targetSource.top;
if (bFromZBuffer)
{
if (bScaleByHalf || g_ActiveConfig.iMultisampleMode)
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
else
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
}
}
else
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
FramebufferManager::GetEFBDepthTexture(source_rect) :
FramebufferManager::GetEFBColorTexture(source_rect);
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
int SSAAMode = g_ActiveConfig.iMultisampleMode;
D3D::drawShadedTexQuad(read_texture, &sourcerect,
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
Scaledw, Scaledh,
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer) ?
PixelShaderCache::GetDepthMatrixProgram(SSAAMode) :
PixelShaderCache::GetColorMatrixProgram(SSAAMode),
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
Rendersurf->Release();
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
D3D::SetTexture(0,NULL);
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
}
void TextureCache::TCacheEntry::Bind(unsigned int stage)
{
D3D::SetTexture(stage, texture);
}
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt)
{
D3DFORMAT d3d_fmt;
bool swap_r_b = false;
switch (pcfmt)
{
case PC_TEX_FMT_BGRA32:
d3d_fmt = D3DFMT_A8R8G8B8;
break;
case PC_TEX_FMT_RGBA32:
d3d_fmt = D3DFMT_A8R8G8B8;
swap_r_b = true;
break;
case PC_TEX_FMT_RGB565:
d3d_fmt = D3DFMT_R5G6B5;
break;
case PC_TEX_FMT_IA4_AS_IA8:
d3d_fmt = D3DFMT_A8L8;
break;
case PC_TEX_FMT_I8:
case PC_TEX_FMT_I4_AS_I8:
// A hack which means the format is a packed
// 8-bit intensity texture. It is unpacked
// to A8L8 in D3DTexture.cpp
d3d_fmt = D3DFMT_A8P8;
break;
case PC_TEX_FMT_IA8:
d3d_fmt = D3DFMT_A8L8;
break;
case PC_TEX_FMT_DXT1:
d3d_fmt = D3DFMT_DXT1;
break;
}
TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels));
entry->swap_r_b = swap_r_b;
entry->d3d_fmt = d3d_fmt;
return entry;
}
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
{
LPDIRECT3DTEXTURE9 texture;
D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
return new TCacheEntry(texture);
}
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3dx9.h>
#include "Statistics.h"
#include "MemoryUtil.h"
#include "Hash.h"
#include "CommonPaths.h"
#include "FileUtil.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h"
#include "DX9_D3DUtil.h"
#include "DX9_FramebufferManager.h"
#include "DX9_PixelShaderCache.h"
#include "PixelShaderManager.h"
#include "VertexShaderManager.h"
#include "DX9_VertexShaderCache.h"
#include "VideoConfig.h"
#include "DX9_Render.h"
#include "TextureDecoder.h"
#include "DX9_TextureCache.h"
#include "HiresTextures.h"
#include "DX9_TextureConverter.h"
#include "../Main.h"
//#include "debugger/debugger.h"
namespace DX9
{
TextureCache::TCacheEntry::TCacheEntry(LPDIRECT3DTEXTURE9 _texture)
: texture(_texture), isDynamic(false)
{
}
TextureCache::TCacheEntry::~TCacheEntry()
{
texture->Release();
}
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int level)
{
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
}
void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect)
{
LPDIRECT3DSURFACE9 Rendersurf = NULL;
texture->GetSurfaceLevel(0, &Rendersurf);
D3D::dev->SetDepthStencilSurface(NULL);
D3D::dev->SetRenderTarget(0, Rendersurf);
D3DVIEWPORT9 vp;
// Stretch picture with increased internal resolution
vp.X = 0;
vp.Y = 0;
vp.Width = Scaledw;
vp.Height = Scaledh;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
D3D::dev->SetViewport(&vp);
RECT destrect;
destrect.bottom = Scaledh;
destrect.left = 0;
destrect.right = Scaledw;
destrect.top = 0;
const float* const fConstAdd = colmat + 16; // fConstAdd is the last 4 floats of colmat
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
RECT sourcerect;
sourcerect.bottom = targetSource.bottom;
sourcerect.left = targetSource.left;
sourcerect.right = targetSource.right;
sourcerect.top = targetSource.top;
if (bFromZBuffer)
{
if (bScaleByHalf || g_ActiveConfig.iMultisampleMode)
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
else
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
}
}
else
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
const LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ?
FramebufferManager::GetEFBDepthTexture(source_rect) :
FramebufferManager::GetEFBColorTexture(source_rect);
D3DFORMAT bformat = FramebufferManager::GetEFBDepthRTSurfaceFormat();
int SSAAMode = g_ActiveConfig.iMultisampleMode;
D3D::drawShadedTexQuad(read_texture, &sourcerect,
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
Scaledw, Scaledh,
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer) ?
PixelShaderCache::GetDepthMatrixProgram(SSAAMode) :
PixelShaderCache::GetColorMatrixProgram(SSAAMode),
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
Rendersurf->Release();
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
D3D::SetTexture(0,NULL);
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
}
void TextureCache::TCacheEntry::Bind(unsigned int stage)
{
D3D::SetTexture(stage, texture);
}
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt)
{
D3DFORMAT d3d_fmt;
bool swap_r_b = false;
switch (pcfmt)
{
case PC_TEX_FMT_BGRA32:
d3d_fmt = D3DFMT_A8R8G8B8;
break;
case PC_TEX_FMT_RGBA32:
d3d_fmt = D3DFMT_A8R8G8B8;
swap_r_b = true;
break;
case PC_TEX_FMT_RGB565:
d3d_fmt = D3DFMT_R5G6B5;
break;
case PC_TEX_FMT_IA4_AS_IA8:
d3d_fmt = D3DFMT_A8L8;
break;
case PC_TEX_FMT_I8:
case PC_TEX_FMT_I4_AS_I8:
// A hack which means the format is a packed
// 8-bit intensity texture. It is unpacked
// to A8L8 in D3DTexture.cpp
d3d_fmt = D3DFMT_A8P8;
break;
case PC_TEX_FMT_IA8:
d3d_fmt = D3DFMT_A8L8;
break;
case PC_TEX_FMT_DXT1:
d3d_fmt = D3DFMT_DXT1;
break;
}
TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels));
entry->swap_r_b = swap_r_b;
entry->d3d_fmt = d3d_fmt;
return entry;
}
TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h)
{
LPDIRECT3DTEXTURE9 texture;
D3D::dev->CreateTexture(scaled_tex_w, scaled_tex_h, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
return new TCacheEntry(texture);
}
}
@@ -1,67 +1,67 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURECACHE_H
#define _TEXTURECACHE_H
#include <map>
#include "DX9_D3DBase.h"
#include "VideoCommon.h"
#include "BPMemory.h"
#include "../TextureCache.h"
namespace DX9
{
class TextureCache : public TextureCacheBase
{
public:
struct TCacheEntry : TCacheEntryBase
{
LPDIRECT3DTEXTURE9 texture;
D3DFORMAT d3d_fmt;
bool swap_r_b;
bool isDynamic; // mofified from cpu
TCacheEntry(LPDIRECT3DTEXTURE9 _texture);
~TCacheEntry();
void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int levels);
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
void Bind(unsigned int stage);
};
public:
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
};
}
#endif
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURECACHE_H
#define _TEXTURECACHE_H
#include <map>
#include "DX9_D3DBase.h"
#include "VideoCommon.h"
#include "BPMemory.h"
#include "../TextureCache.h"
namespace DX9
{
class TextureCache : public TextureCacheBase
{
public:
struct TCacheEntry : TCacheEntryBase
{
LPDIRECT3DTEXTURE9 texture;
D3DFORMAT d3d_fmt;
bool swap_r_b;
bool isDynamic; // mofified from cpu
TCacheEntry(LPDIRECT3DTEXTURE9 _texture);
~TCacheEntry();
void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int levels);
void FromRenderTarget(bool bFromZBuffer, bool bScaleByHalf,
unsigned int cbufid, const float colmat[], const EFBRectangle &source_rect);
void Bind(unsigned int stage);
};
public:
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt);
TCacheEntryBase* CreateRenderTargetTexture(int scaled_tex_w, int scaled_tex_h);
};
}
#endif
File diff suppressed because it is too large Load Diff
@@ -1,53 +1,53 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURECONVERTER_H_
#define _TEXTURECONVERTER_H_
#include "VideoCommon.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h"
#include "DX9_D3DUtil.h"
#include "DX9_D3DShader.h"
namespace DX9
{
// Converts textures between formats
// TODO: support multiple texture formats
namespace TextureConverter
{
void Init();
void Shutdown();
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
}
}
#endif // _TEXTURECONVERTER_H_
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURECONVERTER_H_
#define _TEXTURECONVERTER_H_
#include "VideoCommon.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DTexture.h"
#include "DX9_D3DUtil.h"
#include "DX9_D3DShader.h"
namespace DX9
{
// Converts textures between formats
// TODO: support multiple texture formats
namespace TextureConverter
{
void Init();
void Shutdown();
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
}
}
#endif // _TEXTURECONVERTER_H_
@@ -1,135 +1,135 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "FileUtil.h"
#include "DX9_D3DBase.h"
#include "Fifo.h"
#include "Statistics.h"
#include "Profiler.h"
#include "DX9_VertexManager.h"
#include "OpcodeDecoding.h"
#include "IndexGenerator.h"
#include "VertexShaderManager.h"
#include "DX9_VertexShaderCache.h"
#include "PixelShaderManager.h"
#include "DX9_PixelShaderCache.h"
#include "NativeVertexFormat.h"
#include "NativeVertexWriter.h"
#include "DX9_TextureCache.h"
#include "../Main.h"
#include "BPStructs.h"
#include "XFStructs.h"
//#include "debugger/debugger.h"
namespace DX9
{
using namespace D3D;
// internal state for loading vertices
extern NativeVertexFormat *g_nativeVertexFmt;
inline void DumpBadShaders()
{
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string error_shaders;
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
char filename[512] = "bad_shader_combo_0.txt";
int which = 0;
while (File::Exists(filename))
{
which++;
sprintf(filename, "bad_shader_combo_%i.txt", which);
}
File::WriteStringToFile(true, error_shaders, filename);
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);
#endif
}
void VertexManager::Draw(u32 stride, bool alphapass)
{
if (alphapass)
{
DWORD write = 0;
if (false == g_pixel_shader_cache->SetShader(true))
{
//DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
//goto shader_fail;
return;
}
// update alpha only
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
}
if (IndexGenerator::GetNumTriangles() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_TRIANGLELIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
TIBuffer,
D3DFMT_INDEX16,
LocalVBuffer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumLines() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_LINELIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
LIBuffer,
D3DFMT_INDEX16,
LocalVBuffer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumPoints() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_POINTLIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
PIBuffer,
D3DFMT_INDEX16,
LocalVBuffer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (alphapass)
{
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
}
}
} // namespace
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "FileUtil.h"
#include "DX9_D3DBase.h"
#include "Fifo.h"
#include "Statistics.h"
#include "Profiler.h"
#include "DX9_VertexManager.h"
#include "OpcodeDecoding.h"
#include "IndexGenerator.h"
#include "VertexShaderManager.h"
#include "DX9_VertexShaderCache.h"
#include "PixelShaderManager.h"
#include "DX9_PixelShaderCache.h"
#include "NativeVertexFormat.h"
#include "NativeVertexWriter.h"
#include "DX9_TextureCache.h"
#include "../Main.h"
#include "BPStructs.h"
#include "XFStructs.h"
//#include "debugger/debugger.h"
namespace DX9
{
using namespace D3D;
// internal state for loading vertices
extern NativeVertexFormat *g_nativeVertexFmt;
inline void DumpBadShaders()
{
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string error_shaders;
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
char filename[512] = "bad_shader_combo_0.txt";
int which = 0;
while (File::Exists(filename))
{
which++;
sprintf(filename, "bad_shader_combo_%i.txt", which);
}
File::WriteStringToFile(true, error_shaders, filename);
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to %s", filename);
#endif
}
void VertexManager::Draw(u32 stride, bool alphapass)
{
if (alphapass)
{
DWORD write = 0;
if (false == g_pixel_shader_cache->SetShader(true))
{
//DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
//goto shader_fail;
return;
}
// update alpha only
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
}
if (IndexGenerator::GetNumTriangles() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_TRIANGLELIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(),
TIBuffer,
D3DFMT_INDEX16,
LocalVBuffer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumLines() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_LINELIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(),
LIBuffer,
D3DFMT_INDEX16,
LocalVBuffer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumPoints() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
D3DPT_POINTLIST,
0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(),
PIBuffer,
D3DFMT_INDEX16,
LocalVBuffer,
stride)))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (alphapass)
{
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
}
}
} // namespace
@@ -1,39 +1,39 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXMANAGER_H
#define _VERTEXMANAGER_H
#include "CPMemory.h"
#include "VertexLoader.h"
#include "../VertexManager.h"
namespace DX9
{
class VertexManager : public ::VertexManagerBase
{
public:
void Draw(u32 stride, bool alphapass);
NativeVertexFormat* CreateNativeVertexFormat();
};
}
#endif
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXMANAGER_H
#define _VERTEXMANAGER_H
#include "CPMemory.h"
#include "VertexLoader.h"
#include "../VertexManager.h"
namespace DX9
{
class VertexManager : public ::VertexManagerBase
{
public:
void Draw(u32 stride, bool alphapass);
NativeVertexFormat* CreateNativeVertexFormat();
};
}
#endif
@@ -1,302 +1,302 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <map>
#include "Common.h"
#include "FileUtil.h"
#include "LinearDiskCache.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DShader.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VideoConfig.h"
#include "DX9_VertexShaderCache.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
//#include "debugger/debugger.h"
#include "../Main.h"
namespace DX9
{
VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
#define MAX_SSAA_SHADERS 3
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS];
static LPDIRECT3DVERTEXSHADER9 ClearVertexShader;
LinearDiskCache g_vs_disk_cache;
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level)
{
return SimpleVertexShader[level % MAX_SSAA_SHADERS];
}
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
{
return ClearVertexShader;
}
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
const float f[4] = { f1, f2, f3, f4 };
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
}
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
{
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
}
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
{
float buf[4*C_VENVCONST_END];
for (unsigned int i = 0; i < count; i++)
{
buf[4*i ] = *f++;
buf[4*i+1] = *f++;
buf[4*i+2] = *f++;
buf[4*i+3] = 0.f;
}
D3D::dev->SetVertexShaderConstantF(const_number, buf, count);
}
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
D3D::dev->SetVertexShaderConstantF(const_number, f, count);
}
class VertexShaderCacheInserter : public LinearDiskCacheReader {
public:
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
{
VERTEXSHADERUID uid;
if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
return;
}
memcpy(&uid, key, key_size);
VertexShaderCache::InsertByteCode(uid, value, value_size, false);
}
};
VertexShaderCache::VertexShaderCache()
{
char* vProg = new char[2048];
sprintf(vProg,"struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float2 vTexCoord : TEXCOORD0;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
"{\n"
"VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0;\n"
"return OUT;\n"
"}\n");
SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg,"struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float4 vColor0 : COLOR0;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
"{\n"
"VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n"
"OUT.vColor0 = inColor0;\n"
"return OUT;\n"
"}\n");
ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg, "struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float4 vTexCoord : TEXCOORD0;\n"
"float4 vTexCoord1 : TEXCOORD1;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
"{\n"
"VSOUTPUT OUT;"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xyyx;\n"
"OUT.vTexCoord1 = inTEX2;\n"
"return OUT;\n"
"}\n");
SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg, "struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float4 vTexCoord : TEXCOORD0;\n"
"float4 vTexCoord1 : TEXCOORD1;\n"
"float4 vTexCoord2 : TEXCOORD2;\n"
"float4 vTexCoord3 : TEXCOORD3;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
"{\n"
"VSOUTPUT OUT;"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xyyx;\n"
"OUT.vTexCoord1 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n"
"OUT.vTexCoord2 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n"
"OUT.vTexCoord3 = inTEX2;\n"
"return OUT;\n"
"}\n");
SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
Clear();
delete [] vProg;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
SETSTAT(stats.numVertexShadersCreated, 0);
SETSTAT(stats.numVertexShadersAlive, 0);
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
VertexShaderCacheInserter inserter;
int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
}
void VertexShaderCache::Clear()
{
VSCache::iterator
iter = vshaders.begin(),
vsend = vshaders.end();
for (; iter != vsend; ++iter)
iter->second.Destroy();
vshaders.clear();
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
}
VertexShaderCache::~VertexShaderCache()
{
for (int i = 0; i < MAX_SSAA_SHADERS; i++)
{
if (SimpleVertexShader[i])
SimpleVertexShader[i]->Release();
SimpleVertexShader[i] = NULL;
}
if (ClearVertexShader)
ClearVertexShader->Release();
ClearVertexShader = NULL;
g_vs_disk_cache.Sync();
g_vs_disk_cache.Close();
}
bool VertexShaderCache::SetShader(u32 components)
{
DVSTARTPROFILE();
VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
{
if (vshaders[uid].shader)
return true;
else
return false;
}
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
VSCache::iterator iter;
iter = vshaders.find(uid);
if (iter != vshaders.end())
{
iter->second.frameCount = frameCount;
const VSCacheEntry &entry = iter->second;
last_entry = &entry;
//DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
if (entry.shader)
{
D3D::SetVertexShader(entry.shader);
return true;
}
else
return false;
}
const char *code = GenerateVertexShaderCode(components, API_D3D9);
u8 *bytecode;
int bytecodelen;
if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen))
{
if (g_ActiveConfig.bShowShaderErrors)
{
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
}
return false;
}
g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode;
return result;
}
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
// Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount = frameCount;
vshaders[uid] = entry;
last_entry = &vshaders[uid];
if (!shader)
return false;
INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
if (activate)
{
D3D::SetVertexShader(shader);
return true;
}
return false;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string VertexShaderCache::GetCurrentShaderCode()
{
return "(N/A)\n";
}
#endif
}
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <map>
#include "Common.h"
#include "FileUtil.h"
#include "LinearDiskCache.h"
#include "DX9_D3DBase.h"
#include "DX9_D3DShader.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VideoConfig.h"
#include "DX9_VertexShaderCache.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
//#include "debugger/debugger.h"
#include "../Main.h"
namespace DX9
{
VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
#define MAX_SSAA_SHADERS 3
static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS];
static LPDIRECT3DVERTEXSHADER9 ClearVertexShader;
LinearDiskCache g_vs_disk_cache;
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexShader(int level)
{
return SimpleVertexShader[level % MAX_SSAA_SHADERS];
}
LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
{
return ClearVertexShader;
}
void VertexShaderCache::SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
const float f[4] = { f1, f2, f3, f4 };
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
}
void VertexShaderCache::SetVSConstant4fv(unsigned int const_number, const float *f)
{
D3D::dev->SetVertexShaderConstantF(const_number, f, 1);
}
void VertexShaderCache::SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f)
{
float buf[4*C_VENVCONST_END];
for (unsigned int i = 0; i < count; i++)
{
buf[4*i ] = *f++;
buf[4*i+1] = *f++;
buf[4*i+2] = *f++;
buf[4*i+3] = 0.f;
}
D3D::dev->SetVertexShaderConstantF(const_number, buf, count);
}
void VertexShaderCache::SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
{
D3D::dev->SetVertexShaderConstantF(const_number, f, count);
}
class VertexShaderCacheInserter : public LinearDiskCacheReader {
public:
void Read(const u8 *key, int key_size, const u8 *value, int value_size)
{
VERTEXSHADERUID uid;
if (key_size != sizeof(uid)) {
ERROR_LOG(VIDEO, "Wrong key size in vertex shader cache");
return;
}
memcpy(&uid, key, key_size);
VertexShaderCache::InsertByteCode(uid, value, value_size, false);
}
};
VertexShaderCache::VertexShaderCache()
{
char* vProg = new char[2048];
sprintf(vProg,"struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float2 vTexCoord : TEXCOORD0;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0)\n"
"{\n"
"VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0;\n"
"return OUT;\n"
"}\n");
SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg,"struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float4 vColor0 : COLOR0;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
"{\n"
"VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n"
"OUT.vColor0 = inColor0;\n"
"return OUT;\n"
"}\n");
ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg, "struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float4 vTexCoord : TEXCOORD0;\n"
"float4 vTexCoord1 : TEXCOORD1;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
"{\n"
"VSOUTPUT OUT;"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xyyx;\n"
"OUT.vTexCoord1 = inTEX2;\n"
"return OUT;\n"
"}\n");
SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
sprintf(vProg, "struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float4 vTexCoord : TEXCOORD0;\n"
"float4 vTexCoord1 : TEXCOORD1;\n"
"float4 vTexCoord2 : TEXCOORD2;\n"
"float4 vTexCoord3 : TEXCOORD3;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float4 inTEX2 : TEXCOORD2)\n"
"{\n"
"VSOUTPUT OUT;"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xyyx;\n"
"OUT.vTexCoord1 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n"
"OUT.vTexCoord2 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n"
"OUT.vTexCoord3 = inTEX2;\n"
"return OUT;\n"
"}\n");
SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg));
Clear();
delete [] vProg;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
SETSTAT(stats.numVertexShadersCreated, 0);
SETSTAT(stats.numVertexShadersAlive, 0);
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), g_globals->unique_id);
VertexShaderCacheInserter inserter;
int read_items = g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
}
void VertexShaderCache::Clear()
{
VSCache::iterator
iter = vshaders.begin(),
vsend = vshaders.end();
for (; iter != vsend; ++iter)
iter->second.Destroy();
vshaders.clear();
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
}
VertexShaderCache::~VertexShaderCache()
{
for (int i = 0; i < MAX_SSAA_SHADERS; i++)
{
if (SimpleVertexShader[i])
SimpleVertexShader[i]->Release();
SimpleVertexShader[i] = NULL;
}
if (ClearVertexShader)
ClearVertexShader->Release();
ClearVertexShader = NULL;
g_vs_disk_cache.Sync();
g_vs_disk_cache.Close();
}
bool VertexShaderCache::SetShader(u32 components)
{
DVSTARTPROFILE();
VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
{
if (vshaders[uid].shader)
return true;
else
return false;
}
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
VSCache::iterator iter;
iter = vshaders.find(uid);
if (iter != vshaders.end())
{
iter->second.frameCount = frameCount;
const VSCacheEntry &entry = iter->second;
last_entry = &entry;
//DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
if (entry.shader)
{
D3D::SetVertexShader(entry.shader);
return true;
}
else
return false;
}
const char *code = GenerateVertexShaderCode(components, API_D3D9);
u8 *bytecode;
int bytecodelen;
if (!D3D::CompileVertexShader(code, (int)strlen(code), &bytecode, &bytecodelen))
{
if (g_ActiveConfig.bShowShaderErrors)
{
PanicAlert("Failed to compile Vertex Shader:\n\n%s", code);
}
return false;
}
g_vs_disk_cache.Append((u8 *)&uid, sizeof(uid), bytecode, bytecodelen);
g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode;
return result;
}
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
LPDIRECT3DVERTEXSHADER9 shader = D3D::CreateVertexShaderFromByteCode(bytecode, bytecodelen);
// Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount = frameCount;
vshaders[uid] = entry;
last_entry = &vshaders[uid];
if (!shader)
return false;
INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
if (activate)
{
D3D::SetVertexShader(shader);
return true;
}
return false;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string VertexShaderCache::GetCurrentShaderCode()
{
return "(N/A)\n";
}
#endif
}
@@ -1,81 +1,81 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXSHADERCACHE_H
#define _VERTEXSHADERCACHE_H
#include "DX9_D3DBase.h"
#include <map>
#include <string>
#include "DX9_D3DBase.h"
#include "VertexShaderGen.h"
#include "../VertexShaderCache.h"
namespace DX9
{
class VertexShaderCache : public ::VertexShaderCacheBase
{
private:
struct VSCacheEntry
{
LPDIRECT3DVERTEXSHADER9 shader;
int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string code;
#endif
VSCacheEntry() : shader(NULL), frameCount(0) {}
void Destroy()
{
if (shader)
shader->Release();
shader = NULL;
}
};
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
static VSCache vshaders;
static const VSCacheEntry *last_entry;
static void Clear();
public:
VertexShaderCache();
~VertexShaderCache();
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetVSConstant4fv(unsigned int const_number, const float *f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
bool SetShader(u32 components);
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
#if defined(_DEBUG) || defined(DEBUGFAST)
static std::string GetCurrentShaderCode();
#endif
static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram);
};
}
#endif // _VERTEXSHADERCACHE_H
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXSHADERCACHE_H
#define _VERTEXSHADERCACHE_H
#include "DX9_D3DBase.h"
#include <map>
#include <string>
#include "DX9_D3DBase.h"
#include "VertexShaderGen.h"
#include "../VertexShaderCache.h"
namespace DX9
{
class VertexShaderCache : public ::VertexShaderCacheBase
{
private:
struct VSCacheEntry
{
LPDIRECT3DVERTEXSHADER9 shader;
int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string code;
#endif
VSCacheEntry() : shader(NULL), frameCount(0) {}
void Destroy()
{
if (shader)
shader->Release();
shader = NULL;
}
};
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
static VSCache vshaders;
static const VSCacheEntry *last_entry;
static void Clear();
public:
VertexShaderCache();
~VertexShaderCache();
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
void SetVSConstant4fv(unsigned int const_number, const float *f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
bool SetShader(u32 components);
static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexShader(int level);
static LPDIRECT3DVERTEXSHADER9 GetClearVertexShader();
static bool InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
#if defined(_DEBUG) || defined(DEBUGFAST)
static std::string GetCurrentShaderCode();
#endif
static LPDIRECT3DVERTEXSHADER9 CompileCgShader(const char *pstrprogram);
};
}
#endif // _VERTEXSHADERCACHE_H