Page 1 of 1

wxWidgets 3.1.2 / wxGLCanvas crashes OpenGL-context

Posted: Wed Jan 30, 2019 10:02 pm
by art-ganseforth
Hey folks!

Since changing from wxWidgets 2.9.3 to 3.1.2 (Win10 / MingW32), i have the problem, that additional wxGLCanvas-creation seem to crash the existing OpenGL-context. The program is executes normal, but there are textures 'getting lost', like this:

The first wxGLCanvas and the wxGLContext is created succesfully. After initialisation, of basic OpenGL-things, three textures (black, b/w-noise, hsv-noise) are created using glGenTextures(), which also works. The next step is to create a second wxGLCanvas. Further glGenTextures() return an invalid value and glGetError() returns GL_INVALID_OPERATION.

I tested it with both wxGLCanvas-constructors documented in the 3.1.2-reference. I have a small class "clsBuffer" that is used to organize textures. Each time, when an new instance of this class is created, there is allocated a texture. Also it logs the returned handle and the active texture and errors if there are. This class, i used to find the exact progeamline, where the OpenGL-context seems to get lost.

Here you see the version with wxGLAttributes:

Code: Select all

        CTRLframe   = new       clsFrame            (this,   -1, GetTitle(), wxDefaultPosition, wxSize(1024, 630), wxCAPTION | wxRESIZE_BORDER | wxSYSTEM_MENU | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "OUTPUT");
        new clsBuffer   (   2,    2, "test 1"   );   

        wxGLAttributes attrib; attrib.RGBA ().DoubleBuffer ().PlatformDefaults 	( 		) 	.EndList();
        new clsBuffer   (   2,    2, "test 2"   );   

        CTRLcanvas  = new       wxGLCanvas          (CTRLframe,  attrib ,-1,  wxPoint(0,0), wxSize(1024, 630), 0);
        new clsBuffer   (   2,    2, "test 3"   );   
As you can see, i am creatin a new clsBuffer after each program-line. The third one does not work anymore.

When i later start rendering, the first textures still work but none of them that were created after the second wxGLCanvas. I also tested if, especially this one is the reason, but later wxGLCanvas calls have the same effect.

Is there anyone knowig a reson, why this might happen?


Best,
Frank

Re: wxWidgets 3.1.2 / wxGLCanvas crashes OpenGL-context

Posted: Thu Jan 31, 2019 1:05 am
by Manolo

Code: Select all

new clsBuffer   (   2,    2, "test 2"   );
Nomal C++ should store the object, something like

Code: Select all

clsBuffer *clsBuf1 = new clsBuffer   (   2,    2, "test 2"   );
...but perhaps you have a rare "new" overloading... I don't think so.

You can create two wxGLContext and bind them (IOW, set as current) one for each wxGLCanvas. The rendering on each wxGLCanvas will be done for the gl-commands after this myglcontext->SetCurrent(myglCanvas);, which means you can call this function only once for each canvas.
If the canvases have the same attributes, then an unique gl-context is enough, but now you need to call SetCurrent each time before rendering to a canvas.

The textures issues have nothing to do with wxWidgets, supposed you respect the gl-context "current" I told above.

Again, for each canvas, at its paint event, do the following procedure:
1) Create a wxPaintDC
2) Set the required context as current.
3) Do all gl-job: buffers, textures, viewport, rendering

Re: wxWidgets 3.1.2 / wxGLCanvas crashes OpenGL-context

Posted: Thu Jan 31, 2019 2:22 am
by art-ganseforth
Thank you, but i'm not sure, if you understand what i mean.

These lines...

Code: Select all

new clsBuffer   (   2,    2, "test 2"   );
...are only used to test if the openGL-context still accepts texture-allocations, after the leine before, and to get a log-outpout. 5-6 lines later i call exit(0);, so the pointer needes not to be stored. I don't do any rendering in this context up to this point. I only allocate texture-buffers, using glGenTextures and fill them with a (default) 2x2 black bitmap and the two mentioned noise-bitmaps. Also: in clsBuffer::clsBuffer i don't call SetCurrent or someting else concerning wxGL. So, wxPaintEvent / wxPaintDC is not relevat.

There is no wxWidgets-possibility, to check the state of the context. So i use glGenTextures. If it works and as long as you don't delete a texture), it returns a simple integer-index (1, 2, 3, ...). If doesn't work (like here after creating the canvas), it returns a negative value. So the error a opeGL thing but caused by the wxGLCanvas::wxGLCanvas-call.

By the way: all the "links" between context and canvas-controls are identical with the version that workes with wxWidgets 2.9.3. So, there i am abel to create these canvases and link them on one context the same way, like i try here (and as it is described in wx 2.9.x online-reference). I never had problems with this.

Best,
Frank

Re: wxWidgets 3.1.2 / wxGLCanvas crashes OpenGL-context

Posted: Thu Jan 31, 2019 2:57 am
by art-ganseforth
One more interesting point: In fact there is only one SetCurrent-call up to this point - the one that is used to initialitze the context. So, creating the canvas seem to has an effect on a context that is not it's current.

Re: wxWidgets 3.1.2 / wxGLCanvas crashes OpenGL-context

Posted: Thu Jan 31, 2019 12:11 pm
by art-ganseforth
I've found the solution.

The point is, that after creating a second wxGLCanvas, the Context has to be SetCurrent again. For this SetCurrent-call it's not relevant which canvas is used. It needn't necessarily to be the new one.

I found the point after isolating it in a short single-file-test-project (code below). This code compiles on my system and shows - while main-window-creation - two message-boxes displaying information if a valid texture-buffer-id can be retrieved from openGL.

Code: Select all

#include <wx/wx.h>

#define GLEW_STATIC
#include <GL/glew.h>

#include <wx/glcanvas.h>

class MyApp: public wxApp {
    virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)

class MyFrame : public wxFrame {
    public:
        MyFrame();
        
        wxGLCanvas  *Canvas1,*Canvas2;
        wxGLContext *Kontext;
};

bool MyApp::OnInit() {
    MyFrame *frame = new MyFrame( );
    SetTopWindow(frame);
    return true;
}

MyFrame::MyFrame() : wxFrame( NULL, -1, "Test", wxPoint(50, 50), wxSize(450, 350) ) {
    wxGLAttributes dispAttrs;
    dispAttrs.RGBA ().DoubleBuffer ().PlatformDefaults().EndList();
       
    Canvas1 = new wxGLCanvas(this, dispAttrs, -1,  wxDefaultPosition, wxDefaultSize);
    Kontext = new wxGLContext (Canvas1);
    Kontext->SetCurrent(*Canvas1);

    if (glewInit() != GLEW_OK) {    wxMessageBox("FATAL ERROR");       exit(0);    } 

    glActiveTexture  (GL_TEXTURE0);                                 
    GLuint buf_Texture1, buf_Texture2;

    glGenTextures    (1, &buf_Texture1);         
    wxMessageBox(buf_Texture1 <1000 ? "OK":"ERR");                    

    Canvas2 = new wxGLCanvas(this, dispAttrs, -1,  wxDefaultPosition, wxDefaultSize);
    Kontext->SetCurrent(*Canvas1);       /// If this is missing, the next glGenTextures fails. Note, that it's not relevant, which canvas is used 

    glGenTextures    (1, &buf_Texture2);         
    wxMessageBox(buf_Texture2 <1000 ? "OK":"ERR");                    
    
    SetAutoLayout(true);
    Show(true);
}