canvas widget on windows 7

Started by billarhos, 15 March 2018, 07:57:24

billarhos

Hi.

Well this time it is a crush. I installed my app to windows 7, 64 and after some tests i realized that canvas widget causing the problem. I removed it and the app stop crushing.
I am using a lot of different widgets but only this causing the problem. I have install a lot of versions of vga drivers and the problem remains. Maybe there is some version that stops the problem. Of cource, the crushing happening only on win 7 64 and not on windows 10, 64.
The code snippet shows when the crush occurs. (on destroy)



//cpp
//-----------------------------------------------------------------------------
cForm::cForm() :
{
sf::RectangleShape line(sf::Vector2f(1, 800));
line.setFillColor(sf::Color::Black);
line.setPosition(sf::Vector2f(0, 1));

pCanvas = tgui::Canvas::create({ 10, 800 });
pCanvas->setPosition(330, 70);
pCanvas->clear(sf::Color(194, 206, 200));
pCanvas->draw(line);
pCanvas->display();

GAME_MANAGER->getGui()->add(pCanvas);
}

cForm::~cForm()
{
GAME_MANAGER->getGui()->removeAllWidgets();
       //-->the crash problem
}
//h
//-----------------------------------------------------------------------------
class cForm
{
public:
cForm::cForm();
~cForm();
private:
tgui::Canvas::Ptr pCanvas;
}


Any clue mates?




texus

Is GAME_MANAGER or cForm a global object? Make sure that "GAME_MANAGER->getGui()->removeAllWidgets();" is called before the end of the main function.

I can't immediately come up with any other reason why the code could crash. If it isn't because the widget is still alive after the main function exits (which causes the internal sf::RenderTexture to still be alive), then you should try to find some minimal code that reproduces the problem.

billarhos

I do so texus and make a minimal project that reproduces the problem. As i said the problem occurs only on windows 7. Not in windows 10. GAME_MANAGER is a global static object. cForm is a private pointer in an onother class header (cForm* pForm;). So i create a new cform object.

pForm = new cForm();

and the problem occurs when SAFE_DELETE(pForm);

#ifndef SAFE_DELETE
#define SAFE_DELETE(p)         { if(p)      { delete (p);      (p)=NULL; }      }
#endif


texus

The important question that I would like an answer to is whether the crash happens after the main function ends or not. Try placing a breakpoint at the end of the main function to check if it passes that place before the crash. If the crash happens after the main function has ended then you are relying on undefined behavior since SFML objects (and thus also TGUI objects) are not guaranteed to work in global scope (due to the undefined order of construction and destruction of global objects).

If the crash happens before the end of the main function then this has to be investigated. Could you run your code in debug mode (while using the debug libraries of TGUI and SFML of course) and get a stack trace when it crashes? That should narrow down the problem, without a stacktrace I can only make guesses.

billarhos

#4
Ok, made an simple app (find some time) that behaves just like my other app. This app crush only in windows 7. I will debug this code as soon as i find time.

http://www.mediafire.com/file/u6u5zo8njlrbmdg/Tgui.rar

http://www.mediafire.com/file/e7wxjzj5dildwzs/Test.rar

the same test app in the same windows 7 64 bit machine but with differrent vga drivers produce a message box about "createsurface : 3" just when i create second form (u have to have a look at the code)

The crash occurs when u exit from form 2 back to form 1. i am using visual studio 2015 for ide.

Tomorrow i will have some more news. If u want something just ask.

billarhos

Well, debugging the test project, the problem is when the shared pointer is destroyed in memory file (_Decref() function). This happen only for canvas widgets and only in windows 7. Also the opegl version is 2.1. Well, i am not sure if it is tgui or sfml or vga drivers (opengl) problem.

texus

#6
Although likely unrelated, move the following lines into your main function. Keeping them in global scope relies on undefined behavior.
Code (cpp) Select
sf::RenderWindow mWindow;
tgui::Gui mGui;


Could you try replacing the following code in cForm with something similar like you did with the back button in cFormMore (i.e. don't remove the widgets and create the form inside the callback function, but do it later during the update function)?
Code (cpp) Select
pButtonFormMore->connect("MousePressed", [=]()
{
pGui->removeAllWidgets();
formMore = new cFormMore(gui, guiTheme);
});


I can't really see anything wrong with the code that could cause it. Canvas is the only widget that uses an sf::RenderTexture, which is likely related to why the problem only occurs with this widget, but the actual issue could still be anywhere.

I'll try to build it here and run valgrind on it.

billarhos

Moving things to main function did not help. Also loading formmore in update function (create a boolean  to set it true in connect function and then create formmore in update function) did not work.

texus

Since it works on linux and windows 7 here, I don't see any more undefined behavior and you already mentioned that it works on windows 10, the only thing left that I can blame is the graphics driver. So I can't help you with getting it working on that pc.

Maybe you can try reproducing it with just SFML, i.e. create an sf::RenderTexture instead of a tgui::Canvas and delete it in ~cFormMore. If you can reduce the code to a simple program in a single file that doesn't use TGUI then you could ask on the SFML forum.

billarhos

#9
Confirm that is the rendertexture. Can not be deleted once it created. Has nothing to do with tgui.

thank u Texus for your time. Cheers

billarhos

Come back to share a solution to my problem. Definately has to do with old drives of intel. But as long as i did not managed to find proper good drivers for this old "gigabyte"
motherboard, i was still looking and digging forums and source codes. The problem is the old opengl version and has to do with the context of rendertexture. The solution was to deactivate context of sfml's window and activate it just before displaying the context. Did some tests and now i do not have any issues.

here is the solution for tgui canvas

//-----------------------------------------------------------------------
sf::RectangleShape line(sf::Vector2f(1, 800));
line.setFillColor(sf::Color::Black);
line.setPosition(sf::Vector2f(0, 1));

pWindow->setActive(false); //pWindow is the main sf::RenderWindow

pCanvas = tgui::Canvas::create({ 5, 300 });
pCanvas->setPosition(200, 70);
pCanvas->clear(sf::Color(194, 206, 200));
pCanvas->draw(line);

pWindow->setActive(true);

pCanvas->display();


here is the solution of creating sf::RenderTexture without crashing


                pWindow->setActive(false);

sf::RenderTexture *pTex = new sf::RenderTexture();
pTex->create(128, 128);
        SAFE_DELETE(pTex);

pWindow->setActive(true);


hope it helps


texus

#11
https://github.com/SFML/SFML/pull/1379 changes a lot of code related to render textures and context switches. It might be interesting to see if it solves the problem as well or not.
You could try that PR and see if it solves the issue, but you would have to compile both SFML and TGUI yourself if you do (and you have to change the SFML version number to 2.5.0 in Config.hpp in order to compile TGUI).

billarhos

Ok, thanks, i will try it.
Question: It does matter what tgui version i ll use? I am using the 0.7.5 one in my projects.

texus

It looks like you would need TGUI 0.7.6 unless you make a small modification to the cmake script.
SFML made some changes in their dependencies in their github version. If TGUI detects version 2.5.0 (which doesn't exist yet) then it will expect the new dependencies while otherwise it will search for the old dependencies. This patch was only made in TGUI 0.7.6, so if you use an older TGUI version or you don't set the SFML version number to 2.5.0 then it will try to search for a dependency that no longer exists.

It might be possible with TGUI 0.7.5 and an unmodified SFML version if you just copy the SFML/cmake/Modules/FindSFML.cmake file to TGUI/cmake/Modules/FindSFML.cmake, but this was not tested.