D3D: Basic EFB copy-to-texture support. Fixes star domes in SMG (but does not fix the pull star, need EFB reads for that) and some other things.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4188 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
baede3a7f3
commit
efc74c77a9
|
@ -110,20 +110,18 @@ inline float Memory_Read_Float(u32 _uAddress)
|
|||
void HandleGLError();
|
||||
|
||||
|
||||
// This structure should only be used to represent a rectangle in OpenGL target
|
||||
// coordinates, where the origin is at the lower left and the frame dimensions
|
||||
// depend on the resolution settings. Use Renderer::ConvertEFBRectangle to
|
||||
// convert an EFBRectangle to a TargetRectangle.
|
||||
struct TargetRectangle : public MathUtil::Rectangle<int>
|
||||
{};
|
||||
|
||||
// This structure should only be used to represent a rectangle in EFB
|
||||
// coordinates, where the origin is at the upper left and the frame dimensions
|
||||
// are 640 x 528.
|
||||
struct EFBRectangle : public MathUtil::Rectangle<int>
|
||||
{};
|
||||
|
||||
|
||||
// This structure should only be used to represent a rectangle in standard target
|
||||
// coordinates, where the origin is at the lower left and the frame dimensions
|
||||
// depend on the resolution settings. Use Renderer::ConvertEFBRectangle to
|
||||
// convert an EFBRectangle to a TargetRectangle.
|
||||
struct TargetRectangle : public MathUtil::Rectangle<int>
|
||||
{};
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PRIM_LOG(...) {DEBUG_LOG(VIDEO, __VA_ARGS__)}
|
||||
|
|
|
@ -207,9 +207,7 @@ void SetColorMask(const BPCmd &bp)
|
|||
|
||||
void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf)
|
||||
{
|
||||
// TODO: Scale EFBRectangle correctly
|
||||
RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
|
||||
TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest << 5, &rec);
|
||||
TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
||||
}
|
||||
|
||||
void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
|
||||
|
|
|
@ -41,10 +41,8 @@
|
|||
|
||||
#include "debugger/debugger.h"
|
||||
|
||||
static float m_x;
|
||||
static float m_y;
|
||||
static float m_width;
|
||||
static float m_height;
|
||||
static float m_targetWidth;
|
||||
static float m_targetHeight;
|
||||
static float xScale;
|
||||
static float yScale;
|
||||
|
||||
|
@ -63,15 +61,11 @@ bool Renderer::Init()
|
|||
|
||||
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
|
||||
|
||||
float width = (float)D3D::GetDisplayWidth();
|
||||
float height = (float)D3D::GetDisplayHeight();
|
||||
m_targetWidth = (float)D3D::GetDisplayWidth();
|
||||
m_targetHeight = (float)D3D::GetDisplayHeight();
|
||||
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
xScale = m_width / (float)EFB_WIDTH;
|
||||
yScale = m_height / (float)EFB_HEIGHT;
|
||||
xScale = m_targetWidth / (float)EFB_WIDTH;
|
||||
yScale = m_targetHeight / (float)EFB_HEIGHT;
|
||||
|
||||
m_LastFrameDumped = false;
|
||||
m_AVIDumping = false;
|
||||
|
@ -129,11 +123,23 @@ void dumpMatrix(D3DXMATRIX &mtx)
|
|||
}
|
||||
}
|
||||
|
||||
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
{
|
||||
TargetRectangle result;
|
||||
result.left = (rc.left * m_targetWidth) / EFB_WIDTH;
|
||||
result.top = (rc.top * m_targetHeight) / EFB_HEIGHT;
|
||||
result.right = (rc.right * m_targetWidth) / EFB_WIDTH;
|
||||
result.bottom = (rc.bottom * m_targetHeight) / EFB_HEIGHT;
|
||||
return result;
|
||||
}
|
||||
|
||||
void formatBufferDump(const char *in, char *out, int w, int h, int p)
|
||||
{
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int y = 0; y < h; y++)
|
||||
{
|
||||
const char *line = in + (h - y - 1) * p;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
memcpy(out, line, 3);
|
||||
out += 3;
|
||||
line += 4;
|
||||
|
@ -250,16 +256,16 @@ void Renderer::SwapBuffers()
|
|||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = (DWORD)m_width;
|
||||
vp.Height = (DWORD)m_height;
|
||||
vp.Width = (DWORD)m_targetWidth;
|
||||
vp.Height = (DWORD)m_targetHeight;
|
||||
vp.MinZ = 0;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT rc;
|
||||
rc.left = 0;
|
||||
rc.top = 0;
|
||||
rc.right = (LONG)m_width;
|
||||
rc.bottom = (LONG)m_height;
|
||||
rc.right = (LONG)m_targetWidth;
|
||||
rc.bottom = (LONG)m_targetHeight;
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
D3D::dev->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||
|
||||
|
@ -315,8 +321,8 @@ void Renderer::SetColorMask()
|
|||
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||
}
|
||||
|
||||
// mtx.m[0][3] = pMatrix[1]; // -0.5f/m_width; <-- fix d3d pixel center?
|
||||
// mtx.m[1][3] = pMatrix[3]; // +0.5f/m_height; <-- fix d3d pixel center?
|
||||
// mtx.m[0][3] = pMatrix[1]; // -0.5f/m_targetWidth; <-- fix d3d pixel center?
|
||||
// mtx.m[1][3] = pMatrix[3]; // +0.5f/m_targetHeight; <-- fix d3d pixel center?
|
||||
|
||||
// Called from VertexShaderManager
|
||||
void UpdateViewport()
|
||||
|
|
|
@ -248,9 +248,16 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
return &entry;
|
||||
}
|
||||
|
||||
|
||||
void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
|
||||
// EXTREMELY incomplete.
|
||||
void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, const EFBRectangle &source_rect)
|
||||
{
|
||||
int efb_w = source_rect.GetWidth();
|
||||
int efb_h = source_rect.GetHeight();
|
||||
|
||||
int mult = bScaleByHalf ? 2 : 1;
|
||||
int tex_w = (abs(source_rect.GetWidth()) / mult);
|
||||
int tex_h = (abs(source_rect.GetHeight()) / mult);
|
||||
|
||||
TexCache::iterator iter;
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
iter = textures.find(address);
|
||||
|
@ -259,27 +266,50 @@ void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
|
|||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Using non-rendertarget texture as render target!!! WTF?", FALSE);
|
||||
//TODO: remove it and recreate it as a render target
|
||||
// Remove it and recreate it as a render target
|
||||
iter->second.texture->Release();
|
||||
iter->second.texture = 0;
|
||||
textures.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = iter->second.texture;
|
||||
iter->second.frameCount = frameCount;
|
||||
goto have_texture;
|
||||
}
|
||||
tex = iter->second.texture;
|
||||
iter->second.frameCount = frameCount;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
TCacheEntry entry;
|
||||
entry.isRenderTarget = true;
|
||||
entry.hash = 0;
|
||||
entry.hashoffset = 0;
|
||||
entry.frameCount = frameCount;
|
||||
entry.w = tex_w;
|
||||
entry.h = tex_h;
|
||||
|
||||
// TODO(ector): infer this size in some sensible way
|
||||
D3D::dev->CreateTexture(512, 512, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
|
||||
D3D::dev->CreateTexture(tex_w, tex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
|
||||
textures[address] = entry;
|
||||
tex = entry.texture;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 srcSurface,destSurface;
|
||||
tex->GetSurfaceLevel(0,&destSurface);
|
||||
have_texture:
|
||||
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
|
||||
RECT source_rc;
|
||||
source_rc.left = targetSource.left;
|
||||
source_rc.top = targetSource.top;
|
||||
source_rc.right = targetSource.right;
|
||||
source_rc.bottom = targetSource.bottom;
|
||||
RECT dest_rc;
|
||||
dest_rc.left = 0;
|
||||
dest_rc.top = 0;
|
||||
dest_rc.right = tex_w;
|
||||
dest_rc.bottom = tex_h;
|
||||
|
||||
LPDIRECT3DSURFACE9 srcSurface, destSurface;
|
||||
tex->GetSurfaceLevel(0, &destSurface);
|
||||
srcSurface = D3D::GetBackBufferSurface();
|
||||
D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE);
|
||||
D3D::dev->StretchRect(srcSurface, &source_rc, destSurface, &dest_rc, D3DTEXF_LINEAR);
|
||||
destSurface->Release();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <map>
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "BPMemory.h"
|
||||
|
||||
class TextureCache
|
||||
|
@ -62,7 +63,7 @@ public:
|
|||
static void Shutdown();
|
||||
static void Invalidate(bool shutdown);
|
||||
static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt);
|
||||
static void CopyEFBToRenderTarget(u32 address, RECT *source);
|
||||
static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, bool bScaleByHalf, const EFBRectangle &source_rect);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -548,7 +548,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (!bIsInit || !entry.isRenderTarget)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
|
Loading…
Reference in New Issue