SFML community forums

Help => Graphics => Topic started by: Jaenis on October 15, 2009, 08:21:28 am

Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 08:21:28 am
Hi
I tried latest SVN version of SFML2 in Ubuntu(9.4) and I can't get textures working.
Textures work fine if I use SFML 1.6 from SVN, so there seems to be something in SFML2 branch.

Here's working example:
Code: [Select]
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
 
int main()
{
// Create the main window
sf::RenderWindow App(sf::VideoMode(500, 200), "SFML window");
//sf::RenderWindow App(sf::VideoMode::GetDesktopMode(), "SFML window", sf::Style::Fullscreen);

// Load a sprite to display
sf::Image Image;
if (!Image.LoadFromFile("Logo.png"))
return EXIT_FAILURE;
sf::Sprite Sprite(Image);

// Main loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
if (Event.Type == sf::Event::KeyPressed)
App.Close();
}

// Clear screen
App.Clear();

// Draw white box
App.SetActive();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glBegin(GL_QUADS);
{
glColor3f(1.0,1.0,1.0);
glVertex3f(0.25, 0.25, 0.0);
glVertex3f(0.75, 0.25, 0.0);
glVertex3f(0.75, 0.75, 0.0);
glVertex3f(0.25, 0.75, 0.0);
}
glEnd();

// Draw the sprite
App.Draw(Sprite);

// Update the window
App.Display();
}

return EXIT_SUCCESS;
}


Only white box that I draw manually gets displayed. It is not even overlapped that 400x200 image, so it seems that image drawing is just totally skipped. Adding App.Flush() calls didn't change anything.

Title bar was also missing, but this was fixed by disabling Compiz, which didn't affect anything else.

Any idea what is happening?
Title: Textures missing in Ubuntu
Post by: Laurent on October 15, 2009, 08:51:25 am
I recently made changes to the OpenGL contexts handling on Linux, so you should try older revisions (like 5 or 6 revisions ago) to see whether the problem was already there before or not.
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 10:06:38 am
I backtraced this in SVN, here's my findings:

1214-1220: Can't open window, prints this error
X Error of failed request:  GLXBadContext
  Major opcode of failed request:  154 (GLX)
  Minor opcode of failed request:  3 (X_GLXCreateContext)
  Serial number of failed request:  30
  Current serial number in output stream:  33

Fixed by commenting this if-line in Graphics/Linux/ContextGLX.cpp
    //if (shared)
        SetActive(true);

Opens window, draws texture


1223-1234: Can't open window, prints same error as above, fixed by same modification.
Opens window, does not draw texture


1235-: Opens window, does not draw texture


So textures were broken in changes at revision 1221, following files were modified from 1220->1221:
Code: [Select]
U    build/vc2005/sfml-graphics.vcproj
U    build/vc2005/sfml-audio.vcproj
U    build/vc2008/sfml-graphics.vcproj
U    build/codeblocks/sfml-graphics.cbp
U    include/SFML/Graphics/Shape.hpp
U    include/SFML/Graphics/String.hpp
U    include/SFML/Graphics/Sprite.hpp
U    include/SFML/Graphics/RenderWindow.hpp
U    include/SFML/Graphics/Drawable.hpp
U    include/SFML/Graphics/Image.hpp
U    include/SFML/Graphics/RenderImage.hpp
U    include/SFML/Graphics/PostFX.hpp
A    include/SFML/Graphics/RenderQueue.hpp
U    include/SFML/Graphics/RenderTarget.hpp
U    include/SFML/Graphics.hpp
U    include/SFML/Window/Window.hpp
U    include/SFML/Config.hpp
U    CSFML/build/VC2008/csfml-graphics.def
U    CSFML/include/SFML/Graphics/RenderImage.h
U    CSFML/include/SFML/Graphics/RenderWindow.h
U    CSFML/src/SFML/Graphics/RenderWindow.cpp
U    CSFML/src/SFML/Graphics/RenderImage.cpp
U    samples/opengl/OpenGL.cpp
U    samples/window/Window.cpp
U    src/SFML/Graphics/Sprite.cpp
U    src/SFML/Graphics/String.cpp
A    src/SFML/Graphics/GeometryRendererIM.cpp
A    src/SFML/Graphics/GeometryRendererIM.hpp
A    src/SFML/Graphics/Batch.cpp
U    src/SFML/Graphics/Drawable.cpp
U    src/SFML/Graphics/Win32/RenderImageImplPBuffer.cpp
A    src/SFML/Graphics/GeometryRenderer.cpp
U    src/SFML/Graphics/Image.cpp
U    src/SFML/Graphics/RenderImage.cpp
U    src/SFML/Graphics/PostFX.cpp
A    src/SFML/Graphics/Batch.hpp
A    src/SFML/Graphics/GeometryRenderer.hpp
A    src/SFML/Graphics/GeometryRendererVBO.cpp
U    src/SFML/Graphics/FontLoader.cpp
A    src/SFML/Graphics/GeometryRendererVBO.hpp
U    src/SFML/Graphics/Shape.cpp
U    src/SFML/Graphics/RenderWindow.cpp
A    src/SFML/Graphics/GeometryRendererVA.cpp
A    src/SFML/Graphics/GeometryRendererVA.hpp
A    src/SFML/Graphics/RenderQueue.cpp
U    src/SFML/Graphics/RenderTarget.cpp
U    src/SFML/Window/Window.cpp
U    dotnet/samples/opengl/OpenGL.cs
U    dotnet/src/Graphics/RenderImage.cs
U    dotnet/src/Graphics/RenderTarget.cs
U    dotnet/src/Graphics/RenderWindow.cs


This seems to be related to that new batch mode?
Title: Textures missing in Ubuntu
Post by: Laurent on October 15, 2009, 10:26:17 am
Thanks for your help :)

Quote
This seems to be related to that new batch mode?

Absolutely. And this is a pretty huge modification, so it won't be easy to spot the problem...

Do you have any error message in the console? Did you try a code without direct OpenGL calls? What about the SFML samples?
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 10:48:21 am
Quote from: "Laurent"
Thanks for your help :)

You're welcome :)
Let's see if I can help debugging this too

Quote from: "Laurent"
Do you have any error message in the console? Did you try a code without direct OpenGL calls? What about the SFML samples

Didn't get any error messages in console. Even debug version didn't print any errors.
I commented OpenGL calls from the source above, no change in behavior.
Haven't tried samples, though my test code is a stripped down sample from here: http://www.sfml-dev.org/documentation/1.5/
Title: Textures missing in Ubuntu
Post by: Laurent on October 15, 2009, 10:58:48 am
Quote
Haven't tried samples, though my test code is a stripped down sample from here

Yep, but samples are always updated and tested according to the latest modifications, so this is the safest reference for tests ;)
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 11:42:41 am
Quote from: "Laurent"
Quote
Haven't tried samples, though my test code is a stripped down sample from here

Yep, but samples are always updated and tested according to the latest modifications, so this is the safest reference for tests ;)

I'll be damned, you are right :D
I tried OpenGL sample and it worked perfectly, did load image and all

The key difference was to call "Window::SetActive()" before loading textures.
Shouldn't this be automatic?  :wink:

Edit:
Just found out that for example pong sample does not work, since it does not have this SetActive call before loading textures.
It seems that in Windows context is activated by default and in Linux it is not activated. (or there is difference in image loading code)
Title: Textures missing in Ubuntu
Post by: Tank on October 15, 2009, 12:44:49 pm
Quote from: "Jaenis"
Just found out that for example pong sample does not work, since it does not have this SetActive call before loading textures.
It seems that in Windows context is activated by default and in Linux it is not activated. (or there is difference in image loading code)

How does it look like? Do you only have crashes or graphical issues? If the latter applies to you, welcome to the club. :)
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 12:59:19 pm
Quote from: "Tank"
How does it look like? Do you only have crashes or graphical issues? If the latter applies to you, welcome to the club. :)

It is just black, nothing is displayed on screen, except some flickering.
But when I add "window.SetActive();" call just after RenderWindow was created it works perfectly. No issues at all.
(well, title bar is missing, but it is fixed by disabling that Compiz :) )
Title: Textures missing in Ubuntu
Post by: Tank on October 15, 2009, 02:12:29 pm
I can confirm that from my side (nothings gets displayed). But I've also got problems when activating the window. Most sprites get drawn, but not all.

What graphics card do you use?
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 02:23:49 pm
It is integrated Intel GMA 950 (Samsung NC10 laptop)
Title: Textures missing in Ubuntu
Post by: Laurent on October 15, 2009, 02:35:21 pm
Quote
The key difference was to call "Window::SetActive()" before loading textures.
Shouldn't this be automatic?

It should. There's always an active context in SFML, and all contexts are shared so I really don't understand.

Maybe you can do a quick test: call glXGetCurrentContext() before loading your image: if it's NULL then there's no context, if not then it is obviously the sharing operation that failed.

I think it's about shared contexts, otherwise you would get a fatal OpenGL error. And it's more consistent with the fact that it is absolutely impossible to have no context activated.

In my comments, I wrote that sharing a context which is enabled always fails, so there may be a relation with this. But if I remove default activation of contexts we go back to the previous issue (GLX error)...
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 02:45:15 pm
Quote from: "Laurent"
Maybe you can do a quick test: call glXGetCurrentContext() before loading your image

I tried this, it did return valid pointer.
Title: Textures missing in Ubuntu
Post by: Laurent on October 15, 2009, 02:55:47 pm
So the context sharing stuff is broken... which doesn't really surprises me ;)
Title: Textures missing in Ubuntu
Post by: Jaenis on October 15, 2009, 08:14:32 pm
Quote from: "Laurent"
So the context sharing stuff is broken... which doesn't really surprises me ;)

Hmm, but interesting thing is that that context sharing did work before that batch mode modification...
Title: Textures missing in Ubuntu
Post by: Jaenis on October 18, 2009, 08:38:39 am
I found one (possibly) illogical bit on window creation.
In src/SFML/Window/Window.cpp, line 133:
Code: [Select]
   // Make sure another context is bound, so that:
    // - the context creation can request OpenGL extensions if necessary
    // - myContext can safely be destroyed (it's no longer bound)
    Context context;

    // Recreate the context
    delete myContext;
    myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings);

    // Perform common initializations
    Initialize();
}

Here you create another context so you can get OpenGL extensions data, as said in comments. But isn't it so that this temporary context will get destroyed - and thereby marked not active - when it goes out of scope. And after this there is no active context? Or is there?

I made a test to modify this code in following way:
Code: [Select]
   // Initialize window in it's own scope
    {
        // Make sure another context is bound, so that:
        // - the context creation can request OpenGL extensions if necessary
        // - myContext can safely be destroyed (it's no longer bound)
        Context context;

        // Recreate the context
        delete myContext;
        myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings);

        // Perform common initializations
        Initialize();
    }

    // Activate context
    SetActive(true);
}


Now there is some context active when window initialization is done.
This modification fixes this problem what I am facing here in Ubuntu.

So, could it be that in Linux implementation when you call SetActive(false) to some context, all contexes will get deactivated?


Edit:
Actually it seems that "threadContext" (sfml/Window/ContextGL.cpp, line 131) will get activated when this happens.
So, there is an active context, but it is not the window that was created. That's why the SetActive(true) call on the end of the function was required.
Title: Textures missing in Ubuntu
Post by: Laurent on October 18, 2009, 09:40:38 am
Like you said, when a context is deactivated another one is activated, so that there's always an active context at any time.

It's not the window's one, but it shouldn't matter because all contexts are shared. Thus if you load an image with the "global" context activated, it will be available on the window's one as well. And when something must be drawn on the window, of course its context is activated ;)

However your "fix" is interesting, it will probably help me to spot the error. Actually I did like that before I implemented the batching feature, but since then something has changed: a window is no longer active all the time (so you don't have to deactivate it before using it in another thread, for example), that's why I no longer activate it by default after creation.
Title: Textures missing in Ubuntu
Post by: Jaenis on October 18, 2009, 10:33:58 am
Actually it seems that you have bug in context activation/deactivation logic:
Every time when you deactivate an inactive context, the "threadContext" will get activated.

Way to test:
Code: [Select]
int main()
{
    // Create main window
    sf::RenderWindow Window(sf::VideoMode(500, 200), "SFML window");

    // Main window is now active
    {
        // Create context, which gets activated
        sf::Context context;

        // Activate the main window, this disables "context"
        Window.SetActive();

    }    // Context will get destroyed and deactivated

    // Main window is not active anymore
}


This is illogical, since user just activated main window.

Let's follow what happens when inactive context will get deactivated... First it cals Context::SetActive(false), which calls ContextGL::SetActive(false), which looks like this:
Code: [Select]

bool ContextGL::SetActive(bool active)
{
    if (MakeCurrent(active))
    {


MakeCurrent will get called with false:
Code: [Select]

bool ContextGLX::MakeCurrent(bool active)
{
    if (active)
    {
    ...
    }
    else
    {
        if (glXGetCurrentContext() == myContext)
            ...
        else
            return true;
    }
}

So MakeCurrent returns true, because current context was not "myContext"

This returns to SetActive function:
Code: [Select]

    if (MakeCurrent(active))   // <-- Just returned true
    {
        if (active && (threadContext == 0))
        {
            ...
        }
        else if (!active && (threadContext != NULL) && (threadContext != this))
        {
            // Activate the reference context for this thread to ensure
            // that there is always an active context for subsequent graphics operations
            threadContext->SetActive(true);
        }

The else-if branch is run, since active is false and thread context exists and it is not this.
So, now we just activated threadContext when we were deactivating an context that was not active. This sounds like a bug to me :)

Shouldn't that MakeCurrent return false when we are deactivating an inactive context? Then nothing would happen and the previously active context would stay active.

Edit: Just changing MakeCurrent to return false was not enough, also this had to be changed:
Code: [Select]
ContextGL::~ContextGL()
{
    if (threadContext == this)
    {
        threadContext = NULL;
    }
    /*else if (threadContext != NULL)
    {
        threadContext->SetActive(true);
    }*/
}