From 9a8ece04d646dec72a2e3ffa0a2188a5eab3e0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 1 Jun 2025 01:35:05 -0300 Subject: [PATCH] Adjust scissor test to current FBO coordinates. Fixes some clipping bugs when using FBOs withing UI components. --- include/eepp/graphics/framebuffer.hpp | 24 +++++++++++---- .../eepp/graphics/renderer/clippingmask.hpp | 2 ++ src/eepp/graphics/framebuffer.cpp | 18 +++++++++++- src/eepp/graphics/renderer/clippingmask.cpp | 4 +++ .../eterm/terminal/terminaldisplay.hpp | 3 ++ .../src/eterm/terminal/terminaldisplay.cpp | 29 +++++++++++++++---- 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/include/eepp/graphics/framebuffer.hpp b/include/eepp/graphics/framebuffer.hpp index 9a38593a1..d88cdf482 100644 --- a/include/eepp/graphics/framebuffer.hpp +++ b/include/eepp/graphics/framebuffer.hpp @@ -107,20 +107,32 @@ class EE_API FrameBuffer { /** @return If the frame buffer was created */ virtual bool created() const = 0; + void setPosition( Vector2f position ) { mPosition = position; } + + const Vector2f& getPosition() const { return mPosition; } + + void setAdjustCurrentClipping( bool enabled ) { mAdjustCurrentClipping = enabled; } + + bool adjustCurrentClipping() const { return mAdjustCurrentClipping; } + protected: EE::Window::Window* mWindow; + Vector2f mPosition; Sizei mSize; - Uint32 mChannels; + Uint32 mChannels{ 4 }; std::string mName; - String::HashType mId; - bool mHasColorBuffer; - bool mHasDepthBuffer; - bool mHasStencilBuffer; - Texture* mTexture; + String::HashType mId{ 0 }; + bool mHasColorBuffer{ false }; + bool mHasDepthBuffer{ false }; + bool mHasStencilBuffer{ false }; + bool mAdjustCurrentClipping{ true }; + bool mNeedsToRestoreScissorsClipping{ false }; + Texture* mTexture{ nullptr }; ColorAf mClearColor; View mView; float mProjMat[16]; float mModelViewMat[16]; + std::vector mOldScissorsRect; FrameBuffer( EE::Window::Window* window ); diff --git a/include/eepp/graphics/renderer/clippingmask.hpp b/include/eepp/graphics/renderer/clippingmask.hpp index 382971837..38fd8af07 100644 --- a/include/eepp/graphics/renderer/clippingmask.hpp +++ b/include/eepp/graphics/renderer/clippingmask.hpp @@ -17,6 +17,8 @@ class EE_API ClippingMask { /** Disable the Clipping area */ void clipDisable(); + bool isScissorsClipEnabled() const; + /** Clip the area with a plane. */ void clipPlaneEnable( const Int32& x, const Int32& y, const Int32& Width, const Int32& Height ); diff --git a/src/eepp/graphics/framebuffer.cpp b/src/eepp/graphics/framebuffer.cpp index 32a066063..8631539f0 100644 --- a/src/eepp/graphics/framebuffer.cpp +++ b/src/eepp/graphics/framebuffer.cpp @@ -51,7 +51,7 @@ Texture* FrameBuffer::getTexture() const { } void FrameBuffer::setClearColor( const ColorAf& color ) { - mClearColor = color; + mClearColor.assign( color ); } ColorAf FrameBuffer::getClearColor() const { @@ -78,6 +78,17 @@ void FrameBuffer::setBufferView() { GLi->ortho( 0.0f, mSize.getWidth(), 0.f, mSize.getHeight(), -1000.0f, 1000.0f ); GLi->matrixMode( GL_MODELVIEW ); GLi->loadIdentity(); + + auto cm = GLi->getClippingMask(); + if ( mAdjustCurrentClipping && cm->isScissorsClipEnabled() ) { + mNeedsToRestoreScissorsClipping = true; + mOldScissorsRect = cm->getScissorsClipped(); + Rectf currentClip = mOldScissorsRect.back(); + Rectf fboScreenRect( mPosition.floor(), mSize.asFloat() ); + Rectf newClipRect( fboScreenRect.getPosition() - currentClip.getPosition(), + currentClip.getSize() ); + cm->setScissorsClipped( { newClipRect } ); + } } void FrameBuffer::recoverView() { @@ -101,6 +112,11 @@ void FrameBuffer::recoverView() { GLi->matrixMode( GL_MODELVIEW ); GLi->loadIdentity(); GLi->loadMatrixf( mModelViewMat ); + + if ( mNeedsToRestoreScissorsClipping ) { + GLi->getClippingMask()->setScissorsClipped( mOldScissorsRect ); + mNeedsToRestoreScissorsClipping = false; + } } const Int32& FrameBuffer::getWidth() const { diff --git a/src/eepp/graphics/renderer/clippingmask.cpp b/src/eepp/graphics/renderer/clippingmask.cpp index cff67adce..f83e70c9f 100644 --- a/src/eepp/graphics/renderer/clippingmask.cpp +++ b/src/eepp/graphics/renderer/clippingmask.cpp @@ -47,6 +47,10 @@ void ClippingMask::clipDisable() { } } +bool ClippingMask::isScissorsClipEnabled() const { + return !mScissorsClipped.empty(); +} + void ClippingMask::clipPlaneEnable( const Int32& x, const Int32& y, const Int32& Width, const Int32& Height ) { GlobalBatchRenderer::instance()->draw(); diff --git a/src/modules/eterm/include/eterm/terminal/terminaldisplay.hpp b/src/modules/eterm/include/eterm/terminal/terminaldisplay.hpp index 9b2382b2d..0de0e960d 100644 --- a/src/modules/eterm/include/eterm/terminal/terminaldisplay.hpp +++ b/src/modules/eterm/include/eterm/terminal/terminaldisplay.hpp @@ -283,6 +283,7 @@ class TerminalDisplay : public ITerminalDisplay { bool mDirty{ true }; bool mDirtyCursor{ true }; bool mDrawing{ false }; + bool mFullDirty{ false }; Vector2i mCursor; TerminalGlyph mCursorGlyph; bool mUseColorEmoji{ true }; @@ -349,6 +350,8 @@ class TerminalDisplay : public ITerminalDisplay { void drawboxlines( float x, float y, float w, float h, Color fg, ushort bd ); Rectf updateIMELocation(); + + void drawBg( bool toFBO = false ); }; }} // namespace eterm::Terminal diff --git a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp index c8dd6b2f0..798c36954 100644 --- a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp +++ b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp @@ -1081,9 +1081,14 @@ void TerminalDisplay::drawbox( float x, float y, float w, float h, Color fg, Col } void TerminalDisplay::drawGrid( const Vector2f& pos ) { - if ( mFrameBuffer ) + if ( mFrameBuffer ) { + mFrameBuffer->setPosition( mPosition.floor() + Vector2f( mPadding.Left, mPadding.Top ) ); mFrameBuffer->bind(); + if ( mFullDirty ) + drawBg( true ); + } + auto fontSize = mFont->getFontHeight( mFontSize ); auto spaceCharAdvanceX = mFont->getGlyph( 'A', mFontSize, false, false ).advance; @@ -1388,17 +1393,26 @@ void TerminalDisplay::drawGrid( const Vector2f& pos ) { mFrameBuffer->unbind(); } +void TerminalDisplay::drawBg( bool toFBO ) { + auto defaultBg = termColor( mEmulator->getDefaultBackground(), mColors ); + Primitives p; + p.setForceDraw( toFBO ); + p.setColor( defaultBg ); + + if ( toFBO ) { + p.drawRectangle( Rectf( Vector2f::Zero, mFrameBuffer->getSize().asFloat() ) ); + } else { + p.drawRectangle( Rectf( mPosition.floor().asFloat(), mSize.asFloat() ) ); + } +} + void TerminalDisplay::draw( const Vector2f& pos ) { if ( !mEmulator || !mTerminal ) return; mDrawing = true; - auto defaultBg = termColor( mEmulator->getDefaultBackground(), mColors ); - Primitives p; - p.setForceDraw( false ); - p.setColor( defaultBg ); - p.drawRectangle( Rectf( mPosition.floor().asFloat(), mSize.asFloat() ) ); + drawBg(); if ( !mFrameBuffer || mDirty ) drawGrid( pos ); @@ -1418,6 +1432,7 @@ void TerminalDisplay::draw( const Vector2f& pos ) { mDrawing = false; mDirty = false; + mFullDirty = false; } Vector2i TerminalDisplay::positionToGrid( const Vector2i& pos ) { @@ -1455,6 +1470,7 @@ void TerminalDisplay::onSizeChange() { Sizei gridSize( gridSizeFromTermDimensions( mFont, mFontSize, mSize - Vector2f( mPadding.Left + mPadding.Right, mPadding.Top + mPadding.Bottom ) ) ); + if ( mTerminal ) { if ( gridSize.getWidth() != mTerminal->getNumColumns() || gridSize.getHeight() != mTerminal->getNumRows() ) { @@ -1682,6 +1698,7 @@ void TerminalDisplay::invalidateLine( const int& line ) { void TerminalDisplay::invalidateLines() { mDirtyLines.assign( mDirtyLines.size(), 1 ); mDirty = true; + mFullDirty = true; } void TerminalDisplay::setFocus( bool focus ) { if ( focus )