Merge pull request #2720 from booto/efb-copy

[WIP] Video: respect stride of efb copies to xfb
This commit is contained in:
Markus Wick 2015-07-25 12:03:03 +02:00
commit 96b77aaa81
15 changed files with 60 additions and 63 deletions

View File

@ -159,10 +159,10 @@ FramebufferManager::~FramebufferManager()
SAFE_RELEASE(m_efb.resolved_depth_tex); SAFE_RELEASE(m_efb.resolved_depth_tex);
} }
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma)
{ {
u8* dst = Memory::GetPointer(xfbAddr); u8* dst = Memory::GetPointer(xfbAddr);
s_xfbEncoder.Encode(dst, fbWidth, fbHeight, sourceRc, Gamma); s_xfbEncoder.Encode(dst, fbStride, fbHeight, sourceRc, Gamma);
} }
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers)

View File

@ -83,7 +83,7 @@ private:
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) override; XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) override;
void GetTargetSize(unsigned int *width, unsigned int *height) override; void GetTargetSize(unsigned int *width, unsigned int *height) override;
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) override; void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) override;
static struct Efb static struct Efb
{ {

View File

@ -288,7 +288,7 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
D3D::stateman->PushDepthState(m_xfbEncodeDepthState); D3D::stateman->PushDepthState(m_xfbEncodeDepthState);
D3D::stateman->PushRasterizerState(m_xfbEncodeRastState); D3D::stateman->PushRasterizerState(m_xfbEncodeRastState);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width/2), FLOAT(height)); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width/4), FLOAT(height));
D3D::context->RSSetViewports(1, &vp); D3D::context->RSSetViewports(1, &vp);
D3D::stateman->SetInputLayout(m_quadLayout); D3D::stateman->SetInputLayout(m_quadLayout);
@ -300,7 +300,7 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect); TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect);
XFBEncodeParams params = { 0 }; XFBEncodeParams params = { 0 };
params.Width = FLOAT(width); params.Width = FLOAT(width/2);
params.Height = FLOAT(height); params.Height = FLOAT(height);
params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetTargetWidth(); params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetTargetWidth();
params.TexTop = FLOAT(targetRect.top) / g_renderer->GetTargetHeight(); params.TexTop = FLOAT(targetRect.top) / g_renderer->GetTargetHeight();
@ -325,7 +325,7 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
// Copy to staging buffer // Copy to staging buffer
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, width/2, height, 1); D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, width/4, height, 1);
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox); D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
// Clean up state // Clean up state
@ -353,7 +353,7 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
u8* src = (u8*)map.pData; u8* src = (u8*)map.pData;
for (unsigned int y = 0; y < height; ++y) for (unsigned int y = 0; y < height; ++y)
{ {
memcpy(dst, src, 2*width); memcpy(dst, src, width);
dst += bpmem.copyMipMapStrideChannels*32; dst += bpmem.copyMipMapStrideChannels*32;
src += map.RowPitch; src += map.RowPitch;
} }

View File

@ -481,7 +481,7 @@ GLuint FramebufferManager::GetEFBDepthTexture(const EFBRectangle& sourceRc)
} }
} }
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma)
{ {
u8* xfb_in_ram = Memory::GetPointer(xfbAddr); u8* xfb_in_ram = Memory::GetPointer(xfbAddr);
if (!xfb_in_ram) if (!xfb_in_ram)
@ -491,7 +491,7 @@ void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, c
} }
TargetRectangle targetRc = g_renderer->ConvertEFBRectangle(sourceRc); TargetRectangle targetRc = g_renderer->ConvertEFBRectangle(sourceRc);
TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, fbWidth, fbHeight); TextureConverter::EncodeToRamYUYV(ResolveAndGetRenderTarget(sourceRc), targetRc, xfb_in_ram, sourceRc.GetWidth(), fbStride, fbHeight);
} }
void FramebufferManager::SetFramebuffer(GLuint fb) void FramebufferManager::SetFramebuffer(GLuint fb)

View File

@ -97,7 +97,7 @@ private:
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) override; XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) override;
void GetTargetSize(unsigned int *width, unsigned int *height) override; void GetTargetSize(unsigned int *width, unsigned int *height) override;
void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) override; void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) override;
static int m_targetWidth; static int m_targetWidth;
static int m_targetHeight; static int m_targetHeight;

View File

@ -1456,10 +1456,16 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
xfbSource = (const XFBSource*) xfbSourceList[i]; xfbSource = (const XFBSource*) xfbSourceList[i];
TargetRectangle drawRc; TargetRectangle drawRc;
TargetRectangle sourceRc;
sourceRc.left = xfbSource->sourceRc.left;
sourceRc.right = xfbSource->sourceRc.right;
sourceRc.top = xfbSource->sourceRc.top;
sourceRc.bottom = xfbSource->sourceRc.bottom;
if (g_ActiveConfig.bUseRealXFB) if (g_ActiveConfig.bUseRealXFB)
{ {
drawRc = flipped_trc; drawRc = flipped_trc;
sourceRc.right -= fbStride - fbWidth;
} }
else else
{ {
@ -1481,18 +1487,12 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
//drawRc.bottom *= vScale; //drawRc.bottom *= vScale;
//drawRc.left *= hScale; //drawRc.left *= hScale;
//drawRc.right *= hScale; //drawRc.right *= hScale;
sourceRc.right -= Renderer::EFBToScaledX(fbStride - fbWidth);
} }
// Tell the OSD Menu about the current internal resolution // Tell the OSD Menu about the current internal resolution
OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight(); OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight();
TargetRectangle sourceRc;
sourceRc.left = xfbSource->sourceRc.left;
sourceRc.right = xfbSource->sourceRc.right;
sourceRc.top = xfbSource->sourceRc.top;
sourceRc.bottom = xfbSource->sourceRc.bottom;
sourceRc.right -= Renderer::EFBToScaledX(fbStride - fbWidth);
BlitScreen(sourceRc, drawRc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight); BlitScreen(sourceRc, drawRc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight);
} }
} }

View File

@ -269,7 +269,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
isIntensity, isIntensity,
dstFormat, dstFormat,
scaleByHalf, scaleByHalf,
srcRect); srcRect,
copyMipMapStrideChannels * 32);
u8* dst = Memory::GetPointer(dstAddr); u8* dst = Memory::GetPointer(dstAddr);
u64 const new_hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples); u64 const new_hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);

View File

@ -213,12 +213,12 @@ void Shutdown()
s_texConvFrameBuffer[1] = 0; s_texConvFrameBuffer[1] = 0;
} }
// dst_line_size, writeStride in bytes
static void EncodeToRamUsingShader(GLuint srcTexture, static void EncodeToRamUsingShader(GLuint srcTexture,
u8* destAddr, int dstWidth, int dstHeight, int readStride, u8* destAddr, u32 dst_line_size, u32 dstHeight,
bool linearFilter) u32 writeStride, bool linearFilter)
{ {
// switch to texture converter frame buffer // switch to texture converter frame buffer
// attach render buffer as color destination // attach render buffer as color destination
FramebufferManager::SetFramebuffer(s_texConvFrameBuffer[0]); FramebufferManager::SetFramebuffer(s_texConvFrameBuffer[0]);
@ -234,19 +234,13 @@ static void EncodeToRamUsingShader(GLuint srcTexture,
else else
g_sampler_cache->BindNearestSampler(9); g_sampler_cache->BindNearestSampler(9);
glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight); glViewport(0, 0, (GLsizei)(dst_line_size / 4), (GLsizei)dstHeight);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// .. and then read back the results. int dstSize = dst_line_size * dstHeight;
// TODO: make this less slow.
int writeStride = bpmem.copyMipMapStrideChannels * 32; if ((writeStride != dst_line_size) && (dstHeight > 1))
int dstSize = dstWidth*dstHeight*4;
int readHeight = readStride / dstWidth / 4; // 4 bytes per pixel
int readLoops = dstHeight / readHeight;
if (writeStride != readStride && readLoops > 1)
{ {
// writing to a texture of a different size // writing to a texture of a different size
// also copy more then one block line, so the different strides matters // also copy more then one block line, so the different strides matters
@ -255,13 +249,13 @@ static void EncodeToRamUsingShader(GLuint srcTexture,
// CPU overhead because of the pbo // CPU overhead because of the pbo
glBindBuffer(GL_PIXEL_PACK_BUFFER, s_PBO); glBindBuffer(GL_PIXEL_PACK_BUFFER, s_PBO);
glBufferData(GL_PIXEL_PACK_BUFFER, dstSize, nullptr, GL_STREAM_READ); glBufferData(GL_PIXEL_PACK_BUFFER, dstSize, nullptr, GL_STREAM_READ);
glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, nullptr); glReadPixels(0, 0, (GLsizei)(dst_line_size / 4), (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
u8* pbo = (u8*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, dstSize, GL_MAP_READ_BIT); u8* pbo = (u8*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, dstSize, GL_MAP_READ_BIT);
for (int i = 0; i < readLoops; i++) for (size_t i = 0; i < dstHeight; ++i)
{ {
memcpy(destAddr, pbo, readStride); memcpy(destAddr, pbo, dst_line_size);
pbo += readStride; pbo += dst_line_size;
destAddr += writeStride; destAddr += writeStride;
} }
@ -270,11 +264,11 @@ static void EncodeToRamUsingShader(GLuint srcTexture,
} }
else else
{ {
glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr); glReadPixels(0, 0, (GLsizei)(dst_line_size / 4), (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
} }
} }
int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source, u32 writeStride)
{ {
u32 format = copyfmt; u32 format = copyfmt;
@ -323,13 +317,13 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
cacheLinesPerRow = numBlocksX; cacheLinesPerRow = numBlocksX;
EncodeToRamUsingShader(source_texture, EncodeToRamUsingShader(source_texture,
dest_ptr, cacheLinesPerRow * 8, numBlocksY, cacheLinesPerRow * 32, dest_ptr, cacheLinesPerRow * 32, numBlocksY,
bScaleByHalf > 0 && !bFromZBuffer); writeStride, bScaleByHalf > 0 && !bFromZBuffer);
return size_in_bytes; // TODO: D3D11 is calculating this value differently! return size_in_bytes; // TODO: D3D11 is calculating this value differently!
} }
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight) void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight)
{ {
g_renderer->ResetAPIState(); g_renderer->ResetAPIState();
@ -341,7 +335,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
// We enable linear filtering, because the GameCube does filtering in the vertical direction when // We enable linear filtering, because the GameCube does filtering in the vertical direction when
// yscale is enabled. // yscale is enabled.
// Otherwise we get jaggies when a game uses yscaling (most PAL games) // Otherwise we get jaggies when a game uses yscaling (most PAL games)
EncodeToRamUsingShader(srcTexture, destAddr, dstWidth / 2, dstHeight, dstWidth*dstHeight*2, true); EncodeToRamUsingShader(srcTexture, destAddr, dstWidth * 2, dstHeight, dstStride, true);
FramebufferManager::SetFramebuffer(0); FramebufferManager::SetFramebuffer(0);
TextureCache::DisableStage(0); TextureCache::DisableStage(0);
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();

View File

@ -19,12 +19,12 @@ void Init();
void Shutdown(); void Shutdown();
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight); u8* destAddr, u32 dstWidth, u32 dstStride, u32 dstHeight);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
// returns size of the encoded data (in bytes) // returns size of the encoded data (in bytes)
int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source, u32 writeStride);
} }

View File

@ -251,9 +251,10 @@ static void BPWritten(const BPCmd& bp)
height = MAX_XFB_HEIGHT; height = MAX_XFB_HEIGHT;
} }
u32 width = bpmem.copyMipMapStrideChannels << 4; u32 stride = bpmem.copyMipMapStrideChannels << 5;
WARN_LOG(VIDEO, "RenderToXFB: destAddr: %08x | srcRect {%d %d %d %d} | fbWidth: %u | fbStride: %u | fbHeight: %u",
Renderer::RenderToXFB(destAddr, srcRect, width, height, s_gammaLUT[PE_copy.gamma]); destAddr, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, bpmem.copyTexSrcWH.x + 1, stride, height);
Renderer::RenderToXFB(destAddr, srcRect, stride, height, s_gammaLUT[PE_copy.gamma]);
} }
// Clear the rectangular region after copying it. // Clear the rectangular region after copying it.

View File

@ -115,17 +115,17 @@ const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbA
return &m_overlappingXFBArray[0]; return &m_overlappingXFBArray[0];
} }
void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)
{ {
if (g_ActiveConfig.bUseRealXFB) if (g_ActiveConfig.bUseRealXFB)
g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma); g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma);
else else
CopyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma); CopyToVirtualXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma);
} }
void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)
{ {
VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, fbWidth, fbHeight); VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, sourceRc.GetWidth(), fbHeight);
if (m_virtualXFBList.end() == vxfb) if (m_virtualXFBList.end() == vxfb)
{ {
@ -165,7 +165,7 @@ void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHe
} }
vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr; vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr;
vxfb->xfbSource->srcWidth = vxfb->xfbWidth = fbWidth; vxfb->xfbSource->srcWidth = vxfb->xfbWidth = sourceRc.GetWidth();
vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight; vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight;
vxfb->xfbSource->sourceRc = g_renderer->ConvertEFBRectangle(sourceRc); vxfb->xfbSource->sourceRc = g_renderer->ConvertEFBRectangle(sourceRc);

View File

@ -45,7 +45,7 @@ public:
FramebufferManagerBase(); FramebufferManagerBase();
virtual ~FramebufferManagerBase(); virtual ~FramebufferManagerBase();
static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma); static void CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma);
static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCount); static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCount);
static void SetLastXfbWidth(unsigned int width) { s_last_xfb_width = width; } static void SetLastXfbWidth(unsigned int width) { s_last_xfb_width = width; }
@ -87,7 +87,7 @@ private:
static void ReplaceVirtualXFB(); static void ReplaceVirtualXFB();
// TODO: merge these virtual funcs, they are nearly all the same // TODO: merge these virtual funcs, they are nearly all the same
virtual void CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma = 1.0f) = 0; virtual void CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma = 1.0f) = 0;
static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma = 1.0f); static void CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma = 1.0f);
static const XFBSourceBase* const* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCount); static const XFBSourceBase* const* GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCount);

View File

@ -112,22 +112,22 @@ Renderer::~Renderer()
#endif #endif
} }
void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidth, u32 fbHeight, float Gamma) void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStride, u32 fbHeight, float Gamma)
{ {
CheckFifoRecording(); CheckFifoRecording();
if (!fbWidth || !fbHeight) if (!fbStride || !fbHeight)
return; return;
XFBWrited = true; XFBWrited = true;
if (g_ActiveConfig.bUseXFB) if (g_ActiveConfig.bUseXFB)
{ {
FramebufferManagerBase::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc, Gamma); FramebufferManagerBase::CopyToXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma);
} }
else else
{ {
Swap(xfbAddr, fbWidth, fbWidth, fbHeight, sourceRc, Gamma); Swap(xfbAddr, sourceRc.GetWidth(), fbStride, fbHeight, sourceRc, Gamma);
} }
} }

View File

@ -109,7 +109,7 @@ public:
virtual void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) = 0; virtual void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) = 0;
virtual void ReinterpretPixelData(unsigned int convtype) = 0; virtual void ReinterpretPixelData(unsigned int convtype) = 0;
static void RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidth, u32 fbHeight, float Gamma = 1.0f); static void RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStride, u32 fbHeight, float Gamma = 1.0f);
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) = 0; virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) = 0;
virtual void PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data); virtual void PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data);

View File

@ -19,9 +19,10 @@ enum
EFB_HEIGHT = 528, EFB_HEIGHT = 528,
}; };
// XFB width is decided by EFB copy operation. The VI can do horizontal // Max XFB width is 720. You can only copy out 640 wide areas of efb to XFB
// scaling (TODO: emulate). // so you need multiple copies to do the full width.
const u32 MAX_XFB_WIDTH = EFB_WIDTH; // The VI can do horizontal scaling (TODO: emulate).
const u32 MAX_XFB_WIDTH = 720;
// Although EFB height is 528, 574-line XFB's can be created either with // Although EFB height is 528, 574-line XFB's can be created either with
// vertical scaling by the EFB copy operation or copying to multiple XFB's // vertical scaling by the EFB copy operation or copying to multiple XFB's