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

GL::Context: unsupported OpenGL version (0, 0) output while building base-wxwidgets #26

Open
astinus87 opened this issue Dec 31, 2020 · 12 comments

Comments

@astinus87
Copy link

I am getting GL::Context: unsupported OpenGL version (0, 0) output when I run MyApplication that is created by building the base-wxwidgets branch of magnum-bootstrap. My distro is Arch Linux.
Btw I moved _wxGlCanvas->SetCurrent(_wxGlContext) method to MainFrame::OnPaint because otherwise I get a failed assert. Assert error is glx11.cpp assert xid failed in setcurrent window must be shown.

[src]$ ldd MyApplication 
	linux-vdso.so.1 (0x00007ffcd8b2c000)
	libMagnumGL.so.2 => /usr/lib/libMagnumGL.so.2 (0x00007fee7f091000)
	libMagnum.so.2 => /usr/lib/libMagnum.so.2 (0x00007fee7f041000)
	libwx_baseu-3.1.so.4 => /usr/lib/libwx_baseu-3.1.so.4 (0x00007fee7edb1000)
	libwx_gtk3u_core-3.1.so.4 => /usr/lib/libwx_gtk3u_core-3.1.so.4 (0x00007fee7e57a000)
	libwx_gtk3u_gl-3.1.so.4 => /usr/lib/libwx_gtk3u_gl-3.1.so.4 (0x00007fee7e55f000)
	libCorradeUtility.so.2 => /usr/lib/libCorradeUtility.so.2 (0x00007fee7e502000)
	libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fee7e4fa000)
	libGLX.so.0 => /usr/lib/libGLX.so.0 (0x00007fee7e4c7000)
	libOpenGL.so.0 => /usr/lib/libOpenGL.so.0 (0x00007fee7e49b000)
	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fee7e2be000)
	libm.so.6 => /usr/lib/libm.so.6 (0x00007fee7e178000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fee7e15e000)
	libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fee7e13a000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007fee7df71000)
	/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fee7f167000)
	libz.so.1 => /usr/lib/libz.so.1 (0x00007fee7df57000)
	libsecret-1.so.0 => /usr/lib/libsecret-1.so.0 (0x00007fee7def4000)
	libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0x00007fee7de9c000)
	libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x00007fee7dd68000)
	liblzma.so.5 => /usr/lib/liblzma.so.5 (0x00007fee7dd3e000)
	libgtk-3.so.0 => /usr/lib/libgtk-3.so.0 (0x00007fee7d596000)
	libgdk-3.so.0 => /usr/lib/libgdk-3.so.0 (0x00007fee7d497000)
	libpangocairo-1.0.so.0 => /usr/lib/libpangocairo-1.0.so.0 (0x00007fee7d486000)
	libpango-1.0.so.0 => /usr/lib/libpango-1.0.so.0 (0x00007fee7d434000)
	libcairo.so.2 => /usr/lib/libcairo.so.2 (0x00007fee7d315000)
	libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0 (0x00007fee7d2ee000)
	libgio-2.0.so.0 => /usr/lib/libgio-2.0.so.0 (0x00007fee7d132000)
	libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fee7cff1000)
	libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x00007fee7cfea000)
	libSM.so.6 => /usr/lib/libSM.so.6 (0x00007fee7cfe0000)
	libnotify.so.4 => /usr/lib/libnotify.so.4 (0x00007fee7cfd6000)
	libXtst.so.6 => /usr/lib/libXtst.so.6 (0x00007fee7cfcc000)
	libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0x00007fee7cfb0000)
	libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x00007fee7cf65000)
	libpng16.so.16 => /usr/lib/libpng16.so.16 (0x00007fee7cf2e000)
	libjpeg.so.8 => /usr/lib/libjpeg.so.8 (0x00007fee7ceaa000)
	libtiff.so.5 => /usr/lib/libtiff.so.5 (0x00007fee7ce1a000)
	libGL.so.1 => /usr/lib/libGL.so.1 (0x00007fee7cd92000)
	libGLdispatch.so.0 => /usr/lib/libGLdispatch.so.0 (0x00007fee7ccdb000)
	libgcrypt.so.20 => /usr/lib/libgcrypt.so.20 (0x00007fee7cbba000)
	libffi.so.7 => /usr/lib/libffi.so.7 (0x00007fee7cbae000)
	libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007fee7cb3c000)
	libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0x00007fee7cb35000)
	libharfbuzz.so.0 => /usr/lib/libharfbuzz.so.0 (0x00007fee7ca61000)
	libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007fee7c98d000)
	libfribidi.so.0 => /usr/lib/libfribidi.so.0 (0x00007fee7c96e000)
	libcairo-gobject.so.2 => /usr/lib/libcairo-gobject.so.2 (0x00007fee7c962000)
	libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0 (0x00007fee7c939000)
	libepoxy.so.0 => /usr/lib/libepoxy.so.0 (0x00007fee7c806000)
	libXi.so.6 => /usr/lib/libXi.so.6 (0x00007fee7c7f3000)
	libatk-bridge-2.0.so.0 => /usr/lib/libatk-bridge-2.0.so.0 (0x00007fee7c7bd000)
	libcloudproviders.so.0 => /usr/lib/libcloudproviders.so.0 (0x00007fee7c7a5000)
	libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00007fee7c79c000)
	librt.so.1 => /usr/lib/librt.so.1 (0x00007fee7c791000)
	libxkbcommon.so.0 => /usr/lib/libxkbcommon.so.0 (0x00007fee7c74a000)
	libwayland-client.so.0 => /usr/lib/libwayland-client.so.0 (0x00007fee7c739000)
	libwayland-cursor.so.0 => /usr/lib/libwayland-cursor.so.0 (0x00007fee7c730000)
	libwayland-egl.so.1 => /usr/lib/libwayland-egl.so.1 (0x00007fee7c72b000)
	libXext.so.6 => /usr/lib/libXext.so.6 (0x00007fee7c716000)
	libXcursor.so.1 => /usr/lib/libXcursor.so.1 (0x00007fee7c70a000)
	libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x00007fee7c703000)
	libXcomposite.so.1 => /usr/lib/libXcomposite.so.1 (0x00007fee7c6fe000)
	libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0x00007fee7c6f1000)
	libXinerama.so.1 => /usr/lib/libXinerama.so.1 (0x00007fee7c6ec000)
	libthai.so.0 => /usr/lib/libthai.so.0 (0x00007fee7c6e1000)
	libXrender.so.1 => /usr/lib/libXrender.so.1 (0x00007fee7c6d2000)
	libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007fee7c6a8000)
	libxcb-render.so.0 => /usr/lib/libxcb-render.so.0 (0x00007fee7c698000)
	libxcb-shm.so.0 => /usr/lib/libxcb-shm.so.0 (0x00007fee7c693000)
	libpixman-1.so.0 => /usr/lib/libpixman-1.so.0 (0x00007fee7c5eb000)
	libmount.so.1 => /usr/lib/libmount.so.1 (0x00007fee7c58e000)
	libresolv.so.2 => /usr/lib/libresolv.so.2 (0x00007fee7c572000)
	libICE.so.6 => /usr/lib/libICE.so.6 (0x00007fee7c555000)
	libuuid.so.1 => /usr/lib/libuuid.so.1 (0x00007fee7c54c000)
	libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007fee7c51d000)
	libzstd.so.1 => /usr/lib/libzstd.so.1 (0x00007fee7c44b000)
	libgpg-error.so.0 => /usr/lib/libgpg-error.so.0 (0x00007fee7c422000)
	libgraphite2.so.3 => /usr/lib/libgraphite2.so.3 (0x00007fee7c3fd000)
	libbz2.so.1.0 => /usr/lib/libbz2.so.1.0 (0x00007fee7c3ea000)
	libdbus-1.so.3 => /usr/lib/libdbus-1.so.3 (0x00007fee7c395000)
	libatspi.so.0 => /usr/lib/libatspi.so.0 (0x00007fee7c35e000)
	libdatrie.so.1 => /usr/lib/libdatrie.so.1 (0x00007fee7c352000)
	libXau.so.6 => /usr/lib/libXau.so.6 (0x00007fee7c34d000)
	libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007fee7c345000)
	libblkid.so.1 => /usr/lib/libblkid.so.1 (0x00007fee7c2f4000)
	libsystemd.so.0 => /usr/lib/libsystemd.so.0 (0x00007fee7c23e000)
	liblz4.so.1 => /usr/lib/liblz4.so.1 (0x00007fee7c219000)
@mosra mosra added this to the 2020.0b milestone Jan 1, 2021
@mosra
Copy link
Owner

mosra commented Jan 1, 2021

Hi, thanks for the report!

Interesting, looks like things changed significantly since I last checked on Arch. I got stuck already at CMake not being able to find wxgtk3, I had to convince it by supplying an extra name for wx-config (fix commited in d8f6221). For the assertion, it seems the following patch fixes it (instead of moving SetCurrent() to OnPaint()):

diff --git a/src/MyApplication.cpp b/src/MyApplication.cpp
index 21d1672..05756d3 100644
--- a/src/MyApplication.cpp
+++ b/src/MyApplication.cpp
@@ -61,6 +61,7 @@ MainFrame::MainFrame(int argc, char** argv): wxFrame{nullptr, wxID_ANY, "Magnum
     #endif
 
     _wxGlContext = new wxGLContext{_wxGlCanvas};
+    Show();
     _wxGlCanvas->SetCurrent(*_wxGlContext);
     _glContext.create();
 

The GL::Context: unsupported OpenGL version (0, 0) was just a consequence of the SetCurrent() being moved -- _glContext needs an active OpenGL context in order to query version and setup Magnum's GL wrapper and if it doesn't have it, it usually ends up getting all zeros for everything it queries.

However, I have zero idea what I'm doing here (not a wxWidgets user at all), so I didn't commit the above. Can you confirm that Show() is allowed to be called in the constructor? Or do I need to attach to some wxEVT_SHOW event and do the GL context and Magnum GLContext setup in there instead? @williamjcm, you were the original author of this code, can you advise? Thanks :)

@astinus87
Copy link
Author

@mosra Thanks for the fix. Calling Show in the constructor as you did fixed it for me.

CMake couldn't find wxWidgets for me too. I fixed it by creating a symlink /usr/bin/wx-config pointing to /usr/bin/wx-config-gtk3 instead of your CMakeLists solution. wxgtk3 package only installs /usr/bin/wx-config-gtk3. I think there should be a wx-config executable on the system because there might be other projects using it.

I am an absolute beginner in wxWidgets and I chose it because it is said to provide native look. I will develop a cross platform app for Windows and Linux. I have used .Net WPF before. I didn't like Qt because it seemed too tied to the Qt Creator. Do you use any GUI framework? I appreciate it if you have any suggestion.

@mosra
Copy link
Owner

mosra commented Jan 1, 2021

I think there should be a wx-config executable on the system

By looking at the FindwxWidgets module, there's about 15 of them already, so I suppose this was only one case that wasn't added there yet. I'd rather have that patched up by the buildsystem than requiring users to create symlinks. Ideally the CMake module would be updated to recognize this name as well, but I'm too busy to open a PR on the cmake repository...

I didn't like Qt because it seemed too tied to the Qt Creator.

I was happily using Qt without QtCreator for several years in the Qt4 days, and didn't really miss any of its features for Qt development. Though I have to admit it "jumped the shark" after that, and version 5 (and now 6) seems rather bloated. (OTOH I'm a happy KDE user and wouldn't trade it for a GTK-based environment ever, the difference in overall polish and flexibility is just too huge between the two.)

Qt is bloated, GTK lacks critical features like fractional DPI scaling, .NET is, well, C#... I don't have a suggestion, sorry, it's all various levels of bad nowadays :( Depending on what you'll be doing, using ImGui might be just fine and flexible enough (and Magnum has integration for it). That one is very feature-rich although I don't personally like the default look, and the only major downside is that it's not suited for "idle" apps because it requires constant redraw in order to function properly.

@williamjcm
Copy link

williamjcm commented Jan 5, 2021

Sorry for the late answer! I don't check GitHub as often as I used to. 😅

Show() is allowed to be called in the constructor? [...] @williamjcm, you were the original author of this code, can you advise? Thanks :)

Yes, it can. In fact, in my wxWidgets/Magnum project, I do all of the context setup in the constructor for the window.

Here's what I have in that project:

_wxGlContext.emplace(_glCanvas, nullptr, &context_attributes);
#ifdef __WXGTK__
Show();
#endif
_wxGlContext->SetCurrent(*_glCanvas);
#ifdef __WXGTK__
Hide();
#endif

Since I only target Windows and Linux, I use #ifdef __WXGTK__, but if it happens on other targets, those lines should be replaced with #ifndef __WXMSW__.

If there are any further questions, I'll try to answer them ASAP.

@mosra
Copy link
Owner

mosra commented Jan 6, 2021

Oh, so you're saying it's backend-dependent? Interesting. Are there any "good practice" docs explaining this in more detail? Like if it's a GTK quirk or something one should expect in general.

@williamjcm
Copy link

williamjcm commented Jan 8, 2021

Oh, so you're saying it's backend-dependent?

In a way, yeah.

On Windows, wxWidgets will assert in the same way as on GTK when calling wxGLCanvas::SetCurrent() when the window is hidden, but, for some reason, it doesn't when calling wxGLContext::SetCurrent().

Are there any "good practice" docs explaining this in more detail? Like if it's a GTK quirk or something one should expect in general.

The "good practice" on all platforms would be to only set a context as current when the canvas is shown, as the docs for wxGLCanvas::SetCurrent() say.

While the docs also say to not call it in the constructor of the window, it worked fine during my testing of the bootstrap project. And in my main project, I do the initialisation of the context in another class that inherits from the window's class, so the window itself is technically ready by that point.

It's... a bit of a mess, I admit.

@asmwarrior
Copy link

Hi, I just try the base-wxwidgets project under Code::Blocks (I'm using msys2's prebuild magnum library, and msys2's wx 3.1.5 library)

The pure base-wxwidgets works OK without any issue. See the image show below:
ok

But if I try to add some member variables in the MainFrame class, I got crashed.

Here is the code:

#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/Platform/GLContext.h>


#include <Magnum/GL/Buffer.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Shaders/VertexColor.h>


#include <wx/app.h>
#include <wx/frame.h>
#include <wx/glcanvas.h>
#include <wx/sizer.h>
#include <wx/version.h>

using namespace Magnum;

class MyApplication: public wxApp {
    public:
        bool OnInit();
};

class MainFrame: public wxFrame {
    public:
        explicit MainFrame(int argc, char** argv);
        ~MainFrame();

    private:
        void OnPaint(wxPaintEvent& event);

        wxGLCanvas* _wxGlCanvas;
        wxGLContext* _wxGlContext;
        Platform::GLContext _glContext;

#if 1
        //GL::Mesh _mesh;
        //Shaders::VertexColor2D _shader;
#endif // 0

};

wxIMPLEMENT_APP(MyApplication);

bool MyApplication::OnInit() {
    MainFrame *frame = new MainFrame{argc, argv};
    frame->Show(true);
    return true;
}

MainFrame::MainFrame(int argc, char** argv)
    : wxFrame{nullptr, wxID_ANY, "Magnum wxWidgets Application"},
    _glContext{NoCreate, argc, argv}
{
    wxBoxSizer* bSizer;
    bSizer = new wxBoxSizer{wxVERTICAL};

    #if (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION >= 1)
    wxGLAttributes attributes;
    attributes.PlatformDefaults()
              .BufferSize(24)
              .MinRGBA(8, 8, 8, 0)
              .Depth(24)
              .Stencil(0)
              .DoubleBuffer()
              .EndList();
    _wxGlCanvas = new wxGLCanvas{this, attributes, wxID_ANY, wxDefaultPosition, wxSize{800, 600}};
    #elif (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION == 0)
    int attributes[] = { WX_GL_RGBA,
                         WX_GL_DOUBLEBUFFER,
                         WX_GL_DEPTH_SIZE, 24,
                         WX_GL_STENCIL_SIZE, 0,
                         0 };
    _wxGlCanvas = new wxGLCanvas{this, wxID_ANY, &attributes[0], wxDefaultPosition, wxSize{800, 600}};
    #else
    #error You need wxWidgets version 3.0 or later.
    #endif

    _wxGlContext = new wxGLContext{_wxGlCanvas};
    _wxGlCanvas->SetCurrent(*_wxGlContext);
    _glContext.create();

    bSizer->Add(_wxGlCanvas, 1, wxALL|wxEXPAND, 5);
    SetSizer(bSizer);

    Layout();

    bSizer->Fit(this);

    Centre(wxBOTH);

    _wxGlCanvas->Connect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);

    /* TODO: Add your initialization code here */

#if 0
    // https://doc.magnum.graphics/magnum/triangle_2TriangleExample_8cpp-example.html
    using namespace Math::Literals;

    struct TriangleVertex {
        Vector2 position;
        Color3 color;
    };
    const TriangleVertex data[]{
        {{-0.5f, -0.5f}, 0xff0000_rgbf},    /* Left vertex, red color */
        {{ 0.5f, -0.5f}, 0x00ff00_rgbf},    /* Right vertex, green color */
        {{ 0.0f,  0.5f}, 0x0000ff_rgbf}     /* Top vertex, blue color */
    };

    GL::Buffer buffer;
    buffer.setData(data);

    _mesh.setCount(3)
         .addVertexBuffer(std::move(buffer), 0,
            Shaders::VertexColor2D::Position{},
            Shaders::VertexColor2D::Color3{});
#endif // 0
}

MainFrame::~MainFrame() {
    _wxGlCanvas->Disconnect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);
}

void MainFrame::OnPaint(wxPaintEvent& event) {
    GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);

    /* TODO: Add your drawing code here */

#if 0
    _shader.draw(_mesh);
#endif // 0
    _wxGlCanvas->SwapBuffers();


}

Note that there are two member variables

        GL::Mesh _mesh;
        Shaders::VertexColor2D _shader;

If you umcomment either one of them, or all of them, I got crash on the construction of the MainFrame.
The crash just open a message below:

crash

Note that I'm using the msys2's prebuild version, which is: mingw64/mingw-w64-x86_64-magnum 2020.06-1
and mingw64/mingw-w64-x86_64-wxmsw3.1 3.1.5-3

Any ideas how to solve this issue? Thanks.

@asmwarrior
Copy link

Some extra information, if I enable the console window, I see when it crashed, some message was shown in the console, see below image show:

GL::Context::current(): no current context

crash2

So, when the member variable get initialized, they need an active context?

@asmwarrior
Copy link

asmwarrior commented Jul 16, 2021

By searching the error message, I got this:

Context::current(): no current context · Issue #167 · mosra/magnum

As the internal context is created by the NoCreate parameter.

_glContext{NoCreate, argc, argv}

How can we create a mesh and shader object if the _glContext is not created yet?

@asmwarrior
Copy link

I solved this issue by a hack that I just create a function to initialize the _glContext member variable before the other shader and mesh members, see the full code below and screen shot.

#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/Platform/GLContext.h>


#include <Magnum/GL/Buffer.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Shaders/VertexColor.h>


#include <wx/app.h>
#include <wx/frame.h>
#include <wx/glcanvas.h>
#include <wx/sizer.h>
#include <wx/version.h>

using namespace Magnum;

class MyApplication: public wxApp {
    public:
        bool OnInit();
};

class MainFrame: public wxFrame {
    public:
        explicit MainFrame(int argc, char** argv);
        ~MainFrame();

    private:
        void OnPaint(wxPaintEvent& event);

       void InitContext();

        wxGLCanvas* _wxGlCanvas;
        wxGLContext* _wxGlContext;
        Platform::GLContext _glContext;

        int m_a;

#if 1
        GL::Mesh _mesh;
        Shaders::VertexColor2D _shader;
#endif // 0

};

wxIMPLEMENT_APP(MyApplication);


void CreateConsole()
{
    if (!AllocConsole()) {
        // Add some error handling here.
        // You can call GetLastError() to get more info about the error.
        return;
    }

    // std::cout, std::clog, std::cerr, std::cin
    FILE* fDummy;
    freopen_s(&fDummy, "CONOUT$", "w", stdout);
    freopen_s(&fDummy, "CONOUT$", "w", stderr);
    freopen_s(&fDummy, "CONIN$", "r", stdin);
    std::cout.clear();
    std::clog.clear();
    std::cerr.clear();
    std::cin.clear();

    // std::wcout, std::wclog, std::wcerr, std::wcin
    HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
    SetStdHandle(STD_ERROR_HANDLE, hConOut);
    SetStdHandle(STD_INPUT_HANDLE, hConIn);
    std::wcout.clear();
    std::wclog.clear();
    std::wcerr.clear();
    std::wcin.clear();
}


bool MyApplication::OnInit() {

    CreateConsole();

    MainFrame *frame = new MainFrame{argc, argv};
    frame->Show(true);
    return true;
}

MainFrame::MainFrame(int argc, char** argv)
    : wxFrame{nullptr, wxID_ANY, "Magnum wxWidgets Application"},
    _glContext{NoCreate, argc,  argv},
    m_a{(InitContext(),0)}
{
    wxBoxSizer* bSizer;
    bSizer = new wxBoxSizer{wxVERTICAL};



    bSizer->Add(_wxGlCanvas, 1, wxALL|wxEXPAND, 5);
    SetSizer(bSizer);

    Layout();

    bSizer->Fit(this);

    Centre(wxBOTH);

    _wxGlCanvas->Connect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);

    /* TODO: Add your initialization code here */

#if 1
    // https://doc.magnum.graphics/magnum/triangle_2TriangleExample_8cpp-example.html
    using namespace Math::Literals;

    struct TriangleVertex {
        Vector2 position;
        Color3 color;
    };
    const TriangleVertex data[]{
        {{-0.5f, -0.5f}, 0xff0000_rgbf},    /* Left vertex, red color */
        {{ 0.5f, -0.5f}, 0x00ff00_rgbf},    /* Right vertex, green color */
        {{ 0.0f,  0.5f}, 0x0000ff_rgbf}     /* Top vertex, blue color */
    };

    GL::Buffer buffer;
    buffer.setData(data);

    _mesh.setCount(3)
         .addVertexBuffer(std::move(buffer), 0,
            Shaders::VertexColor2D::Position{},
            Shaders::VertexColor2D::Color3{});
#endif // 0
}


void MainFrame::InitContext()
{
    #if (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION >= 1)
    wxGLAttributes attributes;
    attributes.PlatformDefaults()
              .BufferSize(24)
              .MinRGBA(8, 8, 8, 0)
              .Depth(24)
              .Stencil(0)
              .DoubleBuffer()
              .EndList();
    _wxGlCanvas = new wxGLCanvas{this, attributes, wxID_ANY, wxDefaultPosition, wxSize{800, 600}};
    #elif (wxMAJOR_VERSION == 3) && (wxMINOR_VERSION == 0)
    int attributes[] = { WX_GL_RGBA,
                         WX_GL_DOUBLEBUFFER,
                         WX_GL_DEPTH_SIZE, 24,
                         WX_GL_STENCIL_SIZE, 0,
                         0 };
    _wxGlCanvas = new wxGLCanvas{this, wxID_ANY, &attributes[0], wxDefaultPosition, wxSize{800, 600}};
    #else
    #error You need wxWidgets version 3.0 or later.
    #endif

    _wxGlContext = new wxGLContext{_wxGlCanvas};
    _wxGlCanvas->SetCurrent(*_wxGlContext);
    _glContext.create();
}

MainFrame::~MainFrame() {
    _wxGlCanvas->Disconnect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), nullptr, this);
}

void MainFrame::OnPaint(wxPaintEvent& event) {
    GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);

    /* TODO: Add your drawing code here */

#if 1
    _shader.draw(_mesh);
#endif // 0
    _wxGlCanvas->SwapBuffers();


}

ok2

It is dirty, because I have to use the method mentioned here:
constructor - C++ - Run a function before initializing a class member - Stack Overflow

Now, the next step is I just try to see if I can add the mouse event handling, so I can tweak the camera (to rotate, scale the scene)

@mosra
Copy link
Owner

mosra commented Jul 17, 2021

@asmwarrior delayed context creation is a rather common workflow, the solution is using the NoCreate constructors for GL objects as well:

        GL::Mesh _mesh{NoCreate};
        Shaders::VertexColor2D _shader{NoCreate};

and then, once you have the context created, populating them with proper live instances:

_glContext.create();

// Now it's safe to call into GL
_mesh = GL::Mesh{};
_shader = Shaders::VertexColor2D{};

I realized the documentation for this workflow was rather nonexistent (sorry about that), so I mentioned this in the OpenGL wrapper overview and a few other places (mosra/magnum@2bd933d).

@asmwarrior
Copy link

Hi, @mosra , many thanks!
The document: in the OpenGL wrapper overview is so nice, especially for the beginners.

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

4 participants