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:
hrydgard 2009-09-03 21:56:08 +00:00
parent baede3a7f3
commit efc74c77a9
6 changed files with 75 additions and 43 deletions

View File

@ -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__)}

View File

@ -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 &copyfmt, 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)

View File

@ -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()

View File

@ -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();
}

View File

@ -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

View File

@ -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);