Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ASxa86 opened this issue Jun 8, 2021 · 4 comments

Comments

@ASxa86
Copy link

ASxa86 commented Jun 8, 2021

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();

@eXpl0it3r
Copy link
Member

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

Would you be interested in providing a fix for this?

@Snowapril
Copy link

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

@Bromeon
Copy link
Member

Bromeon commented Oct 20, 2021

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

@Snowapril
Copy link

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants