mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-27 06:35:39 +00:00
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();
|
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
|
// 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
|
// coordinates, where the origin is at the upper left and the frame dimensions
|
||||||
// are 640 x 528.
|
// are 640 x 528.
|
||||||
struct EFBRectangle : public MathUtil::Rectangle<int>
|
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
|
#ifdef _WIN32
|
||||||
#define PRIM_LOG(...) {DEBUG_LOG(VIDEO, __VA_ARGS__)}
|
#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)
|
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
|
TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
||||||
RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
|
|
||||||
TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest << 5, &rec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
|
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"
|
#include "debugger/debugger.h"
|
||||||
|
|
||||||
static float m_x;
|
static float m_targetWidth;
|
||||||
static float m_y;
|
static float m_targetHeight;
|
||||||
static float m_width;
|
|
||||||
static float m_height;
|
|
||||||
static float xScale;
|
static float xScale;
|
||||||
static float yScale;
|
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);
|
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
|
||||||
|
|
||||||
float width = (float)D3D::GetDisplayWidth();
|
m_targetWidth = (float)D3D::GetDisplayWidth();
|
||||||
float height = (float)D3D::GetDisplayHeight();
|
m_targetHeight = (float)D3D::GetDisplayHeight();
|
||||||
|
|
||||||
m_x = 0;
|
xScale = m_targetWidth / (float)EFB_WIDTH;
|
||||||
m_y = 0;
|
yScale = m_targetHeight / (float)EFB_HEIGHT;
|
||||||
m_width = width;
|
|
||||||
m_height = height;
|
|
||||||
xScale = m_width / (float)EFB_WIDTH;
|
|
||||||
yScale = m_height / (float)EFB_HEIGHT;
|
|
||||||
|
|
||||||
m_LastFrameDumped = false;
|
m_LastFrameDumped = false;
|
||||||
m_AVIDumping = 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)
|
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;
|
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);
|
memcpy(out, line, 3);
|
||||||
out += 3;
|
out += 3;
|
||||||
line += 4;
|
line += 4;
|
||||||
@ -250,16 +256,16 @@ void Renderer::SwapBuffers()
|
|||||||
D3DVIEWPORT9 vp;
|
D3DVIEWPORT9 vp;
|
||||||
vp.X = 0;
|
vp.X = 0;
|
||||||
vp.Y = 0;
|
vp.Y = 0;
|
||||||
vp.Width = (DWORD)m_width;
|
vp.Width = (DWORD)m_targetWidth;
|
||||||
vp.Height = (DWORD)m_height;
|
vp.Height = (DWORD)m_targetHeight;
|
||||||
vp.MinZ = 0;
|
vp.MinZ = 0;
|
||||||
vp.MaxZ = 1.0f;
|
vp.MaxZ = 1.0f;
|
||||||
D3D::dev->SetViewport(&vp);
|
D3D::dev->SetViewport(&vp);
|
||||||
RECT rc;
|
RECT rc;
|
||||||
rc.left = 0;
|
rc.left = 0;
|
||||||
rc.top = 0;
|
rc.top = 0;
|
||||||
rc.right = (LONG)m_width;
|
rc.right = (LONG)m_targetWidth;
|
||||||
rc.bottom = (LONG)m_height;
|
rc.bottom = (LONG)m_targetHeight;
|
||||||
D3D::dev->SetScissorRect(&rc);
|
D3D::dev->SetScissorRect(&rc);
|
||||||
D3D::dev->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
D3D::dev->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||||
|
|
||||||
@ -315,8 +321,8 @@ void Renderer::SetColorMask()
|
|||||||
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mtx.m[0][3] = pMatrix[1]; // -0.5f/m_width; <-- 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_height; <-- fix d3d pixel center?
|
// mtx.m[1][3] = pMatrix[3]; // +0.5f/m_targetHeight; <-- fix d3d pixel center?
|
||||||
|
|
||||||
// Called from VertexShaderManager
|
// Called from VertexShaderManager
|
||||||
void UpdateViewport()
|
void UpdateViewport()
|
||||||
|
@ -248,9 +248,16 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||||||
return &entry;
|
return &entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EXTREMELY incomplete.
|
||||||
void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
|
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;
|
TexCache::iterator iter;
|
||||||
LPDIRECT3DTEXTURE9 tex;
|
LPDIRECT3DTEXTURE9 tex;
|
||||||
iter = textures.find(address);
|
iter = textures.find(address);
|
||||||
@ -259,27 +266,50 @@ void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
|
|||||||
if (!iter->second.isRenderTarget)
|
if (!iter->second.isRenderTarget)
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Using non-rendertarget texture as render target!!! WTF?", FALSE);
|
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();
|
||||||
tex = iter->second.texture;
|
iter->second.texture = 0;
|
||||||
iter->second.frameCount = frameCount;
|
textures.erase(iter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
tex = iter->second.texture;
|
||||||
|
iter->second.frameCount = frameCount;
|
||||||
|
goto have_texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TCacheEntry entry;
|
TCacheEntry entry;
|
||||||
entry.isRenderTarget = true;
|
entry.isRenderTarget = true;
|
||||||
entry.hash = 0;
|
entry.hash = 0;
|
||||||
entry.hashoffset = 0;
|
entry.hashoffset = 0;
|
||||||
entry.frameCount = frameCount;
|
entry.frameCount = frameCount;
|
||||||
|
entry.w = tex_w;
|
||||||
|
entry.h = tex_h;
|
||||||
|
|
||||||
// TODO(ector): infer this size in some sensible way
|
// 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;
|
textures[address] = entry;
|
||||||
tex = entry.texture;
|
tex = entry.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 srcSurface,destSurface;
|
have_texture:
|
||||||
tex->GetSurfaceLevel(0,&destSurface);
|
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();
|
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();
|
destSurface->Release();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
|
#include "VideoCommon.h"
|
||||||
#include "BPMemory.h"
|
#include "BPMemory.h"
|
||||||
|
|
||||||
class TextureCache
|
class TextureCache
|
||||||
@ -62,7 +63,7 @@ public:
|
|||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static void Invalidate(bool shutdown);
|
static void Invalidate(bool shutdown);
|
||||||
static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt);
|
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
|
#endif
|
@ -548,7 +548,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!bIsInit || !entry.isRenderTarget)
|
if (!bIsInit || !entry.isRenderTarget)
|
||||||
{
|
{
|
||||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user