diff --git a/bin/assets/fontrendering/eepp-subpixel-text.webp b/bin/assets/fontrendering/eepp-subpixel-text.webp new file mode 100644 index 000000000..85bbb729a Binary files /dev/null and b/bin/assets/fontrendering/eepp-subpixel-text.webp differ diff --git a/include/eepp/graphics/renderer/renderer.hpp b/include/eepp/graphics/renderer/renderer.hpp index fdda462b9..55aeb3f0b 100644 --- a/include/eepp/graphics/renderer/renderer.hpp +++ b/include/eepp/graphics/renderer/renderer.hpp @@ -362,8 +362,6 @@ class EE_API Renderer { void waitForIdle(); protected: - static const Vector3ff& textureColorChannel( Int32 mode ); - static Renderer* sSingleton; enum RendererStateFlags { diff --git a/include/eepp/graphics/renderer/renderergl.hpp b/include/eepp/graphics/renderer/renderergl.hpp index f3d2a9da0..231e6aa9b 100644 --- a/include/eepp/graphics/renderer/renderergl.hpp +++ b/include/eepp/graphics/renderer/renderergl.hpp @@ -14,6 +14,8 @@ class EE_API RendererGL : public Renderer { ~RendererGL(); + void init(); + GraphicsLibraryVersion version(); std::string versionStr(); diff --git a/include/eepp/graphics/renderer/rendererglshader.hpp b/include/eepp/graphics/renderer/rendererglshader.hpp index 9b6f0622b..0d19f8baa 100644 --- a/include/eepp/graphics/renderer/rendererglshader.hpp +++ b/include/eepp/graphics/renderer/rendererglshader.hpp @@ -64,8 +64,6 @@ class EE_API RendererGLShader : public Renderer { int mTextureColorMode_id; int mTextureColorChannel_id; Int32 mTextureColorMode; - ShaderProgram* mTextureColorPreviousShader; - bool mUsingTextureColorFallbackShader; unsigned int mCurrentMode; ShaderProgram* mCurShader; ShaderProgram* mShaderPrev; diff --git a/src/eepp/graphics/renderer/renderer.cpp b/src/eepp/graphics/renderer/renderer.cpp index fc66f95e2..31f77763e 100644 --- a/src/eepp/graphics/renderer/renderer.cpp +++ b/src/eepp/graphics/renderer/renderer.cpp @@ -483,8 +483,7 @@ bool Renderer::drawSubpixelArrays( unsigned int mode, int first, int count ) { Uint8 previousColorMask[4]; getColorMask( previousColorMask ); for ( Int32 channel = 0; channel < 3; ++channel ) { - if ( channel != 0 ) - setTextureColorMode( channel + 1 ); + setTextureColorMode( channel + 1 ); colorMask( channel == 0 && previousColorMask[0], channel == 1 && previousColorMask[1], channel == 2 && previousColorMask[2], 0 ); drawArrays( mode, first, count ); @@ -590,15 +589,6 @@ bool Renderer::setTextureColorMode( Int32 ) { return false; } -const Vector3ff& Renderer::textureColorChannel( Int32 mode ) { - static const Vector3ff channels[] = { { 0.f, 0.f, 0.f }, - { 1.f, 0.f, 0.f }, - { 0.f, 1.f, 0.f }, - { 0.f, 0.f, 1.f }, - { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } }; - return channels[mode]; -} - bool Renderer::isLineSmooth() { return BitOp::readBitKey( &mStateFlags, RSF_LINE_SMOOTH ); } diff --git a/src/eepp/graphics/renderer/renderergl.cpp b/src/eepp/graphics/renderer/renderergl.cpp index 76b0b544f..45cae505b 100644 --- a/src/eepp/graphics/renderer/renderergl.cpp +++ b/src/eepp/graphics/renderer/renderergl.cpp @@ -61,6 +61,10 @@ RendererGL::RendererGL() { RendererGL::~RendererGL() {} +void RendererGL::init() { + Renderer::init(); +} + bool RendererGL::ensureSubpixelShader() { #ifndef EE_GLES1 if ( mSubpixelShader ) @@ -117,8 +121,6 @@ bool RendererGL::setTextureColorMode( Int32 mode ) { #ifdef EE_GLES1 return false; #else - if ( mode < 0 || mode > 4 ) - return false; if ( mode != 0 && !ensureSubpixelShader() ) return false; if ( !mSubpixelShader || !mSubpixelShader->isValid() || mSubpixelChannelLoc == -1 ) @@ -134,7 +136,12 @@ bool RendererGL::setTextureColorMode( Int32 mode ) { Renderer::setShader( mSubpixelShader.get() ); mUsingSubpixelShader = true; } - mSubpixelShader->setUniform( mSubpixelChannelLoc, textureColorChannel( mode ) ); + static const Vector3ff channels[] = { { 0.f, 0.f, 0.f }, + { 1.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 0.f, 0.f, 1.f }, + { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } }; + mSubpixelShader->setUniform( mSubpixelChannelLoc, channels[mode] ); return true; #endif } diff --git a/src/eepp/graphics/renderer/renderergl3.cpp b/src/eepp/graphics/renderer/renderergl3.cpp index 2d3235a5a..9d40dee25 100644 --- a/src/eepp/graphics/renderer/renderergl3.cpp +++ b/src/eepp/graphics/renderer/renderergl3.cpp @@ -173,7 +173,12 @@ void RendererGL3::setShader( ShaderProgram* Shader ) { if ( mTextureColorMode_id != -1 ) mCurShader->setUniform( mTextureColorMode_id, mTextureColorMode ); if ( mTextureColorChannel_id != -1 && mTextureColorMode != 0 ) { - mCurShader->setUniform( mTextureColorChannel_id, textureColorChannel( mTextureColorMode ) ); + static const Vector3ff channels[] = { { 0.f, 0.f, 0.f }, + { 1.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 0.f, 0.f, 1.f }, + { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } }; + mCurShader->setUniform( mTextureColorChannel_id, channels[mTextureColorMode] ); } if ( -1 != mAttribsLoc[EEGL_VERTEX_ARRAY] ) diff --git a/src/eepp/graphics/renderer/renderergl3cp.cpp b/src/eepp/graphics/renderer/renderergl3cp.cpp index e22ef6687..8bbe6e405 100644 --- a/src/eepp/graphics/renderer/renderergl3cp.cpp +++ b/src/eepp/graphics/renderer/renderergl3cp.cpp @@ -200,7 +200,12 @@ void RendererGL3CP::setShader( ShaderProgram* Shader ) { if ( mTextureColorMode_id != -1 ) mCurShader->setUniform( mTextureColorMode_id, mTextureColorMode ); if ( mTextureColorChannel_id != -1 && mTextureColorMode != 0 ) { - mCurShader->setUniform( mTextureColorChannel_id, textureColorChannel( mTextureColorMode ) ); + static const Vector3ff channels[] = { { 0.f, 0.f, 0.f }, + { 1.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 0.f, 0.f, 1.f }, + { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } }; + mCurShader->setUniform( mTextureColorChannel_id, channels[mTextureColorMode] ); } if ( -1 != mAttribsLoc[EEGL_VERTEX_ARRAY] ) diff --git a/src/eepp/graphics/renderer/renderergles2.cpp b/src/eepp/graphics/renderer/renderergles2.cpp index 6a96f9621..3f0c38bb1 100644 --- a/src/eepp/graphics/renderer/renderergles2.cpp +++ b/src/eepp/graphics/renderer/renderergles2.cpp @@ -227,7 +227,12 @@ void RendererGLES2::setShader( ShaderProgram* Shader ) { if ( mTextureColorMode_id != -1 ) mCurShader->setUniform( mTextureColorMode_id, mTextureColorMode ); if ( mTextureColorChannel_id != -1 && mTextureColorMode != 0 ) { - mCurShader->setUniform( mTextureColorChannel_id, textureColorChannel( mTextureColorMode ) ); + static const Vector3ff channels[] = { { 0.f, 0.f, 0.f }, + { 1.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 0.f, 0.f, 1.f }, + { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } }; + mCurShader->setUniform( mTextureColorChannel_id, channels[mTextureColorMode] ); } if ( -1 != mAttribsLoc[EEGL_VERTEX_ARRAY] ) diff --git a/src/eepp/graphics/renderer/rendererglshader.cpp b/src/eepp/graphics/renderer/rendererglshader.cpp index 2ffe8ee9c..5fca99084 100644 --- a/src/eepp/graphics/renderer/rendererglshader.cpp +++ b/src/eepp/graphics/renderer/rendererglshader.cpp @@ -11,8 +11,6 @@ RendererGLShader::RendererGLShader() : mTextureColorMode_id( -1 ), mTextureColorChannel_id( -1 ), mTextureColorMode( 0 ), - mTextureColorPreviousShader( nullptr ), - mUsingTextureColorFallbackShader( false ), mCurrentMode( 0 ), mCurShader( NULL ), mShaderPrev( NULL ) { @@ -27,31 +25,20 @@ RendererGLShader::~RendererGLShader() { } bool RendererGLShader::setTextureColorMode( Int32 mode ) { - if ( mode < 0 || mode > 4 ) + if ( mTextureColorMode_id == -1 ) return false; - if ( mode != 0 && ( mTextureColorMode_id == -1 || mTextureColorChannel_id == -1 ) ) { - mTextureColorPreviousShader = mCurShader; - setShader( static_cast( nullptr ) ); - if ( mTextureColorMode_id == -1 || mTextureColorChannel_id == -1 ) { - setShader( mTextureColorPreviousShader ); - mTextureColorPreviousShader = nullptr; - return false; - } - mUsingTextureColorFallbackShader = true; - } if ( mTextureColorMode != mode ) { mTextureColorMode = mode; mCurShader->setUniform( mTextureColorMode_id, mode ); if ( mTextureColorChannel_id != -1 ) { - mCurShader->setUniform( mTextureColorChannel_id, textureColorChannel( mode ) ); + static const Vector3ff channels[] = { { 0.f, 0.f, 0.f }, + { 1.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 0.f, 0.f, 1.f }, + { 1.f / 3.f, 1.f / 3.f, 1.f / 3.f } }; + mCurShader->setUniform( mTextureColorChannel_id, channels[mode] ); } } - if ( mode == 0 && mUsingTextureColorFallbackShader ) { - ShaderProgram* previousShader = mTextureColorPreviousShader; - mTextureColorPreviousShader = nullptr; - mUsingTextureColorFallbackShader = false; - setShader( previousShader ); - } return true; } diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 8c2e2cb82..de2a820e3 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -1732,7 +1732,8 @@ void Text::draw( const Float& X, const Float& Y, const Vector2f& scale, const Fl return; unsigned int numvert = mVertices.size(); - const bool containsSubpixel = !mRenderModes.empty(); + const bool containsSubpixel = std::find( mRenderModes.begin(), mRenderModes.end(), + GlyphRenderMode::Subpixel ) != mRenderModes.end(); const Float drawX = containsSubpixel && rotation == 0.f && scale == 1.f ? std::trunc( X ) : X; const Float drawY = containsSubpixel && rotation == 0.f && scale == 1.f ? std::trunc( Y ) : Y; @@ -2681,9 +2682,8 @@ void Text::setFillColor( const std::vector& colors ) { // Add an underline or strikethrough line to the vertex array void Text::addLine( std::vector& vertices, Float lineLength, Float lineTop, Float offset, Float thickness, Float outlineThickness, Int32 centerDiffX ) { - auto& renderModes = &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes; - if ( !renderModes.empty() ) - renderModes.push_back( GlyphRenderMode::Mask ); + ( &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes ) + .push_back( GlyphRenderMode::Mask ); Float top = std::floor( lineTop + offset - ( thickness / 2 ) + 0.5f ); Float bottom = top + std::floor( thickness + 0.5f ); Float u1 = 0; @@ -2759,13 +2759,8 @@ void Text::addLine( std::vector& vertices, Float lineLength, Float void Text::addGlyphQuad( std::vector& vertices, Vector2f position, const EE::Graphics::Glyph& glyph, Float italic, Float outlineThickness, Int32 centerDiffX ) { - auto& renderModes = &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes; - if ( glyph.renderMode == GlyphRenderMode::Subpixel && renderModes.empty() ) - renderModes.resize( vertices.size() / GLi->quadVertex(), GlyphRenderMode::Mask ); - if ( !renderModes.empty() ) - renderModes.push_back( glyph.renderMode == GlyphRenderMode::Subpixel - ? GlyphRenderMode::Subpixel - : GlyphRenderMode::Mask ); + ( &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes ) + .push_back( glyph.renderMode ); if ( glyph.renderMode == GlyphRenderMode::Subpixel ) position = position.trunc(); Float padding = 1.0; diff --git a/src/tests/unit_tests/fontrendering_tests.cpp b/src/tests/unit_tests/fontrendering_tests.cpp index e5fd66d04..c69cecfb5 100644 --- a/src/tests/unit_tests/fontrendering_tests.cpp +++ b/src/tests/unit_tests/fontrendering_tests.cpp @@ -77,7 +77,7 @@ UTEST( FontRendering, glyphAdvanceDoesNotCreateTexturePages ) { UTEST( FontRendering, subpixelCoverageCompositesPerChannel ) { UIApplication app( - WindowSettings( 360, 120, "eepp - Subpixel Text Test", WindowStyle::Default, + WindowSettings( 360, 220, "eepp - Subpixel Text Test", WindowStyle::Default, WindowBackend::Default, 32 ), UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) ); ResourceScope& scope = *app.getUI()->getResourceScope(); @@ -103,7 +103,16 @@ UTEST( FontRendering, subpixelCoverageCompositesPerChannel ) { Text retained( "Subpixel retained", font.get(), 28 ); retained.setFillColor( Color::Black ); - retained.draw( 8.f, 60.f ); + retained.draw( 8.f, 52.f ); + + Primitives primitives; + primitives.setColor( Color( 40, 42, 54 ) ); + primitives.drawRectangle( Rectf( Vector2f( 0.f, 110.f ), Sizef( 360.f, 110.f ) ) ); + const Color lightText( 248, 248, 242 ); + Text::draw( String( "Subpixel static light" ), { 8.f, 114.f }, font.get(), 28, lightText ); + retained.setString( "Subpixel retained light" ); + retained.setFillColor( lightText ); + retained.draw( 8.f, 162.f ); Image image = window->getFrontBufferImage(); auto hasColoredCoverage = [&image]( Uint32 top, Uint32 bottom ) { @@ -122,6 +131,7 @@ UTEST( FontRendering, subpixelCoverageCompositesPerChannel ) { "Static text lost independent LCD channel coverage" ); EXPECT_TRUE_MSG( hasColoredCoverage( image.getHeight() / 2, image.getHeight() ), "Retained text lost independent LCD channel coverage" ); + compareImages( utest_state, utest_result, window, "eepp-subpixel-text" ); FrameBufferUniquePtr frameBuffer = FrameBuffer::New( 240, 48, false, false, false, 4, window ); ASSERT_TRUE( frameBuffer && frameBuffer->created() );