SFML community forums

Help => Graphics => Topic started by: mazellan on July 21, 2013, 08:24:40 pm

Title: sf::RenderTexture bug when destroyed in fullscreen
Post by: mazellan on July 21, 2013, 08:24:40 pm
Greetings everyone.

I have integrated SFML in my project development that uses some RenderTextues, Sprites,... and when try it t run in fullscreen, the entity that stores the RenderTexture is destroyed, cause some sort of flickering in the screen.

For 1-2 frames, the screen goes black and then return to normal. Trying to reproduce this problem, I've discovered what causes this comportament but not why.

In the following code, I find that when a RenderTexture is destroyed (out of scope/delete), the problem appears.

My specs are Win 7 64 bits, Nvidia 560Ti (driver version 320.49 WHQL), i5 2500k.

#include <iostream>
#include <SFML\Graphics.hpp>
#include <SFML\Window.hpp>


int main()
{
    sf::RenderWindow App(sf::VideoMode(640, 480, 32), "SFML Test", sf::Style::Fullscreen);
        App.setFramerateLimit(60);

        sf::RectangleShape rect(sf::Vector2f(300,300));
        rect.setFillColor(sf::Color::White);
        rect.setPosition(170, 100);
       
        sf::RenderTexture *tex_ptr = NULL;
       
        while (App.isOpen())
        {
                sf::Event Event;

                while (App.pollEvent(Event))
        {
            // Close Window
            if (Event.type == sf::Event::Closed)
                return 1;

                        if (Event.type == sf::Event::KeyPressed)
                        {
                                // Exit
                                if (Event.key.code == sf::Keyboard::Escape)
                                        return 1;      

                                // Each time F1 is pressed, screen goes black in some sort flickering
                                if (Event.key.code == sf::Keyboard::F1)
                                {  
                                        sf::RenderTexture tex;
                                        tex.create(200,200);
                                }

                                // Each time F2 is pressed, screen goes black in some sort flickering
                                if (Event.key.code == sf::Keyboard::F2)
                                {  
                                        tex_ptr = new sf::RenderTexture();
                                        tex_ptr->create(200,200);
                                        delete tex_ptr; // if this line is commented, does not flick
                                }
                        }
                }

                App.clear();
                App.draw(rect);
                App.display();
        }

    return 0;
}
 
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: mazellan on July 22, 2013, 02:36:29 pm
Try it today on another computer (win 7 32 bits, nvidia 8600GT) and the result is the same "black blink" effect when Rendertexture is destroyed.

In windowed mode all run fine, smooth, without any flickering. But in fullscreen, everytime I destroy a rendertexture, or a entity that stores a rendertexture, because I don't gonna use it anymore, the flicker appears.

Try it with Vsynch enabled and same result.

¿Anyone with nvidia cards (or ati) can confirm this?

PS: I use Visual Studio 2010.
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: Laurent on July 22, 2013, 02:45:36 pm
I'll test your code and see if I can reproduce the problem.
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: Laurent on July 22, 2013, 08:33:55 pm
I can reproduce the problem.

This is caused by a call to DestroyWindow in the destructor of WglContext, but I don't know why and how to avoid it.
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: mazellan on July 22, 2013, 11:36:39 pm
Thanks for the answer :)

¿Should I add a new track issue on github for this problem?

I hope there is a solution, somehow...
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: Laurent on July 23, 2013, 07:53:56 am
Quote
¿Should I add a new track issue on github for this problem?
Yes, you can.
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: binary1248 on July 23, 2013, 08:54:13 am
Well... the solution is quite simple to understand but would require a little change in the RenderTexture API that I'm sure won't make so big of a difference.

The problem is that SFML controls the target of OpenGL operations using many (sometimes too many ;)) OpenGL contexts. To control the destination window of OpenGL operations this makes sense, but for some reason contexts are also used to control whether or not to draw to a RenderTexture (even if the FBO implementation is being used, for the default implementation there is no other way). In a normal scenario, you would bind the FBO, do your drawing, and unbind it when you are done. For unknown reasons (probably just uniformity with the rest of SFML) Laurent chose to create the FBO in its own context and leave it bound forever, using context switching to control whether to draw to it or not as opposed to binding/unbinding. If you don't already have a context from a previously created window, this would make sense, however that is what ensureGlContext() is for. There is no point creating a new context for every RenderTexture if you can just reuse the currently active one, except if you use it for selection as mentioned above.

If RenderTexture were to use some kind of bind/unbind API then at least the FBO implementation wouldn't have to rely on contexts for target selection. This would mean less overhead and less hidden windows that are created/destroyed which would also solve this problem.
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: Laurent on July 23, 2013, 09:11:54 am
Quote
The problem is that SFML controls the target of OpenGL operations using many (sometimes too many ;)) OpenGL contexts.
True :D

Quote
For unknown reasons (probably just uniformity with the rest of SFML) Laurent chose to create the FBO in its own context and leave it bound forever, using context switching to control whether to draw to it or not as opposed to binding/unbinding
The reason is that implementation becomes straight-forward: switching a target is just a context switch internally.
If I just bind/unbind the FBO, I would also have to restore all the OpenGL states and matrices of the render-target, which may also badly interact with my states cache algorithm.

I'm not saying that it is impossible, maybe I would end up with a cleaner and more efficient implementation if I investigated in this direction; but it would require extra efforts to ensure that everything works as expected.

And yes, I would love to clean the context system. There are too many of them, and the dummy contexts with their hidden window are definitely ugly.
Title: Re: sf::RenderTexture bug when destroyed in fullscreen
Post by: ChronicRat on March 24, 2014, 10:09:38 am
So, guys, there is solution of the problem? I'm tried to deactivate RenderWindow and RenderTexture before it destroyed - still i have flickering on full screen. Or may be i can avoid the problem? I'm recreating texture when GUI window resized... May be it's better to create max sized RenderTexture and then just copy part of it to sprite... Yeah! Thank you for reading this!!! =)