diff --git a/src/OpenGL.cpp b/src/OpenGL.cpp index dbc7c18c..ddb5d846 100644 --- a/src/OpenGL.cpp +++ b/src/OpenGL.cpp @@ -193,6 +193,7 @@ void OGLVideo::updateScale() void OGLVideo::_setBufferSize() { + m_bAdjustScreen = false; if (config.frameBufferEmulation.enable) { switch (config.frameBufferEmulation.aspect) { case Config::aStretch: // stretch @@ -223,7 +224,16 @@ void OGLVideo::_setBufferSize() m_height = m_screenHeight; } break; - default: + case Config::aAdjust: // adjust + m_width = m_screenWidth; + m_height = m_screenHeight; + if (m_screenWidth * 3 / 4 > m_screenHeight) { + f32 width43 = m_screenHeight * 4.0f / 3.0f; + m_adjustScale = width43 / m_screenWidth; + m_bAdjustScreen = true; + } + break; + default: assert(false && "Unknown aspect ratio"); m_width = m_screenWidth; m_height = m_screenHeight; @@ -438,6 +448,14 @@ void OGLRender::_updateCullFace() const glDisable( GL_CULL_FACE ); } +inline +float _adjustViewportX(f32 _X0) +{ + const float halfX = gDP.colorImage.width / 2.0f; + const float halfVP = gSP.viewport.width / 2.0f; + return (_X0 + halfVP - halfX) * video().getAdjustScale() + halfX - halfVP; +} + void OGLRender::_updateViewport() const { OGLVideo & ogl = video(); @@ -445,14 +463,20 @@ void OGLRender::_updateViewport() const if (pCurrentBuffer == NULL) { const f32 scaleX = ogl.getScaleX(); const f32 scaleY = ogl.getScaleY(); - const GLint X = gSP.viewport.vscale[0] < 0 ? (GLint)((gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) * scaleX) : (GLint)(gSP.viewport.x * scaleX); + float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x; + if (ogl.isAdjustScreen() && gSP.viewport.width < gDP.colorImage.width && gDP.colorImage.width > VI.width * 98 / 100) + Xf = _adjustViewportX(Xf); + const GLint X = (GLint)(Xf * scaleX); const GLint Y = gSP.viewport.vscale[1] < 0 ? (GLint)((gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) * scaleY) : (GLint)((VI.height - (gSP.viewport.y + gSP.viewport.height)) * scaleY); - glViewport( X, Y + ogl.getHeightOffset(), + glViewport(X, Y + ogl.getHeightOffset(), max((GLint)(gSP.viewport.width * scaleX), 0), max((GLint)(gSP.viewport.height * scaleY), 0)); } else { const f32 scaleX = pCurrentBuffer->m_scaleX; const f32 scaleY = pCurrentBuffer->m_scaleY; - const GLint X = gSP.viewport.vscale[0] < 0 ? (GLint)((gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) * scaleX) : (GLint)(gSP.viewport.x * scaleX); + float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x; + if (ogl.isAdjustScreen() && gSP.viewport.width < gDP.colorImage.width && gDP.colorImage.width > VI.width * 98 / 100) + Xf = _adjustViewportX(Xf); + const GLint X = (GLint)(Xf * scaleX); const GLint Y = gSP.viewport.vscale[1] < 0 ? (GLint)((gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) * scaleY) : (GLint)((pCurrentBuffer->m_height - (gSP.viewport.y + gSP.viewport.height)) * scaleY); glViewport(X, Y, max((GLint)(gSP.viewport.width * scaleX), 0), max((GLint)(gSP.viewport.height * scaleY), 0)); @@ -460,6 +484,43 @@ void OGLRender::_updateViewport() const gSP.changed &= ~CHANGED_VIEWPORT; } +inline +void _adjustScissorX(f32 & _X0, f32 & _X1, float _scale) +{ + const float halfX = gDP.colorImage.width / 2.0f; + _X0 = (_X0 - halfX) * _scale + halfX; + _X1 = (_X1 - halfX) * _scale + halfX; +} + +void OGLRender::_updateScissor() const +{ + OGLVideo & ogl = video(); + f32 scaleX, scaleY; + u32 heightOffset, screenHeight; + FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent(); + if (pCurrentBuffer == NULL) { + scaleX = ogl.getScaleX(); + scaleY = ogl.getScaleY(); + heightOffset = ogl.getHeightOffset(); + screenHeight = VI.height; + } + else { + scaleX = pCurrentBuffer->m_scaleX; + scaleY = pCurrentBuffer->m_scaleY; + heightOffset = 0; + screenHeight = (pCurrentBuffer->m_height == 0) ? VI.height : pCurrentBuffer->m_height; + } + + float SX0 = gDP.scissor.ulx; + float SX1 = gDP.scissor.lrx; + if (ogl.isAdjustScreen() && gSP.viewport.width < gDP.colorImage.width && gDP.colorImage.width > VI.width * 98 / 100) + _adjustScissorX(SX0, SX1, ogl.getAdjustScale()); + + glScissor((GLint)(SX0 * scaleX), (GLint)((screenHeight - gDP.scissor.lry) * scaleY + heightOffset), + max((GLint)((SX1 - SX0) * scaleX), 0), max((GLint)((gDP.scissor.lry - gDP.scissor.uly) * scaleY), 0)); + gDP.changed &= ~CHANGED_SCISSOR; +} + void OGLRender::_updateDepthUpdate() const { if (gDP.otherMode.depthUpdate != 0) @@ -527,21 +588,8 @@ void OGLRender::_updateStates(RENDER_STATE _renderState) const } } - if (gDP.changed & CHANGED_SCISSOR) { - FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent(); - if (pCurrentBuffer == NULL) { - const f32 scaleX = ogl.getScaleX(); - const f32 scaleY = ogl.getScaleY(); - glScissor((GLint)(gDP.scissor.ulx * scaleX), (GLint)((VI.height - gDP.scissor.lry) * scaleY) + ogl.getHeightOffset(), - max((GLint)((gDP.scissor.lrx - gDP.scissor.ulx) * scaleX), 0), max((GLint)((gDP.scissor.lry - gDP.scissor.uly) * scaleY), 0)); - } else { - const f32 scaleX = pCurrentBuffer->m_scaleX; - const f32 scaleY = pCurrentBuffer->m_scaleY; - glScissor((GLint)(gDP.scissor.ulx * scaleX), (GLint)((pCurrentBuffer->m_height - gDP.scissor.lry) * scaleY), - max((GLint)((gDP.scissor.lrx - gDP.scissor.ulx) * scaleX), 0), max((GLint)((gDP.scissor.lry - gDP.scissor.uly) * scaleY), 0)); - } - gDP.changed &= ~CHANGED_SCISSOR; - } + if (gDP.changed & CHANGED_SCISSOR) + _updateScissor(); if (gSP.changed & CHANGED_VIEWPORT) _updateViewport(); @@ -783,10 +831,17 @@ void OGLRender::drawRect(int _ulx, int _uly, int _lrx, int _lry, float *_pColor) m_rect[3].z = Z; m_rect[3].w = W; + if (ogl.isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100) && (_lrx - _ulx < VI.width * 9 / 10)) { + const float scale = ogl.getAdjustScale(); + for (u32 i = 0; i < 4; ++i) + m_rect[i].x *= scale; + } + if (gDP.otherMode.cycleType == G_CYC_FILL) glVertexAttrib4fv(SC_COLOR, _pColor); else glVertexAttrib4f(SC_COLOR, 0.0f, 0.0f, 0.0f, 0.0f); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); gSP.changed |= CHANGED_GEOMETRYMODE | CHANGED_VIEWPORT; } @@ -1067,6 +1122,12 @@ void OGLRender::drawTexturedRect(const TexturedRectParams & _params) m_rect[2].t1 = texST[1].t1; } + if (ogl.isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100) && (_params.lrx - _params.ulx < VI.width * 9 / 10)) { + const float scale = ogl.getAdjustScale(); + for (u32 i = 0; i < 4; ++i) + m_rect[i].x *= scale; + } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); gSP.changed |= CHANGED_GEOMETRYMODE | CHANGED_VIEWPORT; } diff --git a/src/OpenGL.h b/src/OpenGL.h index 298a38e3..2c4dbf1d 100644 --- a/src/OpenGL.h +++ b/src/OpenGL.h @@ -100,6 +100,7 @@ private: void _setBlendMode() const; void _updateCullFace() const; void _updateViewport() const; + void _updateScissor() const; void _updateDepthUpdate() const; void _updateStates(RENDER_STATE _renderState) const; void _prepareDrawTriangle(bool _dma); @@ -146,12 +147,14 @@ public: void updateScale(); f32 getScaleX() const {return m_scaleX;} f32 getScaleY() const {return m_scaleY;} - u32 getWidth() const {return m_width;} + f32 getAdjustScale() const {return m_adjustScale;} + u32 getWidth() const { return m_width; } u32 getHeight() const {return m_height;} u32 getScreenWidth() const {return m_screenWidth;} u32 getScreenHeight() const {return m_screenHeight;} u32 getHeightOffset() const {return m_heightOffset;} bool isFullscreen() const {return m_bFullscreen;} + bool isAdjustScreen() const {return m_bAdjustScreen;} OGLRender & getRender() {return m_render;} @@ -159,10 +162,10 @@ public: protected: OGLVideo() : - m_bCaptureScreen(false), m_bToggleFullscreen(false), m_bResizeWindow(false), m_bFullscreen(false), + m_bCaptureScreen(false), m_bToggleFullscreen(false), m_bResizeWindow(false), m_bFullscreen(false), m_bAdjustScreen(false), m_width(0), m_height(0), m_heightOffset(0), m_screenWidth(0), m_screenHeight(0), m_resizeWidth(0), m_resizeHeight(0), - m_scaleX(0), m_scaleY(0), m_strScreenDirectory(NULL) + m_scaleX(0), m_scaleY(0), m_adjustScale(0), m_strScreenDirectory(NULL) {} void _setBufferSize(); @@ -171,11 +174,13 @@ protected: bool m_bToggleFullscreen; bool m_bResizeWindow; bool m_bFullscreen; + bool m_bAdjustScreen; u32 m_width, m_height, m_heightOffset; u32 m_screenWidth, m_screenHeight; u32 m_resizeWidth, m_resizeHeight; f32 m_scaleX, m_scaleY; + f32 m_adjustScale; const char * m_strScreenDirectory; diff --git a/src/gSP.cpp b/src/gSP.cpp index ba6a0026..fc9b7719 100644 --- a/src/gSP.cpp +++ b/src/gSP.cpp @@ -554,11 +554,15 @@ void gSPProcessVertex(u32 v) if (gSP.changed & CHANGED_MATRIX) gSPCombineMatrices(); - OGLRender & render = video().getRender(); + OGLVideo & ogl = video(); + OGLRender & render = ogl.getRender(); SPVertex & vtx = render.getVertex(v); float vPos[3] = {(float)vtx.x, (float)vtx.y, (float)vtx.z}; gSPTransformVertex( &vtx.x, gSP.matrix.combined ); + if (ogl.isAdjustScreen() && (gDP.colorImage.width > VI.width * 98 / 100)) + vtx.x *= ogl.getAdjustScale(); + if (gSP.viewport.vscale[0] < 0) vtx.x = -vtx.x;