SFML icon indicating copy to clipboard operation
SFML copied to clipboard

sf::RenderTarget::pushGLStates()/sf::RenderTarget::popGLStates() does not track last active texture.

Open ASxa86 opened this issue 3 years ago • 4 comments

Subject of the issue

When pushing/popping OpenGL state to run custom OpenGL code; SFML will fail to recall the correct active texture and therefore fail to pop the correct GL_TEXTURE matrix mode. I provided my minimally complete reproduction of the error (barring any spelling mistakes). Essentially, my custom OpenGL code makes use of active texture units other than 0. So, after the first frame of rendering, SFML will begin reporting GL_STACK_UNDERFLOW and GL_STACK_OVERFLOW errors when pushing/popping glMatrixMode(GL_TEXTURE) as the active texture is no longer being correctly tracked.

Your environment

  • Microsoft Windows 10
  • SFML v2.5.1 (from VCPKG)
  • VS2019 v16.5.5
  • Default compiler flags from CMake v3.20

Steps to reproduce

#include <gl/glew.h>
#include <SFML/Graphics.hpp>

int main()
{
    sf::ContextSettings settings;
    settings.depthBits = 24;
    settings.stencilBits = 8;
    sf::RenderWindow window{sf::VideoMode(1280, 720}, "test", 7, settings};
    window.setActive(true);
    
    glewInit();

    sf::RenderTexture rtt1;
    rtt1.create(window.getSize().x / 2, 720, settings);

    sf::RenderTexture rtt2;
    rtt2.create(window.getSize().x / 2, 720, settings);

    sf::CircleShape circle;
    circle.setPosition(300, 300);
    circle.setRadius(100.0f);
    circle.setFillColor(sf::Color::Blue);

    // Configure sprites to render side-by-side horizontally.
    sf::Sprite sprite1{rtt1.getTexture()};
    sf::Sprite sprite2{rtt2.getTexture()};
    sprite2.setPosition(window.getSize().x / 2.0f, 0.0f);

    sf::Event e;
    while(window.isOpen() == true)
    {
        while(window.pollEvent(e) == true)
        {
            switch(e.type)
            {
            case sf::Event::Closed:
                window.close();
                break;
            default:
                break;
        }

        rtt2.setActive(true);
        rtt2.clear();
        rtt2.pushGLStates();
        rtt2.draw(circle);
        rtt2.popGLStates();
        rtt2.display();

        // Custom OpenGL code narrowed down to the fact that glActiveTexture is being called with a non-zero texture unit.
        rtt1.setActive(true);
        constexpr auto myActiveTexture{4};
        glActiveTexture(GL_TEXTURE0 + myActiveTexture);
        rtt1.display();
        rtt1.setActive(false);

        window.setActive(true);
        window.clear();
        window.pushGLStates();
        window.draw(sprite1);
        window.draw(sprite2);
        window.popGLStates();
        window.display();
    }
    
    return 0;
}

Expected behavior

I would expect that SFML will push the correct active texture unit (which it does) and then restore this same texture unit as active (which it does not).

Actual behavior

After pushing the active texture with glMatrixMode(GL_TEXTURE); glPushMatrix(); SFML will reset the state to glActiveTexture(GL_TEXTURE0) and then fail to restore the previous state with glPopMatrix();

ASxa86 avatar Jun 08 '21 14:06 ASxa86

According to @binary1248 it would make sense to also handle glClientActiveTexture and glActiveTexture.

Would you be interested in providing a fix for this?

eXpl0it3r avatar Jun 10 '21 17:06 eXpl0it3r

@eXpl0it3r If anyone not working on this issue, can I try this? 😊

Snowapril avatar Oct 20 '21 09:10 Snowapril

@Snowapril I don't think anyone is actively working on it, so your help would definitely be appreciated! 🙂

Bromeon avatar Oct 20 '21 09:10 Bromeon

Sorry for late. I'm trying to solve this issue from today but stucked.. 😢 I thought that glPushAttrib(GL_ALL_ATTRIB_BITS) push the glActiveTexture and glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS) push the glClientActiveTexture, thus glActiveTexture(GL_TEXTURE0 + myActiveTexture); in above reproduce code must be handled correctly. But it was not.. Could I get some hint about it?

Snowapril avatar Oct 22 '21 12:10 Snowapril