diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h index c52b28691b..b48ef9b0ce 100644 --- a/Source/Core/VideoCommon/Src/VideoCommon.h +++ b/Source/Core/VideoCommon/Src/VideoCommon.h @@ -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 -{}; - // 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 {}; - +// 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 +{}; #ifdef _WIN32 #define PRIM_LOG(...) {DEBUG_LOG(VIDEO, __VA_ARGS__)} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp index 182c508d94..3e39843c23 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp @@ -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) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index a49b457fe7..8e807e650a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -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() diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 04fb246bb7..30fb7a77b7 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -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(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h index 690f78d28c..daab6b0ca3 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h @@ -22,6 +22,7 @@ #include #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 \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index eec936d554..f3f0686d9d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -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);