after a good commit lets make some experiments:

implemented fixed efb scale to improve alignment and discard some error caused by incorrect scale.
make both plugins work similar. this must improve opengl image quality a lot.
also implemented dynamic resizing in opengl, this way the resolution math the windows resolution on resize.
this is highly experimental so please test a lot.
implemented shader dumping on error thinking  in future experiments with shaders.
enjoy :)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5458 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2010-05-19 03:15:36 +00:00
parent 7947543d98
commit 2c7a08fc61
9 changed files with 249 additions and 125 deletions

View File

@ -79,6 +79,9 @@ public:
static float GetTargetScaleX();
static float GetTargetScaleY();
static float GetXFBScaleX();
static float GetXFBScaleY();
static TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc);
static u32 AccessEFB(EFBAccessType type, int x, int y);

View File

@ -322,27 +322,28 @@ void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight
it--;
}
float MultiSampleCompensation = 1.0f;
float SuperSampleCompensation = 1.0f;
float scaleX = Renderer::GetXFBScaleX();
float scaleY = Renderer::GetXFBScaleY();
if(g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.iMultisampleMode < 4)
{
switch (g_ActiveConfig.iMultisampleMode)
{
case 1:
MultiSampleCompensation = 2.0f/3.0f;
break;
case 2:
MultiSampleCompensation = 0.5f;
SuperSampleCompensation = 0.5f;
break;
case 3:
MultiSampleCompensation = 1.0f/3.0f;
SuperSampleCompensation = 1.0f/3.0f;
break;
default:
break;
};
}
float scaleX = Renderer::GetTargetScaleX() * MultiSampleCompensation ;
float scaleY = Renderer::GetTargetScaleY() * MultiSampleCompensation;
scaleX *= SuperSampleCompensation ;
scaleY *= SuperSampleCompensation;
TargetRectangle targetSource,efbSource;
efbSource = Renderer::ConvertEFBRectangle(sourceRc);
targetSource.top = (sourceRc.top *scaleY);

View File

@ -397,6 +397,10 @@ bool PixelShaderCache::SetShader(bool dstAlpha)
if (g_ActiveConfig.bShowShaderErrors)
{
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code);
}
return false;
}

View File

@ -69,6 +69,9 @@ static int s_XFB_height;
static float xScale;
static float yScale;
static int EFBxScale;
static int EFByScale;
static int s_recordWidth;
static int s_recordHeight;
@ -303,28 +306,17 @@ bool Renderer::Init()
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
}
s_target_width = EFB_WIDTH * xScale;
s_target_height = EFB_HEIGHT * yScale;
s_LastAA = (g_ActiveConfig.iMultisampleMode > 3)?0:g_ActiveConfig.iMultisampleMode;
float SupersampleCoeficient = 1.0f;
switch (s_LastAA)
{
case 1:
s_target_width = (s_target_width * 3) / 2;
s_target_height = (s_target_height * 3) / 2;
SupersampleCoeficient = 3.0f/2.0f;
break;
case 2:
s_target_width *= 2;
s_target_height *= 2;
SupersampleCoeficient = 2.0f;
break;
case 3:
s_target_width *= 3;
s_target_height *= 3;
SupersampleCoeficient = 3.0f;
break;
default:
@ -334,6 +326,12 @@ bool Renderer::Init()
xScale *= SupersampleCoeficient;
yScale *= SupersampleCoeficient;
EFBxScale = ceilf(xScale);
EFByScale = ceilf(yScale);
s_target_width = EFB_WIDTH * EFBxScale;
s_target_height = EFB_HEIGHT * EFByScale;
s_Fulltarget_width = s_target_width;
s_Fulltarget_height = s_target_height;
@ -393,8 +391,12 @@ int Renderer::GetTargetWidth() { return s_target_width; }
int Renderer::GetTargetHeight() { return s_target_height; }
int Renderer::GetFullTargetWidth() { return s_Fulltarget_width; }
int Renderer::GetFullTargetHeight() { return s_Fulltarget_height; }
float Renderer::GetTargetScaleX() { return xScale; }
float Renderer::GetTargetScaleY() { return yScale; }
float Renderer::GetTargetScaleX() { return EFBxScale; }
float Renderer::GetTargetScaleY() { return EFByScale; }
float Renderer::GetXFBScaleX() { return xScale; }
float Renderer::GetXFBScaleY() { return yScale; }
int Renderer::GetFrameBufferWidth()
{
@ -507,10 +509,10 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
TargetRectangle result;
result.left = (int)(rc.left * xScale) + Xstride;
result.top = (int)(rc.top * yScale) + Ystride;
result.right = (int)(rc.right * xScale) + Xstride;
result.bottom = (int)(rc.bottom * yScale) + Ystride;
result.left = (int)(rc.left * EFBxScale) + Xstride;
result.top = (int)(rc.top * EFByScale) + Ystride;
result.right = (int)(rc.right * EFBxScale) + Xstride;
result.bottom = (int)(rc.bottom * EFByScale) + Ystride;
return result;
}
@ -573,12 +575,13 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect
if(!fbWidth || !fbHeight)
return;
VideoFifo_CheckEFBAccess();
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
FBManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
XFBWrited = true;
XFBWrited = true;
// XXX: Without the VI, how would we know what kind of field this is? So
// just use progressive.
if (!g_ActiveConfig.bUseXFB)
{
// XXX: Without the VI, how would we know what kind of field this is? So
// just use progressive.
Renderer::Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight);
Common::AtomicStoreRelease(s_swapRequested, FALSE);
}
@ -597,10 +600,10 @@ bool Renderer::SetScissorRect()
int Xstride = (s_Fulltarget_width - s_target_width) / 2;
int Ystride = (s_Fulltarget_height - s_target_height) / 2;
rc.left = (int)(rc.left * xScale);
rc.top = (int)(rc.top * yScale);
rc.right = (int)(rc.right * xScale);
rc.bottom = (int)(rc.bottom * yScale);
rc.left = (int)(rc.left * EFBxScale);
rc.top = (int)(rc.top * EFByScale);
rc.right = (int)(rc.right * EFBxScale);
rc.bottom = (int)(rc.bottom * EFByScale);
if (rc.left < 0) rc.left = 0;
if (rc.right < 0) rc.right = 0;
@ -1006,9 +1009,9 @@ void Renderer::SetBlendMode(bool forceUpdate)
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{
if (g_bSkipCurrentFrame || !XFBWrited || !fbWidth || !fbHeight)
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.bUseRealXFB) || !fbWidth || !fbHeight)
{
g_VideoInitialize.pCopiedToXFB(false);
g_VideoInitialize.pCopiedToXFB(false);
return;
}
// this function is called after the XFB field is changed, not after
@ -1238,29 +1241,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
}
s_target_width = EFB_WIDTH * xScale;
s_target_height = EFB_HEIGHT * yScale;
}
s_LastAA = (g_ActiveConfig.iMultisampleMode > 3)?0:g_ActiveConfig.iMultisampleMode;
float SupersampleCoeficient = 1.0f;
float SupersampleCoeficient = 1.0f;
switch (s_LastAA)
{
case 1:
s_target_width = (s_target_width * 3) / 2;
s_target_height = (s_target_height * 3) / 2;
SupersampleCoeficient = 3.0f/2.0f;
break;
case 2:
s_target_width *= 2;
s_target_height *= 2;
SupersampleCoeficient = 2.0f;
SupersampleCoeficient = 2.0f;
break;
case 3:
s_target_width *= 3;
s_target_height *= 3;
SupersampleCoeficient = 3.0f;
break;
default:
@ -1269,6 +1260,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
xScale *= SupersampleCoeficient;
yScale *= SupersampleCoeficient;
EFBxScale = ceilf(xScale);
EFByScale = ceilf(yScale);
s_target_width = EFB_WIDTH * ceilf(EFBxScale);
s_target_height = EFB_HEIGHT * ceilf(EFByScale);
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
if(WindowResized)

View File

@ -361,26 +361,27 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
int tex_w = (abs(source_rect.GetWidth()) >> bScaleByHalf);
int tex_h = (abs(source_rect.GetHeight()) >> bScaleByHalf);
//compensate the texture grow if supersampling is enabled to conserve memory usage
float MultiSampleCompensation = 1.0f;
float SuperSampleCompensation = 1.0f;
float xScale = Renderer::GetTargetScaleX();
float yScale = Renderer::GetTargetScaleY();
if(g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.iMultisampleMode < 4)
{
switch (g_ActiveConfig.iMultisampleMode)
{
case 1:
MultiSampleCompensation = 2.0f/3.0f;
break;
case 2:
MultiSampleCompensation = 0.5f;
SuperSampleCompensation = 0.5f;
break;
case 3:
MultiSampleCompensation = 1.0f/3.0f;
SuperSampleCompensation = 1.0f/3.0f;
break;
default:
break;
};
}
int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleX() * MultiSampleCompensation * tex_w)):tex_w;
int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleY() * MultiSampleCompensation * tex_h)):tex_h;
int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(xScale * SuperSampleCompensation * tex_w)):tex_w;
int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(yScale * SuperSampleCompensation * tex_h)):tex_h;
TexCache::iterator iter;
LPDIRECT3DTEXTURE9 tex = NULL;

View File

@ -268,9 +268,9 @@ TargetRectangle FramebufferManager::ConvertEFBRectangle(const EFBRectangle& rc)
float XScale = Renderer::GetTargetScaleX();
float YScale = Renderer::GetTargetScaleY();
result.left = rc.left * XScale;
result.top = Renderer::GetTargetHeight() - (rc.top * YScale);
result.top = ((EFB_HEIGHT - rc.top) * YScale);
result.right = rc.right * XScale ;
result.bottom = Renderer::GetTargetHeight() - (rc.bottom * YScale);
result.bottom = ((EFB_HEIGHT - rc.bottom) * YScale);
return result;
}
@ -411,6 +411,10 @@ void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight
newVirt.xfbWidth = fbWidth;
newVirt.xfbHeight = fbHeight;
newVirt.xfbSource.srcAddr = xfbAddr;
newVirt.xfbSource.srcWidth = fbWidth;
newVirt.xfbSource.srcHeight = fbHeight;
newVirt.xfbSource.texture = xfbTexture;
newVirt.xfbSource.texWidth = m_targetWidth;
newVirt.xfbSource.texHeight = m_targetHeight;

View File

@ -221,6 +221,10 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
// printf("Compiling pixel shader. size = %i\n", strlen(code));
if (!code || !CompilePixelShader(newentry.shader, code)) {
ERROR_LOG(VIDEO, "failed to create pixel shader");
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++);
SaveData(szTemp, code);
return NULL;
}

View File

@ -114,6 +114,18 @@ static int m_FrameBufferHeight;
static GLuint s_tempScreenshotFramebuffer = 0;
static int s_XFB_width;
static int s_XFB_height;
static float xScale;
static float yScale;
static int EFBxScale;
static int EFByScale;
static int s_recordWidth;
static int s_recordHeight;
static bool s_skipSwap = false;
#ifndef _WIN32
@ -156,12 +168,33 @@ static const GLenum glDestFactors[8] = {
};
static const GLenum glCmpFuncs[8] = {
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
GL_NEVER,
GL_LESS,
GL_EQUAL,
GL_LEQUAL,
GL_GREATER,
GL_NOTEQUAL,
GL_GEQUAL,
GL_ALWAYS
};
static const GLenum glLogicOpCodes[16] = {
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR,
GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET
GL_CLEAR,
GL_AND,
GL_AND_REVERSE,
GL_COPY,
GL_AND_INVERTED,
GL_NOOP,
GL_XOR,
GL_OR,
GL_NOR,
GL_EQUIV,
GL_INVERT,
GL_OR_REVERSE,
GL_COPY_INVERTED,
GL_OR_INVERTED,
GL_NAND,
GL_SET
};
void SetDefaultRectTexParams()
@ -203,15 +236,15 @@ bool Renderer::Init()
s_MSAACoverageSamples = 0;
switch (g_ActiveConfig.iMultisampleMode)
{
case MULTISAMPLE_OFF: s_MSAASamples = 1; break;
case MULTISAMPLE_2X: s_MSAASamples = 2; break;
case MULTISAMPLE_4X: s_MSAASamples = 4; break;
case MULTISAMPLE_8X: s_MSAASamples = 8; break;
case MULTISAMPLE_CSAA_8X: s_MSAASamples = 4; s_MSAACoverageSamples = 8; break;
case MULTISAMPLE_CSAA_8XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 8; break;
case MULTISAMPLE_CSAA_16X: s_MSAASamples = 4; s_MSAACoverageSamples = 16; break;
case MULTISAMPLE_CSAA_16XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 16; break;
default:
case MULTISAMPLE_OFF: s_MSAASamples = 1; break;
case MULTISAMPLE_2X: s_MSAASamples = 2; break;
case MULTISAMPLE_4X: s_MSAASamples = 4; break;
case MULTISAMPLE_8X: s_MSAASamples = 8; break;
case MULTISAMPLE_CSAA_8X: s_MSAASamples = 4; s_MSAACoverageSamples = 8; break;
case MULTISAMPLE_CSAA_8XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 8; break;
case MULTISAMPLE_CSAA_16X: s_MSAASamples = 4; s_MSAACoverageSamples = 16; break;
case MULTISAMPLE_CSAA_16XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 16; break;
default:
s_MSAASamples = 1;
}
GLint numvertexattribs = 0;
@ -307,31 +340,40 @@ bool Renderer::Init()
// Decide frambuffer size
int W = (int)OpenGL_GetBackbufferWidth(), H = (int)OpenGL_GetBackbufferHeight();
s_XFB_width = MAX_XFB_WIDTH;
s_XFB_height = MAX_XFB_HEIGHT;
TargetRectangle dst_rect;
ComputeDrawRectangle(W, H, false, &dst_rect);
xScale = 1.0f;
yScale = 1.0f;
if(!g_ActiveConfig.bNativeResolution)
{
if (g_ActiveConfig.b2xResolution)
{
xScale = 2.0f;
yScale = 2.0f;
}
else
{
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
}
}
if (g_ActiveConfig.b2xResolution)
{
m_FrameBufferWidth = (2 * EFB_HEIGHT >= W) ? 2 * EFB_HEIGHT : W;
m_FrameBufferHeight = (2 * EFB_HEIGHT >= H) ? 2 * EFB_HEIGHT : H;
}
else
{
// The size of the framebuffer targets should really NOT be the size of the OpenGL viewport.
// The EFB is larger than 640x480 - in fact, it's 640x528, give or take a couple of lines.
m_FrameBufferWidth = (EFB_WIDTH >= W) ? EFB_WIDTH : W;
m_FrameBufferHeight = (480 >= H) ? 480 : H;
EFBxScale = ceilf(xScale);
EFByScale = ceilf(yScale);
// Adjust all heights with this ratio, the resulting height will be the same as H or EFB_HEIGHT. I.e.
// 768 (-1) for 1024x768 etc.
m_FrameBufferHeight *= (float)EFB_HEIGHT / 480.0;
// Ensure a minimum target size so that the native res target always fits
if (m_FrameBufferWidth < EFB_WIDTH) m_FrameBufferWidth = EFB_WIDTH;
if (m_FrameBufferHeight < EFB_HEIGHT) m_FrameBufferHeight = EFB_HEIGHT;
}
m_FrameBufferWidth = EFB_WIDTH * EFBxScale;
m_FrameBufferHeight = EFB_HEIGHT * EFByScale;
// Save the custom resolution
m_CustomWidth = (int)OpenGL_GetBackbufferWidth();
m_CustomHeight = (int)OpenGL_GetBackbufferHeight();
m_CustomWidth = W;
m_CustomHeight = H;
// Because of the fixed framebuffer size we need to disable the resolution options while running
g_Config.bRunning = true;
@ -432,8 +474,8 @@ void Renderer::Shutdown(void)
cgDestroyContext(g_cgcontext);
g_cgcontext = 0;
}
glDeleteFramebuffersEXT(1, &s_tempScreenshotFramebuffer);
if(s_tempScreenshotFramebuffer)
glDeleteFramebuffersEXT(1, &s_tempScreenshotFramebuffer);
s_tempScreenshotFramebuffer = 0;
g_framebufferManager.Shutdown();
@ -486,29 +528,33 @@ int Renderer::GetCustomHeight()
// Return the rendering target width and height
int Renderer::GetTargetWidth()
{
return (g_ActiveConfig.bNativeResolution || g_ActiveConfig.b2xResolution) ?
(g_ActiveConfig.bNativeResolution ? EFB_WIDTH : EFB_WIDTH * 2) : m_CustomWidth;
return m_FrameBufferWidth;
}
int Renderer::GetTargetHeight()
{
return (g_ActiveConfig.bNativeResolution || g_ActiveConfig.b2xResolution) ?
(g_ActiveConfig.bNativeResolution ? EFB_HEIGHT : EFB_HEIGHT * 2) : m_CustomHeight;
return m_FrameBufferHeight;
}
float Renderer::GetTargetScaleX()
{
return (float)GetTargetWidth() / (float)EFB_WIDTH;
return EFBxScale;
}
float Renderer::GetTargetScaleY()
{
return (float)GetTargetHeight() / (float)EFB_HEIGHT;
return EFByScale;
}
float Renderer::GetXFBScaleX() { return xScale; }
float Renderer::GetXFBScaleY() { return yScale; }
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
{
return g_framebufferManager.ConvertEFBRectangle(rc);
}
void Renderer::ResetAPIState()
{
// Gets us to a reasonably sane state where it's possible to do things like
@ -693,25 +739,20 @@ bool Renderer::SetScissorRect()
{
int xoff = bpmem.scissorOffset.x * 2 - 342;
int yoff = bpmem.scissorOffset.y * 2 - 342;
float MValueX = GetTargetScaleX();
float MValueY = GetTargetScaleY();
float rc_left = (float)bpmem.scissorTL.x - xoff - 342; // left = 0
rc_left *= MValueX;
if (rc_left < 0) rc_left = 0;
float rc_left = (float)bpmem.scissorTL.x - xoff - 342; // left = 0
if (rc_left < 0) rc_left = 0;
float rc_top = (float)bpmem.scissorTL.y - yoff - 342; // right = 0
rc_top *= MValueY;
if (rc_top < 0) rc_top = 0;
if (rc_top < 0) rc_top = 0;
float rc_right = (float)bpmem.scissorBR.x - xoff - 341; // right = 640
rc_right *= MValueX;
if (rc_right > EFB_WIDTH * MValueX) rc_right = EFB_WIDTH * MValueX;
if (rc_right > EFB_WIDTH) rc_right = EFB_WIDTH;
float rc_bottom = (float)bpmem.scissorBR.y - yoff - 341; // bottom = 480
rc_bottom *= MValueY;
if (rc_bottom > EFB_HEIGHT * MValueY) rc_bottom = EFB_HEIGHT * MValueY;
if (rc_bottom > EFB_HEIGHT) rc_bottom = EFB_HEIGHT;
if(rc_left > rc_right)
if(rc_left > rc_right)
{
int temp = rc_right;
rc_right = rc_left;
@ -724,18 +765,27 @@ bool Renderer::SetScissorRect()
rc_top = temp;
}
// Check that the coordinates are good
if (rc_right >= rc_left && rc_bottom >= rc_top)
{
glScissor(
(int)rc_left, // x = 0 for example
Renderer::GetTargetHeight() - (int)(rc_bottom), // y = 0 for example
(int)(rc_right - rc_left), // width = 640 for example
(int)(rc_bottom - rc_top) // height = 480 for example
glScissor(
(int)(rc_left * EFBxScale), // x = 0 for example
(int)((EFB_HEIGHT - rc_bottom) * EFByScale), // y = 0 for example
(int)((rc_right - rc_left)* EFBxScale), // width = 640 for example
(int)((rc_bottom - rc_top) * EFByScale) // height = 480 for example
);
return true;
}
else
{
glScissor(
0,
0,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight()
);
}
return false;
}
@ -770,6 +820,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glClear(bits);
SetScissorRect();
}
static bool XFBWrited = false;
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc)
@ -808,13 +859,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
return;
}
OpenGL_Update(); // just updates the render window position and the backbuffer size
DVSTARTPROFILE();
ResetAPIState();
TargetRectangle back_rc;
ComputeDrawRectangle(OpenGL_GetBackbufferWidth(), OpenGL_GetBackbufferHeight(), true, &back_rc);
ComputeDrawRectangle(m_CustomWidth, m_CustomHeight, true, &back_rc);
// Make sure that the wireframe setting doesn't screw up the screen copy.
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@ -1055,6 +1105,69 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
}
#endif
OpenGL_Update(); // just updates the render window position and the backbuffer size
bool xfbchanged = false;
if(s_XFB_width != fbWidth || s_XFB_height != fbHeight)
{
xfbchanged = true;
s_XFB_width = fbWidth;
s_XFB_height = fbHeight;
if(s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH;
if(s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH;
if(s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT;
if(s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT;
}
bool WindowResized = false;
int W = (int)OpenGL_GetBackbufferWidth(), H = (int)OpenGL_GetBackbufferHeight();
if (W != m_CustomWidth || H != m_CustomHeight)
{
WindowResized = true;
m_CustomWidth = W;
m_CustomHeight = H;
}
if( xfbchanged || WindowResized)
{
TargetRectangle dst_rect;
ComputeDrawRectangle(m_CustomWidth, m_CustomHeight, false, &dst_rect);
xScale = 1.0f;
yScale = 1.0f;
if(!g_ActiveConfig.bNativeResolution)
{
if (g_ActiveConfig.b2xResolution)
{
xScale = 2.0f;
yScale = 2.0f;
}
else
{
xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width;
yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height;
}
}
EFBxScale = ceilf(xScale);
EFByScale = ceilf(yScale);
int m_newFrameBufferWidth = EFB_WIDTH * EFBxScale;
int m_newFrameBufferHeight = EFB_HEIGHT * EFByScale;
if(m_newFrameBufferWidth != m_FrameBufferWidth || m_newFrameBufferHeight != m_FrameBufferHeight )
{
m_FrameBufferWidth = m_newFrameBufferWidth;
m_FrameBufferHeight = m_newFrameBufferHeight;
g_framebufferManager.Shutdown();
g_framebufferManager.Init(m_FrameBufferWidth, m_FrameBufferHeight, s_MSAASamples, s_MSAACoverageSamples);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
}
// Place messages on the picture, then copy it to the screen
// ---------------------------------------------------------------------
// Count FPS.
@ -1432,15 +1545,12 @@ void UpdateViewport()
// [5] = 16777215 * farz
int scissorXOff = bpmem.scissorOffset.x * 2; // 342
int scissorYOff = bpmem.scissorOffset.y * 2; // 342
float MValueX = Renderer::GetTargetScaleX();
float MValueY = Renderer::GetTargetScaleY();
// Stretch picture with increased internal resolution
int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - scissorXOff) * MValueX);
int GLy = (int)ceil(Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4] - xfregs.rawViewport[1] - scissorYOff)) * MValueY);
int GLWidth = (int)ceil((int)(2 * xfregs.rawViewport[0]) * MValueX);
int GLHeight = (int)ceil((int)(-2 * xfregs.rawViewport[1]) * MValueY);
int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - scissorXOff) * EFBxScale);
int GLy = (int)ceil((float)((int)(EFB_HEIGHT - xfregs.rawViewport[4] + xfregs.rawViewport[1] + scissorYOff)) * EFByScale);
int GLWidth = (int)ceil((float)(2 * xfregs.rawViewport[0]) * EFBxScale);
int GLHeight = (int)ceil((float)(-2 * xfregs.rawViewport[1]) * EFByScale);
double GLNear = (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f;
double GLFar = xfregs.rawViewport[5] / 16777216.0f;
if(GLWidth < 0)

View File

@ -294,7 +294,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
float MValueX = Renderer::GetTargetScaleX();
float MValueY = Renderer::GetTargetScaleY();
float top = Renderer::GetTargetHeight() - (source.top + expandedHeight) * MValueY ;
float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ;
float sampleStride = bScaleByHalf?2.0f:1.0f;