Add a DX11 video plugin.

Might or might not work for you, yet.
Anyway, read the soon to be created forum thread on this plugin before asking any questions.

Huge thanks to rodolfoosvaldobogado for helping me out in various areas.
Also, thanks to everyone on IRC who supported me during development ;)


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5680 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
NeoBrainX 2010-06-13 19:50:06 +00:00
parent 20e3919033
commit 3ea2a1387c
45 changed files with 8016 additions and 1 deletions

View File

@ -511,6 +511,7 @@ const char *GeneratePixelShaderCode(u32 texture_mask, bool dstAlphaEnable, u32 H
// alpha test will always fail, so restart the shader and just make it an empty function
p = pmainstart;
WRITE(p, "ocol0 = 0;\n");
WRITE(p, "depth = 1.f;\n");
WRITE(p, "discard;return;\n");
}
else
@ -952,7 +953,7 @@ static bool WriteAlphaTest(char *&p, u32 HLSL)
compindex = bpmem.alphaFunc.comp1 % 8;
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[1]);//lookup the second component from the alpha function table
WRITE(p, ")){ocol0 = 0;discard;return;}\n");
WRITE(p, ")){ocol0 = 0;depth = 1.f;discard;return;}\n");
return true;
}

View File

@ -198,6 +198,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_WiimoteNew", "Plugin
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InputUICommon", "Core\InputUICommon\InputUICommon.vcproj", "{374E2DB7-42DF-4E59-8474-62B6687F4978}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin_VideoDX11", "Plugins\Plugin_VideoDX11\Plugin_VideoDX11.vcproj", "{21DBE606-2958-43AC-A14E-B6B798D56554}"
ProjectSection(ProjectDependencies) = postProject
{11F55366-12EC-4C44-A8CB-1D4E315D61ED} = {11F55366-12EC-4C44-A8CB-1D4E315D61ED}
{E5D1F0C0-AA07-4841-A4EB-4CF4DAA6B0FA} = {E5D1F0C0-AA07-4841-A4EB-4CF4DAA6B0FA}
{1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE} = {1C8436C9-DBAF-42BE-83BC-CF3EC9175ABE}
{C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -570,6 +578,18 @@ Global
{374E2DB7-42DF-4E59-8474-62B6687F4978}.Release|Win32.Build.0 = Release|Win32
{374E2DB7-42DF-4E59-8474-62B6687F4978}.Release|x64.ActiveCfg = Release|x64
{374E2DB7-42DF-4E59-8474-62B6687F4978}.Release|x64.Build.0 = Release|x64
{21DBE606-2958-43AC-A14E-B6B798D56554}.Debug|Win32.ActiveCfg = Debug|Win32
{21DBE606-2958-43AC-A14E-B6B798D56554}.Debug|Win32.Build.0 = Debug|Win32
{21DBE606-2958-43AC-A14E-B6B798D56554}.Debug|x64.ActiveCfg = Debug|x64
{21DBE606-2958-43AC-A14E-B6B798D56554}.Debug|x64.Build.0 = Debug|x64
{21DBE606-2958-43AC-A14E-B6B798D56554}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
{21DBE606-2958-43AC-A14E-B6B798D56554}.DebugFast|Win32.Build.0 = DebugFast|Win32
{21DBE606-2958-43AC-A14E-B6B798D56554}.DebugFast|x64.ActiveCfg = DebugFast|x64
{21DBE606-2958-43AC-A14E-B6B798D56554}.DebugFast|x64.Build.0 = DebugFast|x64
{21DBE606-2958-43AC-A14E-B6B798D56554}.Release|Win32.ActiveCfg = Release|Win32
{21DBE606-2958-43AC-A14E-B6B798D56554}.Release|Win32.Build.0 = Release|Win32
{21DBE606-2958-43AC-A14E-B6B798D56554}.Release|x64.ActiveCfg = Release|x64
{21DBE606-2958-43AC-A14E-B6B798D56554}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,846 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Plugin_VideoDX11"
ProjectGUID="{21DBE606-2958-43AC-A14E-B6B798D56554}"
RootNamespace="Plugin_VideoDX11"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release/Video_DirectX11.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="false"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../../PluginSpecs;../../Core/Common/Src;../../Core/VideoCommon/Src;../../../Externals;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="_WIN32;WIN32;NDEBUG;_WINDOWS;_USRDLL;VIDEO_DIRECTX11_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
StringPooling="true"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="true"
EnableEnhancedInstructionSet="2"
FloatingPointModel="2"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
DisableSpecificWarnings="4005;"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1053"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="&quot;..\..\core\common\win32\release\common.lib&quot;"
AdditionalDependencies="odbc32.lib d3dcompiler.lib odbccp32.lib comctl32.lib dxguid.lib d3d10.lib d3d11.lib d3dx11.lib winmm.lib vfw32.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_VideoDX11.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../../../Externals/Cg;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
GenerateManifest="false"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Release/Video_DirectX11.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="false"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../../../Externals;../../PluginSpecs;../../Core/Common/Src;../../Core/VideoCommon/Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VIDEO_DIRECTX11_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
FloatingPointModel="2"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
DisableSpecificWarnings="4005;"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1053"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib d3dcompiler.lib odbccp32.lib comctl32.lib dxguid.lib d3d10.lib d3d11.lib d3dx11.lib winmm.lib vfw32.lib wxbase28u.lib wxmsw28u_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoDX11.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\Externals\Cg64;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Debug/Video_DirectX11.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../PluginSpecs;../../Core/Common/Src;../../Core/VideoCommon/Src;../../../Externals;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="_WIN32;WIN32;_DEBUG;_WINDOWS;_USRDLL;VIDEO_DIRECTX11_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="0"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1053"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="&quot;..\..\core\common\win32\debug\common.lib&quot;"
AdditionalDependencies="odbc32.lib d3dcompiler.lib odbccp32.lib comctl32.lib uuid.lib dxguid.lib d3d10.lib d3d11.lib d3dx11.lib Rpcrt4.lib winmm.lib vfw32.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\Win32/Plugins\Plugin_VideoDX11D.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../../../Externals/Cg;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Debug/Video_DirectX11.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../PluginSpecs;../../Core/Common/Src;../../Core/VideoCommon/Src;../../../Externals;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;VIDEO_DIRECTX11_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1053"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib d3dcompiler.lib odbccp32.lib comctl32.lib uuid.lib dxguid.lib d3d10.lib d3d11.lib d3dx11.lib Rpcrt4.lib winmm.lib vfw32.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoDX11D.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\Externals\Cg64;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\Release/Video_DirectX11.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="false"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../../PluginSpecs;../../Core/Common/Src;../../Core/VideoCommon/Src;../../../Externals;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="_WIN32;WIN32;NDEBUG;_WINDOWS;_USRDLL;VIDEO_DIRECTX11_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;DEBUGFAST"
StringPooling="true"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="true"
EnableEnhancedInstructionSet="2"
FloatingPointModel="2"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1053"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib d3dcompiler.lib odbccp32.lib comctl32.lib uuid.lib dxguid.lib d3d10.lib d3d11.lib d3dx11.lib Rpcrt4.lib winmm.lib vfw32.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\Win32\Plugins\Plugin_VideoDX11DF.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../../../Externals/Cg;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
GenerateManifest="false"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="DebugFast|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\Release/Video_DirectX11.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP4"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="false"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../../../Externals;../../PluginSpecs;../../Core/Common/Src;../../Core/VideoCommon/Src;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals\wxWidgets\Include\msvc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VIDEO_DIRECTX11_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;;DEBUGFAST"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="true"
EnableEnhancedInstructionSet="0"
FloatingPointModel="2"
UsePrecompiledHeader="0"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
CompileAs="0"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1053"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib d3dcompiler.lib odbccp32.lib comctl32.lib uuid.lib dxguid.lib d3d10.lib d3d11.lib d3dx11.lib Rpcrt4.lib winmm.lib vfw32.lib wxbase28ud.lib wxmsw28ud_core.lib"
OutputFile="..\..\..\Binary\x64\Plugins\Plugin_VideoDX11DF.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\..\Externals\Cg64;&quot;..\..\..\Externals\wxWidgets\lib\vc_lib\$(PlatformName)&quot;"
GenerateManifest="false"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(PlatformName)\$(ConfigurationName)\$(TargetName).pdb"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(PlatformName)\$(ConfigurationName)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
<File
RelativePath=".\Src\resource.h"
>
</File>
<File
RelativePath=".\Src\Resource.rc"
>
</File>
</Filter>
<Filter
Name="win32"
>
<File
RelativePath=".\Src\W32Util\DialogManager.cpp"
>
</File>
<File
RelativePath=".\Src\W32Util\DialogManager.h"
>
</File>
<File
RelativePath=".\Src\EmuWindow.cpp"
>
</File>
<File
RelativePath=".\Src\EmuWindow.h"
>
</File>
<File
RelativePath=".\Src\W32Util\Misc.cpp"
>
</File>
<File
RelativePath=".\Src\W32Util\Misc.h"
>
</File>
<File
RelativePath=".\Src\W32Util\PropertySheet.cpp"
>
</File>
<File
RelativePath=".\Src\W32Util\PropertySheet.h"
>
</File>
<File
RelativePath=".\Src\W32Util\TabControl.cpp"
>
</File>
<File
RelativePath=".\Src\W32Util\TabControl.h"
>
</File>
<File
RelativePath=".\Src\W32Util\Thread.cpp"
>
</File>
<File
RelativePath=".\Src\W32Util\Thread.h"
>
</File>
</Filter>
<Filter
Name="Render"
>
<File
RelativePath=".\Src\FBManager.cpp"
>
</File>
<File
RelativePath=".\Src\FBManager.h"
>
</File>
<File
RelativePath=".\Src\NativeVertexFormat.cpp"
>
</File>
<File
RelativePath=".\Src\PixelShaderCache.cpp"
>
</File>
<File
RelativePath=".\Src\PixelShaderCache.h"
>
</File>
<File
RelativePath=".\Src\Render.cpp"
>
</File>
<File
RelativePath=".\Src\TextureCache.cpp"
>
</File>
<File
RelativePath=".\Src\TextureCache.h"
>
</File>
<File
RelativePath=".\Src\VertexManager.cpp"
>
</File>
<File
RelativePath=".\Src\VertexManager.h"
>
</File>
<File
RelativePath=".\Src\VertexShaderCache.cpp"
>
</File>
<File
RelativePath=".\Src\VertexShaderCache.h"
>
</File>
</Filter>
<Filter
Name="D3D"
>
<File
RelativePath=".\Src\D3DBase.cpp"
>
</File>
<File
RelativePath=".\Src\D3DBase.h"
>
</File>
<File
RelativePath=".\Src\D3DShader.cpp"
>
</File>
<File
RelativePath=".\Src\D3DShader.h"
>
</File>
<File
RelativePath=".\Src\D3DTexture.cpp"
>
</File>
<File
RelativePath=".\Src\D3DTexture.h"
>
</File>
<File
RelativePath=".\Src\D3DUtil.cpp"
>
</File>
<File
RelativePath=".\Src\D3DUtil.h"
>
</File>
</Filter>
<Filter
Name="Decoder"
>
<File
RelativePath=".\Src\BPFunctions.cpp"
>
</File>
</Filter>
<Filter
Name="UI"
>
<File
RelativePath=".\Src\DlgSettings.cpp"
>
</File>
<File
RelativePath=".\Src\DlgSettings.h"
>
</File>
</Filter>
<File
RelativePath=".\Src\Globals.h"
>
</File>
<File
RelativePath=".\Src\main.cpp"
>
</File>
<File
RelativePath=".\Src\main.h"
>
</File>
<File
RelativePath=".\Src\stdafx.cpp"
>
</File>
<File
RelativePath=".\Src\stdafx.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,139 @@
// 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 "BPFunctions.h"
#include "D3DBase.h"
#include "VideoConfig.h"
#include "Common.h"
#include "TextureCache.h"
#include "VertexManager.h"
#include "VertexShaderManager.h"
#include "Render.h"
namespace BPFunctions
{
void FlushPipeline()
{
VertexManager::Flush();
}
void SetGenerationMode(const BPCmd &bp)
{
Renderer::SetGenerationMode();
}
void SetScissor(const BPCmd &bp)
{
Renderer::SetScissorRect();
}
void SetLineWidth(const BPCmd &bp)
{
Renderer::SetLineWidth();
}
void SetDepthMode(const BPCmd &bp)
{
Renderer::SetDepthMode();
}
void SetBlendMode(const BPCmd &bp)
{
Renderer::SetBlendMode(false);
}
void SetDitherMode(const BPCmd &bp)
{
Renderer::SetDitherMode();
}
void SetLogicOpMode(const BPCmd &bp)
{
Renderer::SetLogicOpMode();
}
void SetColorMask(const BPCmd &bp)
{
Renderer::SetColorMask();
}
void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const int &scaleByHalf)
{
if (!g_ActiveConfig.bEFBCopyDisable)
{
if (g_ActiveConfig.bCopyEFBToTexture)
{
TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
}
else
{
PanicAlert("TODO: Implement EFB copying to RAM %s %d\n", __FILE__, __LINE__);
}
}
}
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
{
bool colorEnable = bpmem.blendmode.colorupdate;
bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate);
bool zEnable = bpmem.zmode.updateenable;
if (colorEnable || alphaEnable || zEnable)
{
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
u32 z = bpmem.clearZValue;
Renderer::ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z);
}
}
void RestoreRenderState(const BPCmd &bp)
{
Renderer::RestoreAPIState();
}
bool GetConfig(const int &type)
{
switch (type)
{
case CONFIG_ISWII:
return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG:
return g_ActiveConfig.bDisableFog;
case CONFIG_SHOWEFBREGIONS:
return false;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
}
}
u8 *GetPointer(const u32 &address)
{
return g_VideoInitialize.pGetMemoryPointer(address);
}
void SetTextureMode(const BPCmd &bp)
{
Renderer::SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
}
void SetInterlacingMode(const BPCmd &bp)
{
// TODO
}
};

View File

@ -0,0 +1,391 @@
// 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 "D3DBase.h"
#include "D3DTexture.h"
#include "D3DShader.h"
#include "D3Dcompiler.h"
#include "VideoConfig.h"
#include "Render.h"
#include "XFStructs.h"
#include <map>
#include <string>
#include <algorithm>
using namespace std;
namespace D3D
{
ID3D11Device* device = NULL;
ID3D11DeviceContext* context = NULL;
IDXGISwapChain* swapchain = NULL;
D3D_FEATURE_LEVEL featlevel;
D3DTexture2D* backbuf = NULL;
HWND hWnd;
unsigned int xres, yres;
bool bFrameInProgress = false;
EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(NULL), psbytecode(NULL)
{
for (unsigned int k = 0;k < 8;k++)
{
float border[4] = {0.f, 0.f, 0.f, 0.f};
shader_resources[k] = NULL;
samplerdesc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
}
blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE;
blenddesc.RenderTarget[0].BlendEnable = FALSE;
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
depthdesc.DepthEnable = TRUE;
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
depthdesc.StencilEnable = FALSE;
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
// this probably must be changed once multisampling support gets added
rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0, false, false, false, false);
pscbuf = NULL;
vscbuf = NULL;
vshaderchanged = false;
inp_layout = NULL;
num_inp_elems = 0;
pscbufchanged = false;
vscbufchanged = false;
}
EmuGfxState::~EmuGfxState()
{
for (unsigned int k = 0;k < 8;k++)
SAFE_RELEASE(shader_resources[k])
SAFE_RELEASE(vsbytecode);
SAFE_RELEASE(psbytecode);
SAFE_RELEASE(vertexshader);
SAFE_RELEASE(pixelshader);
SAFE_RELEASE(pscbuf);
SAFE_RELEASE(vscbuf);
SAFE_RELEASE(inp_layout);
}
// TODO: No need to store the whole bytecode, signature might be enough (?)
void EmuGfxState::SetVShader(ID3D11VertexShader* shader, ID3D10Blob* bcode)
{
// TODO: vshaderchanged actually just needs to be true if the signature changed
if (bcode && vsbytecode != bcode->GetBufferPointer()) vshaderchanged = true;
SAFE_RELEASE(vsbytecode);
SAFE_RELEASE(vertexshader);
if (shader && bcode)
{
vertexshader = shader;
shader->AddRef();
vsbytecode = bcode;
bcode->AddRef();
}
else if (shader || bcode)
{
PanicAlert("Invalid parameters!\n");
}
}
void EmuGfxState::SetPShader(ID3D11PixelShader* shader)
{
if (pixelshader) pixelshader->Release();
pixelshader = shader;
if (shader) shader->AddRef();
}
void EmuGfxState::SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num)
{
num_inp_elems = num;
memcpy(inp_elems, elems, num*sizeof(D3D11_INPUT_ELEMENT_DESC));
}
void EmuGfxState::SetShaderResource(int stage, ID3D11ShaderResourceView* srv)
{
if (shader_resources[stage]) shader_resources[stage]->Release();
shader_resources[stage] = srv;
if (srv) srv->AddRef();
}
void EmuGfxState::SetAlphaBlendEnable(bool enable)
{
blenddesc.RenderTarget[0].BlendEnable = enable;
}
void EmuGfxState::SetRenderTargetWriteMask(UINT8 mask)
{
blenddesc.RenderTarget[0].RenderTargetWriteMask = mask;
}
void EmuGfxState::ApplyState()
{
HRESULT hr;
// input layout (only needs to be updated if the vertex shader signature changed)
if (vshaderchanged)
{
if (inp_layout) inp_layout->Release();
hr = D3D::device->CreateInputLayout(inp_elems, num_inp_elems, vsbytecode->GetBufferPointer(), vsbytecode->GetBufferSize(), &inp_layout);
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
SetDebugObjectName((ID3D11DeviceChild*)inp_layout, "an input layout of EmuGfxState");
vshaderchanged = false;
}
D3D::context->IASetInputLayout(inp_layout);
// vertex shader
// TODO: divide the global variables of the generated shaders into about 5 constant buffers
// TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time
if (!vscbuf)
{
unsigned int size = ((sizeof(float)*952)&(~0xffff))+0x10000; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
device->CreateBuffer(&cbdesc, NULL, &vscbuf);
SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState");
}
if (vscbufchanged)
{
D3D11_MAPPED_SUBRESOURCE map;
context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, vsconstants, sizeof(vsconstants));
context->Unmap(vscbuf, 0);
}
D3D::context->VSSetConstantBuffers(0, 1, &vscbuf);
// pixel shader
if (!pscbuf)
{
unsigned int size = ((sizeof(float)*116)&(~0xffff))+0x10000; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
device->CreateBuffer(&cbdesc, NULL, &pscbuf);
SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState");
}
if (pscbufchanged)
{
D3D11_MAPPED_SUBRESOURCE map;
context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, psconstants, sizeof(psconstants));
context->Unmap(pscbuf, 0);
pscbufchanged = false;
}
D3D::context->PSSetConstantBuffers(0, 1, &pscbuf);
ID3D11SamplerState* samplerstate[8];
for (unsigned int stage = 0; stage < 8; stage++)
{
if (shader_resources[stage])
{
hr = D3D::device->CreateSamplerState(&samplerdesc[stage], &samplerstate[stage]);
if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage);
else SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "a sampler state of EmuGfxState");
}
else samplerstate[stage] = NULL;
}
D3D::context->PSSetSamplers(0, 8, samplerstate);
for (unsigned int stage = 0; stage < 8; stage++)
SAFE_RELEASE(samplerstate[stage]);
ID3D11BlendState* blstate;
hr = device->CreateBlendState(&blenddesc, &blstate);
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
context->OMSetBlendState(blstate, NULL, 0xFFFFFFFF);
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState");
blstate->Release();
rastdesc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
ID3D11RasterizerState* raststate;
hr = device->CreateRasterizerState(&rastdesc, &raststate);
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
SetDebugObjectName((ID3D11DeviceChild*)raststate, "a rasterizer state of EmuGfxState");
context->RSSetState(raststate);
raststate->Release();
ID3D11DepthStencilState* depth_state;
hr = device->CreateDepthStencilState(&depthdesc, &depth_state);
if (SUCCEEDED(hr)) SetDebugObjectName((ID3D11DeviceChild*)depth_state, "a depth-stencil state of EmuGfxState");
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
context->OMSetDepthStencilState(depth_state, 0);
depth_state->Release();
context->PSSetShader(pixelshader, NULL, 0);
context->VSSetShader(vertexshader, NULL, 0);
context->PSSetShaderResources(0, 8, shader_resources);
}
void EmuGfxState::AlphaPass()
{
context->PSSetShader(pixelshader, NULL, 0);
ID3D11BlendState* blstate;
D3D11_BLEND_DESC desc = blenddesc;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
desc.RenderTarget[0].BlendEnable = FALSE;
HRESULT hr = device->CreateBlendState(&desc, &blstate);
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState (created during alpha pass)");
context->OMSetBlendState(blstate, NULL, 0xFFFFFFFF);
blstate->Release();
}
void EmuGfxState::ResetShaderResources()
{
for (unsigned int k = 0;k < 8;k++)
SAFE_RELEASE(shader_resources[k]);
}
EmuGfxState* gfxstate = NULL;
HRESULT Create(HWND wnd)
{
hWnd = wnd;
HRESULT hr;
RECT client;
GetClientRect(hWnd, &client);
xres = client.right - client.left;
yres = client.bottom - client.top;
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sd.BufferDesc.Width = xres;
sd.BufferDesc.Height = yres;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = wnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
#if defined(_DEBUG) || defined(DEBUGFAST)
D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_SINGLETHREADED);
#else
D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
#endif
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, device_flags, NULL, 0, D3D11_SDK_VERSION, &sd, &swapchain, &device, &featlevel, &context);
if (FAILED(hr) || !device || !context || !swapchain)
{
MessageBox(wnd, _T("Failed to initialize Direct3D."), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(device);
SAFE_RELEASE(context);
SAFE_RELEASE(swapchain);
return E_FAIL;
}
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
ID3D11Texture2D* buf;
hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
if (FAILED(hr))
{
MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 plugin"), MB_OK | MB_ICONERROR);
device->Release();
context->Release();
swapchain->Release();
return E_FAIL;
}
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
buf->Release();
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view");
context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL);
gfxstate = new EmuGfxState;
return S_OK;
}
void Close()
{
// release all bound resources
context->ClearState();
if (gfxstate) delete gfxstate;
SAFE_RELEASE(backbuf);
SAFE_RELEASE(context);
SAFE_RELEASE(swapchain);
ULONG references = device->Release();
if (references)
{
ERROR_LOG(VIDEO, "Unreleased references: %i.", references);
}
else
{
NOTICE_LOG(VIDEO, "Successfully released all device references!");
}
device = NULL;
}
/* just returning the 4_0 ones here */
const char* VertexShaderVersionString() { return "vs_4_0"; }
const char* PixelShaderVersionString() { return "ps_4_0"; }
D3DTexture2D* &GetBackBuffer() { return backbuf; }
unsigned int GetBackBufferWidth() { return xres; }
unsigned int GetBackBufferHeight() { return yres; }
void Reset()
{
// TODO: Check whether we need to do anything here
}
bool BeginFrame()
{
if (bFrameInProgress)
{
PanicAlert("BeginFrame called although a frame is already in progress");
return false;
}
bFrameInProgress = true;
return (device != NULL);
}
void EndFrame()
{
if (!bFrameInProgress)
{
PanicAlert("EndFrame called although no frame is in progress");
return;
}
bFrameInProgress = false;
}
void Present()
{
// TODO: Is 1 the correct value for vsyncing?
swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
}
} // namespace

View File

@ -0,0 +1,147 @@
// 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 <vector>
#include <set>
#include <d3d11.h>
#include "Common.h"
#include <vector>
#include <list>
#include <map>
using std::vector;
using std::list;
using std::map;
using std::pair;
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
class D3DTexture2D;
namespace D3D
{
HRESULT Create(HWND wnd);
void Close();
extern ID3D11Device *device;
extern ID3D11DeviceContext *context;
extern IDXGISwapChain *swapchain;
extern bool bFrameInProgress;
void Reset();
bool BeginFrame();
void EndFrame();
void Present();
unsigned int GetBackBufferWidth();
unsigned int GetBackBufferHeight();
D3DTexture2D* &GetBackBuffer();
const char *PixelShaderVersionString();
const char *VertexShaderVersionString();
// Ihis function will assign a name to the given resource.
// The DirectX debug layer will make it easier to identify resources that way,
// e.g. when listing up all resources who have unreleased references.
inline void SetDebugObjectName(ID3D11DeviceChild* resource, const char *name)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
resource->SetPrivateData( WKPDID_D3DDebugObjectName, strlen(name), name);
#endif
}
// stores the pipeline state to use when calling VertexManager::Flush()
class EmuGfxState
{
public:
EmuGfxState();
~EmuGfxState();
void SetVShader(ID3D11VertexShader *shader, ID3D10Blob *bcode);
void SetPShader(ID3D11PixelShader *shader);
void SetInputElements(const D3D11_INPUT_ELEMENT_DESC *elems, UINT num);
void SetShaderResource(int stage, ID3D11ShaderResourceView *srv);
void ApplyState(); // apply current state
void AlphaPass(); // only modify the current state to enable the alpha pass
void ResetShaderResources(); // disable all shader resources
// blend state
void SetAlphaBlendEnable(bool enable);
void SetRenderTargetWriteMask(UINT8 mask);
void SetSrcBlend(D3D11_BLEND val) // TODO: Check whether e.g. the dest color check is needed here
{
blenddesc.RenderTarget[0].SrcBlend = val;
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
else blenddesc.RenderTarget[0].SrcBlendAlpha = val;
}
void SetDestBlend(D3D11_BLEND val)
{
blenddesc.RenderTarget[0].DestBlend = val;
if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
else blenddesc.RenderTarget[0].DestBlendAlpha = val;
}
void SetBlendOp(D3D11_BLEND_OP val)
{
blenddesc.RenderTarget[0].BlendOp = val;
blenddesc.RenderTarget[0].BlendOpAlpha = val;
}
// sampler states
void SetSamplerFilter(DWORD stage, D3D11_FILTER filter) { samplerdesc[stage].Filter = filter; }
// TODO: add methods for changing the other states instead of modifying them directly
D3D11_SAMPLER_DESC samplerdesc[8];
D3D11_RASTERIZER_DESC rastdesc;
D3D11_DEPTH_STENCIL_DESC depthdesc;
float psconstants[116];
float vsconstants[952];
bool vscbufchanged;
bool pscbufchanged;
private:
ID3D11VertexShader* vertexshader;
ID3D10Blob* vsbytecode;
ID3D11PixelShader* pixelshader;
ID3D10Blob* psbytecode;
bool vshaderchanged;
ID3D11Buffer* vscbuf;
ID3D11Buffer* pscbuf;
ID3D11InputLayout* inp_layout;
D3D11_INPUT_ELEMENT_DESC inp_elems[32];
int num_inp_elems;
ID3D11ShaderResourceView* shader_resources[8];
D3D11_BLEND_DESC blenddesc;
};
extern EmuGfxState *gfxstate;
} // namespace

View File

@ -0,0 +1,141 @@
// 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 <d3dx11.h>
#include <d3dcompiler.h>
#include <string>
#include "VideoConfig.h"
#include "D3DShader.h"
namespace D3D
{
// bytecode->shader
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len)
{
ID3D11VertexShader* v_shader;
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, NULL, &v_shader);
if (FAILED(hr))
{
PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__);
v_shader = NULL;
}
return v_shader;
}
// code->bytecode
bool CompileVertexShader(const char* code, unsigned int len, ID3D10Blob** blob)
{
ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
#endif
HRESULT hr = D3DCompile(code, len, NULL, NULL, NULL, "main", D3D::VertexShaderVersionString(),
flags, 0, &shaderBuffer, &errorBuffer);
if (FAILED(hr))
{
std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
*blob = NULL;
}
else *blob = shaderBuffer;
//cleanup
if (errorBuffer) errorBuffer->Release();
return SUCCEEDED(hr);
}
// bytecode->shader
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len)
{
ID3D11PixelShader* p_shader;
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, NULL, &p_shader);
if (FAILED(hr))
{
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
p_shader = NULL;
}
return p_shader;
}
// code->bytecode
bool CompilePixelShader(const char* code, unsigned int len, ID3D10Blob** blob)
{
ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
#endif
HRESULT hr = D3DCompile(code, len, NULL, NULL, NULL, "main", D3D::PixelShaderVersionString(),
flags, 0, &shaderBuffer, &errorBuffer);
if (FAILED(hr))
{
std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
*blob = NULL;
}
else *blob = shaderBuffer;
// cleanup
if (errorBuffer) errorBuffer->Release();
return SUCCEEDED(hr);
}
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len)
{
ID3D10Blob* blob = NULL;
if (CompileVertexShader(code, len, &blob))
{
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
blob->Release();
return v_shader;
}
PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
return NULL;
}
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len)
{
ID3D10Blob* blob = NULL;
CompilePixelShader(code, len, &blob);
if (blob)
{
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob);
blob->Release();
return p_shader;
}
PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__);
return NULL;
}
} // namespace

View File

@ -0,0 +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 "D3DBase.h"
namespace D3D
{
ID3D11VertexShader* CreateVertexShaderFromByteCode(void* bytecode, unsigned int len);
ID3D11PixelShader* CreatePixelShaderFromByteCode(void* bytecode, unsigned int len);
// The returned bytecode buffers should be Release()d.
bool CompileVertexShader(const char* code, unsigned int len, ID3D10Blob** blob);
bool CompilePixelShader(const char* code, unsigned int len, ID3D10Blob** blob);
// Utility functions
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, unsigned int len);
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code, unsigned int len);
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(ID3D10Blob* bytecode) { return CreateVertexShaderFromByteCode(bytecode->GetBufferPointer(), bytecode->GetBufferSize()); }
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(ID3D10Blob* bytecode) { return CreatePixelShaderFromByteCode(bytecode->GetBufferPointer(), bytecode->GetBufferSize()); }
inline ID3D11VertexShader* CompileAndCreateVertexShader(ID3D10Blob* code) { return CompileAndCreateVertexShader((const char*)code->GetBufferPointer(), code->GetBufferSize()); }
inline ID3D11PixelShader* CompileAndCreatePixelShader(ID3D10Blob* code) { return CompileAndCreatePixelShader((const char*)code->GetBufferPointer(), code->GetBufferSize()); }
}

View File

@ -0,0 +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 "d3dx11.h"
#include "D3DBase.h"
#include "D3DTexture.h"
namespace D3D
{
// buffers for storing the data for DEFAULT textures
const char* texbuf = NULL;
unsigned int texbufsize = 0;
void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, DXGI_FORMAT fmt, PC_TexFormat pcfmt, unsigned int level, D3D11_USAGE usage)
{
void* outptr;
unsigned int destPitch;
bool bExpand = false;
if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
{
if (level != 0) PanicAlert("Dynamic textures don't support mipmaps, but given level is not 0 at %s %d\n", __FILE__, __LINE__);
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
outptr = map.pData;
destPitch = map.RowPitch;
}
else if (usage == D3D11_USAGE_DEFAULT)
{
if (texbufsize < 4*width*height)
{
if (texbuf) delete[] texbuf;
texbuf = new char[4*width*height];
texbufsize = 4*width*height;
}
outptr = (void*)texbuf;
destPitch = width * 4;
}
else
{
PanicAlert("ReplaceTexture2D called on an immutable texture!\n");
return;
}
// TODO: Merge the conversions done here to VideoDecoder
switch (pcfmt)
{
case PC_TEX_FMT_IA4_AS_IA8:
case PC_TEX_FMT_IA8:
for (unsigned int y = 0; y < height; y++)
{
u16* in = (u16*)buffer + y * pitch;
u32* pBits = (u32*)((u8*)outptr + y * destPitch);
for (unsigned int x = 0; x < width; x++)
{
const u8 I = (*in & 0xFF);
const u8 A = (*in & 0xFF00) >> 8;
*pBits = (A << 24) | (I << 16) | (I << 8) | I;
in++;
pBits++;
}
}
break;
case PC_TEX_FMT_I8:
case PC_TEX_FMT_I4_AS_I8:
for (unsigned int y = 0; y < height; y++)
{
u8* in = (u8*)buffer + y * pitch;
u32* pBits = (u32*)((u8*)outptr + y * destPitch);
for (unsigned int x = 0; x < width; x++)
{
const u8 col = *in;
*pBits = 0xFF000000 | (col << 16) | (col << 8) | col;
in++;
pBits++;
}
}
break;
case PC_TEX_FMT_BGRA32:
// BGRA32 textures can be uploaded directly to VRAM when using DEFAULT textures
if (usage == D3D11_USAGE_DEFAULT) break;
for (unsigned int y = 0; y < height; y++)
{
u32* in = (u32*)buffer + y * pitch;
u32* pBits = (u32*)((u8*)outptr + y * destPitch);
for (unsigned int x = 0; x < width; x++)
{
const u32 col = *in;
*pBits = col;
in++;
pBits++;
}
}
break;
case PC_TEX_FMT_RGB565:
for (unsigned int y = 0; y < height; y++)
{
u16* in = (u16*)buffer + y * pitch;
u32* pBits = (u32*)((u8*)outptr + y * destPitch);
for (unsigned int x = 0; x < width; x++)
{
const u16 col = *in;
*pBits = 0xFF000000 | (((col&0x1f)<<3)) | ((col&0x7e0)<<5) | ((col&0xF800)<<8);
pBits++;
in++;
}
}
break;
default:
PanicAlert("Unknown tex fmt %d\n", pcfmt);
break;
}
if (usage == D3D11_USAGE_DYNAMIC)
{
// TODO: UpdateSubresource might be faster than mapping
D3D::context->Unmap(pTexture, 0);
}
else if (usage == D3D11_USAGE_DEFAULT)
{
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
if (pcfmt == PC_TEX_FMT_BGRA32)
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*(4*pitch)*height);
else
D3D::context->UpdateSubresource(pTexture, level, &dest_region, outptr, destPitch, 4*width*height);
}
}
} // namespace
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels)
{
ID3D11Texture2D* pTexture = NULL;
HRESULT hr;
D3D11_CPU_ACCESS_FLAG cpuflags;
if (usage == D3D11_USAGE_STAGING) cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE|(int)D3D11_CPU_ACCESS_READ);
else if (usage == D3D11_USAGE_DYNAMIC) cpuflags = D3D11_CPU_ACCESS_WRITE;
else cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture);
if (FAILED(hr))
{
PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__);
return NULL;
}
D3DTexture2D* ret = new D3DTexture2D(pTexture, bind);
pTexture->Release();
return ret;
}
void D3DTexture2D::AddRef()
{
ref++;
}
UINT D3DTexture2D::Release()
{
ref--;
if (ref == 0)
{
delete this;
return 0;
}
return ref;
}
ID3D11Texture2D* &D3DTexture2D::GetTex() { return tex; }
ID3D11ShaderResourceView* &D3DTexture2D::GetSRV() { return srv; }
ID3D11RenderTargetView* &D3DTexture2D::GetRTV() { return rtv; }
ID3D11DepthStencilView* &D3DTexture2D::GetDSV() { return dsv; }
D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind,
DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format)
: ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D, srv_format);
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, dsv_format);
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D, rtv_format);
if (bind & D3D11_BIND_SHADER_RESOURCE) D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv);
if (bind & D3D11_BIND_RENDER_TARGET) D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
if (bind & D3D11_BIND_DEPTH_STENCIL) D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
tex->AddRef();
}
D3DTexture2D::~D3DTexture2D()
{
if (srv) srv->Release();
if (rtv) rtv->Release();
if (dsv) dsv->Release();
tex->Release();
}

View File

@ -0,0 +1,56 @@
// 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 "D3DBase.h"
#include "TextureDecoder.h"
namespace D3D
{
void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, DXGI_FORMAT fmt, PC_TexFormat pcfmt, unsigned int level, D3D11_USAGE usage);
}
class D3DTexture2D
{
public:
// there are two ways to create a D3DTexture2D object:
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create
// or let the texture automatically be created by D3DTexture2D::Create
D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN);
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt = DXGI_FORMAT_B8G8R8A8_UNORM, unsigned int levels = 1);
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore
void AddRef();
UINT Release();
ID3D11Texture2D* &GetTex();
ID3D11ShaderResourceView* &GetSRV();
ID3D11RenderTargetView* &GetRTV();
ID3D11DepthStencilView* &GetDSV();
private:
~D3DTexture2D();
ID3D11Texture2D* tex;
ID3D11ShaderResourceView* srv;
ID3D11RenderTargetView* rtv;
ID3D11DepthStencilView* dsv;
D3D11_BIND_FLAG bindflags;
UINT ref;
};

View File

@ -0,0 +1,610 @@
// 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 "D3DBase.h"
#include "D3DUtil.h"
#include "D3DTexture.h"
#include "Render.h"
#include "PixelShaderCache.h"
#include "VertexShaderCache.h"
#include "D3DShader.h"
namespace D3D
{
CD3DFont font;
#define MAX_NUM_VERTICES 300
struct FONT2DVERTEX {
float x,y,z;
float col[4];
float tu, tv;
};
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.tu = tu; v.tv = tv;
v.col[0] = ((float)((color >> 16) & 0xFF)) / 255.f;
v.col[1] = ((float)((color >> 8) & 0xFF)) / 255.f;
v.col[2] = ((float)((color >> 0) & 0xFF)) / 255.f;
v.col[3] = ((float)((color >> 24) & 0xFF)) / 255.f;
return v;
}
CD3DFont::CD3DFont() : m_dwTexWidth(512), m_dwTexHeight(512)
{
m_pTexture = NULL;
m_pVB = NULL;
m_InputLayout = NULL;
m_pshader = NULL;
m_vshader = NULL;
}
const char fontpixshader[] = {
"Texture2D tex2D;\n"
"SamplerState linearSampler\n"
"{\n"
" Filter = MIN_MAG_MIP_LINEAR;\n"
" AddressU = Wrap;\n"
" AddressV = Wrap;\n"
"};\n"
"struct PS_INPUT\n"
"{\n"
" float4 pos : SV_POSITION;\n"
" float4 col : COLOR;\n"
" float2 tex : TEXCOORD;\n"
"};\n"
"float4 main( PS_INPUT input ) : SV_Target\n"
"{\n"
" return tex2D.Sample( linearSampler, input.tex ) * input.col;\n"
"};\n"
};
const char fontvertshader[] = {
"struct VS_INPUT\n"
"{\n"
" float4 pos : POSITION;\n"
" float4 col : COLOR;\n"
" float2 tex : TEXCOORD;\n"
"};\n"
"struct PS_INPUT\n"
"{\n"
" float4 pos : SV_POSITION;\n"
" float4 col : COLOR;\n"
" float2 tex : TEXCOORD;\n"
"};\n"
"PS_INPUT main( VS_INPUT input )\n"
"{\n"
" PS_INPUT output;\n"
" output.pos = input.pos;\n"
" output.col = input.col;\n"
" output.tex = input.tex;\n"
" return output;\n"
"};\n"
};
int CD3DFont::Init()
{
HRESULT hr;
// prepare to create a bitmap
unsigned 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 GDI font
int m_dwFontHeight = 24;
int nHeight = -MulDiv(m_dwFontHeight, (int)GetDeviceCaps(hDC, LOGPIXELSY), 72);
int dwBold = FW_NORMAL;
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 characters 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
// possible optimization: store the converted data in a buffer and fill the texture on creation.
// That way, we can use a static texture
ID3D11Texture2D* buftex;
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, m_dwTexWidth, m_dwTexHeight,
1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC,
D3D11_CPU_ACCESS_WRITE);
hr = device->CreateTexture2D(&texdesc, NULL, &buftex);
if (FAILED(hr))
{
PanicAlert("Failed to create font texture");
return hr;
}
// lock the surface and write the alpha values for the set pixels
D3D11_MAPPED_SUBRESOURCE texmap;
hr = context->Map(buftex, 0, D3D11_MAP_WRITE_DISCARD, 0, &texmap);
if (FAILED(hr)) PanicAlert("Failed to map a texture at %s %d\n", __FILE__, __LINE__);
for (y = 0; y < m_dwTexHeight; y++)
{
u32* pDst32 = (u32*)((u8*)texmap.pData + y * texmap.RowPitch);
for (x = 0; x < m_dwTexWidth; x++)
{
const u8 bAlpha = (pBitmapBits[m_dwTexWidth * y + x] & 0xff);
pDst32[x] = ((bAlpha * 255 / 15) << 24) | 0xFFFFFF;
}
}
// clean up
context->Unmap(buftex, 0);
hr = D3D::device->CreateShaderResourceView(buftex, NULL, &m_pTexture);
if (FAILED(hr)) PanicAlert("Failed to create shader resource view at %s %d\n", __FILE__, __LINE__);
buftex->Release();
SelectObject(hDC, hOldbmBitmap);
DeleteObject(hbmBitmap);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
// setup device objects for drawing
m_pshader = D3D::CompileAndCreatePixelShader(fontpixshader, sizeof(fontpixshader));
if (m_pshader == NULL) PanicAlert("Failed to create pixel shader, %s %d\n", __FILE__, __LINE__);
ID3D10Blob* vsbytecode;
D3D::CompileVertexShader(fontvertshader, sizeof(fontvertshader), &vsbytecode);
if (vsbytecode == NULL) PanicAlert("Failed to compile vertex shader, %s %d\n", __FILE__, __LINE__);
m_vshader = D3D::CreateVertexShaderFromByteCode(vsbytecode);
if (m_vshader == NULL) PanicAlert("Failed to create vertex shader, %s %d\n", __FILE__, __LINE__);
const D3D11_INPUT_ELEMENT_DESC desc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = D3D::device->CreateInputLayout(desc, 3, vsbytecode->GetBufferPointer(), vsbytecode->GetBufferSize(), &m_InputLayout);
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
vsbytecode->Release();
D3D11_BLEND_DESC blenddesc;
blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE;
blenddesc.RenderTarget[0].BlendEnable = TRUE;
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
D3D::device->CreateBlendState(&blenddesc, &m_blendstate);
// this might need to be changed when adding multisampling support
D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0.f, false, false, false, false);
D3D::device->CreateRasterizerState(&rastdesc, &m_raststate);
D3D11_BUFFER_DESC vbdesc = CD3D11_BUFFER_DESC(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
if (FAILED(hr = device->CreateBuffer(&vbdesc, NULL, &m_pVB)))
{
PanicAlert("Failed to create vertex buffer!\n");
return hr;
}
return S_OK;
}
int CD3DFont::Shutdown()
{
SAFE_RELEASE(m_pVB);
SAFE_RELEASE(m_pTexture);
SAFE_RELEASE(m_InputLayout);
SAFE_RELEASE(m_pshader);
SAFE_RELEASE(m_vshader);
SAFE_RELEASE(m_blendstate);
SAFE_RELEASE(m_raststate);
return S_OK;
}
int CD3DFont::DrawTextScaled(float x, float y, float scale, float spacing, u32 dwColor, const char* strText, bool center)
{
if (!m_pVB) return 0;
UINT stride = sizeof(FONT2DVERTEX);
UINT bufoffset = 0;
float sx = x;
float sy = y;
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;
D3D11_MAPPED_SUBRESOURCE vbmap;
HRESULT hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap);
if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__);
pVertices = (D3D::FONT2DVERTEX*)vbmap.pData;
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 *= scale*invLineHeight;
mx += w + spacing*scale;
if (mx > maxx) maxx = mx;
}
float offset = -maxx/2;
strText = oldstrText;
//Then let's draw it
if (center)
{
sx += offset;
fStartX += offset;
}
float wScale = scale*invLineHeight;
float hScale = scale*invLineHeight;
// set general pipeline state
D3D::context->OMSetBlendState(m_blendstate, NULL, 0xFFFFFFFF);
D3D::context->RSSetState(m_raststate);
D3D::context->PSSetShader(m_pshader, NULL, 0);
D3D::context->VSSetShader(m_vshader, NULL, 0);
D3D::context->IASetInputLayout(m_InputLayout);
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::context->PSSetShaderResources(0, 1, &m_pTexture);
while (*strText)
{
char c = *strText++;
if (c == ('\n'))
{
sx = fStartX;
sy += scale;
}
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/2;
float h = (ty2-ty1)*m_dwTexHeight/2;
FONT2DVERTEX v[6];
v[0] = InitFont2DVertex( sx /m_dwTexWidth-1.f, 1-((sy+h)/m_dwTexHeight), dwColor, tx1, ty2);
v[1] = InitFont2DVertex( sx /m_dwTexWidth-1.f, 1-( sy /m_dwTexHeight), dwColor, tx1, ty1);
v[2] = InitFont2DVertex((sx+w)/m_dwTexWidth-1.f, 1-((sy+h)/m_dwTexHeight), dwColor, tx2, ty2);
v[3] = InitFont2DVertex((sx+w)/m_dwTexWidth-1.f, 1-( sy /m_dwTexHeight), 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))
{
context->Unmap(m_pVB, 0);
D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset);
D3D::context->Draw(3 * dwNumTriangles, 0);
dwNumTriangles = 0;
D3D11_MAPPED_SUBRESOURCE vbmap;
HRESULT hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap);
if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__);
pVertices = (D3D::FONT2DVERTEX*)vbmap.pData;
}
sx += w + spacing*scale;
}
// Unlock and render the vertex buffer
context->Unmap(m_pVB, 0);
if (dwNumTriangles > 0)
{
D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset);
D3D::context->Draw(3 * dwNumTriangles, 0);
}
D3D::gfxstate->SetShaderResource(0, NULL);
return S_OK;
}
ID3D11Buffer* CreateQuadVertexBuffer(unsigned int size, void* data)
{
ID3D11Buffer* vb;
D3D11_BUFFER_DESC vbdesc;
vbdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbdesc.ByteWidth = size;
vbdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vbdesc.MiscFlags = 0;
vbdesc.Usage = D3D11_USAGE_DYNAMIC;
if (data)
{
D3D11_SUBRESOURCE_DATA bufdata;
bufdata.pSysMem = data;
if (FAILED(device->CreateBuffer(&vbdesc, &bufdata, &vb))) return NULL;
}
else if (FAILED(device->CreateBuffer(&vbdesc, NULL, &vb))) return NULL;
return vb;
}
ID3D11SamplerState* stqsamplerstate = NULL;
ID3D11SamplerState* stsqsamplerstate = NULL;
ID3D11Buffer* stqvb = NULL;
ID3D11Buffer* stsqvb = NULL;
ID3D11Buffer* clearvb = NULL;
typedef struct { float x,y,z,u,v; } STQVertex;
typedef struct { float x,y,z,u,v; } STSQVertex;
typedef struct { float x,y,z; float col[4];} ClearVertex;
void InitUtils()
{
float border[4] = { 0.f, 0.f, 0.f, 0.f };
D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
HRESULT hr = D3D::device->CreateSamplerState(&samDesc, &stqsamplerstate);
if (FAILED(hr)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__);
else SetDebugObjectName((ID3D11DeviceChild*)stqsamplerstate, "sampler state of drawShadedTexQuad");
stqvb = CreateQuadVertexBuffer(4*sizeof(STQVertex), NULL);
SetDebugObjectName((ID3D11DeviceChild*)stqvb, "vertex buffer of drawShadedTexQuad");
stsqvb = CreateQuadVertexBuffer(4*sizeof(STSQVertex), NULL);
SetDebugObjectName((ID3D11DeviceChild*)stsqvb, "vertex buffer of drawShadedTexSubQuad");
clearvb = CreateQuadVertexBuffer(4*sizeof(ClearVertex), NULL);
SetDebugObjectName((ID3D11DeviceChild*)clearvb, "vertex buffer of drawClearQuad");
samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
hr = D3D::device->CreateSamplerState(&samDesc, &stsqsamplerstate);
if (FAILED(hr)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__);
else SetDebugObjectName((ID3D11DeviceChild*)stsqsamplerstate, "sampler state of drawShadedTexSubQuad");
}
void ShutdownUtils()
{
SAFE_RELEASE(stqsamplerstate);
SAFE_RELEASE(stsqsamplerstate);
SAFE_RELEASE(stqvb);
SAFE_RELEASE(stsqvb);
SAFE_RELEASE(clearvb);
}
void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
const D3D11_RECT* rSource,
int SourceWidth,
int SourceHeight,
ID3D11PixelShader* PShader,
ID3D11VertexShader* Vshader,
ID3D11InputLayout* layout)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
float u1 = ((float)rSource->left) * sw;
float u2 = ((float)rSource->right) * sw;
float v1=((float)rSource->top) * sh;
float v2=((float)rSource->bottom) * sh;
static float lastu1 = 0.f, lastv1 = 0.f, lastu2 = 0.f, lastv2 = 0.f;
STQVertex coords[4] = {
{-1.0f, 1.0f, 0.0f, u1, v1},
{ 1.0f, 1.0f, 0.0f, u2, v1},
{-1.0f,-1.0f, 0.0f, u1, v2},
{ 1.0f,-1.0f, 0.0f, u2, v2},
};
// only upload the data to VRAM if it changed
if (lastu1 != u1 || lastv1 != v1 || lastu2 != u2 || lastv2 != v2)
{
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(stqvb, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, coords, sizeof(coords));
D3D::context->Unmap(stqvb, 0);
}
UINT stride = sizeof(STQVertex);
UINT offset = 0;
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D::context->IASetInputLayout(layout);
D3D::context->IASetVertexBuffers(0, 1, &stqvb, &stride, &offset);
D3D::context->PSSetSamplers(0, 1, &stqsamplerstate);
D3D::context->PSSetShader(PShader, NULL, 0);
D3D::context->PSSetShaderResources(0, 1, &texture);
D3D::context->VSSetShader(Vshader, NULL, 0);
D3D::context->Draw(4, 0);
ID3D11ShaderResourceView* texres = NULL;
context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture
D3D::gfxstate->SetShaderResource(0, NULL);
lastu1 = u1;
lastv1 = v1;
lastu2 = u2;
lastv2 = v2;
}
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
const MathUtil::Rectangle<float>* rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float>* rDest,
ID3D11PixelShader* PShader,
ID3D11VertexShader* Vshader,
ID3D11InputLayout* layout)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
float u1 = (rSource->left ) * sw;
float u2 = (rSource->right ) * sw;
float v1 = (rSource->top ) * sh;
float v2 = (rSource->bottom) * sh;
static MathUtil::Rectangle<float> lastrdest = {0.f};
static float lastu1 = 0.f, lastv1 = 0.f, lastu2 = 0.f, lastv2 = 0.f;
STSQVertex coords[4] = {
{ rDest->left , rDest->bottom, 0.0f, u1, v1},
{ rDest->right, rDest->bottom, 0.0f, u2, v1},
{ rDest->left , rDest->top , 0.0f, u1, v2},
{ rDest->right, rDest->top , 0.0f, u2, v2},
};
// only upload the data to VRAM if it changed
if (memcmp(rDest, &lastrdest, sizeof(lastrdest)) != 0 || lastu1 != u1 || lastv1 != v1 || lastu2 != u2 || lastv2 != v2)
{
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(stsqvb, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, coords, sizeof(coords));
D3D::context->Unmap(stsqvb, 0);
}
UINT stride = sizeof(STSQVertex);
UINT offset = 0;
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
context->IASetVertexBuffers(0, 1, &stsqvb, &stride, &offset);
context->IASetInputLayout(layout);
context->PSSetShaderResources(0, 1, &texture);
context->PSSetSamplers(0, 1, &stsqsamplerstate);
context->PSSetShader(PShader, NULL, 0);
context->VSSetShader(Vshader, NULL, 0);
context->Draw(4, 0);
ID3D11ShaderResourceView* texres = NULL;
context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture
D3D::gfxstate->SetShaderResource(0, NULL);
lastu1 = u1;
lastv1 = v1;
lastu2 = u2;
lastv2 = v2;
lastrdest.left = rDest->left;
lastrdest.right = rDest->right;
lastrdest.top = rDest->top;
lastrdest.bottom = rDest->bottom;
}
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout)
{
static u32 lastcol = 0;
static float lastz = -15325.376f; // random value
if (lastcol != Color || lastz != z)
{
float col[4];
col[0] = (float)((Color & 0xFF) << 24);
col[1] = (float)((Color & 0xFF00) << 8);
col[2] = (float)((Color & 0xFF0000) >> 8);
col[3] = (float)((Color & 0xFF000000) >> 24);
ClearVertex coords[4] = {
{-1.0f, 1.0f, z, {col[0],col[1],col[2],col[3]}},
{ 1.0f, 1.0f, z, {col[0],col[1],col[2],col[3]}},
{-1.0f, -1.0f, z, {col[0],col[1],col[2],col[3]}},
{ 1.0f, -1.0f, z, {col[0],col[1],col[2],col[3]}},
};
D3D11_MAPPED_SUBRESOURCE map;
context->Map(clearvb, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, coords, sizeof(coords));
context->Unmap(clearvb, 0);
}
context->VSSetShader(Vshader, NULL, 0);
context->PSSetShader(PShader, NULL, 0);
context->IASetInputLayout(layout);
UINT stride = sizeof(ClearVertex);
UINT offset = 0;
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
context->IASetVertexBuffers(0, 1, &clearvb, &stride, &offset);
context->Draw(4, 0);
lastcol = Color;
lastz = z;
}
} // namespace

View File

@ -0,0 +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/
#pragma once
#include "D3DBase.h"
#include <math.h>
#include <MathUtil.h>
namespace D3D
{
// Font creation flags
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
// Font rendering flags
#define D3DFONT_CENTERED 0x0001
class CD3DFont
{
ID3D11ShaderResourceView* m_pTexture;
ID3D11Buffer* m_pVB;
ID3D11InputLayout* m_InputLayout;
ID3D11PixelShader* m_pshader;
ID3D11VertexShader* m_vshader;
ID3D11BlendState* m_blendstate;
ID3D11RasterizerState* m_raststate;
const int m_dwTexWidth;
const int m_dwTexHeight;
float m_fTexCoords[128-32][4];
public:
CD3DFont();
// 2D text drawing function
// Initializing and destroying device-dependent objects
int Init();
int Shutdown();
int DrawTextScaled(float x, float y,
float scale,
float spacing, u32 dwColor,
const char* strText, bool center=true);
};
extern CD3DFont font;
void InitUtils();
void ShutdownUtils();
void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
const D3D11_RECT* rSource,
int SourceWidth,
int SourceHeight,
ID3D11PixelShader* PShader,
ID3D11VertexShader* VShader,
ID3D11InputLayout* layout);
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
const MathUtil::Rectangle<float>* rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float>* rDest,
ID3D11PixelShader* PShader,
ID3D11VertexShader* Vshader,
ID3D11InputLayout* layout);
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
void SaveRenderStates();
void RestoreRenderStates();
}

View File

@ -0,0 +1,225 @@
// 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 <windowsx.h>
#include "resource.h"
#include "W32Util/PropertySheet.h"
#include "FileUtil.h"
#include "D3DBase.h"
#include "VideoConfig.h"
#include "TextureCache.h"
const char* aspect_ratio_names[4] = {
"Auto",
"Force 16:9 Widescreen",
"Force 4:3 Standard",
"Stretch to Window",
};
struct TabDirect3D : public W32Util::Tab
{
void Init(HWND hDlg)
{
WCHAR tempwstr[2000];
for (int i = 0; i < 4; i++)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, aspect_ratio_names[i], -1, tempwstr, 2000);
ComboBox_AddString(GetDlgItem(hDlg, IDC_ASPECTRATIO), tempwstr);
}
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ASPECTRATIO), g_Config.iAspectRatio);
Button_SetCheck(GetDlgItem(hDlg, IDC_WIDESCREEN_HACK), g_Config.bWidescreenHack);
Button_SetCheck(GetDlgItem(hDlg, IDC_VSYNC), g_Config.bVSync);
Button_SetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE), g_Config.bSafeTextureCache);
if (g_Config.iSafeTextureCache_ColorSamples == 0)
{
Button_SetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_SAFE), true);
}
else
{
if (g_Config.iSafeTextureCache_ColorSamples > 128)
{
Button_SetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_NORMAL), true);
}
else
{
Button_SetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_FAST), true);
}
}
Button_Enable(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_SAFE), g_Config.bSafeTextureCache);
Button_Enable(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_NORMAL), g_Config.bSafeTextureCache);
Button_Enable(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_FAST), g_Config.bSafeTextureCache);
Button_SetCheck(GetDlgItem(hDlg, IDC_EFB_ACCESS_ENABLE), g_Config.bEFBAccessEnable);
}
void Command(HWND hDlg,WPARAM wParam)
{
switch (LOWORD(wParam))
{
case IDC_ASPECTRATIO:
g_Config.iAspectRatio = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ASPECTRATIO));
break;
case IDC_VSYNC:
g_Config.bVSync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
break;
case IDC_WIDESCREEN_HACK:
g_Config.bWidescreenHack = Button_GetCheck(GetDlgItem(hDlg, IDC_WIDESCREEN_HACK)) ? true : false;
break;
case IDC_SAFE_TEXTURE_CACHE:
g_Config.bSafeTextureCache = Button_GetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE)) == 0 ? false : true;
Button_Enable(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_SAFE), g_Config.bSafeTextureCache);
Button_Enable(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_NORMAL), g_Config.bSafeTextureCache);
Button_Enable(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_FAST), g_Config.bSafeTextureCache);
break;
case IDC_EFB_ACCESS_ENABLE:
g_Config.bEFBAccessEnable = Button_GetCheck(GetDlgItem(hDlg, IDC_EFB_ACCESS_ENABLE)) == 0 ? false : true;
break;
default:
break;
}
}
void Apply(HWND hDlg)
{
if (Button_GetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_SAFE)))
{
g_Config.iSafeTextureCache_ColorSamples = 0;
}
else
{
if (Button_GetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE_NORMAL)))
{
if (g_Config.iSafeTextureCache_ColorSamples < 512)
{
g_Config.iSafeTextureCache_ColorSamples = 512;
}
}
else
{
if (g_Config.iSafeTextureCache_ColorSamples > 128 || g_Config.iSafeTextureCache_ColorSamples == 0)
{
g_Config.iSafeTextureCache_ColorSamples = 128;
}
}
}
g_Config.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_dx11.ini").c_str());
}
};
struct TabAdvanced : public W32Util::Tab
{
void Init(HWND hDlg)
{
Button_SetCheck(GetDlgItem(hDlg, IDC_OSDHOTKEY), g_Config.bOSDHotKey);
Button_SetCheck(GetDlgItem(hDlg, IDC_OVERLAYFPS), g_Config.bShowFPS);
Button_SetCheck(GetDlgItem(hDlg, IDC_OVERLAYSTATS), g_Config.bOverlayStats);
Button_SetCheck(GetDlgItem(hDlg, IDC_OVERLAYPROJSTATS), g_Config.bOverlayProjStats);
Button_SetCheck(GetDlgItem(hDlg, IDC_WIREFRAME), g_Config.bWireFrame);
Button_SetCheck(GetDlgItem(hDlg, IDC_DISABLEFOG), g_Config.bDisableFog);
Button_SetCheck(GetDlgItem(hDlg, IDC_ENABLEEFBCOPY), !g_Config.bEFBCopyDisable);
Button_SetCheck(GetDlgItem(hDlg, IDC_TEXFMT_OVERLAY), g_Config.bTexFmtOverlayEnable);
Button_SetCheck(GetDlgItem(hDlg, IDC_TEXFMT_CENTER), g_Config.bTexFmtOverlayCenter);
Button_GetCheck(GetDlgItem(hDlg, IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
Button_SetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY),g_Config.iMaxAnisotropy > 1);
Button_SetCheck(GetDlgItem(hDlg, IDC_EFBSCALEDCOPY), g_Config.bCopyEFBScaled);
if (Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEEFBCOPY))) Button_Enable(GetDlgItem(hDlg,IDC_EFBSCALEDCOPY), true);
else Button_Enable(GetDlgItem(hDlg, IDC_EFBSCALEDCOPY), false);
}
void Command(HWND hDlg,WPARAM wParam)
{
switch (LOWORD(wParam))
{
case IDC_TEXFMT_OVERLAY:
Button_GetCheck(GetDlgItem(hDlg, IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg, IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg, IDC_TEXFMT_CENTER), false);
break;
case IDC_ENABLEEFBCOPY:
if (Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEEFBCOPY))) Button_Enable(GetDlgItem(hDlg, IDC_EFBSCALEDCOPY), true);
else Button_Enable(GetDlgItem(hDlg, IDC_EFBSCALEDCOPY), false);
break;
default: break;
}
}
void Apply(HWND hDlg)
{
g_Config.bTexFmtOverlayEnable = Button_GetCheck(GetDlgItem(hDlg, IDC_TEXFMT_OVERLAY)) ? true : false;
g_Config.bTexFmtOverlayCenter = Button_GetCheck(GetDlgItem(hDlg, IDC_TEXFMT_CENTER)) ? true : false;
g_Config.bOSDHotKey = Button_GetCheck(GetDlgItem(hDlg, IDC_OSDHOTKEY)) ? true : false;
g_Config.bShowFPS = Button_GetCheck(GetDlgItem(hDlg, IDC_OVERLAYFPS)) ? true : false;
g_Config.bOverlayStats = Button_GetCheck(GetDlgItem(hDlg, IDC_OVERLAYSTATS)) ? true : false;
g_Config.bOverlayProjStats = Button_GetCheck(GetDlgItem(hDlg, IDC_OVERLAYPROJSTATS)) ? true : false;
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg, IDC_WIREFRAME)) ? true : false;
g_Config.bDisableFog = Button_GetCheck(GetDlgItem(hDlg, IDC_DISABLEFOG)) ? true : false;
g_Config.bEFBCopyDisable = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEEFBCOPY)) ? false : true;
g_Config.bCopyEFBToTexture = !g_Config.bEFBCopyDisable;
g_Config.bDumpTextures = false;
g_Config.bDumpFrames = false;
g_Config.bShowShaderErrors = true;
g_Config.bUseNativeMips = true;
g_Config.iMaxAnisotropy = Button_GetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY)) ? 8 : 1;
g_Config.bForceFiltering = false;
g_Config.bHiresTextures = false;
g_Config.bCopyEFBScaled = Button_GetCheck(GetDlgItem(hDlg, IDC_EFBSCALEDCOPY)) ? true : false;
g_Config.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_dx11.ini").c_str());
}
};
struct TabAbout : public W32Util::Tab
{
void Init(HWND hDlg) {}
void Command(HWND hDlg,WPARAM wParam) {}
void Apply(HWND hDlg) {}
};
void DlgSettings_Show(HINSTANCE hInstance, HWND _hParent)
{
bool tfoe = g_Config.bTexFmtOverlayEnable;
bool tfoc = g_Config.bTexFmtOverlayCenter;
g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_dx11.ini").c_str());
W32Util::PropSheet sheet;
sheet.Add(new TabDirect3D, (LPCTSTR)IDD_SETTINGS, _T("Direct3D"));
sheet.Add(new TabAdvanced, (LPCTSTR)IDD_ADVANCED, _T("Advanced"));
sheet.Add(new TabAbout, (LPCTSTR)IDD_ABOUT, _T("About"));
#ifdef DEBUGFAST
sheet.Show(hInstance,_hParent,_T("DX11 Graphics Plugin (DEBUGFAST)"));
#elif defined _DEBUG
sheet.Show(hInstance,_hParent,_T("DX11 Graphics Plugin"));
#else
sheet.Show(hInstance,_hParent,_T("DX11 Graphics Plugin (DEBUG)"));
#endif
if ((tfoe != g_Config.bTexFmtOverlayEnable) ||
((g_Config.bTexFmtOverlayEnable) && ( tfoc != g_Config.bTexFmtOverlayCenter)))
{
TextureCache::Invalidate(false);
}
}

View File

@ -0,0 +1,20 @@
// 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
void DlgSettings_Show(HINSTANCE hInstance, HWND parent);

View File

@ -0,0 +1,246 @@
// 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 <windows.h>
#include "VideoConfig.h"
#include "main.h"
#include "EmuWindow.h"
#include "D3DBase.h"
#include "Fifo.h"
int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0;
namespace EmuWindow
{
HWND m_hWnd = NULL;
HWND m_hParent = NULL;
HINSTANCE m_hInstance = NULL;
WNDCLASSEX wndClass;
const TCHAR m_szClassName[] = _T("DolphinEmuWnd");
int g_winstyle;
static volatile bool s_sizing;
bool IsSizing()
{
return s_sizing;
}
HWND GetWnd()
{
return m_hWnd;
}
HWND GetParentWnd()
{
return m_hParent;
}
// ---------------------------------------------------------------------
// KeyDown events
// -------------
void OnKeyDown(WPARAM wParam)
{
switch (LOWORD( wParam ))
{
case '3': // OSD keys
case '4':
case '5':
case '6':
case '7':
if (g_Config.bOSDHotKey)
OSDMenu(wParam);
break;
}
}
// ---------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
switch( iMsg )
{
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
case WM_ENTERSIZEMOVE:
s_sizing = true;
break;
case WM_EXITSIZEMOVE:
s_sizing = false;
break;
/* Post thes mouse events to the main window, it's nessesary because in difference to the
keyboard inputs these events only appear here, not in the parent window or any other WndProc()*/
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
PostMessage(GetParentWnd(), iMsg, wParam, lParam);
break;
case WM_CLOSE:
// When the user closes the window, we post an event to the main window to call Stop()
// Which then handles all the necessary steps to Shutdown the core + the plugins
if (m_hParent == NULL)
PostMessage(m_hParent, WM_USER, WM_USER_STOP, 0);
break;
case WM_USER:
if (wParam == WM_USER_KEYDOWN)
OnKeyDown(lParam);
else if (wParam == WIIMOTE_DISCONNECT)
PostMessage(m_hParent, WM_USER, wParam, lParam);
break;
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
break;
default:
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
break;
case WM_SETCURSOR:
PostMessage(m_hParent, WM_USER, WM_USER_SETCURSOR, 0);
return true;
break;
default:
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
return 0;
}
// ---------------------------------------------------------------------
// OSD Menu
// -------------
// Let's begin with 3 since 1 and 2 are default Wii keys
// -------------
void OSDMenu(WPARAM wParam)
{
switch( LOWORD( wParam ))
{
case '3':
OSDChoice = 1;
// Toggle native resolution
OSDInternalW = D3D::GetBackBufferWidth();
OSDInternalH = D3D::GetBackBufferHeight();
break;
case '4':
OSDChoice = 2;
// Toggle aspect ratio
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
break;
case '5':
OSDChoice = 3;
PanicAlert("Toggling EFB copy not implemented!\n");
break;
case '6':
OSDChoice = 4;
g_Config.bDisableFog = !g_Config.bDisableFog;
break;
case '7':
OSDChoice = 5;
g_Config.bDisableLighting = !g_Config.bDisableLighting;
break;
}
}
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
{
wndClass.cbSize = sizeof( wndClass );
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndClass.hCursor = NULL;
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_szClassName;
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
m_hInstance = hInstance;
RegisterClassEx( &wndClass );
m_hParent = parent;
m_hWnd = CreateWindow(m_szClassName, title, WS_CHILD,
0, 0, width, height, m_hParent, NULL, hInstance, NULL);
return m_hWnd;
}
void Show()
{
ShowWindow(m_hWnd, SW_SHOW);
BringWindowToTop(m_hWnd);
UpdateWindow(m_hWnd);
SetFocus(m_hParent);
}
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
{
// TODO:
// 1. Remove redundant window manipulation,
// 2. Make DX11 in fullscreen can be overlapped by other dialogs
HWND Ret;
int x=0, y=0, width=640, height=480;
g_VideoInitialize.pRequestWindowSize(x, y, width, height);
Ret = OpenWindow(hParent, hInstance, width, height, title);
if (Ret)
{
Show();
}
return Ret;
}
void Close()
{
if (m_hParent == NULL)
DestroyWindow(m_hWnd);
UnregisterClass(m_szClassName, m_hInstance);
}
void SetSize(int width, int height)
{
RECT rc = {0, 0, width, height};
DWORD style = GetWindowLong(m_hWnd, GWL_STYLE);
AdjustWindowRect(&rc, style, false);
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
rc.left = (1280 - w)/2;
rc.right = rc.left + w;
rc.top = (1024 - h)/2;
rc.bottom = rc.top + h;
MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
}
}

View File

@ -0,0 +1,20 @@
#ifndef _EMUWINDOW_H
#define _EMUWINDOW_H
#include <windows.h>
namespace EmuWindow
{
HWND GetWnd();
HWND GetParentWnd();
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR* title);
void Show();
void Close();
void SetSize(int displayWidth, int displayHeight);
bool IsSizing();
void OSDMenu(WPARAM wParam);
}
#endif

View File

@ -0,0 +1,314 @@
// 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 "D3DBase.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "Render.h"
#include "FBManager.h"
#include "VideoConfig.h"
#include "PixelShaderCache.h"
#include "VertexShaderCache.h"
#undef CHECK
#define CHECK(cond, Message) if (!(cond)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: %s" , __FILE__, __LINE__, Message); }
FramebufferManager FBManager;
ID3D11SamplerState* copytoVirtualXFBsampler = NULL;
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; }
ID3D11Texture2D* &FramebufferManager::GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
D3DTexture2D* &FramebufferManager::GetEFBDepthTexture() { return m_efb.depth_tex; }
D3DTexture2D* &FramebufferManager::GetEFBDepthReadTexture() { return m_efb.depth_read_texture; }
ID3D11Texture2D* &FramebufferManager::GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
void FramebufferManager::Create()
{
unsigned int target_width = Renderer::GetFullTargetWidth();
unsigned int target_height = Renderer::GetFullTargetHeight();
ID3D11Texture2D* buf;
D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr;
// create framebuffer color texture
m_efb.color_tex = D3DTexture2D::Create(target_width, target_height, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_B8G8R8A8_UNORM);
CHECK(m_efb.color_tex != NULL, "create EFB color texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
// create a staging texture for Renderer::AccessEFB
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf);
CHECK(hr==S_OK, "create EFB color staging buffer");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
// EFB depth buffer
// TODO: Only bind as shader resource if EFB access enabled
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
CHECK(hr==S_OK, "create EFB depth texture");
m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT);
buf->Release();
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
// render target for depth buffer access in Renderer::AccessEFB
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, D3D11_BIND_RENDER_TARGET);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf);
CHECK(hr==S_OK, "create EFB depth read texture");
m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
buf->Release();
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)");
// staging texture to which we copy the data from m_efb.depth_read_texture
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 4, 4, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.depth_staging_buf);
CHECK(hr==S_OK, "create EFB depth staging buffer");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
// sampler state for FramebufferManager::copyToVirtualXFB
float border[4] = {0.f, 0.f, 0.f, 0.f};
D3D11_SAMPLER_DESC samplerdesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX);
D3D::device->CreateSamplerState(&samplerdesc, &copytoVirtualXFBsampler);
D3D::SetDebugObjectName((ID3D11DeviceChild*)copytoVirtualXFBsampler, "sampler state used for FramebufferManager::copyToVirtualXFB");
}
void FramebufferManager::Destroy()
{
SAFE_RELEASE(m_efb.color_tex);
SAFE_RELEASE(m_efb.color_staging_buf);
SAFE_RELEASE(m_efb.depth_tex);
SAFE_RELEASE(m_efb.depth_staging_buf);
SAFE_RELEASE(m_efb.depth_read_texture);
SAFE_RELEASE(copytoVirtualXFBsampler);
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
SAFE_RELEASE(it->xfbSource.tex);
m_virtualXFBList.clear();
SAFE_RELEASE(m_realXFBSource.tex);
}
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
}
const XFBSource** FramebufferManager::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
}
FramebufferManager::VirtualXFBListType::iterator FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{
u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator it;
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{
u32 dstLower = it->xfbAddr;
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper)
return it;
}
// that address is not in the Virtual XFB list.
return m_virtualXFBList.end();
}
void FramebufferManager::replaceVirtualXFB()
{
VirtualXFBListType::iterator it = m_virtualXFBList.begin();
s32 srcLower = it->xfbAddr;
s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
s32 lineSize = 2 * it->xfbWidth;
it++;
while (it != m_virtualXFBList.end())
{
s32 dstLower = it->xfbAddr;
s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (dstLower >= srcLower && dstUpper <= srcUpper)
{
// invalidate the data
it->xfbAddr = 0;
it->xfbHeight = 0;
it->xfbWidth = 0;
}
else if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{
s32 upperOverlap = (srcUpper - dstLower) / lineSize;
s32 lowerOverlap = (dstUpper - srcLower) / lineSize;
if (upperOverlap > 0 && lowerOverlap < 0)
{
it->xfbAddr += lineSize * upperOverlap;
it->xfbHeight -= upperOverlap;
}
else if (lowerOverlap > 0)
{
it->xfbHeight -= lowerOverlap;
}
}
it++;
}
}
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
// TODO
PanicAlert("copyToRealXFB not implemented, yet\n");
}
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
{
D3DTexture2D* xfbTex;
HRESULT hr = 0;
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
if (it == m_virtualXFBList.end() && (int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
{
PanicAlert("Requested creating a new virtual XFB although the maximum number has already been reached! Report this to the devs");
return;
}
float scaleX = Renderer::GetTargetScaleX();
float scaleY = Renderer::GetTargetScaleY();
TargetRectangle targetSource,efbSource;
efbSource = Renderer::ConvertEFBRectangle(sourceRc);
targetSource.top = (int)(sourceRc.top * scaleY);
targetSource.bottom = (int)(sourceRc.bottom * scaleY);
targetSource.left = (int)(sourceRc.left * scaleX);
targetSource.right = (int)(sourceRc.right * scaleX);
unsigned int target_width = targetSource.right - targetSource.left;
unsigned int target_height = targetSource.bottom - targetSource.top;
if (it != m_virtualXFBList.end()) // overwrite an existing Virtual XFB
{
it->xfbAddr = xfbAddr;
it->xfbWidth = fbWidth;
it->xfbHeight = fbHeight;
it->xfbSource.srcAddr = xfbAddr;
it->xfbSource.srcWidth = fbWidth;
it->xfbSource.srcHeight = fbHeight;
if (it->xfbSource.texWidth != target_width || it->xfbSource.texHeight != target_height || !(it->xfbSource.tex))
{
SAFE_RELEASE(it->xfbSource.tex);
it->xfbSource.tex = D3DTexture2D::Create(target_width, target_height, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_B8G8R8A8_UNORM);
if (it->xfbSource.tex == NULL) PanicAlert("Failed to create XFB texture\n");
}
xfbTex = it->xfbSource.tex;
it->xfbSource.texWidth = target_width;
it->xfbSource.texHeight = target_height;
// move this Virtual XFB to the front of the list.
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
// keep stale XFB data from being used
replaceVirtualXFB();
}
else // create a new Virtual XFB and place it at the front of the list
{
VirtualXFB newVirt;
newVirt.xfbSource.tex = D3DTexture2D::Create(target_width, target_height, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_B8G8R8A8_UNORM);
if (newVirt.xfbSource.tex == NULL) PanicAlert("Failed to create a new virtual XFB");
newVirt.xfbAddr = xfbAddr;
newVirt.xfbWidth = fbWidth;
newVirt.xfbHeight = fbHeight;
xfbTex = newVirt.xfbSource.tex;
newVirt.xfbSource.texWidth = target_width;
newVirt.xfbSource.texHeight = target_height;
// Add the new Virtual XFB to the list
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
{
PanicAlert("Requested creating a new virtual XFB although the maximum number has already been reached! Report this to the devs");
newVirt.xfbSource.tex->Release();
return;
// TODO, possible alternative to failing: just delete the oldest virtual XFB:
// m_virtualXFBList.back().xfbSource.tex->Release();
// m_virtualXFBList.pop_back();
}
m_virtualXFBList.push_front(newVirt);
}
if (!xfbTex->GetRTV()) return;
Renderer::ResetAPIState(); // reset any game specific settings
// copy EFB data to XFB and restore render target again
D3D11_RECT sourcerect = CD3D11_RECT(efbSource.left, efbSource.top, efbSource.right, efbSource.bottom);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)target_width, (float)target_height);
D3D::context->RSSetViewports(1, &vp);
D3D::context->PSSetSamplers(0, 1, &copytoVirtualXFBsampler);
D3D::context->OMSetRenderTargets(1, &xfbTex->GetRTV(), NULL);
D3D::drawShadedTexQuad(GetEFBColorTexture()->GetSRV(), &sourcerect,
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
PixelShaderCache::GetColorCopyProgram(), VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout());
D3D::context->OMSetRenderTargets(1, &GetEFBColorTexture()->GetRTV(), GetEFBDepthTexture()->GetDSV());
Renderer::RestoreAPIState();
}
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
PanicAlert("getRealXFBSource not implemented, yet\n");
return NULL;
}
const XFBSource** FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
{
xfbCount = 0;
if (m_virtualXFBList.size() == 0) // no Virtual XFBs available
return NULL;
u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight;
VirtualXFBListType::iterator it;
for (it = m_virtualXFBList.end(); it != m_virtualXFBList.begin();)
{
--it;
u32 dstLower = it->xfbAddr;
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
{
m_overlappingXFBArray[xfbCount] = &(it->xfbSource);
xfbCount++;
}
}
return &m_overlappingXFBArray[0];
}

View File

@ -0,0 +1,151 @@
// 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 _FBMANAGER_D3D_H_
#define _FBMANAGER_D3D_H_
#include <list>
#include "D3DBase.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.
const int MAX_VIRTUAL_XFB = 8;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return !((aLower >= bUpper) || (bLower >= aUpper));
}
struct XFBSource
{
XFBSource()
{
this->srcAddr = 0;
this->srcWidth = 0;
this->srcHeight = 0;
this->tex = NULL;
this->texWidth = 0;
this->texHeight = 0;
}
u32 srcAddr;
u32 srcWidth;
u32 srcHeight;
D3DTexture2D* tex;
unsigned int texWidth;
unsigned int texHeight;
};
class FramebufferManager
{
public:
FramebufferManager()
{
m_efb.color_tex = NULL;
m_efb.color_staging_buf = NULL;
m_efb.depth_tex = NULL;
m_efb.depth_staging_buf = NULL;
m_efb.depth_read_texture = NULL;
m_realXFBSource.tex = NULL;
}
void Create();
void Destroy();
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc);
const XFBSource** GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
D3DTexture2D* &GetEFBColorTexture();
ID3D11Texture2D* &GetEFBColorStagingBuffer();
D3DTexture2D* &GetEFBDepthTexture();
D3DTexture2D* &GetEFBDepthReadTexture();
ID3D11Texture2D* &GetEFBDepthStagingBuffer();
private:
struct VirtualXFB
{
// Address and size in GameCube RAM
u32 xfbAddr;
u32 xfbWidth;
u32 xfbHeight;
XFBSource xfbSource;
};
typedef std::list<VirtualXFB> VirtualXFBListType;
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
void replaceVirtualXFB();
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);
const XFBSource** getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount);
XFBSource m_realXFBSource; // used in real XFB mode
VirtualXFBListType m_virtualXFBList; // used in virtual XFB mode
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
struct
{
D3DTexture2D* color_tex;
ID3D11Texture2D* color_staging_buf;
D3DTexture2D* depth_tex;
ID3D11Texture2D* depth_staging_buf;
D3DTexture2D* depth_read_texture;
} m_efb;
};
extern FramebufferManager FBManager;
#endif

View File

@ -0,0 +1,31 @@
// Copyright (C) 2003-2009 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 _GLOBALS_H_
#define _GLOBALS_H_
#include "Common.h"
#include "VideoConfig.h"
#include "main.h"
#include "VideoCommon.h"
#include "pluginspecs_video.h"
// A global plugin specification
extern PLUGIN_GLOBALS* globals;
#endif // _GLOBALS_H_

View File

@ -0,0 +1,148 @@
// 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 "D3DBase.h"
#include "Profiler.h"
#include "x64Emitter.h"
#include "ABI.h"
#include "MemoryUtil.h"
#include "VertexShaderGen.h"
#include "VertexShaderCache.h"
#include "CPMemory.h"
#include "NativeVertexFormat.h"
#include <string>
using std::string;
class D3DVertexFormat : public NativeVertexFormat
{
D3D11_INPUT_ELEMENT_DESC m_elems[32];
UINT m_num_elems;
public:
D3DVertexFormat();
~D3DVertexFormat();
void Initialize(const PortableVertexDeclaration &_vtx_decl);
void SetupVertexPointers() const;
};
NativeVertexFormat* NativeVertexFormat::Create()
{
return new D3DVertexFormat();
}
D3DVertexFormat::D3DVertexFormat() : m_num_elems(0) { }
D3DVertexFormat::~D3DVertexFormat() {}
DXGI_FORMAT VarToD3D(VarType t, int size)
{
DXGI_FORMAT retval = DXGI_FORMAT_UNKNOWN;
static const DXGI_FORMAT lookup1[5] = {
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32_FLOAT
};
static const DXGI_FORMAT lookup2[5] = {
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R32G32_FLOAT
};
static const DXGI_FORMAT lookup3[5] = {
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32_FLOAT
};
static const DXGI_FORMAT lookup4[5] = {
DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R32G32B32A32_FLOAT
};
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: break;
}
if (retval == DXGI_FORMAT_UNKNOWN)
{
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;
memset(m_elems, 0, sizeof(m_elems));
m_elems[m_num_elems].SemanticName = "POSITION";
m_elems[m_num_elems].AlignedByteOffset = 0;
m_elems[m_num_elems].Format = DXGI_FORMAT_R32G32B32_FLOAT;
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems;
for (int i = 0; i < 3; i++)
{
if (_vtx_decl.normal_offset[i] > 0)
{
m_elems[m_num_elems].SemanticName = "NORMAL";
m_elems[m_num_elems].SemanticIndex = i;
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.normal_offset[i];
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.normal_gl_type, _vtx_decl.normal_gl_size);
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems;
}
}
for (int i = 0; i < 2; i++)
{
if (_vtx_decl.color_offset[i] > 0)
{
m_elems[m_num_elems].SemanticName = "COLOR";
m_elems[m_num_elems].SemanticIndex = i;
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.color_offset[i];
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.color_gl_type, 4);
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems;
}
}
for (int i = 0; i < 8; i++)
{
if (_vtx_decl.texcoord_offset[i] > 0)
{
m_elems[m_num_elems].SemanticName = "TEXCOORD";
m_elems[m_num_elems].SemanticIndex = i;
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.texcoord_offset[i];
m_elems[m_num_elems].Format = VarToD3D(_vtx_decl.texcoord_gl_type[i], _vtx_decl.texcoord_size[i]);
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems;
}
}
if (_vtx_decl.posmtx_offset != -1)
{
m_elems[m_num_elems].SemanticName = "BLENDINDICES";
m_elems[m_num_elems].AlignedByteOffset = _vtx_decl.posmtx_offset;
m_elems[m_num_elems].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
++m_num_elems;
}
}
void D3DVertexFormat::SetupVertexPointers() const
{
D3D::gfxstate->SetInputElements(m_elems, m_num_elems);
}

View File

@ -0,0 +1,274 @@
// 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 "LinearDiskCache.h"
#include "Globals.h"
#include "D3DBase.h"
#include "D3Dcompiler.h"
#include "D3DShader.h"
#include "Statistics.h"
#include "VideoConfig.h"
#include "PixelShaderGen.h"
#include "PixelShaderManager.h"
#include "PixelShaderCache.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
#include "ImageWrite.h"
extern int frameCount;
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
LinearDiskCache g_ps_disk_cache;
ID3D11PixelShader* s_ColorMatrixProgram = NULL;
ID3D11PixelShader* s_ColorCopyProgram = NULL;
ID3D11PixelShader* s_DepthMatrixProgram = NULL;
ID3D11PixelShader* s_ClearProgram = NULL;
const char clear_program_code[] = {
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 pos : POSITION,\n"
"in float4 incol0 : COLOR0){\n"
"ocol0 = incol0;\n"
"}\n"
};
const char color_copy_program_code[] = {
"uniform sampler samp0 : register(s0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 pos : POSITION,\n"
"in float2 uv0 : TEXCOORD0){\n"
"ocol0 = tex2D(samp0,uv0);\n"
"}\n"
};
const char color_matrix_program_code[] = {
"uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
"in float4 pos : POSITION,\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"
};
const char depth_matrix_program[] = {
"uniform sampler samp0 : register(s0);\n"
"uniform float4 cColMatrix[5] : register(c0);\n"
"void main(\n"
"out float4 ocol0 : COLOR0,\n"
" in float4 pos : POSITION,\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"
};
ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram()
{
return s_ColorMatrixProgram;
}
ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram()
{
return s_DepthMatrixProgram;
}
ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram()
{
return s_ColorCopyProgram;
}
ID3D11PixelShader* PixelShaderCache::GetClearProgram()
{
return s_ClearProgram;
}
// HACK to avoid some invasive VideoCommon changes
// these values are hardcoded, they depend on internal D3DCompile behavior; TODO: Solve this with D3DReflect or something
// offset given in floats, table index is float4
unsigned int ps_constant_offset_table[] = {
0, 4, 8, 12, // C_COLORS, 16
16, 20, 24, 28, // C_KCOLORS, 16
32, // C_ALPHA, 4
36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32
68, 72, // C_ZBIAS, 8
76, 80, // C_INDTEXSCALE, 8
84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24
108, 112, // C_FOG, 8
};
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1;
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2;
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3;
D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4;
D3D::gfxstate->pscbufchanged = true;
}
void SetPSConstant4fv(unsigned int const_number, const float* f)
{
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4);
D3D::gfxstate->pscbufchanged = true;
}
void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
{
memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count);
D3D::gfxstate->pscbufchanged = true;
}
// this class will load the precompiled shaders into our cache
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, (void*)value, value_size);
}
};
void PixelShaderCache::Init()
{
// used when drawing clear quads
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, strlen(clear_program_code));
// used when copying/resolving the color buffer
s_ColorCopyProgram = D3D::CompileAndCreatePixelShader(color_copy_program_code, strlen(color_copy_program_code));
// used for color conversion
s_ColorMatrixProgram = D3D::CompileAndCreatePixelShader(color_matrix_program_code, strlen(color_matrix_program_code));
// used for depth copy
s_DepthMatrixProgram = D3D::CompileAndCreatePixelShader(depth_matrix_program, strlen(depth_matrix_program));
Clear();
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX), globals->unique_id);
PixelShaderCacheInserter inserter;
g_ps_disk_cache.OpenAndRead(cache_filename, &inserter);
}
// ONLY to be used during shutdown.
void PixelShaderCache::Clear()
{
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
iter->second.Destroy();
PixelShaders.clear();
}
void PixelShaderCache::Shutdown()
{
SAFE_RELEASE(s_ColorMatrixProgram);
SAFE_RELEASE(s_ColorCopyProgram);
SAFE_RELEASE(s_DepthMatrixProgram);
SAFE_RELEASE(s_ClearProgram);
Clear();
g_ps_disk_cache.Sync();
g_ps_disk_cache.Close();
}
bool PixelShaderCache::SetShader(bool dstAlpha)
{
PIXELSHADERUID uid;
GetPixelShaderId(&uid, PixelShaderManager::GetTextureMask(), dstAlpha);
// check if the shader is already set
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
{
PSCache::const_iterator iter = PixelShaders.find(uid);
return (iter != PixelShaders.end() && iter->second.shader);
}
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
// check if the shader is 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;
D3D::gfxstate->SetPShader(entry.shader);
return (entry.shader != NULL);
}
// need to compile a new shader
const char* code = GeneratePixelShaderCode(PixelShaderManager::GetTextureMask(), dstAlpha, 2);
ID3D10Blob* pbytecode;
if (!D3D::CompilePixelShader(code, strlen(code), &pbytecode))
{
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
return false;
}
// insert the bytecode into the caches
g_ps_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->GetBufferPointer(), pbytecode->GetBufferSize());
g_ps_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode->GetBufferPointer(), pbytecode->GetBufferSize());
D3D::gfxstate->SetPShader(last_entry->shader);
pbytecode->Release();
return result;
}
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen)
{
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
if (shader == NULL)
{
PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__);
return false;
}
// make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid];
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
return true;
}

View File

@ -0,0 +1,57 @@
// 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 "Common.h"
#include "LinearDiskCache.h"
#include "D3DBase.h"
#include <map>
#include "PixelShaderGen.h"
#include "VertexShaderGen.h"
class PixelShaderCache
{
public:
static void Init();
static void Clear();
static void Shutdown();
static bool SetShader(bool dstAlpha);
static bool InsertByteCode(const PIXELSHADERUID &uid, void* bytecode, unsigned int bytecodelen);
static ID3D11PixelShader* GetColorMatrixProgram();
static ID3D11PixelShader* GetColorCopyProgram();
static ID3D11PixelShader* GetDepthMatrixProgram();
static ID3D11PixelShader* GetClearProgram();
private:
struct PSCacheEntry
{
ID3D11PixelShader* shader;
int frameCount;
PSCacheEntry() : shader(NULL), frameCount(0) {}
void Destroy() { SAFE_RELEASE(shader); }
};
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
static PSCache PixelShaders;
static const PSCacheEntry* last_entry;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
// 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 <d3dx11.h>
#include "Globals.h"
#include "Statistics.h"
#include "MemoryUtil.h"
#include "Hash.h"
#include "CommonPaths.h"
#include "FileUtil.h"
#include "D3DBase.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "FBManager.h"
#include "PixelShaderCache.h"
#include "PixelShaderManager.h"
#include "VertexShaderManager.h"
#include "VertexShaderCache.h"
#include "Render.h"
#include "TextureDecoder.h"
#include "TextureCache.h"
#include "HiresTextures.h"
ID3D11BlendState* efbcopyblendstate = NULL;
ID3D11RasterizerState* efbcopyraststate = NULL;
ID3D11DepthStencilState* efbcopydepthstate = NULL;
ID3D11Buffer* efbcopycbuf[20] = { NULL };
u8* TextureCache::temp = NULL;
TextureCache::TexCache TextureCache::textures;
extern int frameCount;
#define TEMP_SIZE (1024*1024*4)
#define TEXTURE_KILL_THRESHOLD 200
void TextureCache::TCacheEntry::Destroy(bool shutdown)
{
SAFE_RELEASE(texture);
if (!isRenderTarget && !shutdown)
{
u32* ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr);
if (ptr && *ptr == hash)
*ptr = oldpixel;
}
}
void TextureCache::Init()
{
temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
HiresTextures::Init(globals->unique_id);
D3D11_BLEND_DESC blenddesc;
blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE;
blenddesc.RenderTarget[0].BlendEnable = FALSE;
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
D3D::device->CreateBlendState(&blenddesc, &efbcopyblendstate);
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyblendstate, "blend state used in TextureCache::CopyRenderTargetToTexture");
D3D11_DEPTH_STENCIL_DESC depthdesc;
depthdesc.DepthEnable = FALSE;
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
depthdesc.StencilEnable = FALSE;
depthdesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
depthdesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
D3D::device->CreateDepthStencilState(&depthdesc, &efbcopydepthstate);
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopydepthstate, "depth stencil state used in TextureCache::CopyRenderTargetToTexture");
D3D11_RASTERIZER_DESC rastdesc;
rastdesc.CullMode = D3D11_CULL_NONE;
rastdesc.FillMode = D3D11_FILL_SOLID;
rastdesc.FrontCounterClockwise = false;
rastdesc.DepthBias = false;
rastdesc.DepthBiasClamp = 0;
rastdesc.SlopeScaledDepthBias = 0;
rastdesc.DepthClipEnable = false;
rastdesc.ScissorEnable = false;
rastdesc.MultisampleEnable = false;
rastdesc.AntialiasedLineEnable = false;
D3D::device->CreateRasterizerState(&rastdesc, &efbcopyraststate);
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopyraststate, "rasterizer state used in TextureCache::CopyRenderTargetToTexture");
}
void TextureCache::Invalidate(bool shutdown)
{
for (TexCache::iterator iter = textures.begin(); iter != textures.end(); iter++)
iter->second.Destroy(shutdown);
textures.clear();
HiresTextures::Shutdown();
}
void TextureCache::InvalidateRange(u32 start_address, u32 size)
{
TexCache::iterator iter = textures.begin();
while (iter != textures.end())
{
if (iter->second.IntersectsMemoryRange(start_address, size))
{
iter->second.Destroy(false);
textures.erase(iter++);
}
else
{
++iter;
}
}
}
bool TextureCache::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 range_size)
{
if (addr + size_in_bytes < range_address) return false;
if (addr >= range_address + range_size) return false;
return true;
}
void TextureCache::Shutdown()
{
Invalidate(true);
FreeMemoryPages(temp, TEMP_SIZE);
temp = NULL;
SAFE_RELEASE(efbcopyblendstate);
SAFE_RELEASE(efbcopyraststate);
SAFE_RELEASE(efbcopydepthstate);
for (unsigned int k = 0; k < 20;k++)
SAFE_RELEASE(efbcopycbuf[k]);
}
void TextureCache::Cleanup()
{
TexCache::iterator iter = textures.begin();
while (iter != textures.end())
{
if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second.frameCount)
{
iter->second.Destroy(false);
iter = textures.erase(iter);
}
else
{
iter++;
}
}
}
// TODO: Verify that this actually returns the value needed below
unsigned int GetPow2(unsigned int val)
{
unsigned int ret = 0;
for (;val;val>>=1) ret++;
return ret;
}
TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, unsigned int tex_format, unsigned int tlutaddr, unsigned int tlutfmt, bool UseNativeMips, unsigned int maxlevel)
{
if (address == 0) return NULL;
u8* ptr = g_VideoInitialize.pGetMemoryPointer(address);
unsigned int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1; // TexelSizeInNibbles(format)*width*height/16;
unsigned int bsh = TexDecoder_GetBlockHeightInTexels(tex_format) - 1; // TexelSizeInNibbles(format)*width*height/16;
unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(tex_format);
unsigned int expandedWidth = (width + bsw) & (~bsw);
unsigned int expandedHeight = (height + bsh) & (~bsh);
u64 hash_value;
u32 texID = address;
u32 FullFormat = tex_format;
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
u32 FullFormat = (tex_format | (tlutfmt << 16));
bool skip_texture_create = false;
TexCache::iterator iter = textures.find(texID);
if (iter != textures.end())
{
TCacheEntry &entry = iter->second;
hash_value = ((u32*)ptr)[0];
// TODO: Is the (entry.MipLevels == maxlevel) check needed?
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash) && FullFormat == entry.fmt && entry.MipLevels == maxlevel))
{
entry.frameCount = frameCount;
D3D::gfxstate->SetShaderResource(stage, entry.texture->GetSRV());
return &entry;
}
else
{
// Let's reload the new texture data into the same texture,
// instead of destroying it and having to create a new one.
// Might speed up movie playback very, very slightly.
// TODO: Is the (entry.MipLevels < maxlevel) check needed?
if (width == entry.w && height==entry.h && FullFormat == entry.fmt && entry.MipLevels < maxlevel)
{
skip_texture_create = true;
}
else
{
entry.Destroy(false);
textures.erase(iter);
}
}
}
// make an entry in the table
TCacheEntry& entry = textures[texID];
PC_TexFormat pcfmt = PC_TEX_FMT_NONE;
if (pcfmt == PC_TEX_FMT_NONE)
pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
DXGI_FORMAT d3d_fmt = DXGI_FORMAT_B8G8R8A8_UNORM;
bool swap_r_b = false;
entry.oldpixel = ((u32*)ptr)[0];
entry.hash = ((u32*)ptr)[0] = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
entry.addr = address;
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format);
entry.isRenderTarget = false;
bool isPow2 = !((width & (width - 1)) || (height & (height - 1)));
entry.isNonPow2 = false;
unsigned int TexLevels = (isPow2 && UseNativeMips && maxlevel) ? (GetPow2(max(width, height)) + 1) : ((isPow2)? 0 : 1);
if (TexLevels > (maxlevel + 1) && maxlevel)
TexLevels = maxlevel + 1;
entry.MipLevels = maxlevel;
D3D11_USAGE usage = (TexLevels == 1) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
if (!skip_texture_create)
{
if (usage == D3D11_USAGE_DYNAMIC) entry.texture = D3DTexture2D::Create(width, height, D3D11_BIND_SHADER_RESOURCE, usage, d3d_fmt, TexLevels);
else // need to use default textures
{
ID3D11Texture2D* pTexture = NULL;
HRESULT hr;
// possible optimization: Manually create the mipmaps, so that we don't need to bind the texture as render target
// if we automatically generate the mipmaps we need to bind the texture as rendertarget as well
D3D11_BIND_FLAG bindflags = D3D11_BIND_SHADER_RESOURCE;
if (TexLevels == 0) bindflags = (D3D11_BIND_FLAG)(bindflags | D3D11_BIND_RENDER_TARGET);
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(d3d_fmt, width, height, 1, TexLevels, bindflags, usage, 0, 1, 0, (TexLevels==0)?D3D11_RESOURCE_MISC_GENERATE_MIPS:0);
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture);
if (FAILED(hr))
{
PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__);
return NULL;
}
// we only need the shader resource view
entry.texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE);
pTexture->Release();
}
if (entry.texture == NULL) PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__);
D3D::ReplaceTexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, d3d_fmt, pcfmt, 0, usage);
}
else
{
D3D::ReplaceTexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, d3d_fmt, pcfmt, 0, usage);
}
if (TexLevels == 0 && usage == D3D11_USAGE_DEFAULT) D3D::context->GenerateMips(entry.texture->GetSRV());
else if (TexLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
{
unsigned int level = 1;
unsigned int mipWidth = (width + 1) >> 1;
unsigned int mipHeight = (height + 1) >> 1;
ptr += entry.size_in_bytes;
while ((mipHeight || mipWidth) && (level < TexLevels))
{
unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1;
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
expandedWidth = (currentWidth + bsw) & (~bsw);
expandedHeight = (currentHeight + bsh) & (~bsh);
PC_TexFormat texfmtbuf = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
D3D::ReplaceTexture2D(entry.texture->GetTex(), (BYTE*)temp, currentWidth, currentHeight, expandedWidth, d3d_fmt, texfmtbuf, level, usage);
u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1;
ptr += size;
mipWidth >>= 1;
mipHeight >>= 1;
level++;
}
}
entry.frameCount = frameCount;
entry.w = width;
entry.h = height;
entry.fmt = FullFormat;
INCSTAT(stats.numTexturesCreated);
SETSTAT(stats.numTexturesAlive, (int)textures.size());
D3D::gfxstate->SetShaderResource(stage, entry.texture->GetSRV());
return &entry;
}
// TODO: this doesn't work quite right, yet
void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source_rect)
{
int efb_w = source_rect.GetWidth();
int efb_h = source_rect.GetHeight();
int tex_w = (abs(source_rect.GetWidth()) >> bScaleByHalf);
int tex_h = (abs(source_rect.GetHeight()) >> bScaleByHalf);
int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleX() * tex_w)):tex_w;
int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleY() * tex_h)):tex_h;
TexCache::iterator iter;
D3DTexture2D* tex = NULL;
iter = textures.find(address);
if (iter != textures.end())
{
if (iter->second.isRenderTarget && iter->second.Scaledw == Scaledtex_w && iter->second.Scaledh == Scaledtex_h)
{
tex = iter->second.texture;
iter->second.frameCount = frameCount;
}
else
{
// remove it and recreate it as a render target
SAFE_RELEASE(iter->second.texture);
textures.erase(iter);
}
}
if (!tex)
{
TCacheEntry entry;
entry.isRenderTarget = true;
entry.hash = 0;
entry.frameCount = frameCount;
entry.w = tex_w;
entry.h = tex_h;
entry.Scaledw = Scaledtex_w;
entry.Scaledh = Scaledtex_h;
entry.fmt = copyfmt;
entry.isNonPow2 = true;
entry.texture = D3DTexture2D::Create(Scaledtex_w, Scaledtex_h, (D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET|(int)D3D11_BIND_SHADER_RESOURCE), D3D11_USAGE_DEFAULT, DXGI_FORMAT_B8G8R8A8_UNORM);
if (entry.texture == NULL) PanicAlert("CopyRenderTargetToTexture failed to create entry.texture at %s %d\n", __FILE__, __LINE__);
textures[address] = entry;
tex = entry.texture;
}
float colmat[20]= {0.0f}; // last four floats for fConstAdd
unsigned int cbufid = (unsigned int)-1;
// TODO: Move this to TextureCache::Init()
if (bFromZBuffer)
{
switch(copyfmt)
{
case 0: // Z4
case 1: // Z8
colmat[0] = colmat[4] = colmat[8] = colmat[12] =1.0f;
cbufid = 12;
break;
case 3: // Z16 //?
colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f;
cbufid = 13;
case 11: // Z16 (reverse order)
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
cbufid = 14;
break;
case 6: // Z24X8
colmat[0] = colmat[5] = colmat[10] = 1.0f;
cbufid = 15;
break;
case 9: // Z8M
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
cbufid = 16;
break;
case 10: // Z8L
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
cbufid = 17;
break;
case 12: // Z16L
colmat[2] = colmat[6] = colmat[10] = colmat[13] = 1.0f;
cbufid = 18;
break;
default:
ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", copyfmt);
colmat[2] = colmat[5] = colmat[8] = 1.0f;
cbufid = 19;
break;
}
}
else if (bIsIntensityFmt)
{
colmat[16] = colmat[17] = colmat[18] = 16.0f/255.0f;
switch (copyfmt)
{
case 0: // I4
case 1: // I8
case 2: // IA4
case 3: // IA8
// TODO - verify these coefficients
colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f;
colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f;
colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f;
if (copyfmt < 2)
{
colmat[19] = 16.0f / 255.0f;
colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f;
cbufid = 0;
}
else// alpha
{
colmat[15] = 1;
cbufid = 1;
}
break;
default:
ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", copyfmt);
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
break;
}
}
else
{
switch (copyfmt)
{
case 0: // R4
case 8: // R8
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
cbufid = 2;
break;
case 2: // RA4
case 3: // RA8
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1;
cbufid = 3;
break;
case 7: // A8
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1;
cbufid = 4;
break;
case 9: // G8
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1;
cbufid = 5;
break;
case 10: // B8
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1;
cbufid = 6;
break;
case 11: // RG8
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1;
cbufid = 7;
break;
case 12: // GB8
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1;
cbufid = 8;
break;
case 4: // RGB565
colmat[0] = colmat[5] = colmat[10] = 1;
colmat[19] = 1; // set alpha to 1
cbufid = 9;
break;
case 5: // RGB5A3
case 6: // RGBA8
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
cbufid = 10;
break;
default:
ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", copyfmt);
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
cbufid = 11;
break;
}
}
Renderer::ResetAPIState(); // reset any game specific settings
// stretch picture with increased internal resolution
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)Scaledtex_w, (float)Scaledtex_h);
D3D::context->RSSetViewports(1, &vp);
D3D11_RECT destrect = CD3D11_RECT(0, 0, Scaledtex_w, Scaledtex_h);
// set transformation
if (efbcopycbuf[cbufid] == NULL)
{
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20*sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = colmat;
D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]);
}
D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]);
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);
// TODO: Use linear filtering if (bScaleByHalf), else use point filtering
D3D::context->OMSetBlendState(efbcopyblendstate, NULL, 0xffffffff);
D3D::context->RSSetState(efbcopyraststate);
D3D::context->OMSetDepthStencilState(efbcopydepthstate, 0);
D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL);
D3D::drawShadedTexQuad(
(bFromZBuffer) ? FBManager.GetEFBDepthTexture()->GetSRV() : FBManager.GetEFBColorTexture()->GetSRV(),
&sourcerect,
Renderer::GetFullTargetWidth(),
Renderer::GetFullTargetHeight(),
PixelShaderCache::GetColorMatrixProgram(), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
D3D::context->OMSetRenderTargets(1, &FBManager.GetEFBColorTexture()->GetRTV(), FBManager.GetEFBDepthTexture()->GetDSV());
Renderer::RestoreAPIState();
}

View File

@ -0,0 +1,70 @@
// 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 <map>
#include "D3DBase.h"
#include "D3DTexture.h"
#include "VideoCommon.h"
#include "BPMemory.h"
class TextureCache
{
public:
struct TCacheEntry
{
D3DTexture2D* texture;
u32 addr;
u32 size_in_bytes;
u64 hash;
u32 paletteHash;
u32 oldpixel;
int frameCount;
unsigned int w, h, fmt, MipLevels;
int Scaledw, Scaledh;
float scaleX, scaleY; // for hires texutres
bool isRenderTarget;
bool isNonPow2;
TCacheEntry() : texture(NULL), addr(0), size_in_bytes(0), hash(0), paletteHash(0), oldpixel(0),
frameCount(0), w(0), h(0), fmt(0), MipLevels(0), Scaledw(0), Scaledh(0),
scaleX(1.f), scaleY(1.f), isRenderTarget(false), isNonPow2(true) {}
void Destroy(bool shutdown);
bool IntersectsMemoryRange(u32 range_address, u32 range_size);
};
static void Init();
static void Cleanup();
static void Shutdown();
static void Invalidate(bool shutdown);
static void InvalidateRange(u32 start_address, u32 size);
static TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, unsigned int tex_format, unsigned int tlutaddr, unsigned int tlutfmt, bool UseNativeMips, unsigned int maxlevel);
static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, unsigned int bScaleByHalf, const EFBRectangle &source_rect);
private:
typedef std::map<u32,TCacheEntry> TexCache;
static u8* temp;
static TexCache textures;
};

View File

@ -0,0 +1,383 @@
// 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 "D3DBase.h"
#include "D3DShader.h"
#include "D3DUtil.h"
#include "Statistics.h"
#include "Profiler.h"
#include "FBManager.h"
#include "VertexManager.h"
#include "OpcodeDecoding.h"
#include "IndexGenerator.h"
#include "VertexShaderManager.h"
#include "VertexShaderCache.h"
#include "PixelShaderManager.h"
#include "PixelShaderCache.h"
#include "NativeVertexFormat.h"
#include "NativeVertexWriter.h"
#include "TextureCache.h"
#include "BPStructs.h"
#include "XFStructs.h"
#include "Globals.h"
#include <string>
using std::string;
using namespace D3D;
extern NativeVertexFormat* g_nativeVertexFmt;
namespace VertexManager
{
#define MAXVBUFFERSIZE 0x50000
#define MAXIBUFFERSIZE 0xFFFF
// TODO: find sensible values for these two
#define NUM_VERTEXBUFFERS 6
#define NUM_INDEXBUFFERS 4
int lastPrimitive;
u8* LocalVBuffer = NULL;
u16* TIBuffer = NULL;
u16* LIBuffer = NULL;
u16* PIBuffer = NULL;
bool Flushed=false;
ID3D11Buffer* indexbuffers[NUM_INDEXBUFFERS] = {NULL};
ID3D11Buffer* vertexbuffers[NUM_VERTEXBUFFERS] = {NULL};
ID3D11Buffer* lineindexbuffer = NULL;
ID3D11Buffer* pointindexbuffer = NULL;
inline ID3D11Buffer* GetSuitableIndexBuffer(const unsigned int minsize)
{
for (unsigned int k = 0;k < NUM_INDEXBUFFERS-1;k++)
if (minsize > 2*(unsigned int)MAXIBUFFERSIZE>>(k+1))
return indexbuffers[k];
return indexbuffers[NUM_INDEXBUFFERS-1];
}
inline ID3D11Buffer* GetSuitableVertexBuffer(const unsigned int minsize)
{
for (unsigned int k = 0;k < NUM_VERTEXBUFFERS-1;++k)
if (minsize > (unsigned int)MAXVBUFFERSIZE>>(k+1))
return vertexbuffers[k];
return vertexbuffers[NUM_VERTEXBUFFERS-1];
}
void CreateDeviceObjects()
{
D3D11_BUFFER_DESC bufdesc;
HRESULT hr;
for (unsigned int k = 0;k < NUM_INDEXBUFFERS;++k)
{
bufdesc = CD3D11_BUFFER_DESC(2*MAXIBUFFERSIZE >> k, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&bufdesc, NULL, &indexbuffers[k]);
if (FAILED(hr)) PanicAlert("Failed to create index buffer, %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)indexbuffers[k], "an index buffer of VertexManager");
}
bufdesc = CD3D11_BUFFER_DESC(2*MAXIBUFFERSIZE, D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&bufdesc, NULL, &lineindexbuffer);
if (FAILED(hr)) PanicAlert("Failed to create index buffer, %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)lineindexbuffer, "line index buffer of VertexManager");
hr = D3D::device->CreateBuffer(&bufdesc, NULL, &pointindexbuffer);
if (FAILED(hr)) PanicAlert("Failed to create index buffer, %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)pointindexbuffer, "point index buffer of VertexManager");
for (unsigned int k = 0;k < NUM_VERTEXBUFFERS;++k)
{
bufdesc = CD3D11_BUFFER_DESC(MAXVBUFFERSIZE >> k, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&bufdesc, NULL, &vertexbuffers[k]);
if (FAILED(hr)) PanicAlert("Failed to create vertex buffer, %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)vertexbuffers[k], "a vertex buffer of VertexManager");
}
}
void DestroyDeviceObjects()
{
SAFE_RELEASE(lineindexbuffer);
SAFE_RELEASE(pointindexbuffer);
for (unsigned int k = 0;k < NUM_INDEXBUFFERS;++k)
SAFE_RELEASE(indexbuffers[k]);
for (unsigned int k = 0;k < NUM_VERTEXBUFFERS;++k)
SAFE_RELEASE(vertexbuffers[k]);
}
bool Init()
{
LocalVBuffer = new u8[MAXVBUFFERSIZE];
TIBuffer = new u16[MAXIBUFFERSIZE];
LIBuffer = new u16[MAXIBUFFERSIZE];
PIBuffer = new u16[MAXIBUFFERSIZE];
s_pCurBufferPointer = LocalVBuffer;
Flushed=false;
CreateDeviceObjects();
IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);
return true;
}
void ResetBuffer()
{
s_pCurBufferPointer = LocalVBuffer;
}
void Shutdown()
{
DestroyDeviceObjects();
if (LocalVBuffer) delete[] LocalVBuffer;
if (TIBuffer) delete[] TIBuffer;
if (LIBuffer) delete[] LIBuffer;
if (PIBuffer) delete[] PIBuffer;
LocalVBuffer = NULL;
TIBuffer = NULL;
LIBuffer = NULL;
PIBuffer = NULL;
ResetBuffer();
}
void AddIndices(int _primitive, int _numVertices)
{
switch (_primitive)
{
case GX_DRAW_QUADS: IndexGenerator::AddQuads(_numVertices); break;
case GX_DRAW_TRIANGLES: IndexGenerator::AddList(_numVertices); break;
case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(_numVertices); break;
case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(_numVertices); break;
case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(_numVertices); break;
case GX_DRAW_LINES: IndexGenerator::AddLineList(_numVertices); break;
case GX_DRAW_POINTS: IndexGenerator::AddPoints(_numVertices); break;
}
}
int GetRemainingSize()
{
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
}
int GetRemainingVertices(int primitive)
{
switch (primitive)
{
case GX_DRAW_QUADS:
case GX_DRAW_TRIANGLES:
case GX_DRAW_TRIANGLE_STRIP:
case GX_DRAW_TRIANGLE_FAN:
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen())/3;
case GX_DRAW_LINE_STRIP:
case GX_DRAW_LINES:
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen())/2;
case GX_DRAW_POINTS:
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
default: return 0;
}
}
void AddVertices(int _primitive, int _numVertices)
{
if (_numVertices <= 0) return;
switch (_primitive)
{
case GX_DRAW_QUADS:
case GX_DRAW_TRIANGLES:
case GX_DRAW_TRIANGLE_STRIP:
case GX_DRAW_TRIANGLE_FAN:
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * _numVertices)
Flush();
break;
case GX_DRAW_LINE_STRIP:
case GX_DRAW_LINES:
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * _numVertices)
Flush();
break;
case GX_DRAW_POINTS:
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < _numVertices)
Flush();
break;
default: return;
}
if (Flushed)
{
IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);
Flushed=false;
}
lastPrimitive = _primitive;
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
INCSTAT(stats.thisFrame.numPrimitiveJoins);
AddIndices(_primitive, _numVertices);
}
inline void Draw(unsigned int stride, bool alphapass)
{
D3D11_MAPPED_SUBRESOURCE map;
ID3D11Buffer* vertexbuffer = GetSuitableVertexBuffer(IndexGenerator::GetNumVerts() * stride);
if (!alphapass)
{
context->Map(vertexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, LocalVBuffer, IndexGenerator::GetNumVerts() * stride);
context->Unmap(vertexbuffer, 0);
}
UINT bufoffset = 0;
UINT bufstride = (UINT)stride;
if (!alphapass) gfxstate->ApplyState();
else gfxstate->AlphaPass();
if (IndexGenerator::GetNumTriangles() > 0)
{
ID3D11Buffer* indexbuffer = GetSuitableIndexBuffer(2*3*IndexGenerator::GetNumTriangles());
if (!alphapass)
{
D3D::context->Map(indexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, TIBuffer, 2*3*IndexGenerator::GetNumTriangles());
D3D::context->Unmap(indexbuffer, 0);
}
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset);
D3D::context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->DrawIndexed(3*IndexGenerator::GetNumTriangles(), 0, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumLines() > 0)
{
if (!alphapass)
{
D3D::context->Map(lineindexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, LIBuffer, 2*2*IndexGenerator::GetNumTriangles());
D3D::context->Unmap(lineindexbuffer, 0);
}
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset);
D3D::context->IASetIndexBuffer(lineindexbuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->DrawIndexed(2*IndexGenerator::GetNumLines(), 0, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumPoints() > 0)
{
if (!alphapass)
{
D3D::context->Map(pointindexbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, PIBuffer, 2*IndexGenerator::GetNumTriangles());
D3D::context->Unmap(pointindexbuffer, 0);
}
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D::context->IASetVertexBuffers(0, 1, &vertexbuffer, &bufstride, &bufoffset);
D3D::context->IASetIndexBuffer(pointindexbuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->DrawIndexed(IndexGenerator::GetNumPoints(), 0, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
}
void Flush()
{
if (LocalVBuffer == s_pCurBufferPointer) return;
if (Flushed) return;
Flushed=true;
DVSTARTPROFILE();
u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i)
{
if (bpmem.tevorders[i/2].getEnable(i & 1))
usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1);
}
if (bpmem.genMode.numindstages > 0)
for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1; ++i)
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
for (unsigned int i = 0; i < 8; i++)
{
if (usedtextures & (1 << i))
{
Renderer::SetSamplerState(i & 3, i >> 2);
FourTexUnits &tex = bpmem.tex[i >> 2];
TextureCache::TCacheEntry* tentry = TextureCache::Load(i,
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format,
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
(tex.texMode1[i&3].max_lod >> 4));
if (tentry)
{
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
if (tentry->scaleX != 1.0f || tentry->scaleY != 1.0f)
PixelShaderManager::SetCustomTexScale(i, tentry->scaleX, tentry->scaleY);
}
else
{
ERROR_LOG(VIDEO, "error loading texture");
}
}
}
PixelShaderManager::SetTexturesUsed(0);
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
if (!PixelShaderCache::SetShader(false))
goto shader_fail;
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
goto shader_fail;
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers();
Draw(stride, false);
if (bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
{
DWORD write = 0;
if (!PixelShaderCache::SetShader(true))
goto shader_fail;
// update alpha only
Draw(stride, true);
}
shader_fail:
ResetBuffer();
gfxstate->ResetShaderResources();
}
} // namespace

View File

@ -0,0 +1,38 @@
// 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"
namespace VertexManager
{
bool Init();
void Shutdown();
void AddVertices(int _primitive, int _numVertices);
void Flush();
void CreateDeviceObjects();
void DestroyDeviceObjects();
} // namespace
#endif

View File

@ -0,0 +1,268 @@
// 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 "Globals.h"
#include "D3DBase.h"
#include "D3DShader.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VideoConfig.h"
#include "VertexShaderCache.h"
#include "VertexLoader.h"
#include "BPMemory.h"
#include "XFMemory.h"
VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry;
static ID3D11VertexShader* SimpleVertexShader = NULL;
static ID3D11VertexShader* ClearVertexShader = NULL;
static ID3D11InputLayout* SimpleLayout = NULL;
static ID3D11InputLayout* ClearLayout = NULL;
LinearDiskCache g_vs_disk_cache;
ID3D11VertexShader* VertexShaderCache::GetSimpleVertexShader() { return SimpleVertexShader; }
ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVertexShader; }
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; }
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; }
// maps the constant numbers to float indices in the constant buffer
unsigned int vs_constant_offset_table[238];
void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
{
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1;
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2;
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3;
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4;
D3D::gfxstate->vscbufchanged = true;
}
void SetVSConstant4fv(unsigned int const_number, const float* f)
{
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4);
D3D::gfxstate->vscbufchanged = true;
}
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f)
{
for (unsigned int i = 0; i < count; i++)
{
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3);
D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f;
}
}
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f)
{
memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count);
D3D::gfxstate->vscbufchanged = true;
}
// this class will load the precompiled shaders into our cache
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);
ID3D10Blob* blob;
D3D10CreateBlob(value_size, &blob);
memcpy(blob->GetBufferPointer(), value, value_size);
VertexShaderCache::InsertByteCode(uid, blob);
blob->Release();
}
};
const char simple_shader_code[] = {
"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"
};
const char clear_shader_code[] = {
"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"
};
void VertexShaderCache::Init()
{
const D3D11_INPUT_ELEMENT_DESC simpleelems[2] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
const D3D11_INPUT_ELEMENT_DESC clearelems[2] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
ID3D10Blob* blob;
D3D::CompileVertexShader(simple_shader_code, strlen(simple_shader_code), &blob);
D3D::device->CreateInputLayout(simpleelems, 2, blob->GetBufferPointer(), blob->GetBufferSize(), &SimpleLayout);
SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
blob->Release();
D3D::CompileVertexShader(clear_shader_code, (int)strlen(clear_shader_code), &blob);
D3D::device->CreateInputLayout(clearelems, 2, blob->GetBufferPointer(), blob->GetBufferSize(), &ClearLayout);
ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
blob->Release();
Clear();
// these values are hardcoded, they depend on internal D3DCompile behavior
// TODO: Do this with D3DReflect or something instead
unsigned int k;
for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k;
for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k;
for (k = 0;k < 32;k++) vs_constant_offset_table[C_NORMALMATRICES+k] = 568+4*k;
for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k;
for (k = 0;k < 64;k++) vs_constant_offset_table[C_POSTTRANSFORMMATRICES+k] = 696+4*k;
for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k;
for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k;
for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k;
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX), globals->unique_id);
VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(cache_filename, &inserter);
}
void VertexShaderCache::Clear()
{
VSCache::iterator iter = vshaders.begin();
for (; iter != vshaders.end(); ++iter)
iter->second.Destroy();
vshaders.clear();
}
void VertexShaderCache::Shutdown()
{
SAFE_RELEASE(SimpleVertexShader);
SAFE_RELEASE(ClearVertexShader);
SAFE_RELEASE(SimpleLayout);
SAFE_RELEASE(ClearLayout);
Clear();
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)
return (vshaders[uid].shader != NULL);
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;
if (entry.shader) D3D::gfxstate->SetVShader(entry.shader, iter->second.bytecode);
return (entry.shader != NULL);
}
const char* code = GenerateVertexShaderCode(components, API_D3D11);
ID3D10Blob* pbytecode = NULL;
D3D::CompileVertexShader(code, (int)strlen(code), &pbytecode);
if (pbytecode == NULL)
{
PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code);
return false;
}
g_vs_disk_cache.Append((u8*)&uid, sizeof(uid), (const u8*)pbytecode->GetBufferPointer(), pbytecode->GetBufferSize());
g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode);
D3D::gfxstate->SetVShader(last_entry->shader, last_entry->bytecode);
pbytecode->Release();
return result;
}
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, ID3D10Blob* bcodeblob)
{
ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob);
if (shader == NULL)
{
PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->GetBufferPointer(), bcodeblob->GetBufferSize(), __FILE__, __LINE__);
return false;
}
// Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount = frameCount;
entry.SetByteCode(bcodeblob);
vshaders[uid] = entry;
last_entry = &vshaders[uid];
INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
return true;
}

View File

@ -0,0 +1,73 @@
// 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 "D3DBase.h"
#include <map>
#include <string>
#include "D3DBase.h"
#include "VertexShaderGen.h"
#include "d3dcompiler.h"
class VertexShaderCache
{
public:
static void Init();
static void Clear();
static void Shutdown();
static bool SetShader(u32 components);
static ID3D11VertexShader* GetSimpleVertexShader();
static ID3D11VertexShader* GetClearVertexShader();
static ID3D11InputLayout* GetSimpleInputLayout();
static ID3D11InputLayout* GetClearInputLayout();
static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, ID3D10Blob* bcodeblob);
private:
struct VSCacheEntry
{
ID3D11VertexShader* shader;
ID3D10Blob* bytecode; // needed to initialize the input layout
int frameCount;
VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {}
void SetByteCode(ID3D10Blob* blob)
{
if (bytecode) bytecode->Release();
bytecode = blob;
blob->AddRef();
}
void Destroy()
{
SAFE_RELEASE(shader);
SAFE_RELEASE(bytecode);
}
};
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
static VSCache vshaders;
static const VSCacheEntry* last_entry;
};
#endif // _VERTEXSHADERCACHE_H

View File

@ -0,0 +1,29 @@
#include <windows.h>
#include <vector>
#include "DialogManager.h"
typedef std::vector <HWND> WindowList;
WindowList dialogs;
void DialogManager::AddDlg(HWND hDialog)
{
dialogs.push_back(hDialog);
}
bool DialogManager::IsDialogMessage(LPMSG message)
{
WindowList::iterator iter;
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
{
if (::IsDialogMessage(*iter,message))
return true;
}
return false;
}
void DialogManager::EnableAll(BOOL enable)
{
WindowList::iterator iter;
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
EnableWindow(*iter,enable);
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <windows.h>
class DialogManager
{
public:
static void AddDlg(HWND hDialog);
static bool IsDialogMessage(LPMSG message);
static void EnableAll(BOOL enable);
};

View File

@ -0,0 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include "Misc.h"
namespace W32Util
{
void CenterWindow(HWND hwnd)
{
HWND hwndParent;
RECT rect, rectP;
int width, height;
int screenwidth, screenheight;
int x, y;
// make the window relative to its parent
hwndParent = GetParent(hwnd);
if (!hwndParent)
return;
GetWindowRect(hwnd, &rect);
GetWindowRect(hwndParent, &rectP);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
screenwidth = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);
// make sure that the dialog box never moves outside of
// the screen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > screenwidth) x = screenwidth - width;
if (y + height > screenheight) y = screenheight - height;
MoveWindow(hwnd, x, y, width, height, FALSE);
}
}

View File

@ -0,0 +1,8 @@
#pragma once
#include <windows.h>
namespace W32Util
{
void CenterWindow(HWND hwnd);
}

View File

@ -0,0 +1,223 @@
#include "Misc.h"
#include "PropertySheet.h"
#include <commctrl.h>
namespace W32Util
{
bool centered;
PropSheet::PropSheet()
{
watermark = 0;
header = 0;
icon = 0;
}
int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
{
switch (uMsg) {
case PSCB_PRECREATE:
{
if (uMsg == PSCB_PRECREATE)
{
/*
if (lParam)
{
DLGTEMPLATE* pDlgTemplate;
DLGTEMPLATEEX* pDlgTemplateEx;
pDlgTemplateEx = (DLGTEMPLATEEX*)lParam;
if (pDlgTemplateEx->signature == 0xFFFF)
{
// pDlgTemplateEx points to an extended
// dialog template structure.
//pDlgTemplate->style |= DS_SETFONT;
u8* tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX);
u16* tmp = (u16*)tmp1;
tmp++; //skip menu
tmp++; //skip dlg class
//Crash();
//Here we should bash in Segoe UI
//It turns out to be way complicated though
//Not worth it
}
else
{
// This is a standard dialog template
// structure.
pDlgTemplate = (DLGTEMPLATE*)lParam;
}
} */
}
}
break;
case PSCB_INITIALIZED:
{
}
return 0;
}
return 0;
}
void PropSheet::Show(HINSTANCE hInstance, HWND hParent, LPCTSTR title, int startpage, bool floating, bool wizard)
{
HPROPSHEETPAGE* pages = new HPROPSHEETPAGE[list.size()];
PROPSHEETPAGE page;
//common settings
memset((void*)&page,0,sizeof(PROPSHEETPAGE));
page.dwSize = sizeof(PROPSHEETPAGE);
page.hInstance = hInstance;
int i=0;
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++)
{
if (wizard)
{
if (i == 0 || i == list.size()-1)
page.dwFlags = PSP_HIDEHEADER;
else
page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
}
else
{
page.dwFlags = PSP_USETITLE;
}
page.pszTemplate = iter->resource;
page.pfnDlgProc = Tab::TabDlgProc;
page.pszTitle = iter->title;
page.pszHeaderTitle = wizard?iter->title:0;
page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0;
page.lParam = (LPARAM)iter->tab;
pages[i] = CreatePropertySheetPage(&page);
}
PROPSHEETHEADER sheet;
memset(&sheet,0,sizeof(sheet));
sheet.dwSize = sizeof(PROPSHEETHEADER);
sheet.hInstance = hInstance;
sheet.hwndParent = hParent;
sheet.pszbmWatermark = watermark;
sheet.pszbmHeader = header;
sheet.pszCaption = title;
sheet.nPages = (UINT)list.size();
sheet.phpage = pages;
sheet.nStartPage = startpage;
sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback;
NONCLIENTMETRICS ncm = {0};
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
hDialogFont = CreateFontIndirect(&ncm.lfMessageFont);
if (wizard)
{
sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0);
//Create the intro/end title font
LOGFONT TitleLogFont = ncm.lfMessageFont;
TitleLogFont.lfWeight = FW_BOLD;
lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold"));
//StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold"));
HDC hdc = GetDC(NULL); //gets the screen DC
int FontSize = 12;
TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72;
hTitleFont = CreateFontIndirect(&TitleLogFont);
ReleaseDC(NULL, hdc);
} else {
sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
hTitleFont = 0;
}
if (icon) {
sheet.dwFlags |= PSH_USEHICON;
sheet.hIcon = icon;
}
sheet.dwFlags |= PSH_NOCONTEXTHELP;
if (floating)
sheet.dwFlags |= PSH_MODELESS;
//else
// sheet.dwFlags |= PSH_NOAPPLYNOW;
centered=false;
PropertySheet(&sheet);
if (!floating)
{
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++)
{
delete iter->tab;
}
DeleteObject(hTitleFont);
}
DeleteObject(hDialogFont);
delete [] pages;
}
void PropSheet::Add(Tab* tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle)
{
tab->sheet = this;
list.push_back(Page(tab,resource,title,subtitle));
}
void WizExteriorPage::Init(HWND hDlg)
{
HWND hwndControl = GetDlgItem(hDlg, captionID);
//SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE);
SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0);
}
INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
Tab* tab = (Tab*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
switch(message)
{
case WM_INITDIALOG:
{
if (!centered) //HACK
{
CenterWindow(GetParent(hDlg));
centered=true;
}
LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam;
tab = (Tab*)l;
SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l);
tab->Init(hDlg);
}
break;
case WM_COMMAND:
tab->Command(hDlg,wParam);
PropSheet_Changed(GetParent(hDlg), hDlg);
break;
case WM_NOTIFY:
{
LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam;
HWND sheet = lppsn->hdr.hwndFrom;
switch(lppsn->hdr.code) {
case PSN_APPLY:
tab->Apply(hDlg);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg),
(tab->HasPrev()?PSWIZB_BACK:0) |
(tab->HasNext()?PSWIZB_NEXT:0) |
(tab->HasFinish()?PSWIZB_FINISH:0));
break;
case PSN_WIZNEXT:
tab->Apply(hDlg); //maybe not always good
break;
case PSN_WIZBACK:
case PSN_RESET: //cancel
break;
}
}
break;
}
return 0;
}
}

View File

@ -0,0 +1,87 @@
#pragma once
#include <windows.h>
#include <vector>
namespace W32Util
{
class PropSheet;
class Tab
{
public:
PropSheet* sheet; //back pointer ..
virtual void Init(HWND hDlg) {}
virtual void Command(HWND hDlg, WPARAM wParam) {}
virtual void Apply(HWND hDlg) {}
virtual bool HasPrev() {return true;}
virtual bool HasFinish() {return false;}
virtual bool HasNext() {return true;}
static INT_PTR __stdcall TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
};
class WizExteriorPage : public Tab
{
int captionID;
public:
WizExteriorPage(int caption) {captionID = caption;}
void Init(HWND hDlg);
};
class WizFirstPage : public WizExteriorPage
{
public:
WizFirstPage(int caption) : WizExteriorPage(caption) {}
bool HasPrev() {return false;}
};
class WizLastPage : public WizExteriorPage
{
public:
WizLastPage(int caption) : WizExteriorPage(caption) {}
bool HasNext() {return false;}
bool HasFinish() {return true;}
};
class WizInteriorPage : public Tab
{
public:
};
class PropSheet
{
LPCTSTR watermark;
LPCTSTR header;
HFONT hTitleFont;
HFONT hDialogFont;
HICON icon;
struct Page
{
Page(Tab* _tab, LPCTSTR _resource, LPCTSTR _title, LPCTSTR _subtitle = 0)
: tab(_tab), resource(_resource), title(_title), hdrSubTitle(_subtitle) {}
Tab* tab;
LPCTSTR resource;
LPCTSTR title;
LPCTSTR hdrSubTitle;
};
public:
PropSheet();
typedef std::vector<Page> DlgList;
DlgList list;
void SetWaterMark(LPCTSTR _watermark) {watermark=_watermark;}
void SetHeader(LPCTSTR _header) {header=_header;}
void SetIcon(HICON _icon) {icon = _icon;}
void Add(Tab* tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle = 0);
void Show(HINSTANCE hInstance, HWND hParent, LPCTSTR title, int startpage=0, bool floating = false, bool wizard = false);
HFONT GetTitleFont() {return hTitleFont;}
HFONT GetFont() {return hDialogFont;}
static int CALLBACK Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam);
};
}

View File

@ -0,0 +1,95 @@
#include <windows.h>
#include <commctrl.h>
#include "TabControl.h"
namespace W32Util
{
// __________________________________________________________________________________________________
// constructor
//
TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) :
m_hInstance(_hInstance),
m_hTabCtrl(_hTabCtrl),
m_numDialogs(0)
{
for (int i=0; i<MAX_WIN_DIALOGS; i++)
m_WinDialogs[i] = NULL;
}
// __________________________________________________________________________________________________
// destructor
//
TabControl::~TabControl(void)
{}
// __________________________________________________________________________________________________
// AddItem
//
HWND TabControl::AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc)
{
TCITEMA tcItem;
ZeroMemory (&tcItem,sizeof (tcItem));
tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
tcItem.dwState = 0;
tcItem.pszText = _szText;
tcItem.cchTextMax = sizeof (_szText);
tcItem.iImage = -1;
int nResult = TabCtrl_InsertItem (m_hTabCtrl,TabCtrl_GetItemCount (m_hTabCtrl),&tcItem);
HWND hDialog = CreateDialogA(m_hInstance,(LPCSTR)_iResource,m_hTabCtrl,_lpDialogFunc);
RECT rectInnerWindow = {0,0,0,0};
GetWindowRect (m_hTabCtrl,&rectInnerWindow);
TabCtrl_AdjustRect (m_hTabCtrl,FALSE,&rectInnerWindow);
POINT pntPosition = {rectInnerWindow.left,rectInnerWindow.top};
ScreenToClient(m_hTabCtrl, &pntPosition);
SetWindowPos(hDialog, 0,
pntPosition.x, pntPosition.y,
rectInnerWindow.right - rectInnerWindow.left,rectInnerWindow.bottom - rectInnerWindow.top,0);
ShowWindow(hDialog,SW_NORMAL);
m_WinDialogs[m_numDialogs] = hDialog;
m_numDialogs++;
SelectDialog (0);
return hDialog;
}
// __________________________________________________________________________________________________
// SelectDialog
//
void TabControl::SelectDialog (int _nDialogId)
{
for (int i = 0 ; i < m_numDialogs ; i ++)
if (m_WinDialogs[i] != NULL)
ShowWindow(m_WinDialogs[i],i == _nDialogId ? SW_NORMAL : SW_HIDE);
}
// __________________________________________________________________________________________________
// MessageHandler
//
void TabControl::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_NOTIFY)
{
NMHDR* pNotifyMessage = NULL;
pNotifyMessage = (LPNMHDR)lParam;
if (pNotifyMessage->hwndFrom == m_hTabCtrl)
{
int iPage = TabCtrl_GetCurSel (m_hTabCtrl);
SelectDialog (iPage);
}
}
}
}

View File

@ -0,0 +1,36 @@
#pragma once
namespace W32Util
{
#define MAX_WIN_DIALOGS 32
class TabControl
{
private:
HINSTANCE m_hInstance;
HWND m_hWndParent;
HWND m_hTabCtrl;
HWND m_WinDialogs[MAX_WIN_DIALOGS];
int m_numDialogs;
public:
TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc);
~TabControl(void);
//
// --- tools ---
//
HWND AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc);
void SelectDialog (int _nDialogId);
void MessageHandler(UINT message, WPARAM wParam, LPARAM lParam);
};
}

View File

@ -0,0 +1,82 @@
#include "Thread.h"
namespace W32Util
{
// __________________________________________________________________________________________________
// Constructor
//
Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
{
_handle = CreateThread (
0, // Security attributes
0, // Stack size
pFun,
pArg,
CREATE_SUSPENDED,
&_tid);
}
// __________________________________________________________________________________________________
// Destructor
//
Thread::~Thread (void)
{
if (_handle != NULL)
{
if (CloseHandle (_handle) == FALSE)
{
Terminate();
}
}
}
// __________________________________________________________________________________________________
// Resume
//
void
Thread::Resume (void)
{
if (_handle != NULL)
ResumeThread (_handle);
}
// __________________________________________________________________________________________________
// WaitForDeath
//
void
Thread::WaitForDeath (void)
{
if (_handle != NULL)
WaitForSingleObject (_handle, 100);
}
// __________________________________________________________________________________________________
// Terminate
//
void
Thread::Terminate (void)
{
if (_handle != NULL)
TerminateThread (_handle, 0);
_handle = NULL;
}
// __________________________________________________________________________________________________
// SetPriority
//
void
Thread::SetPriority (int _nPriority)
{
if (_handle != NULL)
SetThreadPriority(_handle, _nPriority);
}
// __________________________________________________________________________________________________
// Suspend
//
void
Thread::Suspend (void)
{
if (_handle != NULL)
SuspendThread(_handle);
}
}

View File

@ -0,0 +1,38 @@
#pragma once
#include <windows.h>
namespace W32Util
{
class Thread
{
private:
HANDLE _handle;
DWORD _tid; // thread id
public:
Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg);
~Thread () ;
//
// --- tools ---
//
void Resume(void);
void Suspend(void);
void WaitForDeath(void);
void Terminate(void);
void SetPriority(int _nPriority);
bool IsActive (void);
HANDLE GetHandle(void) {return _handle;}
};
}

View File

@ -0,0 +1,439 @@
// 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 <tchar.h>
#include <windows.h>
#include <d3dx11.h>
#include <wx/wx.h>
#include <wx/notebook.h>
#include "Common.h"
#include "Atomic.h"
#include "Thread.h"
#include "LogManager.h"
#include "svnrev.h"
#include "resource.h"
#include "main.h"
#include "VideoConfig.h"
#include "Fifo.h"
#include "OpcodeDecoding.h"
#include "TextureCache.h"
#include "BPStructs.h"
#include "VertexManager.h"
#include "VertexLoaderManager.h"
#include "VertexShaderManager.h"
#include "PixelShaderManager.h"
#include "VertexShaderCache.h"
#include "PixelShaderCache.h"
#include "CommandProcessor.h"
#include "PixelEngine.h"
#include "OnScreenDisplay.h"
#include "DlgSettings.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "W32Util/Misc.h"
#include "EmuWindow.h"
#include "VideoState.h"
#include "XFBConvert.h"
#include "render.h"
#if defined(DEBUGFAST)
#define DLL_PLUGIN_NAME "Dolphin Direct3D 11 (DebugFast)"
#elif defined(_DEBUG)
#define DLL_PLUGIN_NAME "Dolphin Direct3D 11 (Debug)"
#else
#define DLL_PLUGIN_NAME "Dolphin Direct3D 11"
#endif
HINSTANCE g_hInstance = NULL;
SVideoInitialize g_VideoInitialize;
PLUGIN_GLOBALS* globals = NULL;
static bool s_PluginInitialized = false;
volatile u32 s_swapRequested = FALSE;
static u32 s_efbAccessRequested = FALSE;
static volatile u32 s_FifoShuttingDown = FALSE;
static bool ForceSwap = true;
static volatile struct
{
u32 xfbAddr;
FieldType field;
u32 fbWidth;
u32 fbHeight;
} s_beginFieldArgs;
static volatile EFBAccessType s_AccessEFBType;
bool HandleDisplayList(u32 address, u32 size)
{
return false;
}
bool IsD3D()
{
return true;
}
bool IsD3D9()
{
return false;
}
bool IsD3D11()
{
return true;
}
// This is used for the functions right below here which use wxwidgets
#if defined(HAVE_WX) && HAVE_WX
#ifdef _WIN32
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
wxWindow* GetParentedWxWindow(HWND Parent)
{
#ifdef _WIN32
wxSetInstance((HINSTANCE)g_hInstance);
#endif
wxWindow* win = new wxWindow();
#ifdef _WIN32
win->SetHWND((WXHWND)Parent);
win->AdoptAttributesFromHWND();
#endif
return win;
}
#endif
void DllDebugger(HWND _hParent, bool Show)
{
}
#if defined(HAVE_WX) && HAVE_WX
class wxDLLApp : public wxApp
{
bool OnInit()
{
return true;
}
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
#endif
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
#if defined(HAVE_WX) && HAVE_WX
wxSetInstance((HINSTANCE)hinstDLL);
wxInitialize();
#endif
}
break;
case DLL_PROCESS_DETACH:
#if defined(HAVE_WX) && HAVE_WX
wxUninitialize();
#endif
break;
}
g_hInstance = hinstDLL;
return TRUE;
}
unsigned int Callback_PeekMessages()
{
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return FALSE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return TRUE;
}
void UpdateFPSDisplay(const char* text)
{
char temp[512];
sprintf_s(temp, 512, "SVN R%i: DX11: %s", SVN_REV, text);
SetWindowTextA(EmuWindow::GetWnd(), temp);
}
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
sprintf_s(_PluginInfo->Name, 100, DLL_PLUGIN_NAME);
}
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
{
globals = _pPluginGlobals;
LogManager::SetInstance((LogManager*)globals->logManager);
}
void DllAbout(HWND _hParent)
{
MessageBoxA(NULL, "DllAbout not implemented, how did you come here? Anyway, report this to the devs.", "Error!", MB_OK);
}
void DllConfig(HWND _hParent)
{
DlgSettings_Show(g_hInstance, _hParent);
}
void Initialize(void* init)
{
frameCount = 0;
SVideoInitialize* _pVideoInitialize = (SVideoInitialize*)init;
g_VideoInitialize = *_pVideoInitialize;
InitXFBConvTables();
g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_dx11.ini").c_str());
g_Config.GameIniLoad(globals->game_ini);
UpdateActiveConfig();
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, _T("Loading - Please wait."));
if (g_VideoInitialize.pWindowHandle == NULL)
{
ERROR_LOG(VIDEO, "An error has occurred while trying to create the window.");
return;
}
g_VideoInitialize.pPeekMessages = &Callback_PeekMessages;
g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay;
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
OSD::AddMessage("Dolphin Direct3D 11 Video Plugin.", 5000);
s_PluginInitialized = true;
}
void Video_Prepare()
{
s_efbAccessRequested = FALSE;
s_FifoShuttingDown = FALSE;
s_swapRequested = FALSE;
ForceSwap = true;
Renderer::Init();
TextureCache::Init();
BPInit();
VertexManager::Init();
Fifo_Init();
VertexLoaderManager::Init();
OpcodeDecoder_Init();
VertexShaderCache::Init();
VertexShaderManager::Init();
PixelShaderCache::Init();
PixelShaderManager::Init();
CommandProcessor::Init();
PixelEngine::Init();
D3D::InitUtils();
// tell the host that the window is ready
g_VideoInitialize.pCoreMessage(WM_USER_CREATE);
}
void Shutdown()
{
s_efbAccessRequested = FALSE;
s_FifoShuttingDown = FALSE;
s_swapRequested = FALSE;
D3D::ShutdownUtils();
CommandProcessor::Shutdown();
PixelShaderManager::Shutdown();
PixelShaderCache::Shutdown();
VertexShaderManager::Shutdown();
VertexShaderCache::Shutdown();
OpcodeDecoder_Shutdown();
VertexLoaderManager::Shutdown();
Fifo_Shutdown();
VertexManager::Shutdown();
TextureCache::Shutdown();
Renderer::Shutdown();
EmuWindow::Close();
s_PluginInitialized = false;
}
void DoState(unsigned char** ptr, int mode)
{
// clear texture cache because it might have written to RAM
CommandProcessor::FifoCriticalEnter();
TextureCache::Invalidate(false);
CommandProcessor::FifoCriticalLeave();
// no need to clear shader caches
PointerWrap p(ptr, mode);
VideoCommon_DoState(p);
}
void EmuStateChange(PLUGIN_EMUSTATE newState)
{
Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false);
}
void Video_EnterLoop()
{
Fifo_EnterLoop(g_VideoInitialize);
}
void Video_ExitLoop()
{
Fifo_ExitLoop();
s_FifoShuttingDown = TRUE;
}
void Video_SetRendering(bool bEnabled)
{
Fifo_SetRendering(bEnabled);
}
// run from the graphics thread
void VideoFifo_CheckSwapRequest()
{
if (Common::AtomicLoadAcquire(s_swapRequested))
{
if (ForceSwap)
Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
Common::AtomicStoreRelease(s_swapRequested, FALSE);
}
}
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return !((aLower >= bUpper) || (bLower >= aUpper));
}
// Run from the graphics thread
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
ForceSwap = false;
}
// Run from the CPU thread (from VideoInterface.cpp)
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{
}
void Video_EndField()
{
}
void Video_AddMessage(const char* pstr, u32 milliseconds)
{
OSD::AddMessage(pstr, milliseconds);
}
HRESULT ScreenShot(const char* filename)
{
return S_OK;
}
void Video_Screenshot(const char* _szFilename)
{
}
static struct
{
EFBAccessType type;
u32 x;
u32 y;
} s_accessEFBArgs;
static u32 s_AccessEFBResult = 0;
void VideoFifo_CheckEFBAccess()
{
if (Common::AtomicLoadAcquire(s_efbAccessRequested))
{
s_AccessEFBResult = Renderer::AccessEFB(s_accessEFBArgs.type, s_accessEFBArgs.x, s_accessEFBArgs.y);
Common::AtomicStoreRelease(s_efbAccessRequested, FALSE);
}
}
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
{
if (s_PluginInitialized)
{
s_accessEFBArgs.type = type;
s_accessEFBArgs.x = x;
s_accessEFBArgs.y = y;
Common::AtomicStoreRelease(s_efbAccessRequested, TRUE);
if (g_VideoInitialize.bOnThread)
{
while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown)
//Common::SleepCurrentThread(1);
Common::YieldCPU();
}
else
VideoFifo_CheckEFBAccess();
return s_AccessEFBResult;
}
return 0;
}
void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
{
CommandProcessor::Read16(_rReturnValue, _Address);
}
void Video_CommandProcessorWrite16(const u16 _Data, const u32 _Address)
{
CommandProcessor::Write16(_Data, _Address);
}
void Video_PixelEngineRead16(u16& _rReturnValue, const u32 _Address)
{
PixelEngine::Read16(_rReturnValue, _Address);
}
void Video_PixelEngineWrite16(const u16 _Data, const u32 _Address)
{
PixelEngine::Write16(_Data, _Address);
}
void Video_PixelEngineWrite32(const u32 _Data, const u32 _Address)
{
PixelEngine::Write32(_Data, _Address);
}
inline void Video_GatherPipeBursted(void)
{
CommandProcessor::GatherPipeBursted();
}
void Video_WaitForFrameFinish(void)
{
CommandProcessor::WaitForFrameFinish();
}

View File

@ -0,0 +1,27 @@
// 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 MAIN_H
#define MAIN_H
#include "PluginSpecs_Video.h"
#include "Render.h"
extern SVideoInitialize g_VideoInitialize;
extern volatile u32 s_swapRequested;
#endif

View File

@ -0,0 +1,52 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define IDD_ABOUT 102
#define IDD_SETTINGS 103
#define IDD_ADVANCED 105
//#define IDC_ADAPTER 1001
//#define IDC_ANTIALIASMODE 1002
//#define IDC_RESOLUTION 1003
#define IDC_VSYNC 1006
#define IDC_ASPECT_16_9 1008
#define IDC_ASPECT_4_3 1009
#define IDC_WIDESCREEN_HACK 1010
#define IDC_SAFE_TEXTURE_CACHE 1011
#define IDC_EFB_ACCESS_ENABLE 1012
#define IDC_WIREFRAME 1013
#define IDC_DISABLEFOG 1014
#define IDC_OVERLAYFPS 1015
#define IDC_OVERLAYSTATS 1016
#define IDC_OVERLAYPROJSTATS 1017
#define IDC_ENABLEEFBCOPY 1018
//#define IDC_EFBTORAM 1019
//#define IDC_EFBTOTEX 1020
#define IDC_TEXFMT_OVERLAY 1024
#define IDC_TEXFMT_CENTER 1025
#define IDC_ENABLEXFB 1026
#define IDC_FORCEANISOTROPY 1027
//#define IDC_ENABLEXFB2 1027
//#define IDC_ENABLEREALXFB 1027
//#define IDC_LOADHIRESTEXTURE 1028
#define IDC_EFBSCALEDCOPY 1029
#define IDC_OSDHOTKEY 1030
#define IDC_COMBO2 1040
#define IDC_ASPECTRATIO 1040
#define IDC_SAFE_TEXTURE_CACHE_SAFE 1041
#define IDC_SAFE_TEXTURE_CACHE_NORMAL 1042
#define IDC_RADIO3 1043
#define IDC_SAFE_TEXTURE_CACHE_FAST 1043
//#define IDC_DISABLEMIPS 1100
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1044
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,167 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <windows.h>
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUT DIALOGEX 0, 0, 188, 81
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_BORDER | WS_SYSMENU
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
LTEXT "Created by neobrain.",IDC_STATIC,7,7,85,9
LTEXT "Licensed under the terms of the GNU General Public License.",IDC_STATIC,7,17,85,9
LTEXT "Hardware requirements:",IDC_STATIC,7,37,174,26
LTEXT "Any GPU which supports at least DX10.",IDC_STATIC,15,47,174,26
LTEXT "DX9 hardware might work as well though.",IDC_STATIC,15,57,170,8
END
IDD_SETTINGS DIALOGEX 0, 0, 244, 183
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_BORDER | WS_SYSMENU
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
CONTROL "&V-Sync",IDC_VSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,61,10,36,8
CONTROL "&Widescreen Hack",IDC_WIDESCREEN_HACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,161,10,67,10
LTEXT "&Aspect Ratio:",IDC_STATIC,9,25,48,8
COMBOBOX IDC_ASPECTRATIO,60,23,89,57,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "&Enable CPU->EFB access ",IDC_EFB_ACCESS_ENABLE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,45,94,11
CONTROL "Enable &Safe Texture Cache",IDC_SAFE_TEXTURE_CACHE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,59,108,11
CONTROL "Safe",IDC_SAFE_TEXTURE_CACHE_SAFE,"Button",BS_AUTORADIOBUTTON,20,72,32,10
CONTROL "Normal",IDC_SAFE_TEXTURE_CACHE_NORMAL,"Button",BS_AUTORADIOBUTTON,52,72,40,10
CONTROL "Fast",IDC_SAFE_TEXTURE_CACHE_FAST,"Button",BS_AUTORADIOBUTTON,92,72,32,10
END
IDD_ADVANCED DIALOGEX 0, 0, 244, 200
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_BORDER | WS_SYSMENU
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
GROUPBOX "&Settings",IDC_STATIC,6,7,228,74
CONTROL "Overlay FPS counter",IDC_OVERLAYFPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,18,82,8
CONTROL "Disable Fog",IDC_DISABLEFOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,18,78,8
CONTROL "Enable Hotkey",IDC_OSDHOTKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,33,87,8
CONTROL "Enable EFB copy",IDC_ENABLEEFBCOPY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,33,81,8
CONTROL "EFB Scaled Copy",IDC_EFBSCALEDCOPY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,48,64,8
CONTROL "Enable &Wireframe",IDC_WIREFRAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,48,87,8
CONTROL "Enable 16x &anisotropy filtering",IDC_FORCEANISOTROPY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,63,110,8
GROUPBOX "Debugging Tools",IDC_STATIC,7,148,228,46
CONTROL "&Overlay some statistics",IDC_OVERLAYSTATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,159,90,8
CONTROL "Enable TexFmt Overlay",IDC_TEXFMT_OVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,174,92,10
CONTROL "Centered",IDC_TEXFMT_CENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,174,52,10
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 181
TOPMARGIN, 7
BOTTOMMARGIN, 74
END
IDD_SETTINGS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 237
VERTGUIDE, 7
VERTGUIDE, 68
VERTGUIDE, 81
VERTGUIDE, 87
TOPMARGIN, 7
BOTTOMMARGIN, 176
END
IDD_ADVANCED, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 237
VERTGUIDE, 14
VERTGUIDE, 29
VERTGUIDE, 114
TOPMARGIN, 7
BOTTOMMARGIN, 195
HORZGUIDE, 18
HORZGUIDE, 33
HORZGUIDE, 49
HORZGUIDE, 156
END
IDD_ENHANCEMENTS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 217
VERTGUIDE, 16
VERTGUIDE, 74
TOPMARGIN, 7
BOTTOMMARGIN, 168
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include <windows.h\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,18 @@
// 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 "stdafx.h"

View File

@ -0,0 +1,25 @@
// 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
#define _WIN32_WINNT 0x501
#ifndef _WIN32_IE
#define _WIN32_IE 0x0500 // Default value is 0x0400
#endif
#include <tchar.h>
#include <windows.h>