this is a ugly unstable commit but i'm going to be out for work some days so ...
implemented donko's xfb in D3D: the bad things: *is solower in some cases, slower as opengl *it do not work in dual core mode, it seems direct3d has serious synchronization problems, to the other devs please if you can take a look and help me :) *real xfb still not working i have to give it more time to make it work. the good: *games that uses multiples xfbs will work now using the virtual XFB. *implemented a more hardware like approach to scaling, now to calculate the pixel scaling i use the xfb size not the efb so the screen pixels relation is more correct now. *simplified a little donko's virtual xfb to make it less memory consuming as xfb textures are the exact size of the scaled xfb and not full target width. * when it works even real xfb will let us use super sampling. I repeat this commit is totally unstable and in dual core mode it will for sure hang the emulator or at best give totally incorrect results. Other devs please help as thread sync is not one of my strong points :) i'll keep waiting for the comments an the -1 :) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5195 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
ed0740b512
commit
3bdf7d3711
|
@ -20,7 +20,6 @@
|
|||
#include "D3DBase.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "Render.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
@ -385,6 +384,35 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
|||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
float sw = 1.0f /(float) SourceWidth;
|
||||
float sh = 1.0f /(float) SourceHeight;
|
||||
float u1= (rSource->left + 0.5f) * sw;
|
||||
float u2= (rSource->right + 0.5f) * sw;
|
||||
float v1= (rSource->top + 0.5f) * sh;
|
||||
float v2= (rSource->bottom + 0.5f) * sh;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,L,T,R,B; } coords[4] = {
|
||||
{ rDest->left , rDest->bottom, 0.0f,1.0f, u1, v1, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->right, rDest->bottom, 0.0f,1.0f, u2, v1, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->right, rDest->top , 0.0f,1.0f, u2, v2, sw, sh,u1,v1,u2,v2},
|
||||
{ rDest->left , rDest->top , 0.0f,1.0f, u1, v2, sw, sh,u1,v1,u2,v2}
|
||||
};
|
||||
dev->SetVertexShader(Vshader);
|
||||
dev->SetPixelShader(PShader);
|
||||
D3D::SetTexture(0, texture);
|
||||
dev->SetFVF(D3DFVF_XYZW | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2));
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include <math.h>
|
||||
#include <MathUtil.h>
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
|
@ -64,6 +66,13 @@ namespace D3D
|
|||
int SourceHeight,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader);
|
||||
void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
const MathUtil::Rectangle<float> *rSource,
|
||||
int SourceWidth,
|
||||
int SourceHeight,
|
||||
const MathUtil::Rectangle<float> *rDest,
|
||||
IDirect3DPixelShader9 *PShader,
|
||||
IDirect3DVertexShader9 *Vshader);
|
||||
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader);
|
||||
void SaveRenderStates();
|
||||
void RestoreRenderStates();
|
||||
|
|
|
@ -352,15 +352,15 @@ static void DX9DebuggerUpdateScreen()
|
|||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
|
||||
D3D::dev->StretchRect(FBManager::GetEFBColorRTSurface(), NULL,
|
||||
D3D::dev->StretchRect(FBManager.GetEFBColorRTSurface(), NULL,
|
||||
D3D::GetBackBufferSurface(), NULL,
|
||||
D3DTEXF_LINEAR);
|
||||
|
||||
D3D::dev->EndScene();
|
||||
D3D::dev->Present(NULL, NULL, NULL, NULL);
|
||||
|
||||
D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
D3D::dev->BeginScene();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -114,7 +114,7 @@ struct TabDirect3D : public W32Util::Tab
|
|||
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);
|
||||
Button_GetCheck(GetDlgItem(hDlg,IDC_RENDER_TO_MAINWINDOW)) ? Button_Enable(GetDlgItem(hDlg,IDC_FULLSCREENENABLE), false) : Button_Enable(GetDlgItem(hDlg,IDC_FULLSCREENENABLE), true);
|
||||
}
|
||||
|
@ -204,7 +204,9 @@ struct TabAdvanced : public W32Util::Tab
|
|||
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_DISABLEFOG), g_Config.bDisableFog);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_ENABLEEFBCOPY), !g_Config.bEFBCopyDisable);
|
||||
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_ENABLEXFB),g_Config.bUseXFB);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_ENABLEREALXFB),g_Config.bUseRealXFB);
|
||||
|
||||
if(g_Config.bCopyEFBToTexture)
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_EFBTOTEX), true);
|
||||
else
|
||||
|
@ -221,6 +223,11 @@ struct TabAdvanced : public W32Util::Tab
|
|||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_ENABLEXFB:
|
||||
{
|
||||
g_Config.bUseXFB = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEXFB)) ? true : false;
|
||||
}
|
||||
break;
|
||||
case IDC_ENABLEEFBCOPY:
|
||||
{
|
||||
Button_GetCheck(GetDlgItem(hDlg,IDC_ENABLEEFBCOPY)) ? Button_Enable(GetDlgItem(hDlg,IDC_EFBTORAM), true) : Button_Enable(GetDlgItem(hDlg,IDC_EFBTORAM), false);
|
||||
|
@ -252,7 +259,8 @@ struct TabAdvanced : public W32Util::Tab
|
|||
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 = Button_GetCheck(GetDlgItem(hDlg,IDC_EFBTORAM)) ? false : true;
|
||||
|
||||
g_Config.bUseXFB = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEXFB)) ? true : false;
|
||||
g_Config.bUseRealXFB = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEREALXFB)) ? true : false;
|
||||
g_Config.Save((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_dx9.ini").c_str());
|
||||
|
||||
if( D3D::dev != NULL ) {
|
||||
|
|
|
@ -19,79 +19,63 @@
|
|||
#include "Render.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "PixelShaderCache.h"
|
||||
#include "VertexShaderCache.h"
|
||||
#include "TextureConverter.h"
|
||||
|
||||
namespace FBManager
|
||||
{
|
||||
|
||||
static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
|
||||
static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
|
||||
static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
|
||||
static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
|
||||
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
|
||||
|
||||
static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
|
||||
|
||||
static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
|
||||
static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
|
||||
static D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
||||
#undef CHECK
|
||||
#define CHECK(hr,Message) if (FAILED(hr)) { PanicAlert(__FUNCTION__ " FAIL: %s" ,Message); }
|
||||
|
||||
FramebufferManager FBManager;
|
||||
|
||||
|
||||
LPDIRECT3DSURFACE9 GetEFBColorRTSurface()
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorRTSurface()
|
||||
{
|
||||
return s_efb_color_surface;
|
||||
}
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthRTSurface()
|
||||
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthRTSurface()
|
||||
{
|
||||
return s_efb_depth_surface;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface()
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorOffScreenRTSurface()
|
||||
{
|
||||
return s_efb_color_OffScreenReadBuffer;
|
||||
}
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface()
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthOffScreenRTSurface()
|
||||
{
|
||||
return s_efb_depth_OffScreenReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetEFBColorReadSurface()
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBColorReadSurface()
|
||||
{
|
||||
return s_efb_color_ReadBuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthReadSurface()
|
||||
LPDIRECT3DSURFACE9 FramebufferManager::GetEFBDepthReadSurface()
|
||||
{
|
||||
return s_efb_depth_ReadBuffer;
|
||||
}
|
||||
|
||||
D3DFORMAT GetEFBDepthRTSurfaceFormat(){return s_efb_depth_surface_Format;}
|
||||
D3DFORMAT GetEFBDepthReadSurfaceFormat(){return s_efb_depth_ReadBuffer_Format;}
|
||||
D3DFORMAT GetEFBColorRTSurfaceFormat(){return s_efb_color_surface_Format;}
|
||||
D3DFORMAT FramebufferManager::GetEFBDepthRTSurfaceFormat(){return s_efb_depth_surface_Format;}
|
||||
D3DFORMAT FramebufferManager::GetEFBDepthReadSurfaceFormat(){return s_efb_depth_ReadBuffer_Format;}
|
||||
D3DFORMAT FramebufferManager::GetEFBColorRTSurfaceFormat(){return s_efb_color_surface_Format;}
|
||||
|
||||
|
||||
LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
{
|
||||
return s_efb_color_texture;
|
||||
}
|
||||
|
||||
|
||||
LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle &sourceRc)
|
||||
LPDIRECT3DTEXTURE9 FramebufferManager::GetEFBDepthTexture(const EFBRectangle &sourceRc)
|
||||
{
|
||||
return s_efb_depth_texture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Create()
|
||||
void FramebufferManager::Create()
|
||||
{
|
||||
// Simplest possible setup to start with.
|
||||
int target_width = Renderer::GetFullTargetWidth();
|
||||
|
@ -180,49 +164,356 @@ void Create()
|
|||
}
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
|
||||
if(s_efb_depth_surface)
|
||||
s_efb_depth_surface->Release();
|
||||
s_efb_depth_surface=NULL;
|
||||
void FramebufferManager::Destroy()
|
||||
{
|
||||
if (s_efb_depth_surface)
|
||||
s_efb_depth_surface->Release();
|
||||
s_efb_depth_surface=NULL;
|
||||
|
||||
if(s_efb_color_surface)
|
||||
s_efb_color_surface->Release();
|
||||
s_efb_color_surface=NULL;
|
||||
if (s_efb_color_surface)
|
||||
s_efb_color_surface->Release();
|
||||
s_efb_color_surface=NULL;
|
||||
|
||||
if(s_efb_color_ReadBuffer)
|
||||
s_efb_color_ReadBuffer->Release();
|
||||
s_efb_color_ReadBuffer=NULL;
|
||||
if (s_efb_color_ReadBuffer)
|
||||
s_efb_color_ReadBuffer->Release();
|
||||
s_efb_color_ReadBuffer=NULL;
|
||||
|
||||
if(s_efb_depth_ReadBuffer)
|
||||
s_efb_depth_ReadBuffer->Release();
|
||||
s_efb_depth_ReadBuffer=NULL;
|
||||
if (s_efb_depth_ReadBuffer)
|
||||
s_efb_depth_ReadBuffer->Release();
|
||||
s_efb_depth_ReadBuffer=NULL;
|
||||
|
||||
if(s_efb_color_OffScreenReadBuffer)
|
||||
s_efb_color_OffScreenReadBuffer->Release();
|
||||
s_efb_color_OffScreenReadBuffer=NULL;
|
||||
if (s_efb_color_OffScreenReadBuffer)
|
||||
s_efb_color_OffScreenReadBuffer->Release();
|
||||
s_efb_color_OffScreenReadBuffer=NULL;
|
||||
|
||||
if(s_efb_depth_OffScreenReadBuffer)
|
||||
s_efb_depth_OffScreenReadBuffer->Release();
|
||||
s_efb_depth_OffScreenReadBuffer=NULL;
|
||||
if (s_efb_depth_OffScreenReadBuffer)
|
||||
s_efb_depth_OffScreenReadBuffer->Release();
|
||||
s_efb_depth_OffScreenReadBuffer=NULL;
|
||||
|
||||
if(s_efb_color_texture)
|
||||
s_efb_color_texture->Release();
|
||||
s_efb_color_texture=NULL;
|
||||
if (s_efb_color_texture)
|
||||
s_efb_color_texture->Release();
|
||||
s_efb_color_texture=NULL;
|
||||
|
||||
if(s_efb_colorRead_texture)
|
||||
s_efb_colorRead_texture->Release();
|
||||
s_efb_colorRead_texture=NULL;
|
||||
if (s_efb_colorRead_texture)
|
||||
s_efb_colorRead_texture->Release();
|
||||
s_efb_colorRead_texture=NULL;
|
||||
|
||||
if(s_efb_depth_texture)
|
||||
s_efb_depth_texture->Release();
|
||||
s_efb_depth_texture=NULL;
|
||||
if (s_efb_depth_texture)
|
||||
s_efb_depth_texture->Release();
|
||||
s_efb_depth_texture=NULL;
|
||||
|
||||
if(s_efb_depthRead_texture)
|
||||
s_efb_depthRead_texture->Release();
|
||||
s_efb_depthRead_texture=NULL;
|
||||
if (s_efb_depthRead_texture)
|
||||
s_efb_depthRead_texture->Release();
|
||||
s_efb_depthRead_texture=NULL;
|
||||
|
||||
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
||||
{
|
||||
it->xfbSource.texture->Release();
|
||||
}
|
||||
m_virtualXFBList.clear();
|
||||
if(m_realXFBSource.texture)
|
||||
m_realXFBSource.texture->Release();
|
||||
m_realXFBSource.texture = NULL;
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (g_ActiveConfig.bUseRealXFB)
|
||||
copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
else
|
||||
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
}
|
||||
|
||||
const XFBSource** FramebufferManager::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
if (g_ActiveConfig.bUseRealXFB)
|
||||
return getRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
else
|
||||
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)
|
||||
{
|
||||
u8* xfb_in_ram = Memory_GetPtr(xfbAddr);
|
||||
if (!xfb_in_ram)
|
||||
{
|
||||
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||
return;
|
||||
}
|
||||
|
||||
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
TextureConverter::EncodeToRamYUYV(GetEFBColorTexture(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 xfbTexture;
|
||||
|
||||
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
|
||||
|
||||
if (it == m_virtualXFBList.end() && (int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
||||
{
|
||||
// replace the last virtual XFB
|
||||
it--;
|
||||
}
|
||||
|
||||
float MultiSampleCompensation = 1.0f;
|
||||
if(g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.iMultisampleMode < 4)
|
||||
{
|
||||
switch (g_ActiveConfig.iMultisampleMode)
|
||||
{
|
||||
case 1:
|
||||
MultiSampleCompensation = 2.0f/3.0f;
|
||||
break;
|
||||
case 2:
|
||||
MultiSampleCompensation = 0.5f;
|
||||
break;
|
||||
case 3:
|
||||
MultiSampleCompensation = 1.0f/3.0f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
float scaleX = Renderer::GetTargetScaleX() * MultiSampleCompensation ;
|
||||
float scaleY = Renderer::GetTargetScaleY() * MultiSampleCompensation;
|
||||
TargetRectangle targetSource,efbSource;
|
||||
efbSource = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
targetSource.top = (sourceRc.top *scaleY);
|
||||
targetSource.bottom = (sourceRc.bottom *scaleY);
|
||||
targetSource.left = (sourceRc.left *scaleX);
|
||||
targetSource.right = (sourceRc.right * scaleX);
|
||||
int target_width = targetSource.right - targetSource.left;
|
||||
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.texture)
|
||||
{
|
||||
if(it->xfbSource.texture)
|
||||
it->xfbSource.texture->Release();
|
||||
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &it->xfbSource.texture, NULL);
|
||||
}
|
||||
|
||||
xfbTexture = it->xfbSource.texture;
|
||||
|
||||
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.
|
||||
|
||||
D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &xfbTexture, NULL);
|
||||
VirtualXFB newVirt;
|
||||
|
||||
newVirt.xfbAddr = xfbAddr;
|
||||
newVirt.xfbWidth = fbWidth;
|
||||
newVirt.xfbHeight = fbHeight;
|
||||
|
||||
newVirt.xfbSource.texture = xfbTexture;
|
||||
newVirt.xfbSource.texWidth = target_width;
|
||||
newVirt.xfbSource.texHeight = target_height;
|
||||
|
||||
// Add the new Virtual XFB to the list
|
||||
|
||||
if ((int)m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
||||
{
|
||||
// List overflowed; delete the oldest.
|
||||
m_virtualXFBList.back().xfbSource.texture->Release();
|
||||
m_virtualXFBList.pop_back();
|
||||
}
|
||||
|
||||
m_virtualXFBList.push_front(newVirt);
|
||||
}
|
||||
|
||||
// Copy EFB to XFB texture
|
||||
|
||||
if(!xfbTexture)
|
||||
return;
|
||||
// Make sure to resolve anything we need to read from.
|
||||
LPDIRECT3DTEXTURE9 read_texture = GetEFBColorTexture(sourceRc);
|
||||
|
||||
// We have to run a pixel shader, for color conversion.
|
||||
Renderer::ResetAPIState(); // reset any game specific settings
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
|
||||
xfbTexture->GetSurfaceLevel(0,&Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = target_width;
|
||||
vp.Height = target_height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = efbSource.bottom;
|
||||
sourcerect.left = efbSource.left;
|
||||
sourcerect.right = efbSource.right;
|
||||
sourcerect.top = efbSource.top;
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
|
||||
int SSAAMode = ( g_ActiveConfig.iMultisampleMode > 3 )? 0 : g_ActiveConfig.iMultisampleMode;
|
||||
D3D::drawShadedTexQuad(
|
||||
read_texture,
|
||||
&sourcerect,
|
||||
Renderer::GetFullTargetWidth() ,
|
||||
Renderer::GetFullTargetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(SSAAMode),
|
||||
(SSAAMode != 0)? VertexShaderCache::GetFSAAVertexShader() : VertexShaderCache::GetSimpleVertexShader());
|
||||
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0,NULL);
|
||||
D3D::dev->SetRenderTarget(0, GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(GetEFBDepthRTSurface());
|
||||
Renderer::RestoreAPIState();
|
||||
Rendersurf->Release();
|
||||
|
||||
}
|
||||
|
||||
const XFBSource** FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount)
|
||||
{
|
||||
xfbCount = 1;
|
||||
|
||||
m_realXFBSource.texWidth = fbWidth;
|
||||
m_realXFBSource.texHeight = fbHeight;
|
||||
|
||||
m_realXFBSource.srcAddr = xfbAddr;
|
||||
m_realXFBSource.srcWidth = fbWidth;
|
||||
m_realXFBSource.srcHeight = fbHeight;
|
||||
|
||||
if (!m_realXFBSource.texture)
|
||||
{
|
||||
D3D::dev->CreateTexture(fbWidth, fbHeight, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &m_realXFBSource.texture, NULL);
|
||||
}
|
||||
|
||||
// Decode YUYV data from GameCube RAM
|
||||
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
|
||||
|
||||
m_overlappingXFBArray[0] = &m_realXFBSource;
|
||||
|
||||
return &m_overlappingXFBArray[0];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
|
@ -21,50 +21,148 @@
|
|||
#include <list>
|
||||
#include "D3DBase.h"
|
||||
|
||||
namespace FBManager
|
||||
// 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));
|
||||
}
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
struct XFBSource
|
||||
{
|
||||
XFBSource() :
|
||||
texture(0)
|
||||
{}
|
||||
|
||||
// To get the EFB in texture form, these functions may have to transfer
|
||||
// the EFB to a resolved texture first.
|
||||
LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||
LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||
|
||||
LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
|
||||
D3DFORMAT GetEFBDepthRTSurfaceFormat();
|
||||
D3DFORMAT GetEFBColorRTSurfaceFormat();
|
||||
D3DFORMAT GetEFBDepthReadSurfaceFormat();
|
||||
LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// Resolved framebuffer is only used in MSAA mode.
|
||||
LPDIRECT3DTEXTURE9 GetResolvedFramebuffer() const { return m_resolvedFramebuffer; }
|
||||
|
||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) const;
|
||||
|
||||
void SetFramebuffer(LPDIRECT3DSURFACE9 surface);
|
||||
|
||||
// If in MSAA mode, this will perform a resolve of the specified rectangle, and return the resolve target as a texture ID.
|
||||
// Thus, this call may be expensive. Don't repeat it unnecessarily.
|
||||
// If not in MSAA mode, will just return the render target texture ID.
|
||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||
LPDIRECT3DTEXTURE9 ResolveAndGetRenderTarget(const EFBRectangle &rect);
|
||||
|
||||
// Same as above but for the depth Target.
|
||||
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||
LPDIRECT3DTEXTURE9 ResolveAndGetDepthTarget(const EFBRectangle &rect);
|
||||
*/
|
||||
u32 srcAddr;
|
||||
u32 srcWidth;
|
||||
u32 srcHeight;
|
||||
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
};
|
||||
|
||||
class FramebufferManager
|
||||
{
|
||||
public:
|
||||
FramebufferManager()
|
||||
{
|
||||
s_efb_color_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_depth_texture = NULL;
|
||||
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture = NULL;
|
||||
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_surface = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_surface = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer = NULL;
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer = NULL;
|
||||
|
||||
D3DFORMAT s_efb_color_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
D3DFORMAT s_efb_depth_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
D3DFORMAT s_efb_depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
||||
m_realXFBSource.texture = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc);
|
||||
LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle& sourceRc);
|
||||
|
||||
LPDIRECT3DSURFACE9 GetEFBColorRTSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthRTSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface();
|
||||
D3DFORMAT GetEFBDepthRTSurfaceFormat();
|
||||
D3DFORMAT GetEFBColorRTSurfaceFormat();
|
||||
D3DFORMAT GetEFBDepthReadSurfaceFormat();
|
||||
LPDIRECT3DSURFACE9 GetEFBColorReadSurface();
|
||||
LPDIRECT3DSURFACE9 GetEFBDepthReadSurface();
|
||||
|
||||
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; // Only used in Real XFB mode
|
||||
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
||||
|
||||
const XFBSource* m_overlappingXFBArray[MAX_VIRTUAL_XFB];
|
||||
|
||||
LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target
|
||||
LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store
|
||||
LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target
|
||||
LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//4 pixel texture for temporal data store
|
||||
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface
|
||||
LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface
|
||||
LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture
|
||||
LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data
|
||||
|
||||
|
||||
D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface
|
||||
D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth Surface
|
||||
D3DFORMAT s_efb_depth_ReadBuffer_Format;//Format of the Depth color Read Surface
|
||||
};
|
||||
|
||||
extern FramebufferManager FBManager;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "StringUtil.h"
|
||||
#include "Common.h"
|
||||
#include "Atomic.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Thread.h"
|
||||
#include "Timer.h"
|
||||
|
@ -52,6 +53,7 @@
|
|||
|
||||
int s_fps=0;
|
||||
|
||||
static bool WindowResized;
|
||||
static int s_target_width;
|
||||
static int s_target_height;
|
||||
|
||||
|
@ -61,6 +63,9 @@ static int s_Fulltarget_height;
|
|||
static int s_backbuffer_width;
|
||||
static int s_backbuffer_height;
|
||||
|
||||
static int s_XFB_width;
|
||||
static int s_XFB_height;
|
||||
|
||||
static float xScale;
|
||||
static float yScale;
|
||||
|
||||
|
@ -73,7 +78,7 @@ static bool s_AVIDumping;
|
|||
static u32 s_blendMode;
|
||||
static u32 s_LastAA;
|
||||
static bool IS_AMD;
|
||||
|
||||
static bool XFBWrited;
|
||||
|
||||
char st[32768];
|
||||
|
||||
|
@ -229,7 +234,7 @@ void SetupDeviceObjects()
|
|||
{
|
||||
D3D::font.Init();
|
||||
VertexLoaderManager::Init();
|
||||
FBManager::Create();
|
||||
FBManager.Create();
|
||||
|
||||
VertexShaderManager::Dirty();
|
||||
PixelShaderManager::Dirty();
|
||||
|
@ -246,7 +251,7 @@ void TeardownDeviceObjects()
|
|||
ScreenShootMEMSurface = NULL;
|
||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
||||
FBManager::Destroy();
|
||||
FBManager.Destroy();
|
||||
D3D::font.Shutdown();
|
||||
TextureCache::Invalidate(false);
|
||||
VertexManager::DestroyDeviceObjects();
|
||||
|
@ -282,31 +287,53 @@ bool Renderer::Init()
|
|||
s_backbuffer_width = D3D::GetBackBufferWidth();
|
||||
s_backbuffer_height = D3D::GetBackBufferHeight();
|
||||
|
||||
// TODO: Grab target width from configured resolution?
|
||||
s_target_width = s_backbuffer_width;
|
||||
s_target_height = s_backbuffer_height * ((float)EFB_HEIGHT / 480.0f);
|
||||
s_XFB_width = MAX_XFB_WIDTH;
|
||||
s_XFB_height = MAX_XFB_HEIGHT;
|
||||
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
|
||||
if(g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
xScale = yScale = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
|
||||
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
|
||||
}
|
||||
|
||||
|
||||
s_target_width = EFB_WIDTH * xScale;
|
||||
s_target_height = EFB_HEIGHT * yScale;
|
||||
|
||||
s_LastAA = (g_ActiveConfig.iMultisampleMode > 3)?0:g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
float SupersampleCoeficient = 1.0f;
|
||||
switch (s_LastAA)
|
||||
{
|
||||
case 1:
|
||||
s_target_width = (s_target_width * 3) / 2;
|
||||
s_target_height = (s_target_height * 3) / 2;
|
||||
SupersampleCoeficient = 3.0f/2.0f;
|
||||
break;
|
||||
case 2:
|
||||
s_target_width *= 2;
|
||||
s_target_height *= 2;
|
||||
SupersampleCoeficient = 2.0f;
|
||||
break;
|
||||
case 3:
|
||||
s_target_width *= 3;
|
||||
s_target_height *= 3;
|
||||
SupersampleCoeficient = 3.0f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
xScale = (float)s_target_width / (float)EFB_WIDTH;
|
||||
yScale = (float)s_target_height / (float)EFB_HEIGHT;
|
||||
xScale *= SupersampleCoeficient;
|
||||
yScale *= SupersampleCoeficient;
|
||||
|
||||
s_Fulltarget_width = s_target_width;
|
||||
s_Fulltarget_height = s_target_height;
|
||||
|
||||
|
@ -335,8 +362,8 @@ bool Renderer::Init()
|
|||
D3D::dev->SetViewport(&vp);
|
||||
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 0, 0);
|
||||
|
||||
D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
vp.X = (s_Fulltarget_width - s_target_width) / 2;
|
||||
vp.Y = (s_Fulltarget_height - s_target_height) / 2;
|
||||
vp.Width = s_target_width;
|
||||
|
@ -345,7 +372,7 @@ bool Renderer::Init()
|
|||
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x0, 1.0f, 0);
|
||||
D3D::BeginFrame();
|
||||
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true);
|
||||
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, FBManager::GetEFBColorRTSurfaceFormat(), D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
|
||||
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width,s_backbuffer_height, FBManager.GetEFBColorRTSurfaceFormat(), D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -369,6 +396,15 @@ int Renderer::GetFullTargetHeight() { return s_Fulltarget_height; }
|
|||
float Renderer::GetTargetScaleX() { return xScale; }
|
||||
float Renderer::GetTargetScaleY() { return yScale; }
|
||||
|
||||
int Renderer::GetFrameBufferWidth()
|
||||
{
|
||||
return s_backbuffer_width;
|
||||
}
|
||||
int Renderer::GetFrameBufferHeight()
|
||||
{
|
||||
return s_backbuffer_height;
|
||||
}
|
||||
|
||||
// Create On-Screen-Messages
|
||||
void Renderer::DrawDebugText()
|
||||
{
|
||||
|
@ -523,190 +559,33 @@ void CheckForResize()
|
|||
{
|
||||
TeardownDeviceObjects();
|
||||
|
||||
D3D::Reset();
|
||||
|
||||
SetupDeviceObjects();
|
||||
D3D::Reset();
|
||||
s_backbuffer_width = D3D::GetBackBufferWidth();
|
||||
s_backbuffer_height = D3D::GetBackBufferHeight();
|
||||
WindowResized = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void EFBTextureToD3DBackBuffer(const EFBRectangle& sourceRc)
|
||||
{
|
||||
TargetRectangle src_rect, dst_rect;
|
||||
src_rect = Renderer::ConvertEFBRectangle(sourceRc);
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = s_backbuffer_width;
|
||||
vp.Height = s_backbuffer_height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
|
||||
D3D::dev->Clear(0,NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
|
||||
int X = dst_rect.left;
|
||||
int Y = dst_rect.top;
|
||||
int Width = dst_rect.right - dst_rect.left;
|
||||
int Height = dst_rect.bottom - dst_rect.top;
|
||||
|
||||
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;
|
||||
vp.X = X;
|
||||
vp.Y = Y;
|
||||
vp.Width = Width;
|
||||
vp.Height = Height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
|
||||
D3D::dev->SetViewport(&vp);
|
||||
|
||||
EFBRectangle efbRect;
|
||||
|
||||
LPDIRECT3DTEXTURE9 read_texture = FBManager::GetEFBColorTexture(efbRect);
|
||||
RECT destinationrect;
|
||||
destinationrect.bottom = dst_rect.bottom;
|
||||
destinationrect.left = dst_rect.left;
|
||||
destinationrect.right = dst_rect.right;
|
||||
destinationrect.top = dst_rect.top;
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = src_rect.bottom;
|
||||
sourcerect.left = src_rect.left;
|
||||
sourcerect.right = src_rect.right;
|
||||
sourcerect.top = src_rect.top;
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
int SSAAMode = ( g_ActiveConfig.iMultisampleMode > 3 )? 0 : g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
D3D::drawShadedTexQuad(read_texture,&sourcerect,Renderer::GetFullTargetWidth(),Renderer::GetFullTargetHeight(),PixelShaderCache::GetColorCopyProgram(SSAAMode),(SSAAMode != 0)?VertexShaderCache::GetFSAAVertexShader():VertexShaderCache::GetSimpleVertexShader());
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = s_backbuffer_width;
|
||||
vp.Height = s_backbuffer_height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
if(s_bScreenshot)
|
||||
{
|
||||
s_criticalScreenshot.Enter();
|
||||
D3DXSaveSurfaceToFileA(s_sScreenshotName, D3DXIFF_BMP, D3D::GetBackBufferSurface(), NULL, &destinationrect);
|
||||
s_bScreenshot = false;
|
||||
s_criticalScreenshot.Leave();
|
||||
}
|
||||
if (g_ActiveConfig.bDumpFrames)
|
||||
{
|
||||
D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface);
|
||||
if (!s_LastFrameDumped)
|
||||
{
|
||||
s_recordWidth = destinationrect.right - destinationrect.left;
|
||||
s_recordHeight = destinationrect.bottom - destinationrect.top;
|
||||
s_AVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
|
||||
if (!s_AVIDumping)
|
||||
{
|
||||
PanicAlert("Error dumping frames to AVI.");
|
||||
}
|
||||
else
|
||||
{
|
||||
char msg [255];
|
||||
sprintf(msg, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", File::GetUserPath(D_DUMPFRAMES_IDX), s_recordWidth, s_recordHeight);
|
||||
OSD::AddMessage(msg, 2000);
|
||||
}
|
||||
}
|
||||
if (s_AVIDumping)
|
||||
{
|
||||
D3DLOCKED_RECT rect;
|
||||
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, &destinationrect, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
|
||||
{
|
||||
char *data = (char *)malloc(3 * s_recordWidth * s_recordHeight);
|
||||
formatBufferDump((const char *)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch);
|
||||
AVIDump::AddFrame(data);
|
||||
free(data);
|
||||
ScreenShootMEMSurface->UnlockRect();
|
||||
}
|
||||
}
|
||||
s_LastFrameDumped = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_LastFrameDumped && s_AVIDumping)
|
||||
{
|
||||
AVIDump::Stop();
|
||||
s_AVIDumping = false;
|
||||
}
|
||||
s_LastFrameDumped = false;
|
||||
}
|
||||
|
||||
|
||||
// Finish up the current frame, print some stats
|
||||
if (g_ActiveConfig.bShowFPS)
|
||||
{
|
||||
char fps[20];
|
||||
StringCchPrintfA(fps, 20, "FPS: %d\n", s_fps);
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,fps,false);
|
||||
}
|
||||
Renderer::DrawDebugText();
|
||||
|
||||
if (g_ActiveConfig.bOverlayStats)
|
||||
{
|
||||
Statistics::ToString(st);
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
}
|
||||
else if (g_ActiveConfig.bOverlayProjStats)
|
||||
{
|
||||
Statistics::ToStringProj(st);
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
}
|
||||
|
||||
OSD::DrawMessages();
|
||||
}
|
||||
extern volatile u32 s_swapRequested;
|
||||
|
||||
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
|
||||
{
|
||||
if (g_bSkipCurrentFrame)
|
||||
{
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
DEBUGGER_PAUSE_LOG_AT(NEXT_XFB_CMD,false,{printf("RenderToXFB - disabled");});
|
||||
VideoFifo_CheckEFBAccess();
|
||||
XFBWrited = true;
|
||||
if(!fbWidth || !fbHeight)
|
||||
return;
|
||||
// If we're about to write to a requested XFB, make sure the previous
|
||||
// contents make it to the screen first.
|
||||
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
|
||||
FBManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
|
||||
|
||||
// XXX: Without the VI, how would we know what kind of field this is? So
|
||||
// just use progressive.
|
||||
if (!g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
Renderer::Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight);
|
||||
Common::AtomicStoreRelease(s_swapRequested, FALSE);
|
||||
}
|
||||
|
||||
Renderer::ResetAPIState();
|
||||
// Set the backbuffer as the rendering target
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
|
||||
EFBTextureToD3DBackBuffer(sourceRc);
|
||||
|
||||
D3D::EndFrame();
|
||||
|
||||
DEBUGGER_LOG_AT((NEXT_XFB_CMD|NEXT_EFB_CMD|NEXT_FRAME),
|
||||
{printf("StretchRect, EFB->XFB\n");});
|
||||
DEBUGGER_PAUSE_LOG_AT(
|
||||
(NEXT_XFB_CMD),false,
|
||||
{printf("RenderToXFB: addr = %08X, %d x %d, sourceRc = (%d,%d,%d,%d)\n",
|
||||
xfbAddr, fbWidth, fbHeight,
|
||||
sourceRc.left, sourceRc.top, sourceRc.right, sourceRc.bottom);}
|
||||
);
|
||||
|
||||
Swap(0,FIELD_PROGRESSIVE,0,0); // we used to swap the buffer here, now we will wait
|
||||
// until the XFB pointer is updated by VI
|
||||
D3D::BeginFrame();
|
||||
Renderer::RestoreAPIState();
|
||||
D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
UpdateViewport();
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
}
|
||||
|
||||
bool Renderer::SetScissorRect()
|
||||
|
@ -789,18 +668,18 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||
|
||||
//Get the working buffer
|
||||
LPDIRECT3DSURFACE9 pBuffer = (type == PEEK_Z || type == POKE_Z) ?
|
||||
FBManager::GetEFBDepthRTSurface() : FBManager::GetEFBColorRTSurface();
|
||||
FBManager.GetEFBDepthRTSurface() : FBManager.GetEFBColorRTSurface();
|
||||
//get the temporal buffer to move 1pixel data
|
||||
LPDIRECT3DSURFACE9 RBuffer = (type == PEEK_Z || type == POKE_Z) ?
|
||||
FBManager::GetEFBDepthReadSurface() : FBManager::GetEFBColorReadSurface();
|
||||
FBManager.GetEFBDepthReadSurface() : FBManager.GetEFBColorReadSurface();
|
||||
//get the memory buffer that can be locked
|
||||
LPDIRECT3DSURFACE9 pOffScreenBuffer = (type == PEEK_Z || type == POKE_Z) ?
|
||||
FBManager::GetEFBDepthOffScreenRTSurface() : FBManager::GetEFBColorOffScreenRTSurface();
|
||||
FBManager.GetEFBDepthOffScreenRTSurface() : FBManager.GetEFBColorOffScreenRTSurface();
|
||||
//get the buffer format
|
||||
D3DFORMAT BufferFormat = (type == PEEK_Z || type == POKE_Z) ?
|
||||
FBManager::GetEFBDepthRTSurfaceFormat() : FBManager::GetEFBColorRTSurfaceFormat();
|
||||
FBManager.GetEFBDepthRTSurfaceFormat() : FBManager.GetEFBColorRTSurfaceFormat();
|
||||
D3DFORMAT ReadBufferFormat = (type == PEEK_Z || type == POKE_Z) ?
|
||||
FBManager::GetEFBDepthReadSurfaceFormat() : BufferFormat;
|
||||
FBManager.GetEFBDepthReadSurfaceFormat() : BufferFormat;
|
||||
|
||||
if (BufferFormat == D3DFMT_D24X8)
|
||||
return 0;
|
||||
|
@ -872,7 +751,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||
colmat[0] = colmat[5] = colmat[10] = 1.0f;
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
EFBRectangle source_rect;
|
||||
LPDIRECT3DTEXTURE9 read_texture = FBManager::GetEFBDepthTexture(source_rect);
|
||||
LPDIRECT3DTEXTURE9 read_texture = FBManager.GetEFBDepthTexture(source_rect);
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
|
||||
|
@ -886,8 +765,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y)
|
|||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
|
||||
hr = D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
hr = D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
hr = D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
hr = D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
RestoreAPIState();
|
||||
RectToLock.bottom = 4;
|
||||
RectToLock.left = 0;
|
||||
|
@ -1038,10 +917,10 @@ void UpdateViewport()
|
|||
{
|
||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
||||
FBManager::Destroy();
|
||||
FBManager::Create();
|
||||
D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
FBManager.Destroy();
|
||||
FBManager.Create();
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
}
|
||||
vp.X = X;
|
||||
vp.Y = Y;
|
||||
|
@ -1131,55 +1010,279 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||
|
||||
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
if(!fbWidth || !fbHeight)
|
||||
return;
|
||||
// this function is called after the XFB field is changed, not after
|
||||
// EFB is copied to XFB. In this way, flickering is reduced in games
|
||||
// and seems to also give more FPS in ZTP
|
||||
// and seems to also give more FPS in ZTP
|
||||
if(!XFBWrited)
|
||||
return;
|
||||
if (field == FIELD_LOWER)
|
||||
xfbAddr -= fbWidth * 2;
|
||||
|
||||
u32 xfbCount = 0;
|
||||
const XFBSource** xfbSourceList = FBManager.GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
if (!xfbSourceList || xfbCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_bSkipCurrentFrame)
|
||||
{
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Renderer::ResetAPIState();
|
||||
// Set the backbuffer as the rendering target
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = s_backbuffer_width;
|
||||
vp.Height = s_backbuffer_height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
D3D::dev->Clear(0,NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
|
||||
|
||||
int X = dst_rect.left;
|
||||
int Y = dst_rect.top;
|
||||
int Width = dst_rect.right - dst_rect.left;
|
||||
int Height = dst_rect.bottom - dst_rect.top;
|
||||
|
||||
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;
|
||||
vp.X = X;
|
||||
vp.Y = Y;
|
||||
vp.Width = Width;
|
||||
vp.Height = Height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
|
||||
D3D::dev->SetViewport(&vp);
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
const XFBSource* xfbSource;
|
||||
|
||||
// draw each xfb source
|
||||
for (u32 i = 0; i < xfbCount; ++i)
|
||||
{
|
||||
xfbSource = xfbSourceList[i];
|
||||
MathUtil::Rectangle<float> sourceRc;
|
||||
|
||||
sourceRc.left = 0;
|
||||
sourceRc.top = 0;
|
||||
sourceRc.right = xfbSource->texWidth;
|
||||
sourceRc.bottom = xfbSource->texHeight;
|
||||
|
||||
MathUtil::Rectangle<float> drawRc;
|
||||
|
||||
if (g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
// use virtual xfb with offset
|
||||
int xfbHeight = xfbSource->srcHeight;
|
||||
int xfbWidth = xfbSource->srcWidth;
|
||||
int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbWidth * 2);
|
||||
|
||||
drawRc.bottom = 1.0f - 2.0f * ((hOffset) / (float)fbHeight);
|
||||
drawRc.top = 1.0f - 2.0f * ((hOffset + xfbHeight) / (float)fbHeight);
|
||||
drawRc.left = -(xfbWidth / (float)fbWidth);
|
||||
drawRc.right = (xfbWidth / (float)fbWidth);
|
||||
|
||||
|
||||
if (!g_ActiveConfig.bAutoScale)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRc.top = -1;
|
||||
drawRc.bottom = 1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
}
|
||||
|
||||
D3D::drawShadedTexSubQuad(xfbSource->texture,&sourceRc,xfbSource->texWidth,xfbSource->texHeight,&drawRc,PixelShaderCache::GetColorCopyProgram(0),VertexShaderCache::GetSimpleVertexShader());
|
||||
}
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = s_backbuffer_width;
|
||||
vp.Height = s_backbuffer_height;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
if(s_bScreenshot)
|
||||
{
|
||||
s_criticalScreenshot.Enter();
|
||||
D3DXSaveSurfaceToFileA(s_sScreenshotName, D3DXIFF_BMP, D3D::GetBackBufferSurface(), NULL, NULL);
|
||||
s_bScreenshot = false;
|
||||
s_criticalScreenshot.Leave();
|
||||
}
|
||||
if (g_ActiveConfig.bDumpFrames)
|
||||
{
|
||||
D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface);
|
||||
if (!s_LastFrameDumped)
|
||||
{
|
||||
s_recordWidth = s_backbuffer_width;
|
||||
s_recordHeight = s_backbuffer_height;
|
||||
s_AVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
|
||||
if (!s_AVIDumping)
|
||||
{
|
||||
PanicAlert("Error dumping frames to AVI.");
|
||||
}
|
||||
else
|
||||
{
|
||||
char msg [255];
|
||||
sprintf(msg, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", File::GetUserPath(D_DUMPFRAMES_IDX), s_recordWidth, s_recordHeight);
|
||||
OSD::AddMessage(msg, 2000);
|
||||
}
|
||||
}
|
||||
if (s_AVIDumping)
|
||||
{
|
||||
D3DLOCKED_RECT rect;
|
||||
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, NULL, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
|
||||
{
|
||||
char *data = (char *)malloc(3 * s_recordWidth * s_recordHeight);
|
||||
formatBufferDump((const char *)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch);
|
||||
AVIDump::AddFrame(data);
|
||||
free(data);
|
||||
ScreenShootMEMSurface->UnlockRect();
|
||||
}
|
||||
}
|
||||
s_LastFrameDumped = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_LastFrameDumped && s_AVIDumping)
|
||||
{
|
||||
AVIDump::Stop();
|
||||
s_AVIDumping = false;
|
||||
}
|
||||
s_LastFrameDumped = false;
|
||||
}
|
||||
|
||||
|
||||
// Finish up the current frame, print some stats
|
||||
if (g_ActiveConfig.bShowFPS)
|
||||
{
|
||||
char fps[20];
|
||||
StringCchPrintfA(fps, 20, "FPS: %d\n", s_fps);
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,fps,false);
|
||||
}
|
||||
Renderer::DrawDebugText();
|
||||
|
||||
if (g_ActiveConfig.bOverlayStats)
|
||||
{
|
||||
Statistics::ToString(st);
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
}
|
||||
else if (g_ActiveConfig.bOverlayProjStats)
|
||||
{
|
||||
Statistics::ToStringProj(st);
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
}
|
||||
|
||||
OSD::DrawMessages();
|
||||
|
||||
D3D::EndFrame();
|
||||
|
||||
// D3D frame is now over
|
||||
// Clean out old stuff from caches.
|
||||
frameCount++;
|
||||
TextureCache::Cleanup();
|
||||
|
||||
// Make any new configuration settings active.
|
||||
UpdateActiveConfig();
|
||||
|
||||
g_VideoInitialize.pCopiedToXFB(false);
|
||||
|
||||
UpdateActiveConfig();
|
||||
WindowResized = false;
|
||||
CheckForResize();
|
||||
|
||||
bool xfbchanged = false;
|
||||
|
||||
if(s_XFB_width != fbWidth || s_XFB_height != fbHeight)
|
||||
{
|
||||
xfbchanged = true;
|
||||
s_XFB_width = fbWidth;
|
||||
s_XFB_height = fbHeight;
|
||||
if(s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if(s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if(s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
if(s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
|
||||
}
|
||||
|
||||
u32 newAA = g_ActiveConfig.iMultisampleMode;
|
||||
if(newAA != s_LastAA)
|
||||
if(newAA != s_LastAA || xfbchanged || WindowResized)
|
||||
{
|
||||
s_target_width = s_backbuffer_width;
|
||||
s_target_height = s_backbuffer_height * ((float)EFB_HEIGHT / 480.0f);
|
||||
s_LastAA = newAA;
|
||||
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
|
||||
if(g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
xScale = yScale = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
|
||||
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
|
||||
}
|
||||
|
||||
s_target_width = EFB_WIDTH * xScale;
|
||||
s_target_height = EFB_HEIGHT * yScale;
|
||||
|
||||
s_LastAA = (g_ActiveConfig.iMultisampleMode > 3)?0:g_ActiveConfig.iMultisampleMode;
|
||||
|
||||
float SupersampleCoeficient = 1.0f;
|
||||
switch (s_LastAA)
|
||||
{
|
||||
case 1:
|
||||
s_target_width = (s_target_width * 3) / 2;
|
||||
s_target_height = (s_target_height * 3) / 2;
|
||||
SupersampleCoeficient = 3.0f/2.0f;
|
||||
break;
|
||||
case 2:
|
||||
s_target_width *= 2;
|
||||
s_target_height *= 2;
|
||||
SupersampleCoeficient = 2.0f;
|
||||
break;
|
||||
case 3:
|
||||
s_target_width *= 3;
|
||||
s_target_height *= 3;
|
||||
SupersampleCoeficient = 3.0f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
xScale = (float)s_target_width / (float)EFB_WIDTH;
|
||||
yScale = (float)s_target_height / (float)EFB_HEIGHT;
|
||||
s_Fulltarget_width = s_target_width;
|
||||
s_Fulltarget_height = s_target_height;
|
||||
|
||||
xScale *= SupersampleCoeficient;
|
||||
yScale *= SupersampleCoeficient;
|
||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
||||
FBManager::Destroy();
|
||||
FBManager::Create();
|
||||
D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
SetupDeviceObjects();
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
@ -1201,6 +1304,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
|||
|
||||
// Flip/present backbuffer to frontbuffer here
|
||||
D3D::Present();
|
||||
D3D::BeginFrame();
|
||||
Renderer::RestoreAPIState();
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
UpdateViewport();
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
XFBWrited = false;
|
||||
}
|
||||
|
||||
void Renderer::ResetAPIState()
|
||||
|
|
|
@ -330,7 +330,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
|
||||
int tex_w = (abs(source_rect.GetWidth()) >> bScaleByHalf);
|
||||
int tex_h = (abs(source_rect.GetHeight()) >> bScaleByHalf);
|
||||
//compensate the texture grow if multisample is enabled to conserve memory usage
|
||||
//compensate the texture grow if supersampling is enabled to conserve memory usage
|
||||
float MultiSampleCompensation = 1.0f;
|
||||
if(g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.iMultisampleMode < 4)
|
||||
{
|
||||
|
@ -353,16 +353,14 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleY() * MultiSampleCompensation * tex_h)):tex_h;
|
||||
|
||||
TexCache::iterator iter;
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
LPDIRECT3DTEXTURE9 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;
|
||||
goto have_texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -374,6 +372,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
}
|
||||
}
|
||||
|
||||
if(!tex)
|
||||
{
|
||||
TCacheEntry entry;
|
||||
entry.isRenderTarget = true;
|
||||
|
@ -390,7 +389,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
tex = entry.texture;
|
||||
}
|
||||
|
||||
have_texture:
|
||||
|
||||
float colmat[16]= {0.0f};
|
||||
float fConstAdd[4] = {0.0f};
|
||||
|
||||
|
@ -499,7 +498,7 @@ have_texture:
|
|||
}
|
||||
}
|
||||
// Make sure to resolve anything we need to read from.
|
||||
LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? FBManager::GetEFBDepthTexture(source_rect) : FBManager::GetEFBColorTexture(source_rect);
|
||||
LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? FBManager.GetEFBDepthTexture(source_rect) : FBManager.GetEFBColorTexture(source_rect);
|
||||
|
||||
// We have to run a pixel shader, for color conversion.
|
||||
Renderer::ResetAPIState(); // reset any game specific settings
|
||||
|
@ -545,7 +544,7 @@ have_texture:
|
|||
}
|
||||
|
||||
|
||||
D3DFORMAT bformat = FBManager::GetEFBDepthRTSurfaceFormat();
|
||||
D3DFORMAT bformat = FBManager.GetEFBDepthRTSurfaceFormat();
|
||||
int SSAAMode = ( g_ActiveConfig.iMultisampleMode > 3 )? 0 : g_ActiveConfig.iMultisampleMode;
|
||||
D3D::drawShadedTexQuad(
|
||||
read_texture,
|
||||
|
@ -559,8 +558,8 @@ have_texture:
|
|||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0,NULL);
|
||||
D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
Renderer::RestoreAPIState();
|
||||
Rendersurf->Release();
|
||||
}
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
#include "VideoConfig.h"
|
||||
#include "ImageWrite.h"
|
||||
#include "Render.h"
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "D3DShader.h"
|
||||
#include "TextureCache.h"
|
||||
#include "Math.h"
|
||||
#include "FileUtil.h"
|
||||
|
@ -60,14 +56,16 @@ static LPDIRECT3DPIXELSHADER9 s_encodingPrograms[NUM_ENCODING_PROGRAMS];
|
|||
void CreateRgbToYuyvProgram()
|
||||
{
|
||||
// Output is BGRA because that is slightly faster than RGBA.
|
||||
const char *FProgram =
|
||||
char* FProgram = new char[2048];
|
||||
sprintf(FProgram,"uniform float4 blkDims : register(c%d);\n"
|
||||
"uniform float4 textureDims : register(c%d);\n"
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
" float2 uv1 = float2(uv0.x + 1.0f, uv0.y);\n"
|
||||
" float3 c0 = tex2D(samp0, uv0).rgb;\n"
|
||||
" float2 uv1 = float2(uv0.x + (1.0f/blkDims.z), uv0.y);\n"
|
||||
" float3 c0 = tex2D(samp0, uv0.xy).rgb;\n"
|
||||
" float3 c1 = tex2D(samp0, uv1).rgb;\n"
|
||||
" float3 y_const = float3(0.257f,0.504f,0.098f);\n"
|
||||
" float3 u_const = float3(-0.148f,-0.291f,0.439f);\n"
|
||||
|
@ -75,16 +73,20 @@ void CreateRgbToYuyvProgram()
|
|||
" float4 const3 = float4(0.0625f,0.5f,0.0625f,0.5f);\n"
|
||||
" float3 c01 = (c0 + c1) * 0.5f;\n"
|
||||
" ocol0 = float4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
|
||||
"}\n";
|
||||
"}\n",C_COLORMATRIX,C_COLORMATRIX+1);
|
||||
|
||||
s_rgbToYuyvProgram = D3D::CompileAndCreatePixelShader(FProgram, (int)strlen(FProgram));
|
||||
if (!s_rgbToYuyvProgram) {
|
||||
ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program");
|
||||
}
|
||||
delete [] FProgram;
|
||||
}
|
||||
|
||||
void CreateYuyvToRgbProgram()
|
||||
{
|
||||
const char *FProgram =
|
||||
char* FProgram = new char[2048];
|
||||
sprintf(FProgram,"uniform float4 blkDims : register(c%d);\n"
|
||||
"uniform float4 textureDims : register(c%d);\n"
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
|
@ -92,7 +94,7 @@ void CreateYuyvToRgbProgram()
|
|||
"{\n"
|
||||
" float4 c0 = tex2D(samp0, uv0).rgba;\n"
|
||||
|
||||
" float f = step(0.5, frac(uv0.x));\n"
|
||||
" float f = step(0.5, frac(uv0.x * blkDims.z));\n"
|
||||
" float y = lerp(c0.b, c0.r, f);\n"
|
||||
" float yComp = 1.164f * (y - 0.0625f);\n"
|
||||
" float uComp = c0.g - 0.5f;\n"
|
||||
|
@ -102,11 +104,12 @@ void CreateYuyvToRgbProgram()
|
|||
" yComp - (0.813f * vComp) - (0.391f * uComp),\n"
|
||||
" yComp + (2.018f * uComp),\n"
|
||||
" 1.0f);\n"
|
||||
"}\n";
|
||||
"}\n",C_COLORMATRIX,C_COLORMATRIX+1);
|
||||
s_yuyvToRgbProgram = D3D::CompileAndCreatePixelShader(FProgram, (int)strlen(FProgram));
|
||||
if (!s_yuyvToRgbProgram) {
|
||||
ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program");
|
||||
}
|
||||
delete [] FProgram;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 GetOrCreateEncodingShader(u32 format)
|
||||
|
@ -270,8 +273,8 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
|
|||
|
||||
// Draw...
|
||||
D3D::drawShadedTexQuad(srcTexture,&SrcRect,1,1,shader,VertexShaderCache::GetSimpleVertexShader());
|
||||
hr = D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface());
|
||||
hr = D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface());
|
||||
hr = D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
hr = D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
Renderer::RestoreAPIState();
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
// .. and then readback the results.
|
||||
|
@ -337,7 +340,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
|||
|
||||
u8 *dest_ptr = Memory_GetPtr(address);
|
||||
|
||||
LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? FBManager::GetEFBDepthTexture(source) : FBManager::GetEFBColorTexture(source);
|
||||
LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? FBManager.GetEFBDepthTexture(source) : FBManager.GetEFBColorTexture(source);
|
||||
int width = (source.right - source.left) >> bScaleByHalf;
|
||||
int height = (source.bottom - source.top) >> bScaleByHalf;
|
||||
|
||||
|
@ -387,15 +390,23 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
|||
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0);
|
||||
}
|
||||
|
||||
/*void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight)
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,u8* destAddr, int dstWidth, int dstHeight)
|
||||
{
|
||||
TextureConversionShader::SetShaderParameters(
|
||||
(float)dstWidth,
|
||||
(float)dstHeight,
|
||||
0.0f ,
|
||||
0.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
(float)Renderer::GetFullTargetWidth(),
|
||||
(float)Renderer::GetFullTargetHeight());
|
||||
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
|
||||
}
|
||||
|
||||
|
||||
// Should be scale free.
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture)
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture)
|
||||
{
|
||||
u8* srcAddr = Memory_GetPtr(xfbAddr);
|
||||
if (!srcAddr)
|
||||
|
@ -404,64 +415,67 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
|
|||
return;
|
||||
}
|
||||
|
||||
Renderer::ResetAPIState();
|
||||
|
||||
float srcFormatFactor = 0.5f;
|
||||
float srcFmtWidth = srcWidth * srcFormatFactor;
|
||||
|
||||
// swich to texture converter frame buffer
|
||||
// attach destTexture as color destination
|
||||
g_framebufferManager.SetFramebuffer(s_texConvFrameBuffer);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
|
||||
|
||||
GL_REPORT_FBO_ERROR();
|
||||
|
||||
for (int i = 1; i < 8; ++i)
|
||||
TextureMngr::DisableStage(i);
|
||||
|
||||
// activate source texture
|
||||
// set srcAddr as data for source texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_srcTexture);
|
||||
|
||||
// TODO: make this less slow. (How?)
|
||||
if(s_srcTextureWidth == (GLsizei)srcFmtWidth && s_srcTextureHeight == (GLsizei)srcHeight)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,0,0,s_srcTextureWidth, s_srcTextureHeight, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)srcFmtWidth, (GLsizei)srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
|
||||
s_srcTextureWidth = (GLsizei)srcFmtWidth;
|
||||
s_srcTextureHeight = (GLsizei)srcHeight;
|
||||
}
|
||||
|
||||
glViewport(0, 0, srcWidth, srcHeight);
|
||||
|
||||
PixelShaderCache::EnableShader(s_yuyvToRgbProgram.glprogid);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
Renderer::ResetAPIState(); // reset any game specific settings
|
||||
LPDIRECT3DTEXTURE9 s_srcTexture = D3D::CreateTexture2D(srcAddr, srcFmtWidth, srcHeight, srcFmtWidth, D3DFMT_A8R8G8B8, false);
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
destTexture->GetSurfaceLevel(0,&Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(srcFmtWidth, (float)srcHeight); glVertex2f(1,-1);
|
||||
glTexCoord2f(srcFmtWidth, 0); glVertex2f(1,1);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1,1);
|
||||
glTexCoord2f(0, (float)srcHeight); glVertex2f(-1,-1);
|
||||
glEnd();
|
||||
|
||||
// reset state
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||
TextureMngr::DisableStage(0);
|
||||
|
||||
VertexShaderManager::SetViewportChanged();
|
||||
|
||||
g_framebufferManager.SetFramebuffer(0);
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = srcWidth;
|
||||
vp.Height = srcHeight;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = srcHeight;
|
||||
destrect.left = 0;
|
||||
destrect.right = srcWidth;
|
||||
destrect.top = 0;
|
||||
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = srcHeight;
|
||||
sourcerect.left = 0;
|
||||
sourcerect.right = srcFmtWidth;
|
||||
sourcerect.top = 0;
|
||||
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
TextureConversionShader::SetShaderParameters(
|
||||
(float)srcFmtWidth,
|
||||
(float)srcHeight,
|
||||
0.0f ,
|
||||
0.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
(float)srcFmtWidth,
|
||||
(float)srcHeight);
|
||||
D3D::drawShadedTexQuad(
|
||||
s_srcTexture,
|
||||
&sourcerect,
|
||||
srcFmtWidth ,
|
||||
srcHeight,
|
||||
s_yuyvToRgbProgram,
|
||||
VertexShaderCache::GetSimpleVertexShader());
|
||||
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
D3D::SetTexture(0,NULL);
|
||||
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
Renderer::RestoreAPIState();
|
||||
GL_REPORT_ERRORD();
|
||||
Rendersurf->Release();
|
||||
s_srcTexture->Release();
|
||||
}
|
||||
*/
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#define _TEXTURECONVERTER_H_
|
||||
|
||||
#include "VideoCommon.h"
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "D3DShader.h"
|
||||
|
||||
// Converts textures between formats
|
||||
// TODO: support multiple texture formats
|
||||
|
@ -31,10 +35,10 @@ void Shutdown();
|
|||
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
|
||||
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
|
||||
|
||||
/*void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
|
||||
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight);
|
||||
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);*/
|
||||
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -62,11 +62,12 @@ GFXDebuggerDX9 *m_DebuggerFrame = NULL;
|
|||
HINSTANCE g_hInstance = NULL;
|
||||
SVideoInitialize g_VideoInitialize;
|
||||
PLUGIN_GLOBALS* globals = NULL;
|
||||
bool s_initialized;
|
||||
static bool s_PluginInitialized = false;
|
||||
|
||||
volatile u32 s_swapRequested = FALSE;
|
||||
static u32 s_efbAccessRequested = FALSE;
|
||||
static volatile u32 s_FifoShuttingDown = FALSE;
|
||||
static bool s_swapRequested = false;
|
||||
static bool ForceSwap = true;
|
||||
|
||||
static volatile struct
|
||||
{
|
||||
|
@ -205,9 +206,9 @@ void DllAbout(HWND _hParent)
|
|||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
// If not initialized, only init D3D so we can enumerate resolutions.
|
||||
if (!s_initialized) D3D::Init();
|
||||
if (!s_PluginInitialized) D3D::Init();
|
||||
DlgSettings_Show(g_hInstance, _hParent);
|
||||
if (!s_initialized) D3D::Shutdown();
|
||||
if (!s_PluginInitialized) D3D::Shutdown();
|
||||
}
|
||||
|
||||
void Initialize(void *init)
|
||||
|
@ -242,7 +243,7 @@ void Initialize(void *init)
|
|||
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
|
||||
|
||||
OSD::AddMessage("Dolphin Direct3D9 Video Plugin.", 5000);
|
||||
s_initialized = true;
|
||||
s_PluginInitialized = true;
|
||||
}
|
||||
|
||||
void Video_Prepare()
|
||||
|
@ -250,7 +251,8 @@ void Video_Prepare()
|
|||
// Better be safe...
|
||||
s_efbAccessRequested = FALSE;
|
||||
s_FifoShuttingDown = FALSE;
|
||||
|
||||
s_swapRequested = FALSE;
|
||||
ForceSwap = true;
|
||||
Renderer::Init();
|
||||
TextureCache::Init();
|
||||
BPInit();
|
||||
|
@ -270,7 +272,7 @@ void Shutdown()
|
|||
{
|
||||
s_efbAccessRequested = FALSE;
|
||||
s_FifoShuttingDown = FALSE;
|
||||
|
||||
s_swapRequested = FALSE;
|
||||
Fifo_Shutdown();
|
||||
VertexManager::Shutdown();
|
||||
VertexLoaderManager::Shutdown();
|
||||
|
@ -283,7 +285,7 @@ void Shutdown()
|
|||
Renderer::Shutdown();
|
||||
D3D::Shutdown();
|
||||
EmuWindow::Close();
|
||||
s_initialized = false;
|
||||
s_PluginInitialized = false;
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode) {
|
||||
|
@ -318,52 +320,61 @@ void Video_SetRendering(bool bEnabled) {
|
|||
// Run from the graphics thread
|
||||
void VideoFifo_CheckSwapRequest()
|
||||
{
|
||||
// swap unimplemented
|
||||
return;
|
||||
|
||||
if (s_swapRequested)
|
||||
if (Common::AtomicLoadAcquire(s_swapRequested))
|
||||
{
|
||||
// Flip the backbuffer to front buffer now
|
||||
s_swapRequested = false;
|
||||
//if (s_beginFieldArgs.field == FIELD_PROGRESSIVE || s_beginFieldArgs.field == FIELD_LOWER)
|
||||
if (ForceSwap || g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
Renderer::Swap(0,FIELD_PROGRESSIVE,0,0); // The swap function is not finished
|
||||
// so it is ok to pass dummy parameters for now
|
||||
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)
|
||||
{
|
||||
// swap unimplemented
|
||||
if (Common::AtomicLoadAcquire(s_swapRequested) && g_ActiveConfig.bUseXFB)
|
||||
{
|
||||
u32 aLower = xfbAddr;
|
||||
u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight;
|
||||
u32 bLower = s_beginFieldArgs.xfbAddr;
|
||||
u32 bUpper = s_beginFieldArgs.xfbAddr + 2 * s_beginFieldArgs.fbWidth * s_beginFieldArgs.fbHeight;
|
||||
|
||||
if (addrRangesOverlap(aLower, aUpper, bLower, bUpper))
|
||||
VideoFifo_CheckSwapRequest();
|
||||
}
|
||||
|
||||
ForceSwap = false;
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
// swap unimplemented
|
||||
return;
|
||||
|
||||
s_beginFieldArgs.xfbAddr = xfbAddr;
|
||||
s_beginFieldArgs.field = field;
|
||||
s_beginFieldArgs.fbWidth = fbWidth;
|
||||
s_beginFieldArgs.fbHeight = fbHeight;
|
||||
s_swapRequested = true;
|
||||
|
||||
if (s_initialized)
|
||||
if (s_PluginInitialized)
|
||||
{
|
||||
// Make sure previous swap request has made it to the screen
|
||||
if (g_VideoInitialize.bOnThread)
|
||||
{
|
||||
//while (Common::AtomicLoadAcquire(s_swapRequested))
|
||||
//Common::YieldCPU();
|
||||
while (Common::AtomicLoadAcquire(s_swapRequested) && !s_FifoShuttingDown)
|
||||
//Common::SleepCurrentThread(1);
|
||||
Common::YieldCPU();
|
||||
}
|
||||
else
|
||||
VideoFifo_CheckSwapRequest();
|
||||
|
||||
s_beginFieldArgs.xfbAddr = xfbAddr;
|
||||
s_beginFieldArgs.field = field;
|
||||
s_beginFieldArgs.fbWidth = fbWidth;
|
||||
s_beginFieldArgs.fbHeight = fbHeight;
|
||||
|
||||
Common::AtomicStoreRelease(s_swapRequested, TRUE);
|
||||
}
|
||||
DEBUGGER_LOG_AT(NEXT_XFB_CMD,{printf("Begin Field: %08x, %d x %d\n",xfbAddr,fbWidth,fbHeight);});
|
||||
}
|
||||
|
||||
void Video_EndField()
|
||||
|
@ -413,24 +424,27 @@ void VideoFifo_CheckEFBAccess()
|
|||
|
||||
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
|
||||
{
|
||||
if (!g_ActiveConfig.bEFBAccessEnable)
|
||||
return 0;
|
||||
|
||||
s_accessEFBArgs.type = type;
|
||||
s_accessEFBArgs.x = x;
|
||||
s_accessEFBArgs.y = y;
|
||||
|
||||
Common::AtomicStoreRelease(s_efbAccessRequested, TRUE);
|
||||
|
||||
if (g_VideoInitialize.bOnThread)
|
||||
if (s_PluginInitialized)
|
||||
{
|
||||
while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown)
|
||||
Common::YieldCPU();
|
||||
}
|
||||
else
|
||||
VideoFifo_CheckEFBAccess();
|
||||
s_accessEFBArgs.type = type;
|
||||
s_accessEFBArgs.x = x;
|
||||
s_accessEFBArgs.y = y;
|
||||
|
||||
return s_AccessEFBResult;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
#define IDC_TEXFMT_OVERLAY 1024
|
||||
#define IDC_TEXFMT_CENTER 1025
|
||||
#define IDC_FORCEFILTERING 1026
|
||||
#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
|
||||
|
|
|
@ -67,23 +67,25 @@ 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,67
|
||||
GROUPBOX "&Settings",IDC_STATIC,6,7,228,89
|
||||
CONTROL "Overlay FPS counter",IDC_OVERLAYFPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,18,82,8
|
||||
CONTROL "&Overlay some statistics",IDC_OVERLAYSTATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,137,90,8
|
||||
CONTROL "&Overlay some statistics",IDC_OVERLAYSTATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,155,90,8
|
||||
CONTROL "Show s&hader compilation errors",IDC_SHOWSHADERERRORS,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,151,114,8
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,169,114,8
|
||||
CONTROL "Enable &Wireframe",IDC_WIREFRAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,48,87,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 "To RAM",IDC_EFBTORAM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,29,44,59,10
|
||||
CONTROL "To Texture",IDC_EFBTOTEX,"Button",BS_AUTORADIOBUTTON,29,57,60,10
|
||||
GROUPBOX "&Data dumping",IDC_STATIC,7,79,228,41
|
||||
CONTROL "Dump &textures",IDC_TEXDUMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,92,70,9
|
||||
CONTROL "Dump Frames to User/Dump/Frames",IDC_DUMPFRAMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,106,138,9
|
||||
GROUPBOX "Debugging Tools",IDC_STATIC,7,125,228,70
|
||||
CONTROL "Enable TexFmt Overlay",IDC_TEXFMT_OVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,164,92,10
|
||||
CONTROL "Centered",IDC_TEXFMT_CENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,177,52,10
|
||||
GROUPBOX "&Data dumping",IDC_STATIC,7,100,228,41
|
||||
CONTROL "Dump &textures",IDC_TEXDUMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,111,70,9
|
||||
CONTROL "Dump Frames to User/Dump/Frames",IDC_DUMPFRAMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,125,138,9
|
||||
GROUPBOX "Debugging Tools",IDC_STATIC,7,143,228,51
|
||||
CONTROL "Enable TexFmt Overlay",IDC_TEXFMT_OVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,182,92,10
|
||||
CONTROL "Centered",IDC_TEXFMT_CENTER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,183,52,10
|
||||
CONTROL "Enable XFB",IDC_ENABLEXFB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,71,81,8
|
||||
CONTROL "Enable Real XFB",IDC_ENABLEREALXFB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,114,71,81,8
|
||||
END
|
||||
|
||||
IDD_ENHANCEMENTS DIALOGEX 0, 0, 224, 175
|
||||
|
|
Loading…
Reference in New Issue