2010-06-13 19:50:06 +00:00
// 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/
2011-01-25 16:43:08 +00:00
# include <math.h>
2010-06-13 19:50:06 +00:00
# include "Timer.h"
2011-01-25 16:43:08 +00:00
# include "Debugger.h"
# include "DLCache.h"
# include "EmuWindow.h"
# include "Fifo.h"
# include "OnScreenDisplay.h"
2010-10-24 19:52:52 +00:00
# include "PixelEngine.h"
2011-01-25 16:43:08 +00:00
# include "Statistics.h"
2010-06-13 19:50:06 +00:00
# include "VertexShaderManager.h"
2011-01-25 16:43:08 +00:00
# include "VideoConfig.h"
# include "D3DBase.h"
# include "D3DUtil.h"
# include "FramebufferManager.h"
# include "GfxState.h"
2010-06-13 19:50:06 +00:00
# include "PixelShaderCache.h"
2011-01-25 16:43:08 +00:00
# include "Render.h"
2010-06-13 19:50:06 +00:00
# include "TextureCache.h"
2011-01-25 16:43:08 +00:00
# include "VertexShaderCache.h"
2011-01-31 01:28:32 +00:00
# include "Core.h"
2011-06-24 06:50:50 +00:00
# include "Movie.h"
2011-06-11 19:37:21 +00:00
# include "Television.h"
2011-03-15 23:09:12 +00:00
# include "Host.h"
2011-09-05 20:04:28 +00:00
# include "BPFunctions.h"
2011-09-08 13:39:03 +00:00
# include "AVIDump.h"
2012-10-04 03:41:02 +00:00
# include "FPSCounter.h"
2012-11-11 22:57:06 +00:00
# include "ConfigManager.h"
2012-12-23 07:25:11 +00:00
# include <strsafe.h>
2010-06-13 19:50:06 +00:00
2011-01-29 20:16:51 +00:00
namespace DX11
{
2010-06-13 19:50:06 +00:00
static int s_fps = 0 ;
2010-11-23 19:58:02 +00:00
static u32 s_LastAA = 0 ;
2011-06-11 19:37:21 +00:00
static Television s_television ;
ID3D11Buffer * access_efb_cbuf = NULL ;
ID3D11BlendState * clearblendstates [ 4 ] = { NULL } ;
2010-11-01 19:13:50 +00:00
ID3D11DepthStencilState * cleardepthstates [ 3 ] = { NULL } ;
2011-06-11 19:37:21 +00:00
ID3D11BlendState * resetblendstate = NULL ;
2010-06-13 19:50:06 +00:00
ID3D11DepthStencilState * resetdepthstate = NULL ;
ID3D11RasterizerState * resetraststate = NULL ;
2011-09-08 13:39:03 +00:00
static ID3D11Texture2D * s_screenshot_texture = NULL ;
2012-05-29 11:54:20 +00:00
2011-01-24 08:44:32 +00:00
// GX pipeline state
struct
{
D3D11_SAMPLER_DESC sampdc [ 8 ] ;
2011-01-24 10:42:43 +00:00
D3D11_BLEND_DESC blenddc ;
2011-01-24 09:10:35 +00:00
D3D11_DEPTH_STENCIL_DESC depthdc ;
2011-01-24 09:27:16 +00:00
D3D11_RASTERIZER_DESC rastdc ;
2011-01-24 08:44:32 +00:00
} gx_state ;
2012-08-07 12:55:10 +00:00
2010-06-13 19:50:06 +00:00
void SetupDeviceObjects ( )
{
2011-06-11 19:37:21 +00:00
s_television . Init ( ) ;
2010-11-14 23:31:53 +00:00
g_framebuffer_manager = new FramebufferManager ;
2010-06-13 19:50:06 +00:00
2010-07-18 10:11:34 +00:00
HRESULT hr ;
2010-06-13 19:50:06 +00:00
float colmat [ 20 ] = { 0.0f } ;
colmat [ 0 ] = colmat [ 5 ] = colmat [ 10 ] = 1.0f ;
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC ( 20 * sizeof ( float ) , D3D11_BIND_CONSTANT_BUFFER , D3D11_USAGE_DEFAULT ) ;
D3D11_SUBRESOURCE_DATA data ;
data . pSysMem = colmat ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateBuffer ( & cbdesc , & data , & access_efb_cbuf ) ;
CHECK ( hr = = S_OK , " Create constant buffer for Renderer::AccessEFB " ) ;
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) access_efb_cbuf , " constant buffer for Renderer::AccessEFB " ) ;
2010-06-13 19:50:06 +00:00
D3D11_DEPTH_STENCIL_DESC ddesc ;
2010-11-18 02:21:26 +00:00
ddesc . DepthEnable = FALSE ;
2010-06-15 21:19:09 +00:00
ddesc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO ;
2010-11-18 02:21:26 +00:00
ddesc . DepthFunc = D3D11_COMPARISON_ALWAYS ;
ddesc . StencilEnable = FALSE ;
2010-06-13 19:50:06 +00:00
ddesc . StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK ;
ddesc . StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateDepthStencilState ( & ddesc , & cleardepthstates [ 0 ] ) ;
2010-06-18 18:40:58 +00:00
CHECK ( hr = = S_OK , " Create depth state for Renderer::ClearScreen " ) ;
2010-06-15 21:19:09 +00:00
ddesc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL ;
2010-11-18 02:21:26 +00:00
ddesc . DepthEnable = TRUE ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateDepthStencilState ( & ddesc , & cleardepthstates [ 1 ] ) ;
2010-06-18 18:40:58 +00:00
CHECK ( hr = = S_OK , " Create depth state for Renderer::ClearScreen " ) ;
2010-11-01 19:13:50 +00:00
ddesc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateDepthStencilState ( & ddesc , & cleardepthstates [ 2 ] ) ;
2010-11-01 19:13:50 +00:00
CHECK ( hr = = S_OK , " Create depth state for Renderer::ClearScreen " ) ;
2011-06-11 19:37:21 +00:00
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) cleardepthstates [ 0 ] , " depth state for Renderer::ClearScreen (depth buffer disabled) " ) ;
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) cleardepthstates [ 1 ] , " depth state for Renderer::ClearScreen (depth buffer enabled, writing enabled) " ) ;
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) cleardepthstates [ 2 ] , " depth state for Renderer::ClearScreen (depth buffer enabled, writing disabled) " ) ;
2010-06-13 19:50:06 +00:00
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 ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateBlendState ( & blenddesc , & resetblendstate ) ;
CHECK ( hr = = S_OK , " Create blend state for Renderer::ResetAPIState " ) ;
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) resetblendstate , " blend state for Renderer::ResetAPIState " ) ;
2010-06-13 19:50:06 +00:00
2010-10-24 16:53:33 +00:00
clearblendstates [ 0 ] = resetblendstate ;
2011-06-11 19:37:21 +00:00
resetblendstate - > AddRef ( ) ;
2010-10-24 16:53:33 +00:00
2011-06-11 19:37:21 +00:00
blenddesc . RenderTarget [ 0 ] . RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE ;
hr = D3D : : device - > CreateBlendState ( & blenddesc , & clearblendstates [ 1 ] ) ;
CHECK ( hr = = S_OK , " Create blend state for Renderer::ClearScreen " ) ;
2010-10-24 16:53:33 +00:00
blenddesc . RenderTarget [ 0 ] . RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateBlendState ( & blenddesc , & clearblendstates [ 2 ] ) ;
CHECK ( hr = = S_OK , " Create blend state for Renderer::ClearScreen " ) ;
2010-10-24 16:53:33 +00:00
blenddesc . RenderTarget [ 0 ] . RenderTargetWriteMask = 0 ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateBlendState ( & blenddesc , & clearblendstates [ 3 ] ) ;
CHECK ( hr = = S_OK , " Create blend state for Renderer::ClearScreen " ) ;
2010-10-24 16:53:33 +00:00
2010-11-18 02:21:26 +00:00
ddesc . DepthEnable = FALSE ;
ddesc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO ;
ddesc . DepthFunc = D3D11_COMPARISON_LESS ;
ddesc . StencilEnable = FALSE ;
2010-06-13 19:50:06 +00:00
ddesc . StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK ;
ddesc . StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateDepthStencilState ( & ddesc , & resetdepthstate ) ;
2010-06-18 18:40:58 +00:00
CHECK ( hr = = S_OK , " Create depth state for Renderer::ResetAPIState " ) ;
2011-06-11 19:37:21 +00:00
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) resetdepthstate , " depth stencil state for Renderer::ResetAPIState " ) ;
2010-06-13 19:50:06 +00:00
D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC ( D3D11_FILL_SOLID , D3D11_CULL_NONE , false , 0 , 0.f , 0.f , false , false , false , false ) ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateRasterizerState ( & rastdesc , & resetraststate ) ;
2010-11-01 19:13:50 +00:00
CHECK ( hr = = S_OK , " Create rasterizer state for Renderer::ResetAPIState " ) ;
2011-06-11 19:37:21 +00:00
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) resetraststate , " rasterizer state for Renderer::ResetAPIState " ) ;
2011-09-08 13:39:03 +00:00
2012-08-07 12:55:10 +00:00
s_screenshot_texture = NULL ;
2010-06-13 19:50:06 +00:00
}
2011-09-08 13:39:03 +00:00
// Kill off all device objects
2010-06-13 19:50:06 +00:00
void TeardownDeviceObjects ( )
{
2010-11-14 23:31:53 +00:00
delete g_framebuffer_manager ;
2011-06-11 19:37:21 +00:00
SAFE_RELEASE ( access_efb_cbuf ) ;
SAFE_RELEASE ( clearblendstates [ 0 ] ) ;
SAFE_RELEASE ( clearblendstates [ 1 ] ) ;
SAFE_RELEASE ( clearblendstates [ 2 ] ) ;
SAFE_RELEASE ( clearblendstates [ 3 ] ) ;
2010-06-13 19:50:06 +00:00
SAFE_RELEASE ( cleardepthstates [ 0 ] ) ;
SAFE_RELEASE ( cleardepthstates [ 1 ] ) ;
2010-11-01 19:13:50 +00:00
SAFE_RELEASE ( cleardepthstates [ 2 ] ) ;
2011-06-11 19:37:21 +00:00
SAFE_RELEASE ( resetblendstate ) ;
2010-06-13 19:50:06 +00:00
SAFE_RELEASE ( resetdepthstate ) ;
SAFE_RELEASE ( resetraststate ) ;
2011-09-08 13:39:03 +00:00
SAFE_RELEASE ( s_screenshot_texture ) ;
2011-06-11 19:37:21 +00:00
s_television . Shutdown ( ) ;
2010-06-13 19:50:06 +00:00
}
2012-08-07 12:55:10 +00:00
void CreateScreenshotTexture ( )
{
D3D11_TEXTURE2D_DESC scrtex_desc = CD3D11_TEXTURE2D_DESC ( DXGI_FORMAT_R8G8B8A8_UNORM , D3D : : GetBackBufferWidth ( ) , D3D : : GetBackBufferHeight ( ) , 1 , 1 , 0 , D3D11_USAGE_STAGING , D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE ) ;
HRESULT hr = D3D : : device - > CreateTexture2D ( & scrtex_desc , NULL , & s_screenshot_texture ) ;
CHECK ( hr = = S_OK , " Create screenshot staging texture " ) ;
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) s_screenshot_texture , " staging screenshot texture " ) ;
}
2010-11-18 02:21:26 +00:00
Renderer : : Renderer ( )
2010-06-13 19:50:06 +00:00
{
int x , y , w_temp , h_temp ;
2012-10-04 03:41:02 +00:00
InitFPSCounter ( ) ;
2010-06-13 19:50:06 +00:00
2011-03-15 23:09:12 +00:00
Host_GetRenderWindowSize ( x , y , w_temp , h_temp ) ;
2010-06-13 19:50:06 +00:00
D3D : : Create ( EmuWindow : : GetWnd ( ) ) ;
s_backbuffer_width = D3D : : GetBackBufferWidth ( ) ;
s_backbuffer_height = D3D : : GetBackBufferHeight ( ) ;
2012-09-28 21:48:18 +00:00
FramebufferManagerBase : : SetLastXfbWidth ( MAX_XFB_WIDTH ) ;
FramebufferManagerBase : : SetLastXfbHeight ( MAX_XFB_HEIGHT ) ;
2010-06-13 19:50:06 +00:00
2012-09-28 22:04:55 +00:00
UpdateDrawRectangle ( s_backbuffer_width , s_backbuffer_height ) ;
2010-06-13 19:50:06 +00:00
2010-11-23 19:58:02 +00:00
s_LastAA = g_ActiveConfig . iMultisampleMode ;
2010-11-10 16:43:27 +00:00
s_LastEFBScale = g_ActiveConfig . iEFBScale ;
2012-09-28 22:19:28 +00:00
CalculateTargetSize ( s_backbuffer_width , s_backbuffer_height ) ;
2010-06-13 19:50:06 +00:00
SetupDeviceObjects ( ) ;
2011-09-08 13:39:03 +00:00
2011-01-24 08:44:32 +00:00
// Setup GX pipeline state
2011-01-24 10:42:43 +00:00
memset ( & gx_state . blenddc , 0 , sizeof ( gx_state . blenddc ) ) ;
gx_state . blenddc . AlphaToCoverageEnable = FALSE ;
gx_state . blenddc . IndependentBlendEnable = FALSE ;
gx_state . blenddc . RenderTarget [ 0 ] . BlendEnable = FALSE ;
gx_state . blenddc . RenderTarget [ 0 ] . RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL ;
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_ONE ;
gx_state . blenddc . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_ZERO ;
gx_state . blenddc . RenderTarget [ 0 ] . BlendOp = D3D11_BLEND_OP_ADD ;
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_ONE ;
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_ZERO ;
gx_state . blenddc . RenderTarget [ 0 ] . BlendOpAlpha = D3D11_BLEND_OP_ADD ;
2011-01-24 09:10:35 +00:00
memset ( & gx_state . depthdc , 0 , sizeof ( gx_state . depthdc ) ) ;
gx_state . depthdc . DepthEnable = TRUE ;
gx_state . depthdc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL ;
gx_state . depthdc . DepthFunc = D3D11_COMPARISON_LESS ;
gx_state . depthdc . StencilEnable = FALSE ;
gx_state . depthdc . StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK ;
gx_state . depthdc . StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK ;
2011-01-24 09:27:16 +00:00
// TODO: Do we need to enable multisampling here?
gx_state . rastdc = CD3D11_RASTERIZER_DESC ( D3D11_FILL_SOLID , D3D11_CULL_NONE , false , 0 , 0.f , 0 , false , true , false , false ) ;
2011-01-24 08:44:32 +00:00
for ( unsigned int k = 0 ; k < 8 ; k + + )
{
float border [ 4 ] = { 0.f , 0.f , 0.f , 0.f } ;
gx_state . sampdc [ k ] = CD3D11_SAMPLER_DESC ( D3D11_FILTER_MIN_MAG_MIP_LINEAR , D3D11_TEXTURE_ADDRESS_CLAMP , D3D11_TEXTURE_ADDRESS_CLAMP , D3D11_TEXTURE_ADDRESS_CLAMP ,
0.f , 1 < < g_ActiveConfig . iMaxAnisotropy ,
D3D11_COMPARISON_ALWAYS , border ,
- D3D11_FLOAT32_MAX , D3D11_FLOAT32_MAX ) ;
if ( g_ActiveConfig . iMaxAnisotropy ! = 0 ) gx_state . sampdc [ k ] . Filter = D3D11_FILTER_ANISOTROPIC ;
}
2010-06-13 19:50:06 +00:00
2011-01-24 08:44:32 +00:00
// Clear EFB textures
2010-12-21 22:18:40 +00:00
float ClearColor [ 4 ] = { 0.f , 0.f , 0.f , 1.f } ;
2011-06-11 19:37:21 +00:00
D3D : : context - > ClearRenderTargetView ( FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , ClearColor ) ;
D3D : : context - > ClearDepthStencilView ( FramebufferManager : : GetEFBDepthTexture ( ) - > GetDSV ( ) , D3D11_CLEAR_DEPTH , 1.f , 0 ) ;
2010-06-13 19:50:06 +00:00
2011-06-11 19:37:21 +00:00
D3D11_VIEWPORT vp = CD3D11_VIEWPORT ( 0.f , 0.f , ( float ) s_target_width , ( float ) s_target_height ) ;
D3D : : context - > RSSetViewports ( 1 , & vp ) ;
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , FramebufferManager : : GetEFBDepthTexture ( ) - > GetDSV ( ) ) ;
2010-06-13 19:50:06 +00:00
D3D : : BeginFrame ( ) ;
}
2010-11-18 02:21:26 +00:00
Renderer : : ~ Renderer ( )
2010-06-13 19:50:06 +00:00
{
TeardownDeviceObjects ( ) ;
D3D : : EndFrame ( ) ;
D3D : : Present ( ) ;
D3D : : Close ( ) ;
}
2010-09-28 02:15:02 +00:00
void Renderer : : RenderText ( const char * text , int left , int top , u32 color )
2010-06-13 19:50:06 +00:00
{
2010-11-07 10:11:58 +00:00
D3D : : font . DrawTextScaled ( ( float ) left , ( float ) top , 20.f , 0.0f , color , text ) ;
2010-06-13 19:50:06 +00:00
}
TargetRectangle Renderer : : ConvertEFBRectangle ( const EFBRectangle & rc )
{
TargetRectangle result ;
2011-05-12 02:14:45 +00:00
result . left = EFBToScaledX ( rc . left ) ;
result . top = EFBToScaledY ( rc . top ) ;
result . right = EFBToScaledX ( rc . right ) ;
result . bottom = EFBToScaledY ( rc . bottom ) ;
2010-06-13 19:50:06 +00:00
return result ;
}
2010-09-28 02:15:02 +00:00
// With D3D, we have to resize the backbuffer if the window changed
// size.
2010-11-18 02:21:26 +00:00
bool Renderer : : CheckForResize ( )
2010-06-13 19:50:06 +00:00
{
while ( EmuWindow : : IsSizing ( ) )
Sleep ( 10 ) ;
if ( EmuWindow : : GetParentWnd ( ) )
{
2010-09-28 02:15:02 +00:00
// Re-stretch window to parent window size again, if it has a parent window.
2010-06-13 19:50:06 +00:00
RECT rcParentWindow ;
GetWindowRect ( EmuWindow : : GetParentWnd ( ) , & rcParentWindow ) ;
int width = rcParentWindow . right - rcParentWindow . left ;
int height = rcParentWindow . bottom - rcParentWindow . top ;
2010-11-18 02:21:26 +00:00
if ( width ! = Renderer : : GetBackbufferWidth ( ) | | height ! = Renderer : : GetBackbufferHeight ( ) )
2010-09-28 02:15:02 +00:00
MoveWindow ( EmuWindow : : GetWnd ( ) , 0 , 0 , width , height , FALSE ) ;
2010-06-13 19:50:06 +00:00
}
RECT rcWindow ;
GetClientRect ( EmuWindow : : GetWnd ( ) , & rcWindow ) ;
int client_width = rcWindow . right - rcWindow . left ;
int client_height = rcWindow . bottom - rcWindow . top ;
2010-09-28 02:15:02 +00:00
// Sanity check
2010-11-18 02:21:26 +00:00
if ( ( client_width ! = Renderer : : GetBackbufferWidth ( ) | |
client_height ! = Renderer : : GetBackbufferHeight ( ) ) & &
2010-06-13 19:50:06 +00:00
client_width > = 4 & & client_height > = 4 )
{
2010-11-18 02:21:26 +00:00
return true ;
2010-06-13 19:50:06 +00:00
}
2010-11-18 02:21:26 +00:00
return false ;
2010-06-13 19:50:06 +00:00
}
2011-09-05 20:04:28 +00:00
void Renderer : : SetScissorRect ( const TargetRectangle & rc )
2010-06-13 19:50:06 +00:00
{
2011-09-05 20:04:28 +00:00
D3D : : context - > RSSetScissorRects ( 1 , rc . AsRECT ( ) ) ;
2010-06-13 19:50:06 +00:00
}
2010-06-16 10:12:57 +00:00
void Renderer : : SetColorMask ( )
2010-06-13 19:50:06 +00:00
{
2010-12-20 16:57:29 +00:00
// Only enable alpha channel if it's supported by the current EFB format
2010-06-13 19:50:06 +00:00
UINT8 color_mask = 0 ;
2013-01-08 16:23:01 +00:00
if ( bpmem . alpha_test . TestResult ( ) ! = AlphaTest : : FAIL )
{
if ( bpmem . blendmode . alphaupdate & & ( bpmem . zcontrol . pixel_format = = PIXELFMT_RGBA6_Z24 ) )
color_mask = D3D11_COLOR_WRITE_ENABLE_ALPHA ;
if ( bpmem . blendmode . colorupdate )
color_mask | = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE ;
}
2011-01-24 10:42:43 +00:00
gx_state . blenddc . RenderTarget [ 0 ] . RenderTargetWriteMask = color_mask ;
2010-06-13 19:50:06 +00:00
}
2010-10-24 19:52:52 +00:00
// This function allows the CPU to directly access the EFB.
// There are EFB peeks (which will read the color or depth of a pixel)
// and EFB pokes (which will change the color or depth of a pixel).
//
// The behavior of EFB peeks can only be modified by:
// - GX_PokeAlphaRead
// The behavior of EFB pokes can be modified by:
// - GX_PokeAlphaMode (TODO)
// - GX_PokeAlphaUpdate (TODO)
// - GX_PokeBlendMode (TODO)
// - GX_PokeColorUpdate (TODO)
// - GX_PokeDither (TODO)
// - GX_PokeDstAlpha (TODO)
// - GX_PokeZMode (TODO)
2010-10-22 19:40:05 +00:00
u32 Renderer : : AccessEFB ( EFBAccessType type , u32 x , u32 y , u32 poke_data )
2010-06-13 19:50:06 +00:00
{
2010-11-23 19:58:02 +00:00
// TODO: This function currently is broken if anti-aliasing is enabled
2010-10-22 19:40:05 +00:00
D3D11_MAPPED_SUBRESOURCE map ;
2010-06-21 17:54:13 +00:00
ID3D11Texture2D * read_tex ;
2010-06-13 19:50:06 +00:00
if ( ! g_ActiveConfig . bEFBAccessEnable )
return 0 ;
2010-10-22 19:40:05 +00:00
if ( type = = POKE_Z )
2010-07-16 21:51:35 +00:00
{
static bool alert_only_once = true ;
if ( ! alert_only_once ) return 0 ;
2010-10-22 19:40:05 +00:00
PanicAlert ( " EFB: Poke Z not implemented (tried to poke z value %#x at (%d,%d)) " , poke_data , x , y ) ;
2010-07-16 21:51:35 +00:00
alert_only_once = false ;
return 0 ;
}
2010-10-02 11:50:50 +00:00
// Convert EFB dimensions to the ones of our render target
2010-06-13 19:50:06 +00:00
EFBRectangle efbPixelRc ;
efbPixelRc . left = x ;
efbPixelRc . top = y ;
efbPixelRc . right = x + 1 ;
efbPixelRc . bottom = y + 1 ;
TargetRectangle targetPixelRc = Renderer : : ConvertEFBRectangle ( efbPixelRc ) ;
2010-10-22 19:40:05 +00:00
// Take the mean of the resulting dimensions; TODO: Don't use the center pixel, compute the average color instead
2010-10-02 11:50:50 +00:00
D3D11_RECT RectToLock ;
2010-10-22 19:40:05 +00:00
if ( type = = PEEK_COLOR | | type = = PEEK_Z )
{
RectToLock . left = ( targetPixelRc . left + targetPixelRc . right ) / 2 ;
RectToLock . top = ( targetPixelRc . top + targetPixelRc . bottom ) / 2 ;
RectToLock . right = RectToLock . left + 1 ;
RectToLock . bottom = RectToLock . top + 1 ;
}
else
{
RectToLock . left = targetPixelRc . left ;
RectToLock . right = targetPixelRc . right ;
RectToLock . top = targetPixelRc . top ;
RectToLock . bottom = targetPixelRc . bottom ;
}
2010-06-13 19:50:06 +00:00
if ( type = = PEEK_Z )
{
2010-09-28 02:15:02 +00:00
ResetAPIState ( ) ; // Reset any game specific settings
2010-06-13 19:50:06 +00:00
2010-10-02 11:50:50 +00:00
// depth buffers can only be completely CopySubresourceRegion'ed, so we're using drawShadedTexQuad instead
D3D11_VIEWPORT vp = CD3D11_VIEWPORT ( 0.f , 0.f , 1.f , 1.f ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > RSSetViewports ( 1 , & vp ) ;
D3D : : context - > PSSetConstantBuffers ( 0 , 1 , & access_efb_cbuf ) ;
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBDepthReadTexture ( ) - > GetRTV ( ) , NULL ) ;
2010-07-17 15:18:52 +00:00
D3D : : SetPointCopySampler ( ) ;
2010-11-27 11:11:05 +00:00
D3D : : drawShadedTexQuad ( FramebufferManager : : GetEFBDepthTexture ( ) - > GetSRV ( ) ,
2010-06-13 19:50:06 +00:00
& RectToLock ,
2011-05-12 02:14:45 +00:00
Renderer : : GetTargetWidth ( ) ,
Renderer : : GetTargetHeight ( ) ,
2010-11-27 11:11:05 +00:00
PixelShaderCache : : GetDepthMatrixProgram ( true ) ,
2010-06-13 19:50:06 +00:00
VertexShaderCache : : GetSimpleVertexShader ( ) ,
VertexShaderCache : : GetSimpleInputLayout ( ) ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , FramebufferManager : : GetEFBDepthTexture ( ) - > GetDSV ( ) ) ;
2010-06-13 19:50:06 +00:00
2010-06-21 17:54:13 +00:00
// copy to system memory
2010-10-02 11:50:50 +00:00
D3D11_BOX box = CD3D11_BOX ( 0 , 0 , 0 , 1 , 1 , 1 ) ;
2010-11-14 23:31:53 +00:00
read_tex = FramebufferManager : : GetEFBDepthStagingBuffer ( ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > CopySubresourceRegion ( read_tex , 0 , 0 , 0 , 0 , FramebufferManager : : GetEFBDepthReadTexture ( ) - > GetTex ( ) , 0 , & box ) ;
2010-10-02 11:50:50 +00:00
RestoreAPIState ( ) ; // restore game state
2010-10-22 19:40:05 +00:00
// read the data from system memory
2011-06-11 19:37:21 +00:00
D3D : : context - > Map ( read_tex , 0 , D3D11_MAP_READ , 0 , & map ) ;
2010-10-22 19:40:05 +00:00
float val = * ( float * ) map . pData ;
2010-12-27 03:18:01 +00:00
u32 ret = 0 ;
if ( bpmem . zcontrol . pixel_format = = PIXELFMT_RGB565_Z16 )
{
2010-12-27 18:09:03 +00:00
// if Z is in 16 bit format you must return a 16 bit integer
2010-12-27 03:18:01 +00:00
ret = ( ( u32 ) ( val * 0xffff ) ) ;
}
else
{
ret = ( ( u32 ) ( val * 0xffffff ) ) ;
}
2011-06-11 19:37:21 +00:00
D3D : : context - > Unmap ( read_tex , 0 ) ;
2010-10-22 19:40:05 +00:00
// TODO: in RE0 this value is often off by one in Video_DX9 (where this code is derived from), which causes lighting to disappear
return ret ;
2010-06-13 19:50:06 +00:00
}
2010-10-22 19:40:05 +00:00
else if ( type = = PEEK_COLOR )
2010-06-13 19:50:06 +00:00
{
2010-06-21 17:54:13 +00:00
// we can directly copy to system memory here
2010-12-05 22:28:46 +00:00
read_tex = FramebufferManager : : GetEFBColorStagingBuffer ( ) ;
2010-06-13 19:50:06 +00:00
D3D11_BOX box = CD3D11_BOX ( RectToLock . left , RectToLock . top , 0 , RectToLock . right , RectToLock . bottom , 1 ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > CopySubresourceRegion ( read_tex , 0 , 0 , 0 , 0 , FramebufferManager : : GetEFBColorTexture ( ) - > GetTex ( ) , 0 , & box ) ;
2010-06-13 19:50:06 +00:00
2010-10-22 19:40:05 +00:00
// read the data from system memory
2011-06-11 19:37:21 +00:00
D3D : : context - > Map ( read_tex , 0 , D3D11_MAP_READ , 0 , & map ) ;
2010-12-27 03:18:01 +00:00
u32 ret = 0 ;
if ( map . pData )
ret = * ( u32 * ) map . pData ;
2011-06-11 19:37:21 +00:00
D3D : : context - > Unmap ( read_tex , 0 ) ;
2010-10-24 19:52:52 +00:00
// check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine : : UPEAlphaReadReg alpha_read_mode ;
2011-01-07 19:51:28 +00:00
PixelEngine : : Read16 ( ( u16 & ) alpha_read_mode , PE_ALPHAREAD ) ;
2010-12-27 03:18:01 +00:00
if ( bpmem . zcontrol . pixel_format = = PIXELFMT_RGBA6_Z24 )
{
ret = RGBA8ToRGBA6ToRGBA8 ( ret ) ;
}
else if ( bpmem . zcontrol . pixel_format = = PIXELFMT_RGB565_Z16 )
{
2010-12-27 18:09:03 +00:00
ret = RGBA8ToRGB565ToRGBA8 ( ret ) ;
2010-12-27 03:18:01 +00:00
}
if ( bpmem . zcontrol . pixel_format ! = PIXELFMT_RGBA6_Z24 )
{
ret | = 0xFF000000 ;
}
2010-10-24 19:52:52 +00:00
if ( alpha_read_mode . ReadMode = = 2 ) return ret ; // GX_READ_NONE
else if ( alpha_read_mode . ReadMode = = 1 ) return ( ret | 0xFF000000 ) ; // GX_READ_FF
else /*if(alpha_read_mode.ReadMode == 0)*/ return ( ret & 0x00FFFFFF ) ; // GX_READ_00
2010-10-22 19:40:05 +00:00
}
else //if(type == POKE_COLOR)
2010-09-28 02:15:02 +00:00
{
2010-10-22 19:40:05 +00:00
u32 rgbaColor = ( poke_data & 0xFF00FF00 ) | ( ( poke_data > > 16 ) & 0xFF ) | ( ( poke_data < < 16 ) & 0xFF0000 ) ;
2010-10-24 19:52:52 +00:00
// TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet.
ResetAPIState ( ) ;
2010-09-28 02:15:02 +00:00
2011-06-11 19:37:21 +00:00
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , NULL ) ;
2011-05-12 02:14:45 +00:00
D3D : : drawColorQuad ( rgbaColor , ( float ) RectToLock . left * 2.f / ( float ) Renderer : : GetTargetWidth ( ) - 1.f ,
- ( float ) RectToLock . top * 2.f / ( float ) Renderer : : GetTargetHeight ( ) + 1.f ,
( float ) RectToLock . right * 2.f / ( float ) Renderer : : GetTargetWidth ( ) - 1.f ,
- ( float ) RectToLock . bottom * 2.f / ( float ) Renderer : : GetTargetHeight ( ) + 1.f ) ;
2010-09-28 02:15:02 +00:00
2010-10-24 19:52:52 +00:00
RestoreAPIState ( ) ;
return 0 ;
2010-06-13 19:50:06 +00:00
}
}
2011-05-12 02:14:45 +00:00
// Viewport correction:
// Say you want a viewport at (ix, iy) with size (iw, ih),
// but your viewport must be clamped at (ax, ay) with size (aw, ah).
// Just multiply the projection matrix with the following to get the same
// effect:
// [ (iw/aw) 0 0 ((iw - 2*(ax-ix)) / aw - 1) ]
// [ 0 (ih/ah) 0 ((-ih + 2*(ay-iy)) / ah + 1) ]
// [ 0 0 1 0 ]
// [ 0 0 0 1 ]
static void ViewportCorrectionMatrix ( Matrix44 & result ,
float ix , float iy , float iw , float ih , // Intended viewport (x, y, width, height)
float ax , float ay , float aw , float ah ) // Actual viewport (x, y, width, height)
{
Matrix44 : : LoadIdentity ( result ) ;
if ( aw = = 0.f | | ah = = 0.f )
return ;
result . data [ 4 * 0 + 0 ] = iw / aw ;
result . data [ 4 * 0 + 3 ] = ( iw - 2.f * ( ax - ix ) ) / aw - 1.f ;
result . data [ 4 * 1 + 1 ] = ih / ah ;
result . data [ 4 * 1 + 3 ] = ( - ih + 2.f * ( ay - iy ) ) / ah + 1.f ;
}
2010-06-13 19:50:06 +00:00
// Called from VertexShaderManager
2011-05-12 02:14:45 +00:00
void Renderer : : UpdateViewport ( Matrix44 & vpCorrection )
2010-06-13 19:50:06 +00:00
{
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
// [0] = width/2
// [1] = height/2
// [2] = 16777215 * (farz - nearz)
// [3] = xorig + width/2 + 342
// [4] = yorig + height/2 + 342
// [5] = 16777215 * farz
2010-07-11 16:26:46 +00:00
2011-05-12 02:14:45 +00:00
int scissorXOff = bpmem . scissorOffset . x * 2 ;
int scissorYOff = bpmem . scissorOffset . y * 2 ;
2010-06-13 19:50:06 +00:00
2010-12-10 15:54:14 +00:00
// TODO: ceil, floor or just cast to int?
// TODO: Directly use the floats instead of rounding them?
2011-05-12 02:14:45 +00:00
int intendedX = Renderer : : EFBToScaledX ( ( int ) ceil ( xfregs . viewport . xOrig - xfregs . viewport . wd - scissorXOff ) ) ;
int intendedY = Renderer : : EFBToScaledY ( ( int ) ceil ( xfregs . viewport . yOrig + xfregs . viewport . ht - scissorYOff ) ) ;
int intendedWd = Renderer : : EFBToScaledX ( ( int ) ceil ( 2.0f * xfregs . viewport . wd ) ) ;
int intendedHt = Renderer : : EFBToScaledY ( ( int ) ceil ( - 2.0f * xfregs . viewport . ht ) ) ;
if ( intendedWd < 0 )
2010-06-13 19:50:06 +00:00
{
2011-05-12 02:14:45 +00:00
intendedX + = intendedWd ;
intendedWd = - intendedWd ;
2010-06-13 19:50:06 +00:00
}
2011-05-12 02:14:45 +00:00
if ( intendedHt < 0 )
2010-06-13 19:50:06 +00:00
{
2011-05-12 02:14:45 +00:00
intendedY + = intendedHt ;
intendedHt = - intendedHt ;
2010-06-13 19:50:06 +00:00
}
2011-05-12 02:14:45 +00:00
// In D3D, the viewport rectangle must fit within the render target.
int X = intendedX ;
2010-06-13 19:50:06 +00:00
if ( X < 0 )
X = 0 ;
2011-06-11 19:37:21 +00:00
2011-05-12 02:14:45 +00:00
int Y = intendedY ;
2010-06-13 19:50:06 +00:00
if ( Y < 0 )
Y = 0 ;
2011-06-11 19:37:21 +00:00
2011-05-12 02:14:45 +00:00
int Wd = intendedWd ;
if ( X + Wd > GetTargetWidth ( ) )
Wd = GetTargetWidth ( ) - X ;
int Ht = intendedHt ;
if ( Y + Ht > GetTargetHeight ( ) )
Ht = GetTargetHeight ( ) - Y ;
2012-02-09 04:18:46 +00:00
2011-05-12 02:14:45 +00:00
// If GX viewport is off the render target, we must clamp our viewport
// within the bounds. Use the correction matrix to compensate.
ViewportCorrectionMatrix ( vpCorrection ,
2012-02-09 04:18:46 +00:00
( float ) intendedX , ( float ) intendedY ,
( float ) intendedWd , ( float ) intendedHt ,
( float ) X , ( float ) Y ,
( float ) Wd , ( float ) Ht ) ;
2010-06-13 19:50:06 +00:00
2010-09-28 02:15:02 +00:00
// Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work
2012-02-09 04:18:46 +00:00
D3D11_VIEWPORT vp = CD3D11_VIEWPORT ( ( float ) X , ( float ) Y ,
( float ) Wd , ( float ) Ht ,
2011-04-11 01:49:32 +00:00
0.f , // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f;
1.f ) ; // xfregs.viewport.farZ / 16777216.0f;
2011-06-11 19:37:21 +00:00
D3D : : context - > RSSetViewports ( 1 , & vp ) ;
2010-06-13 19:50:06 +00:00
}
2010-09-28 02:15:02 +00:00
2010-12-19 22:00:25 +00:00
void Renderer : : ClearScreen ( const EFBRectangle & rc , bool colorEnable , bool alphaEnable , bool zEnable , u32 color , u32 z )
2010-06-16 10:12:57 +00:00
{
2010-10-24 16:53:33 +00:00
ResetAPIState ( ) ;
2010-12-20 16:57:29 +00:00
if ( colorEnable & & alphaEnable ) D3D : : stateman - > PushBlendState ( clearblendstates [ 0 ] ) ;
else if ( colorEnable ) D3D : : stateman - > PushBlendState ( clearblendstates [ 1 ] ) ;
else if ( alphaEnable ) D3D : : stateman - > PushBlendState ( clearblendstates [ 2 ] ) ;
2010-11-01 19:13:50 +00:00
else D3D : : stateman - > PushBlendState ( clearblendstates [ 3 ] ) ;
2010-12-20 16:57:29 +00:00
// TODO: Should we enable Z testing here?
/*if (!bpmem.zmode.testenable) D3D::stateman->PushDepthState(cleardepthstates[0]);
else */ if ( zEnable ) D3D : : stateman - > PushDepthState ( cleardepthstates [ 1 ] ) ;
else /*if (!zEnable)*/ D3D : : stateman - > PushDepthState ( cleardepthstates [ 2 ] ) ;
2010-11-01 19:13:50 +00:00
2010-09-28 02:15:02 +00:00
// Update the view port for clearing the picture
2010-06-15 21:19:09 +00:00
TargetRectangle targetRc = Renderer : : ConvertEFBRectangle ( rc ) ;
2010-11-01 19:13:50 +00:00
D3D11_VIEWPORT vp = CD3D11_VIEWPORT ( ( float ) targetRc . left , ( float ) targetRc . top , ( float ) targetRc . GetWidth ( ) , ( float ) targetRc . GetHeight ( ) , 0.f , 1.f ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > RSSetViewports ( 1 , & vp ) ;
2010-06-18 23:33:07 +00:00
2010-11-01 19:13:50 +00:00
// Color is passed in bgra mode so we need to convert it to rgba
2010-06-21 02:40:09 +00:00
u32 rgbaColor = ( color & 0xFF00FF00 ) | ( ( color > > 16 ) & 0xFF ) | ( ( color < < 16 ) & 0xFF0000 ) ;
2010-12-16 17:40:45 +00:00
D3D : : drawClearQuad ( rgbaColor , ( z & 0xFFFFFF ) / float ( 0xFFFFFF ) , PixelShaderCache : : GetClearProgram ( ) , VertexShaderCache : : GetClearVertexShader ( ) , VertexShaderCache : : GetClearInputLayout ( ) ) ;
2010-10-20 02:29:20 +00:00
D3D : : stateman - > PopDepthState ( ) ;
2010-11-01 19:13:50 +00:00
D3D : : stateman - > PopBlendState ( ) ;
2010-10-20 02:29:20 +00:00
2010-10-24 16:53:33 +00:00
RestoreAPIState ( ) ;
2010-06-13 19:50:06 +00:00
}
2010-12-27 21:56:20 +00:00
void Renderer : : ReinterpretPixelData ( unsigned int convtype )
{
2011-02-04 17:00:34 +00:00
// TODO: MSAA support..
2011-05-12 02:14:45 +00:00
D3D11_RECT source = CD3D11_RECT ( 0 , 0 , g_renderer - > GetTargetWidth ( ) , g_renderer - > GetTargetHeight ( ) ) ;
2011-02-04 17:00:34 +00:00
ID3D11PixelShader * pixel_shader ;
2011-04-30 14:08:58 +00:00
if ( convtype = = 0 ) pixel_shader = PixelShaderCache : : ReinterpRGB8ToRGBA6 ( true ) ;
else if ( convtype = = 2 ) pixel_shader = PixelShaderCache : : ReinterpRGBA6ToRGB8 ( true ) ;
2011-02-04 17:00:34 +00:00
else
{
2012-01-06 12:45:51 +00:00
ERROR_LOG ( VIDEO , " Trying to reinterpret pixel data with unsupported conversion type %d " , convtype ) ;
2011-02-04 17:00:34 +00:00
return ;
}
// convert data and set the target texture as our new EFB
g_renderer - > ResetAPIState ( ) ;
2011-05-12 02:14:45 +00:00
D3D11_VIEWPORT vp = CD3D11_VIEWPORT ( 0.f , 0.f , ( float ) g_renderer - > GetTargetWidth ( ) , ( float ) g_renderer - > GetTargetHeight ( ) ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > RSSetViewports ( 1 , & vp ) ;
2011-02-04 17:00:34 +00:00
2011-06-11 19:37:21 +00:00
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBColorTempTexture ( ) - > GetRTV ( ) , NULL ) ;
2011-02-04 17:00:34 +00:00
D3D : : SetPointCopySampler ( ) ;
2011-06-11 19:37:21 +00:00
D3D : : drawShadedTexQuad ( FramebufferManager : : GetEFBColorTexture ( ) - > GetSRV ( ) , & source , g_renderer - > GetTargetWidth ( ) , g_renderer - > GetTargetHeight ( ) , pixel_shader , VertexShaderCache : : GetSimpleVertexShader ( ) , VertexShaderCache : : GetSimpleInputLayout ( ) ) ;
2011-02-04 17:00:34 +00:00
g_renderer - > RestoreAPIState ( ) ;
FramebufferManager : : SwapReinterpretTexture ( ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , FramebufferManager : : GetEFBDepthTexture ( ) - > GetDSV ( ) ) ;
2010-12-27 21:56:20 +00:00
}
2011-01-24 10:42:43 +00:00
void SetSrcBlend ( D3D11_BLEND val )
{
// Colors should blend against SRC_ALPHA
if ( val = = D3D11_BLEND_SRC1_ALPHA )
val = D3D11_BLEND_SRC_ALPHA ;
else if ( val = = D3D11_BLEND_INV_SRC1_ALPHA )
val = D3D11_BLEND_INV_SRC_ALPHA ;
if ( val = = D3D11_BLEND_SRC_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA ;
else if ( val = = D3D11_BLEND_INV_SRC_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA ;
else if ( val = = D3D11_BLEND_DEST_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA ;
else if ( val = = D3D11_BLEND_INV_DEST_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA ;
else
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = val ;
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlend = val ;
}
void SetDestBlend ( D3D11_BLEND val )
{
// Colors should blend against SRC_ALPHA
if ( val = = D3D11_BLEND_SRC1_ALPHA )
val = D3D11_BLEND_SRC_ALPHA ;
else if ( val = = D3D11_BLEND_INV_SRC1_ALPHA )
val = D3D11_BLEND_INV_SRC_ALPHA ;
if ( val = = D3D11_BLEND_SRC_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_SRC_ALPHA ;
else if ( val = = D3D11_BLEND_INV_SRC_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA ;
else if ( val = = D3D11_BLEND_DEST_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_DEST_ALPHA ;
else if ( val = = D3D11_BLEND_INV_DEST_COLOR )
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA ;
else
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = val ;
gx_state . blenddc . RenderTarget [ 0 ] . DestBlend = val ;
}
void SetBlendOp ( D3D11_BLEND_OP val )
{
gx_state . blenddc . RenderTarget [ 0 ] . BlendOp = val ;
gx_state . blenddc . RenderTarget [ 0 ] . BlendOpAlpha = val ;
}
2010-06-13 19:50:06 +00:00
void Renderer : : SetBlendMode ( bool forceUpdate )
{
2013-01-13 22:35:07 +00:00
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
bool target_has_alpha = bpmem . zcontrol . pixel_format = = PIXELFMT_RGBA6_Z24 ;
const D3D11_BLEND d3dSrcFactors [ 8 ] =
{
D3D11_BLEND_ZERO ,
D3D11_BLEND_ONE ,
D3D11_BLEND_DEST_COLOR ,
D3D11_BLEND_INV_DEST_COLOR ,
D3D11_BLEND_SRC_ALPHA ,
D3D11_BLEND_INV_SRC_ALPHA , // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
( target_has_alpha ) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE ,
( target_has_alpha ) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO
} ;
const D3D11_BLEND d3dDestFactors [ 8 ] =
{
D3D11_BLEND_ZERO ,
D3D11_BLEND_ONE ,
D3D11_BLEND_SRC_COLOR ,
D3D11_BLEND_INV_SRC_COLOR ,
D3D11_BLEND_SRC_ALPHA ,
D3D11_BLEND_INV_SRC_ALPHA , // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
( target_has_alpha ) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE ,
( target_has_alpha ) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO
} ;
2010-11-30 21:44:54 +00:00
if ( bpmem . blendmode . logicopenable & & ! forceUpdate )
2010-06-13 19:50:06 +00:00
return ;
2013-03-28 21:59:42 +00:00
if ( bpmem . blendmode . subtract )
2010-06-13 19:50:06 +00:00
{
2011-01-24 10:42:43 +00:00
gx_state . blenddc . RenderTarget [ 0 ] . BlendEnable = true ;
SetBlendOp ( D3D11_BLEND_OP_REV_SUBTRACT ) ;
2013-03-28 21:59:42 +00:00
SetSrcBlend ( D3D11_BLEND_ONE ) ;
SetDestBlend ( D3D11_BLEND_ONE ) ;
2010-06-13 19:50:06 +00:00
}
2010-09-28 02:15:02 +00:00
else
2010-06-13 19:50:06 +00:00
{
2013-01-13 22:35:07 +00:00
gx_state . blenddc . RenderTarget [ 0 ] . BlendEnable = bpmem . blendmode . blendenable ;
if ( bpmem . blendmode . blendenable )
2010-06-24 15:58:06 +00:00
{
2011-01-24 10:42:43 +00:00
SetBlendOp ( D3D11_BLEND_OP_ADD ) ;
SetSrcBlend ( d3dSrcFactors [ bpmem . blendmode . srcfactor ] ) ;
SetDestBlend ( d3dDestFactors [ bpmem . blendmode . dstfactor ] ) ;
2010-06-24 15:58:06 +00:00
}
2010-06-13 19:50:06 +00:00
}
}
2010-11-18 02:21:26 +00:00
bool Renderer : : SaveScreenshot ( const std : : string & filename , const TargetRectangle & rc )
{
2012-08-07 12:55:10 +00:00
if ( ! s_screenshot_texture )
CreateScreenshotTexture ( ) ;
2010-11-18 02:21:26 +00:00
// copy back buffer to system memory
2011-09-08 13:39:03 +00:00
D3D : : context - > CopyResource ( s_screenshot_texture , ( ID3D11Resource * ) D3D : : GetBackBuffer ( ) - > GetTex ( ) ) ;
2010-11-18 02:21:26 +00:00
// D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves
D3D11_MAPPED_SUBRESOURCE map ;
2011-09-08 13:39:03 +00:00
D3D : : context - > Map ( s_screenshot_texture , 0 , D3D11_MAP_READ_WRITE , 0 , & map ) ;
2010-11-18 02:21:26 +00:00
for ( unsigned int y = 0 ; y < D3D : : GetBackBufferHeight ( ) ; + + y )
{
u8 * ptr = ( u8 * ) map . pData + y * map . RowPitch + 3 ;
for ( unsigned int x = 0 ; x < D3D : : GetBackBufferWidth ( ) ; + + x )
{
* ptr = 0xFF ;
ptr + = 4 ;
}
}
2011-09-08 13:39:03 +00:00
D3D : : context - > Unmap ( s_screenshot_texture , 0 ) ;
2010-11-18 02:21:26 +00:00
// ready to be saved
2011-09-08 13:39:03 +00:00
HRESULT hr = PD3DX11SaveTextureToFileA ( D3D : : context , s_screenshot_texture , D3DX11_IFF_PNG , filename . c_str ( ) ) ;
2011-06-11 19:37:21 +00:00
2010-11-18 02:21:26 +00:00
return SUCCEEDED ( hr ) ;
}
2013-02-27 01:47:48 +00:00
void formatBufferDump ( const u8 * in , u8 * out , int w , int h , int p )
2011-09-08 13:39:03 +00:00
{
for ( int y = 0 ; y < h ; + + y )
{
2013-02-27 01:47:48 +00:00
auto line = ( in + ( h - y - 1 ) * p ) ;
2011-09-08 13:39:03 +00:00
for ( int x = 0 ; x < w ; + + x )
{
2011-09-08 15:52:01 +00:00
out [ 0 ] = line [ 2 ] ;
out [ 1 ] = line [ 1 ] ;
out [ 2 ] = line [ 0 ] ;
2011-09-08 13:39:03 +00:00
out + = 3 ;
line + = 4 ;
2011-09-08 15:52:01 +00:00
}
2011-09-08 13:39:03 +00:00
}
}
2010-11-18 02:21:26 +00:00
2010-09-28 02:15:02 +00:00
// This function has the final picture. We adjust the aspect ratio here.
2010-12-27 03:18:01 +00:00
void Renderer : : Swap ( u32 xfbAddr , FieldType field , u32 fbWidth , u32 fbHeight , const EFBRectangle & rc , float Gamma )
2010-06-13 19:50:06 +00:00
{
2012-09-28 21:19:50 +00:00
if ( g_bSkipCurrentFrame | | ( ! XFBWrited & & ! g_ActiveConfig . RealXFBEnabled ( ) ) | | ! fbWidth | | ! fbHeight )
2010-06-13 19:50:06 +00:00
{
2013-02-27 01:47:48 +00:00
if ( g_ActiveConfig . bDumpFrames & & ! frame_data . empty ( ) )
AVIDump : : AddFrame ( & frame_data [ 0 ] , fbWidth , fbHeight ) ;
2011-09-08 13:39:03 +00:00
2011-01-31 01:28:32 +00:00
Core : : Callback_VideoCopiedToXFB ( false ) ;
2010-06-13 19:50:06 +00:00
return ;
}
2010-09-28 02:15:02 +00:00
2012-12-31 15:27:22 +00:00
if ( field = = FIELD_LOWER ) xfbAddr - = fbWidth * 2 ;
2010-06-13 19:50:06 +00:00
u32 xfbCount = 0 ;
2010-11-14 23:31:53 +00:00
const XFBSourceBase * const * xfbSourceList = FramebufferManager : : GetXFBSource ( xfbAddr , fbWidth , fbHeight , xfbCount ) ;
2010-07-02 17:09:53 +00:00
if ( ( ! xfbSourceList | | xfbCount = = 0 ) & & g_ActiveConfig . bUseXFB & & ! g_ActiveConfig . bUseRealXFB )
2010-06-13 19:50:06 +00:00
{
2013-02-27 01:47:48 +00:00
if ( g_ActiveConfig . bDumpFrames & & ! frame_data . empty ( ) )
AVIDump : : AddFrame ( & frame_data [ 0 ] , fbWidth , fbHeight ) ;
2011-09-08 13:39:03 +00:00
2011-01-31 01:28:32 +00:00
Core : : Callback_VideoCopiedToXFB ( false ) ;
2010-06-13 19:50:06 +00:00
return ;
2010-06-16 10:12:57 +00:00
}
2010-06-13 19:50:06 +00:00
2010-11-18 02:21:26 +00:00
ResetAPIState ( ) ;
2010-06-21 17:54:13 +00:00
2010-09-28 02:15:02 +00:00
// Prepare to copy the XFBs to our backbuffer
2012-09-28 22:04:55 +00:00
UpdateDrawRectangle ( s_backbuffer_width , s_backbuffer_height ) ;
2010-06-13 19:50:06 +00:00
2013-01-16 20:46:11 +00:00
int X = GetTargetRectangle ( ) . left ;
int Y = GetTargetRectangle ( ) . top ;
int Width = GetTargetRectangle ( ) . right - GetTargetRectangle ( ) . left ;
int Height = GetTargetRectangle ( ) . bottom - GetTargetRectangle ( ) . top ;
2010-11-27 11:11:05 +00:00
2012-09-02 11:12:47 +00:00
// TODO: Redundant checks...
2010-06-13 19:50:06 +00:00
if ( X < 0 ) X = 0 ;
if ( Y < 0 ) Y = 0 ;
if ( X > s_backbuffer_width ) X = s_backbuffer_width ;
if ( Y > s_backbuffer_height ) Y = s_backbuffer_height ;
if ( Width < 0 ) Width = 0 ;
if ( Height < 0 ) Height = 0 ;
if ( Width > ( s_backbuffer_width - X ) ) Width = s_backbuffer_width - X ;
if ( Height > ( s_backbuffer_height - Y ) ) Height = s_backbuffer_height - Y ;
2012-09-02 11:12:47 +00:00
D3D11_VIEWPORT vp = CD3D11_VIEWPORT ( ( float ) X , ( float ) Y , ( float ) Width , ( float ) Height ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > RSSetViewports ( 1 , & vp ) ;
D3D : : context - > OMSetRenderTargets ( 1 , & D3D : : GetBackBuffer ( ) - > GetRTV ( ) , NULL ) ;
2010-06-13 19:50:06 +00:00
2012-09-02 11:12:47 +00:00
float ClearColor [ 4 ] = { 0.f , 0.f , 0.f , 1.f } ;
D3D : : context - > ClearRenderTargetView ( D3D : : GetBackBuffer ( ) - > GetRTV ( ) , ClearColor ) ;
2010-07-17 15:18:52 +00:00
// activate linear filtering for the buffer copies
D3D : : SetLinearCopySampler ( ) ;
2011-03-08 07:39:36 +00:00
if ( g_ActiveConfig . bUseXFB & & g_ActiveConfig . bUseRealXFB )
{
// TODO: Television should be used to render Virtual XFB mode as well.
2011-06-11 19:37:21 +00:00
s_television . Submit ( xfbAddr , fbWidth , fbHeight ) ;
s_television . Render ( ) ;
2011-03-08 07:39:36 +00:00
}
2011-06-11 19:37:21 +00:00
else if ( g_ActiveConfig . bUseXFB )
2010-06-13 19:50:06 +00:00
{
2010-11-14 23:31:53 +00:00
const XFBSourceBase * xfbSource ;
2010-06-13 19:50:06 +00:00
2010-07-02 17:09:53 +00:00
// draw each xfb source
for ( u32 i = 0 ; i < xfbCount ; + + i )
{
2010-09-28 02:15:02 +00:00
xfbSource = xfbSourceList [ i ] ;
2010-07-02 17:09:53 +00:00
MathUtil : : Rectangle < float > sourceRc ;
sourceRc . left = 0 ;
sourceRc . top = 0 ;
2010-12-10 15:54:14 +00:00
sourceRc . right = ( float ) xfbSource - > texWidth ;
sourceRc . bottom = ( float ) xfbSource - > texHeight ;
2010-06-13 19:50:06 +00:00
2010-07-02 17:09:53 +00:00
MathUtil : : Rectangle < float > drawRc ;
2010-06-13 19:50:06 +00:00
2012-09-28 21:21:09 +00:00
if ( g_ActiveConfig . bUseRealXFB )
{
drawRc . top = 1 ;
drawRc . bottom = - 1 ;
drawRc . left = - 1 ;
drawRc . right = 1 ;
}
else
2010-07-02 17:09:53 +00:00
{
// use virtual xfb with offset
int xfbHeight = xfbSource - > srcHeight ;
int xfbWidth = xfbSource - > srcWidth ;
int hOffset = ( ( s32 ) xfbSource - > srcAddr - ( s32 ) xfbAddr ) / ( ( s32 ) fbWidth * 2 ) ;
2011-03-08 07:39:36 +00:00
drawRc . top = 1.0f - ( 2.0f * ( hOffset ) / ( float ) fbHeight ) ;
drawRc . bottom = 1.0f - ( 2.0f * ( hOffset + xfbHeight ) / ( float ) fbHeight ) ;
2010-07-02 17:09:53 +00:00
drawRc . left = - ( xfbWidth / ( float ) fbWidth ) ;
drawRc . right = ( xfbWidth / ( float ) fbWidth ) ;
2010-09-30 15:24:34 +00:00
// The following code disables auto stretch. Kept for reference.
// scale draw area for a 1 to 1 pixel mapping with the draw target
//float vScale = (float)fbHeight / (float)s_backbuffer_height;
//float hScale = (float)fbWidth / (float)s_backbuffer_width;
//drawRc.top *= vScale;
//drawRc.bottom *= vScale;
//drawRc.left *= hScale;
//drawRc.right *= hScale;
2010-07-02 17:09:53 +00:00
}
2010-09-28 02:15:02 +00:00
2010-11-14 23:31:53 +00:00
xfbSource - > Draw ( sourceRc , drawRc , 0 , 0 ) ;
2010-07-02 17:09:53 +00:00
}
}
else
{
TargetRectangle targetRc = Renderer : : ConvertEFBRectangle ( rc ) ;
2010-11-27 11:11:05 +00:00
// TODO: Improve sampling algorithm for the pixel shader so that we can use the multisampled EFB texture as source
2010-11-23 19:58:02 +00:00
D3DTexture2D * read_texture = FramebufferManager : : GetResolvedEFBColorTexture ( ) ;
2011-06-11 19:37:21 +00:00
D3D : : drawShadedTexQuad ( read_texture - > GetSRV ( ) , targetRc . AsRECT ( ) , Renderer : : GetTargetWidth ( ) , Renderer : : GetTargetHeight ( ) , PixelShaderCache : : GetColorCopyProgram ( false ) , VertexShaderCache : : GetSimpleVertexShader ( ) , VertexShaderCache : : GetSimpleInputLayout ( ) , Gamma ) ;
2010-06-13 19:50:06 +00:00
}
2011-03-08 07:39:36 +00:00
2010-06-21 17:54:13 +00:00
// done with drawing the game stuff, good moment to save a screenshot
2010-06-17 10:42:57 +00:00
if ( s_bScreenshot )
{
2012-09-28 22:04:55 +00:00
SaveScreenshot ( s_sScreenshotName , GetTargetRectangle ( ) ) ;
2010-06-17 10:42:57 +00:00
s_bScreenshot = false ;
}
2010-06-13 19:50:06 +00:00
2011-09-08 13:39:03 +00:00
// Dump frames
static int w = 0 , h = 0 ;
if ( g_ActiveConfig . bDumpFrames )
{
static int s_recordWidth ;
static int s_recordHeight ;
2012-08-07 12:55:10 +00:00
if ( ! s_screenshot_texture )
CreateScreenshotTexture ( ) ;
2011-09-08 13:39:03 +00:00
D3D : : context - > CopyResource ( s_screenshot_texture , ( ID3D11Resource * ) D3D : : GetBackBuffer ( ) - > GetTex ( ) ) ;
if ( ! bLastFrameDumped )
{
2012-09-28 22:04:55 +00:00
s_recordWidth = GetTargetRectangle ( ) . GetWidth ( ) ;
s_recordHeight = GetTargetRectangle ( ) . GetHeight ( ) ;
2011-09-08 15:09:24 +00:00
bAVIDumping = AVIDump : : Start ( EmuWindow : : GetParentWnd ( ) , s_recordWidth , s_recordHeight ) ;
if ( ! bAVIDumping )
2011-09-08 13:39:03 +00:00
{
PanicAlert ( " Error dumping frames to AVI. " ) ;
}
else
{
char msg [ 255 ] ;
sprintf_s ( msg , 255 , " Dumping Frames to \" %sframedump0.avi \" (%dx%d RGB24) " ,
File : : GetUserPath ( D_DUMPFRAMES_IDX ) . c_str ( ) , s_recordWidth , s_recordHeight ) ;
OSD : : AddMessage ( msg , 2000 ) ;
}
}
2011-09-08 15:09:24 +00:00
if ( bAVIDumping )
2011-09-08 13:39:03 +00:00
{
D3D11_MAPPED_SUBRESOURCE map ;
D3D : : context - > Map ( s_screenshot_texture , 0 , D3D11_MAP_READ , 0 , & map ) ;
2013-02-27 01:47:48 +00:00
if ( frame_data . empty ( ) | | w ! = s_recordWidth | | h ! = s_recordHeight )
2011-09-08 13:39:03 +00:00
{
2013-02-27 01:47:48 +00:00
frame_data . resize ( 3 * s_recordWidth * s_recordHeight ) ;
2011-09-08 13:39:03 +00:00
w = s_recordWidth ;
h = s_recordHeight ;
}
2013-02-27 01:47:48 +00:00
auto source_ptr = ( const u8 * ) map . pData + GetTargetRectangle ( ) . left * 4 + GetTargetRectangle ( ) . top * map . RowPitch ;
formatBufferDump ( source_ptr , & frame_data [ 0 ] , s_recordWidth , s_recordHeight , map . RowPitch ) ;
AVIDump : : AddFrame ( & frame_data [ 0 ] , fbWidth , fbHeight ) ;
2011-09-08 13:39:03 +00:00
D3D : : context - > Unmap ( s_screenshot_texture , 0 ) ;
}
bLastFrameDumped = true ;
}
else
{
2011-09-08 15:09:24 +00:00
if ( bLastFrameDumped & & bAVIDumping )
2011-09-08 13:39:03 +00:00
{
2013-02-27 01:47:48 +00:00
std : : vector < u8 > ( ) . swap ( frame_data ) ;
2011-09-08 13:39:03 +00:00
w = h = 0 ;
AVIDump : : Stop ( ) ;
2011-09-08 15:09:24 +00:00
bAVIDumping = false ;
2011-09-08 13:39:03 +00:00
OSD : : AddMessage ( " Stop dumping frames to AVI " , 2000 ) ;
}
bLastFrameDumped = false ;
}
2010-09-28 02:15:02 +00:00
// Finish up the current frame, print some stats
2010-06-13 19:50:06 +00:00
if ( g_ActiveConfig . bShowFPS )
{
char fps [ 20 ] ;
StringCchPrintfA ( fps , 20 , " FPS: %d \n " , s_fps ) ;
2011-02-17 09:12:36 +00:00
D3D : : font . DrawTextScaled ( 0 , 0 , 20 , 0.0f , 0xFF00FFFF , fps ) ;
}
2012-11-14 21:21:54 +00:00
if ( SConfig : : GetInstance ( ) . m_ShowLag )
2012-11-11 22:57:06 +00:00
{
char lag [ 10 ] ;
2012-12-07 01:25:07 +00:00
StringCchPrintfA ( lag , 1000 , " Lag: %llu \n " , Movie : : g_currentLagCount ) ;
2012-11-11 22:57:06 +00:00
D3D : : font . DrawTextScaled ( 0 , 18 , 20 , 0.0f , 0xFF00FFFF , lag ) ;
}
2011-02-17 09:12:36 +00:00
if ( g_ActiveConfig . bShowInputDisplay )
{
char inputDisplay [ 1000 ] ;
2011-06-24 06:50:50 +00:00
StringCchPrintfA ( inputDisplay , 1000 , Movie : : GetInputDisplay ( ) . c_str ( ) ) ;
2012-11-11 22:57:06 +00:00
D3D : : font . DrawTextScaled ( 0 , 36 , 20 , 0.0f , 0xFF00FFFF , inputDisplay ) ;
2010-06-13 19:50:06 +00:00
}
Renderer : : DrawDebugText ( ) ;
if ( g_ActiveConfig . bOverlayStats )
{
char buf [ 32768 ] ;
Statistics : : ToString ( buf ) ;
2012-11-11 22:57:06 +00:00
D3D : : font . DrawTextScaled ( 0 , 36 , 20 , 0.0f , 0xFF00FFFF , buf ) ;
2010-06-13 19:50:06 +00:00
}
else if ( g_ActiveConfig . bOverlayProjStats )
{
char buf [ 32768 ] ;
Statistics : : ToStringProj ( buf ) ;
2012-11-11 22:57:06 +00:00
D3D : : font . DrawTextScaled ( 0 , 36 , 20 , 0.0f , 0xFF00FFFF , buf ) ;
2010-06-13 19:50:06 +00:00
}
OSD : : DrawMessages ( ) ;
D3D : : EndFrame ( ) ;
frameCount + + ;
2010-12-05 14:15:36 +00:00
GFX_DEBUGGER_PAUSE_AT ( NEXT_FRAME , true ) ;
2010-08-29 23:08:56 +00:00
DLCache : : ProgressiveCleanup ( ) ;
2010-06-13 19:50:06 +00:00
TextureCache : : Cleanup ( ) ;
2011-12-26 21:04:59 +00:00
// Enable configuration changes
2010-06-13 19:50:06 +00:00
UpdateActiveConfig ( ) ;
2012-05-28 09:31:37 +00:00
TextureCache : : OnConfigChanged ( g_ActiveConfig ) ;
2011-01-07 04:57:59 +00:00
2011-01-25 03:30:12 +00:00
SetWindowSize ( fbWidth , fbHeight ) ;
2011-01-07 04:57:59 +00:00
const bool windowResized = CheckForResize ( ) ;
2010-06-17 10:42:57 +00:00
2010-06-13 19:50:06 +00:00
bool xfbchanged = false ;
2010-09-28 02:15:02 +00:00
2012-09-28 21:48:18 +00:00
if ( FramebufferManagerBase : : LastXfbWidth ( ) ! = fbWidth | | FramebufferManagerBase : : LastXfbHeight ( ) ! = fbHeight )
2010-06-13 19:50:06 +00:00
{
xfbchanged = true ;
2012-09-28 21:48:18 +00:00
unsigned int w = ( fbWidth < 1 | | fbWidth > MAX_XFB_WIDTH ) ? MAX_XFB_WIDTH : fbWidth ;
unsigned int h = ( fbHeight < 1 | | fbHeight > MAX_XFB_HEIGHT ) ? MAX_XFB_HEIGHT : fbHeight ;
FramebufferManagerBase : : SetLastXfbWidth ( w ) ;
FramebufferManagerBase : : SetLastXfbHeight ( h ) ;
2010-06-13 19:50:06 +00:00
}
2010-06-18 14:55:18 +00:00
// update FPS counter
2010-09-28 02:15:02 +00:00
if ( XFBWrited )
2012-10-04 03:41:02 +00:00
s_fps = UpdateFPSCounter ( ) ;
2010-06-18 14:55:18 +00:00
2010-09-28 02:15:02 +00:00
// Begin new frame
// Set default viewport and scissor, for the clear to work correctly
// New frame
2010-06-18 14:55:18 +00:00
stats . ResetFrame ( ) ;
2010-09-28 02:15:02 +00:00
// Flip/present backbuffer to frontbuffer here
2010-06-18 14:55:18 +00:00
D3D : : Present ( ) ;
2010-06-21 17:54:13 +00:00
2010-11-10 16:43:27 +00:00
// resize the back buffers NOW to avoid flickering
2011-01-07 04:57:59 +00:00
if ( xfbchanged | |
windowResized | |
2010-11-23 19:58:02 +00:00
s_LastEFBScale ! = g_ActiveConfig . iEFBScale | |
s_LastAA ! = g_ActiveConfig . iMultisampleMode )
2010-06-13 19:50:06 +00:00
{
2010-11-23 19:58:02 +00:00
s_LastAA = g_ActiveConfig . iMultisampleMode ;
2010-11-27 11:11:05 +00:00
PixelShaderCache : : InvalidateMSAAShaders ( ) ;
2010-11-23 19:58:02 +00:00
2012-08-07 12:55:10 +00:00
if ( windowResized )
{
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D : : Reset ( ) ;
SAFE_RELEASE ( s_screenshot_texture ) ;
s_backbuffer_width = D3D : : GetBackBufferWidth ( ) ;
s_backbuffer_height = D3D : : GetBackBufferHeight ( ) ;
}
2010-06-18 14:55:18 +00:00
2012-09-28 22:04:55 +00:00
UpdateDrawRectangle ( s_backbuffer_width , s_backbuffer_height ) ;
2010-06-13 19:50:06 +00:00
2010-11-10 16:43:27 +00:00
s_LastEFBScale = g_ActiveConfig . iEFBScale ;
2012-09-28 22:19:28 +00:00
CalculateTargetSize ( s_backbuffer_width , s_backbuffer_height ) ;
2010-06-17 10:42:57 +00:00
2011-06-11 19:37:21 +00:00
D3D : : context - > OMSetRenderTargets ( 1 , & D3D : : GetBackBuffer ( ) - > GetRTV ( ) , NULL ) ;
2012-08-07 12:55:10 +00:00
2010-11-14 23:31:53 +00:00
delete g_framebuffer_manager ;
g_framebuffer_manager = new FramebufferManager ;
2010-12-21 22:18:40 +00:00
float clear_col [ 4 ] = { 0.f , 0.f , 0.f , 1.f } ;
2011-06-11 19:37:21 +00:00
D3D : : context - > ClearRenderTargetView ( FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , clear_col ) ;
D3D : : context - > ClearDepthStencilView ( FramebufferManager : : GetEFBDepthTexture ( ) - > GetDSV ( ) , D3D11_CLEAR_DEPTH , 1.f , 0 ) ;
2010-06-13 19:50:06 +00:00
}
2010-06-21 17:54:13 +00:00
// begin next frame
2010-06-13 19:50:06 +00:00
Renderer : : RestoreAPIState ( ) ;
2010-06-21 17:54:13 +00:00
D3D : : BeginFrame ( ) ;
2011-06-11 19:37:21 +00:00
D3D : : context - > OMSetRenderTargets ( 1 , & FramebufferManager : : GetEFBColorTexture ( ) - > GetRTV ( ) , FramebufferManager : : GetEFBDepthTexture ( ) - > GetDSV ( ) ) ;
2010-06-13 19:50:06 +00:00
VertexShaderManager : : SetViewportChanged ( ) ;
2010-11-10 16:43:27 +00:00
2011-01-31 01:28:32 +00:00
Core : : Callback_VideoCopiedToXFB ( XFBWrited | | ( g_ActiveConfig . bUseXFB & & g_ActiveConfig . bUseRealXFB ) ) ;
2010-06-13 19:50:06 +00:00
XFBWrited = false ;
}
2010-06-21 17:54:13 +00:00
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
2010-06-13 19:50:06 +00:00
void Renderer : : ResetAPIState ( )
{
2010-06-18 23:33:07 +00:00
D3D : : stateman - > PushBlendState ( resetblendstate ) ;
D3D : : stateman - > PushDepthState ( resetdepthstate ) ;
D3D : : stateman - > PushRasterizerState ( resetraststate ) ;
2010-06-13 19:50:06 +00:00
}
void Renderer : : RestoreAPIState ( )
{
2010-09-28 02:15:02 +00:00
// Gets us back into a more game-like state.
2011-01-27 10:17:13 +00:00
D3D : : stateman - > PopBlendState ( ) ;
D3D : : stateman - > PopDepthState ( ) ;
D3D : : stateman - > PopRasterizerState ( ) ;
2011-05-12 02:14:45 +00:00
VertexShaderManager : : SetViewportChanged ( ) ;
2011-09-05 20:04:28 +00:00
BPFunctions : : SetScissor ( ) ;
2010-06-13 19:50:06 +00:00
}
2012-08-10 16:57:37 +00:00
void Renderer : : ApplyState ( bool bUseDstAlpha )
2011-01-24 08:44:32 +00:00
{
2011-01-24 09:10:35 +00:00
HRESULT hr ;
2012-08-10 16:57:37 +00:00
if ( bUseDstAlpha )
2011-01-24 10:42:43 +00:00
{
// Colors should blend against SRC1_ALPHA
if ( gx_state . blenddc . RenderTarget [ 0 ] . SrcBlend = = D3D11_BLEND_SRC_ALPHA )
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_SRC1_ALPHA ;
else if ( gx_state . blenddc . RenderTarget [ 0 ] . SrcBlend = = D3D11_BLEND_INV_SRC_ALPHA )
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlend = D3D11_BLEND_INV_SRC1_ALPHA ;
// Colors should blend against SRC1_ALPHA
if ( gx_state . blenddc . RenderTarget [ 0 ] . DestBlend = = D3D11_BLEND_SRC_ALPHA )
gx_state . blenddc . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_SRC1_ALPHA ;
else if ( gx_state . blenddc . RenderTarget [ 0 ] . DestBlend = = D3D11_BLEND_INV_SRC_ALPHA )
gx_state . blenddc . RenderTarget [ 0 ] . DestBlend = D3D11_BLEND_INV_SRC1_ALPHA ;
gx_state . blenddc . RenderTarget [ 0 ] . SrcBlendAlpha = D3D11_BLEND_ONE ;
gx_state . blenddc . RenderTarget [ 0 ] . DestBlendAlpha = D3D11_BLEND_ZERO ;
gx_state . blenddc . RenderTarget [ 0 ] . BlendOpAlpha = D3D11_BLEND_OP_ADD ;
}
2011-06-11 19:37:21 +00:00
ID3D11BlendState * blstate ;
hr = D3D : : device - > CreateBlendState ( & gx_state . blenddc , & blstate ) ;
if ( FAILED ( hr ) ) PanicAlert ( " Failed to create blend state at %s %d \n " , __FILE__ , __LINE__ ) ;
2011-01-24 10:42:43 +00:00
D3D : : stateman - > PushBlendState ( blstate ) ;
2011-06-11 19:37:21 +00:00
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) blstate , " blend state used to emulate the GX pipeline " ) ;
SAFE_RELEASE ( blstate ) ;
2011-01-24 10:42:43 +00:00
2011-01-24 09:10:35 +00:00
ID3D11DepthStencilState * depth_state ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateDepthStencilState ( & gx_state . depthdc , & depth_state ) ;
if ( SUCCEEDED ( hr ) ) D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) depth_state , " depth-stencil state used to emulate the GX pipeline " ) ;
2011-01-24 09:10:35 +00:00
else PanicAlert ( " Failed to create depth state at %s %d \n " , __FILE__ , __LINE__ ) ;
D3D : : stateman - > PushDepthState ( depth_state ) ;
SAFE_RELEASE ( depth_state ) ;
2011-01-24 09:27:16 +00:00
gx_state . rastdc . FillMode = ( g_ActiveConfig . bWireFrame ) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID ;
ID3D11RasterizerState * raststate ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateRasterizerState ( & gx_state . rastdc , & raststate ) ;
2011-01-24 09:27:16 +00:00
if ( FAILED ( hr ) ) PanicAlert ( " Failed to create rasterizer state at %s %d \n " , __FILE__ , __LINE__ ) ;
2011-06-11 19:37:21 +00:00
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) raststate , " rasterizer state used to emulate the GX pipeline " ) ;
2011-01-24 09:27:16 +00:00
D3D : : stateman - > PushRasterizerState ( raststate ) ;
SAFE_RELEASE ( raststate ) ;
2011-01-24 08:44:32 +00:00
ID3D11SamplerState * samplerstate [ 8 ] ;
for ( unsigned int stage = 0 ; stage < 8 ; stage + + )
{
// TODO: unnecessary state changes, we should store a list of shader resources
//if (shader_resources[stage])
{
if ( g_ActiveConfig . iMaxAnisotropy > 0 ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_ANISOTROPIC ;
2011-06-11 19:37:21 +00:00
hr = D3D : : device - > CreateSamplerState ( & gx_state . sampdc [ stage ] , & samplerstate [ stage ] ) ;
2011-01-24 08:44:32 +00:00
if ( FAILED ( hr ) ) PanicAlert ( " Fail %s %d, stage=%d \n " , __FILE__ , __LINE__ , stage ) ;
2011-06-11 19:37:21 +00:00
else D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) samplerstate [ stage ] , " sampler state used to emulate the GX pipeline " ) ;
2011-01-24 08:44:32 +00:00
}
// else samplerstate[stage] = NULL;
}
2011-06-11 19:37:21 +00:00
D3D : : context - > PSSetSamplers ( 0 , 8 , samplerstate ) ;
2011-01-24 08:44:32 +00:00
for ( unsigned int stage = 0 ; stage < 8 ; stage + + )
SAFE_RELEASE ( samplerstate [ stage ] ) ;
2011-01-24 09:10:35 +00:00
D3D : : stateman - > Apply ( ) ;
2011-01-24 10:42:43 +00:00
2012-08-10 16:57:37 +00:00
if ( bUseDstAlpha )
2011-01-24 10:42:43 +00:00
{
// restore actual state
SetBlendMode ( false ) ;
SetLogicOpMode ( ) ;
}
2011-01-24 11:57:17 +00:00
2011-06-11 19:37:21 +00:00
D3D : : context - > PSSetConstantBuffers ( 0 , 1 , & PixelShaderCache : : GetConstantBuffer ( ) ) ;
D3D : : context - > VSSetConstantBuffers ( 0 , 1 , & VertexShaderCache : : GetConstantBuffer ( ) ) ;
2011-01-25 15:08:30 +00:00
2011-06-11 19:37:21 +00:00
D3D : : context - > PSSetShader ( PixelShaderCache : : GetActiveShader ( ) , NULL , 0 ) ;
D3D : : context - > VSSetShader ( VertexShaderCache : : GetActiveShader ( ) , NULL , 0 ) ;
2011-01-24 08:44:32 +00:00
}
2012-03-29 23:56:24 +00:00
void Renderer : : RestoreState ( )
2011-01-24 08:44:32 +00:00
{
ID3D11ShaderResourceView * shader_resources [ 8 ] = { NULL } ;
2011-06-11 19:37:21 +00:00
D3D : : context - > PSSetShaderResources ( 0 , 8 , shader_resources ) ;
2011-01-24 09:10:35 +00:00
2011-01-24 10:42:43 +00:00
D3D : : stateman - > PopBlendState ( ) ;
2011-01-24 09:10:35 +00:00
D3D : : stateman - > PopDepthState ( ) ;
2011-01-24 09:27:16 +00:00
D3D : : stateman - > PopRasterizerState ( ) ;
2011-01-24 08:44:32 +00:00
}
2011-03-15 03:51:31 +00:00
void Renderer : : ApplyCullDisable ( )
{
D3D11_RASTERIZER_DESC rastDesc = gx_state . rastdc ;
rastDesc . CullMode = D3D11_CULL_NONE ;
ID3D11RasterizerState * raststate ;
2011-06-11 19:37:21 +00:00
HRESULT hr = D3D : : device - > CreateRasterizerState ( & rastDesc , & raststate ) ;
2011-03-15 03:51:31 +00:00
if ( FAILED ( hr ) ) PanicAlert ( " Failed to create culling-disabled rasterizer state at %s %d \n " , __FILE__ , __LINE__ ) ;
2011-06-11 19:37:21 +00:00
D3D : : SetDebugObjectName ( ( ID3D11DeviceChild * ) raststate , " rasterizer state (culling disabled) used to emulate the GX pipeline " ) ;
2011-03-15 03:51:31 +00:00
D3D : : stateman - > PushRasterizerState ( raststate ) ;
SAFE_RELEASE ( raststate ) ;
D3D : : stateman - > Apply ( ) ;
}
void Renderer : : RestoreCull ( )
{
D3D : : stateman - > PopRasterizerState ( ) ;
}
2010-06-13 19:50:06 +00:00
void Renderer : : SetGenerationMode ( )
{
2013-01-13 22:35:07 +00:00
const D3D11_CULL_MODE d3dCullModes [ 4 ] =
{
D3D11_CULL_NONE ,
D3D11_CULL_BACK ,
D3D11_CULL_FRONT ,
D3D11_CULL_BACK
} ;
2011-01-24 09:27:16 +00:00
// rastdc.FrontCounterClockwise must be false for this to work
gx_state . rastdc . CullMode = d3dCullModes [ bpmem . genMode . cullmode ] ;
2010-06-13 19:50:06 +00:00
}
void Renderer : : SetDepthMode ( )
{
2013-01-13 22:35:07 +00:00
const D3D11_COMPARISON_FUNC d3dCmpFuncs [ 8 ] =
{
D3D11_COMPARISON_NEVER ,
D3D11_COMPARISON_LESS ,
D3D11_COMPARISON_EQUAL ,
D3D11_COMPARISON_LESS_EQUAL ,
D3D11_COMPARISON_GREATER ,
D3D11_COMPARISON_NOT_EQUAL ,
D3D11_COMPARISON_GREATER_EQUAL ,
D3D11_COMPARISON_ALWAYS
} ;
2010-06-13 19:50:06 +00:00
if ( bpmem . zmode . testenable )
{
2011-01-24 09:10:35 +00:00
gx_state . depthdc . DepthEnable = TRUE ;
gx_state . depthdc . DepthWriteMask = bpmem . zmode . updateenable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO ;
gx_state . depthdc . DepthFunc = d3dCmpFuncs [ bpmem . zmode . func ] ;
2010-06-13 19:50:06 +00:00
}
else
{
2010-09-28 02:15:02 +00:00
// if the test is disabled write is disabled too
2011-01-24 09:10:35 +00:00
gx_state . depthdc . DepthEnable = FALSE ;
gx_state . depthdc . DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO ;
2010-06-13 19:50:06 +00:00
}
}
void Renderer : : SetLogicOpMode ( )
{
2013-01-13 22:35:07 +00:00
// D3D11 doesn't support logic blending, so this is a huge hack
// TODO: Make use of D3D11.1's logic blending support
// 0 0x00
// 1 Source & destination
// 2 Source & ~destination
// 3 Source
// 4 ~Source & destination
// 5 Destination
// 6 Source ^ destination = Source & ~destination | ~Source & destination
// 7 Source | destination
// 8 ~(Source | destination)
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
// 10 ~Destination
// 11 Source | ~destination
// 12 ~Source
// 13 ~Source | destination
// 14 ~(Source & destination)
// 15 0xff
const D3D11_BLEND_OP d3dLogicOps [ 16 ] =
{
D3D11_BLEND_OP_ADD , //0
D3D11_BLEND_OP_ADD , //1
D3D11_BLEND_OP_SUBTRACT , //2
D3D11_BLEND_OP_ADD , //3
D3D11_BLEND_OP_REV_SUBTRACT , //4
D3D11_BLEND_OP_ADD , //5
D3D11_BLEND_OP_MAX , //6
D3D11_BLEND_OP_ADD , //7
D3D11_BLEND_OP_MAX , //8
D3D11_BLEND_OP_MAX , //9
D3D11_BLEND_OP_ADD , //10
D3D11_BLEND_OP_ADD , //11
D3D11_BLEND_OP_ADD , //12
D3D11_BLEND_OP_ADD , //13
D3D11_BLEND_OP_ADD , //14
D3D11_BLEND_OP_ADD //15
} ;
const D3D11_BLEND d3dLogicOpSrcFactors [ 16 ] =
{
D3D11_BLEND_ZERO , //0
D3D11_BLEND_DEST_COLOR , //1
D3D11_BLEND_ONE , //2
D3D11_BLEND_ONE , //3
D3D11_BLEND_DEST_COLOR , //4
D3D11_BLEND_ZERO , //5
D3D11_BLEND_INV_DEST_COLOR , //6
D3D11_BLEND_INV_DEST_COLOR , //7
D3D11_BLEND_INV_SRC_COLOR , //8
D3D11_BLEND_INV_SRC_COLOR , //9
D3D11_BLEND_INV_DEST_COLOR , //10
D3D11_BLEND_ONE , //11
D3D11_BLEND_INV_SRC_COLOR , //12
D3D11_BLEND_INV_SRC_COLOR , //13
D3D11_BLEND_INV_DEST_COLOR , //14
D3D11_BLEND_ONE //15
} ;
const D3D11_BLEND d3dLogicOpDestFactors [ 16 ] =
{
D3D11_BLEND_ZERO , //0
D3D11_BLEND_ZERO , //1
D3D11_BLEND_INV_SRC_COLOR , //2
D3D11_BLEND_ZERO , //3
D3D11_BLEND_ONE , //4
D3D11_BLEND_ONE , //5
D3D11_BLEND_INV_SRC_COLOR , //6
D3D11_BLEND_ONE , //7
D3D11_BLEND_INV_DEST_COLOR , //8
D3D11_BLEND_SRC_COLOR , //9
D3D11_BLEND_INV_DEST_COLOR , //10
D3D11_BLEND_INV_DEST_COLOR , //11
D3D11_BLEND_INV_SRC_COLOR , //12
D3D11_BLEND_ONE , //13
D3D11_BLEND_INV_SRC_COLOR , //14
D3D11_BLEND_ONE //15
} ;
if ( bpmem . blendmode . logicopenable )
2010-06-13 19:50:06 +00:00
{
2011-01-24 10:42:43 +00:00
gx_state . blenddc . RenderTarget [ 0 ] . BlendEnable = true ;
SetBlendOp ( d3dLogicOps [ bpmem . blendmode . logicmode ] ) ;
SetSrcBlend ( d3dLogicOpSrcFactors [ bpmem . blendmode . logicmode ] ) ;
SetDestBlend ( d3dLogicOpDestFactors [ bpmem . blendmode . logicmode ] ) ;
2010-06-13 19:50:06 +00:00
}
else
{
SetBlendMode ( true ) ;
}
}
void Renderer : : SetDitherMode ( )
{
// TODO: Set dither mode to bpmem.blendmode.dither
}
void Renderer : : SetLineWidth ( )
{
// TODO
}
void Renderer : : SetSamplerState ( int stage , int texindex )
{
2013-01-13 22:35:07 +00:00
# define TEXF_NONE 0
# define TEXF_POINT 1
# define TEXF_LINEAR 2
const unsigned int d3dMipFilters [ 4 ] =
{
TEXF_NONE ,
TEXF_POINT ,
TEXF_LINEAR ,
TEXF_NONE , //reserved
} ;
const D3D11_TEXTURE_ADDRESS_MODE d3dClamps [ 4 ] =
{
D3D11_TEXTURE_ADDRESS_CLAMP ,
D3D11_TEXTURE_ADDRESS_WRAP ,
D3D11_TEXTURE_ADDRESS_MIRROR ,
D3D11_TEXTURE_ADDRESS_WRAP //reserved
} ;
2010-06-16 10:12:57 +00:00
const FourTexUnits & tex = bpmem . tex [ texindex ] ;
2010-06-13 19:50:06 +00:00
const TexMode0 & tm0 = tex . texMode0 [ stage ] ;
const TexMode1 & tm1 = tex . texMode1 [ stage ] ;
2013-01-13 22:35:07 +00:00
unsigned int mip = d3dMipFilters [ tm0 . min_filter & 3 ] ;
2010-06-13 19:50:06 +00:00
2010-06-16 10:12:57 +00:00
if ( texindex ) stage + = 4 ;
2010-06-13 19:50:06 +00:00
2010-11-27 11:11:05 +00:00
if ( g_ActiveConfig . bForceFiltering )
{
2011-01-24 08:44:32 +00:00
gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR ;
2010-11-27 11:11:05 +00:00
}
else if ( tm0 . min_filter & 4 ) // linear min filter
2010-06-13 19:50:06 +00:00
{
if ( tm0 . mag_filter ) // linear mag filter
{
2011-01-24 08:44:32 +00:00
if ( mip = = TEXF_NONE ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT ;
else if ( mip = = TEXF_POINT ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT ;
else if ( mip = = TEXF_LINEAR ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR ;
2010-06-13 19:50:06 +00:00
}
else // point mag filter
{
2011-01-24 08:44:32 +00:00
if ( mip = = TEXF_NONE ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT ;
else if ( mip = = TEXF_POINT ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT ;
else if ( mip = = TEXF_LINEAR ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR ;
2010-06-13 19:50:06 +00:00
}
}
else // point min filter
{
if ( tm0 . mag_filter ) // linear mag filter
{
2011-01-24 08:44:32 +00:00
if ( mip = = TEXF_NONE ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT ;
else if ( mip = = TEXF_POINT ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT ;
else if ( mip = = TEXF_LINEAR ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR ;
2010-06-13 19:50:06 +00:00
}
else // point mag filter
{
2011-01-24 08:44:32 +00:00
if ( mip = = TEXF_NONE ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_MIP_POINT ;
else if ( mip = = TEXF_POINT ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_MIP_POINT ;
else if ( mip = = TEXF_LINEAR ) gx_state . sampdc [ stage ] . Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR ;
2010-06-13 19:50:06 +00:00
}
}
2011-01-24 08:44:32 +00:00
gx_state . sampdc [ stage ] . AddressU = d3dClamps [ tm0 . wrap_s ] ;
gx_state . sampdc [ stage ] . AddressV = d3dClamps [ tm0 . wrap_t ] ;
2010-06-13 19:50:06 +00:00
2012-03-24 05:04:00 +00:00
// When mipfilter is set to "none", just disable mipmapping altogether
gx_state . sampdc [ stage ] . MaxLOD = ( mip = = TEXF_NONE ) ? 0.0f : ( float ) tm1 . max_lod / 16.f ;
2011-01-24 08:44:32 +00:00
gx_state . sampdc [ stage ] . MinLOD = ( float ) tm1 . min_lod / 16.f ;
2012-08-10 11:27:35 +00:00
gx_state . sampdc [ stage ] . MipLODBias = ( s32 ) tm0 . lod_bias / 32.0f ;
2010-06-13 19:50:06 +00:00
}
void Renderer : : SetInterlacingMode ( )
{
// TODO
}
2012-01-06 12:45:51 +00:00
} // namespace DX11