How to setup wxGLContext properly? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

How to setup wxGLContext properly?

Post by apoorv569 »

I am trying to setup wxGLCanvas and wxGLContext for drawing OpenGL graphics, but I'm not able to set it up properly. When I open my application I get this error,

Image

And this error as well,

Code: Select all

Error! Could not initialize GLEW.
zsh: segmentation fault (core dumped)  ./wxGL
Not sure but I guess my GLContext is not setup correctly?

I have attacted the minimal app source code I made to test this.
wxGL.zip
(3.73 KiB) Downloaded 78 times
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to setup wxGLContext properly?

Post by doublemax »

Please check the "opengl/pyramid" sample that come with wxWidgets. Under GTK you can't set the GL context before the underlying window is fully initialized. Therefore the samples initialize OGL in the OnSize event handler and don't draw inside the paint event handler until the window size is > 0.
Use the source, Luke!
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

doublemax wrote: Thu Oct 14, 2021 9:25 am Please check the "opengl/pyramid" sample that come with wxWidgets. Under GTK you can't set the GL context before the underlying window is fully initialized. Therefore the samples initialize OGL in the OnSize event handler and don't draw inside the paint event handler until the window size is > 0.
Ok I moved the GLContext code to OnSize(),

Code: Select all

void MainFrame::OnSize(wxSizeEvent &event)
{
    event.Skip();

    if (!IsShownOnScreen())
        return;

    wxGLContext* context = new wxGLContext(m_Canvas);
    context->SetCurrent(*m_Canvas);

    Refresh(false);
}
and moved all the GLEW code to OnPaint()

Code: Select all

void MainFrame::OnPaint(wxPaintEvent &event)
{
    if (this->GetSize().GetHeight() < 0 || this->GetSize().GetWidth() < 0)
    {
        std::cout << "Error! Window size not initalize properly" << std::endl;
        return;
    }

    if (glewInit() != GLEW_OK)
        std::cout << "Error! Could not initialize GLEW." << std::endl;

    /* Print out the OpenGL version we are using */
    std::cout << glGetString(GL_VERSION) << std::endl;

    float positions[] =
    {
        -0.5f, -0.5f, // 0
         0.5f, -0.5f, // 1
         0.5f,  0.5f, // 2
        -0.5f,  0.5f  // 3
    };

    unsigned int indices[] =
    {
        0, 1, 2,
        2, 3, 0
    };

    unsigned int vertex_array_object;
    glGenVertexArrays(1, &vertex_array_object);
    glBindVertexArray(vertex_array_object);

    unsigned int vertex_buffer;
    glGenBuffers(1, &vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), positions, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
    glEnableVertexAttribArray(0);

    unsigned int index_buffer;
    glGenBuffers(1, &index_buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);

    std::string vertexShader = ParseShader("../res/shaders/basic.vert");
    std::string fragmentShader = ParseShader("../res/shaders/basic.frag");

    unsigned int shader = CreateShader(vertexShader, fragmentShader);
    glUseProgram(shader);

    int location = glGetUniformLocation(shader, "u_Color");
    float r = 0.0f, g = 0.0f, b = 0.0f, a =1.0f, inc = 0.01f;

    glUseProgram(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glViewport(0, 0, m_Panel->GetSize().GetHeight(), m_Panel->GetSize().GetWidth());
    glClearColor(0.07f, 0.13f, 0.17f, 1.0f);

    /* Render here */
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shader);

    /* Set the shader color */
    glUniform4f(location, r, 0.3f, 0.02f, a);

    glBindVertexArray(vertex_array_object);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);

    /* Draw call */
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

    if (r > 1.0f)
        inc = -0.01f;
    else if (r < 0.0f)
        inc = 0.01f;

    r += inc;
}
Now the assert is gone, but I either get an error saying could not initialize GLEW or I get a segmentation fault.

Do I have set the window size manually?
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to setup wxGLContext properly?

Post by doublemax »

Sorry, my knowledge about OpenGL is quite limited, hopefully Manolo (or someone else) can help with this.
Use the source, Luke!
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: How to setup wxGLContext properly?

Post by New Pagodi »

If you want to use wxGLCanvas with an extension loader like glew, glad, libepoxy, etc, the easiest thing is to put a helper class in between the wxWidgets code and the GL code and keep all of the GL stuff bottled up in the cpp file for that helper class. Here's an example helper class for use with glew:

glhelper.h

Code: Select all

#ifndef GLHELPER_H_INCLUDED
#define GLHELPER_H_INCLUDED

class GLHelper
{
public:
    bool InitGlew();
    void Render();
    void SetSize(int w, int h);
};

#endif // GLHELPER_H_INCLUDED
glhelper.cpp

Code: Select all

#include <GL/glew.h>

#ifdef __WXMSW__
    #include <GL/wglew.h>
#elif defined(__WXGTK__)
    #include <GL/glxew.h>
#endif // defined

#include "glhelper.h"

bool GLHelper::InitGlew()
{
    GLenum initStatus = glewInit();

    return initStatus == GLEW_OK;
}

void GLHelper::Render()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

void GLHelper::SetSize(int width, int height)
{
    glViewport(0, 0, width, height);
}
Here's a small demo program using this helper class:

Code: Select all

#include "wx/wx.h"

#include <wx/glcanvas.h>
#include "glhelper.h"

class wxGlewFrame: public wxFrame
{
    public:
        wxGlewFrame(wxWindow*);
        ~wxGlewFrame();
    private:
        void OnCanvasSize(wxSizeEvent&);
        void OnCanvasPaint(wxPaintEvent&);

        void InitGL();

        wxGLCanvas* m_canvas;
        wxGLContext* m_context;
        GLHelper m_helper;
};

wxGlewFrame::wxGlewFrame(wxWindow* parent)
    : wxFrame(parent,  wxID_ANY, wxString())
{
    // Create the canvas and context.
    #if wxCHECK_VERSION(3,1,0)
        // These settings should work with any GPU from the last 10 years.
        wxGLAttributes dispAttrs;
        dispAttrs.PlatformDefaults().RGBA().DoubleBuffer().EndList();

        wxGLContextAttrs cxtAttrs;
        cxtAttrs.PlatformDefaults().CoreProfile().OGLVersion(3, 3).EndList();

        m_canvas = new wxGLCanvas(this, dispAttrs);
        m_context = new wxGLContext(m_canvas, NULL, &cxtAttrs);

        if ( !m_context->IsOK() )
        {
            SetTitle("Failed to create context.");
            return;
        }
    #else
        int dispAttrs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_CORE_PROFILE,
                            WX_GL_MAJOR_VERSION ,3, WX_GL_MINOR_VERSION, 3, 0 };

        m_canvas = new wxGLCanvas(this, wxID_ANY, dispAttrs);
        m_context = new wxGLContext(m_canvas, NULL);

        // Unfortunately, there doesn't seem to be any way to check if the
        // context is ok prior to wxWidgets 3.1.0.
    #endif // wxCHECK_VERSION

    // On Linux, we must delay delay initialization until the canvas has
    // been full created.  On windows, we can finish now.
    #ifdef __WXMSW__
        InitGL();
    #elif defined(__WXGTK__)
        m_canvas->Bind(wxEVT_CREATE, [this](wxWindowCreateEvent&){InitGL();});
    #endif // defined
}

wxGlewFrame::~wxGlewFrame()
{
    delete m_context;
}

void wxGlewFrame::OnCanvasSize(wxSizeEvent& event)
{
    wxSize sz = event.GetSize();
    m_helper.SetSize(sz.GetWidth(), sz.GetHeight());
    event.Skip();
}

void wxGlewFrame::OnCanvasPaint(wxPaintEvent&)
{
    wxPaintDC dc(m_canvas);

    m_helper.Render();
    m_canvas->SwapBuffers();
}

void wxGlewFrame::InitGL()
{
    // First call SetCurrent or GL initialization will fail.
    m_context->SetCurrent(*m_canvas);

    // Initialize GLEW.
    bool glewInialized = m_helper.InitGlew();

    if ( !glewInialized )
    {
        SetTitle("Failed it initialize GLEW.");
        return;
    }

    SetTitle("Context and GLEW initialized.");

    // Bind event handlers for the canvas. Binding was delayed until OpenGL was
    // initialized because these handlers will need to call OpenGL functions.
    m_canvas->Bind(wxEVT_SIZE, &wxGlewFrame::OnCanvasSize, this);
    m_canvas->Bind(wxEVT_PAINT, &wxGlewFrame::OnCanvasPaint, this);
}

class MyApp : public wxApp
{
    public:
        virtual bool OnInit()
        {
            wxGlewFrame* frame = new wxGlewFrame(NULL);
            frame->Show();
            return true;
        }
};

wxIMPLEMENT_APP(MyApp);
Feel free to change 'dispAttrs' and 'cxtAttrs' to whatever is appropriate. The settings above are just relatively safe, minimal settings for any GPU from the last 10 years or so.

Edit: updated to show creation on linux plus using with wxWidgets versions prior to 3.1.0.
Edit2: shortened code and corrected comments in the code based on Manolo's post.
Last edited by New Pagodi on Thu Oct 14, 2021 8:32 pm, edited 3 times in total.
Manolo
Can't get richer than this
Can't get richer than this
Posts: 827
Joined: Mon Apr 30, 2012 11:07 pm

Re: How to setup wxGLContext properly?

Post by Manolo »

Are you starting to think OGL is a nightmare? Oh yeah. I know how you feel. Don't worry, it isn't that tricky.
First, take a look at this FAQ post: viewtopic.php?f=27&t=45552
And read wxWidgets docs: https://docs.wxwidgets.org/trunk/classw ... anvas.html, and the "see also" links.

Now, you can create a wxGLContext anywhere you like. But, because you must use later, at SetCurrent(), you'd better store it as a your-class member, and don't forget to delete it at class dtor.
In the code you posted you create it at OnSize() event handler. Good? No. As soon as the handler finishes the pointer you created by "new" is not stored (and not deleted, you have a memory leak), so no other code path can use this context.
And you need to create the context only once instead of every time the window changes its size.

As doublemax told you, in Unix the context must be set as current after the window has been realized. This condition becomes true when the windw has a valid size and it's shown too. That's why pyramid sample uses OnSize() handler, and checks IsShownOnScreen() before using SetCurrent(). Paint events can be handled before the window has a vlaid size, so, again, the sample checks this condition too.

Now, the glew thing. GLEW needs that the gl-context is set as current before trying to initializate its library. But if you haven't a var to store the context, how do you call SetCurrent(*mycontext)?
Be aware of using glewExperimental = GL_TRUE; before glewInit(). It was needed for finding pointers for OGL>2.1 . It was so as for glew 1.12, I don't know if newer versions still need it.

Finally, your OGL code. All shaders stuff and data binding may be executed once. I mean, when they change. Not at every paint-event handler. The GPU stores it all (unlike OGL<2.1) So the only commands really needed at pai nt-event are those that draw (glClear, glViewport if size changed, glDrawXXX,....). Again the pyramid sample splits these tasks and call them only when needed.

Go ahead!! You'll get it.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

New Pagodi wrote: Thu Oct 14, 2021 6:11 pm If you want to use wxGLCanvas with an extension loader like glew, glad, libepoxy, etc, the easiest thing is to put a helper class in between the wxWidgets code and the GL code and keep all of the GL stuff bottled up in the cpp file for that helper class.
Thank you for the example code. Its working now. However I was not able to run the application if I set the parent of wxGLCanvas to a wxPanel instead of the top wxFrame. Is it not possible to use a panel for the canvas? Or is the problem was with using a sizer for panel, as I had a sizer for panel as well?
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

Manolo wrote: Thu Oct 14, 2021 6:23 pm Are you starting to think OGL is a nightmare? Oh yeah. I know how you feel. Don't worry, it isn't that tricky.
First, take a look at this FAQ post: viewtopic.php?f=27&t=45552
And read wxWidgets docs: https://docs.wxwidgets.org/trunk/classw ... anvas.html, and the "see also" links.

Now, you can create a wxGLContext anywhere you like. But, because you must use later, at SetCurrent(), you'd better store it as a your-class member, and don't forget to delete it at class dtor.
In the code you posted you create it at OnSize() event handler. Good? No. As soon as the handler finishes the pointer you created by "new" is not stored (and not deleted, you have a memory leak), so no other code path can use this context.
And you need to create the context only once instead of every time the window changes its size.

As doublemax told you, in Unix the context must be set as current after the window has been realized. This condition becomes true when the windw has a valid size and it's shown too. That's why pyramid sample uses OnSize() handler, and checks IsShownOnScreen() before using SetCurrent(). Paint events can be handled before the window has a vlaid size, so, again, the sample checks this condition too.

Now, the glew thing. GLEW needs that the gl-context is set as current before trying to initializate its library. But if you haven't a var to store the context, how do you call SetCurrent(*mycontext)?
Be aware of using glewExperimental = GL_TRUE; before glewInit(). It was needed for finding pointers for OGL>2.1 . It was so as for glew 1.12, I don't know if newer versions still need it.

Finally, your OGL code. All shaders stuff and data binding may be executed once. I mean, when they change. Not at every paint-event handler. The GPU stores it all (unlike OGL<2.1) So the only commands really needed at pai nt-event are those that draw (glClear, glViewport if size changed, glDrawXXX,....). Again the pyramid sample splits these tasks and call them only when needed.

Go ahead!! You'll get it.
I only recently started learning opengl as you can probably tell by my example code I shared in original post. I found out about wxGL stuff and I wanted to use it in my application. So I started experimenting this as both a project and exercise for learning opengl.

Thanks for the all the helpful tips though.
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: How to setup wxGLContext properly?

Post by New Pagodi »

apoorv569 wrote: Fri Oct 15, 2021 3:20 pm Thank you for the example code. Its working now. However I was not able to run the application if I set the parent of wxGLCanvas to a wxPanel instead of the top wxFrame. Is it not possible to use a panel for the canvas? Or is the problem was with using a sizer for panel, as I had a sizer for panel as well?
I tried changing the constructor to this and it still works for me.

Code: Select all

wxGlewFrame::wxGlewFrame(wxWindow* parent)
    : wxFrame(parent,  wxID_ANY, wxString())
{
    wxPanel* bg = new wxPanel(this,wxID_ANY);

    // Create the canvas and context.
    #if wxCHECK_VERSION(3,1,0)
        // These settings should work with any GPU from the last 10 years.
        wxGLAttributes dispAttrs;
        dispAttrs.PlatformDefaults().RGBA().DoubleBuffer().EndList();

        wxGLContextAttrs cxtAttrs;
        cxtAttrs.PlatformDefaults().CoreProfile().OGLVersion(3, 3).EndList();

        m_canvas = new wxGLCanvas(bg, dispAttrs);
        m_context = new wxGLContext(m_canvas, NULL, &cxtAttrs);

        if ( !m_context->IsOK() )
        {
            SetTitle("Failed to create context.");
            return;
        }
    #else
        int dispAttrs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_CORE_PROFILE,
                            WX_GL_MAJOR_VERSION ,3, WX_GL_MINOR_VERSION, 3, 0 };

        m_canvas = new wxGLCanvas(this, wxID_ANY, dispAttrs);
        m_context = new wxGLContext(m_canvas, NULL);

        // Unfortunately, there doesn't seem to be any way to check if the
        // context is ok prior to wxWidgets 3.1.0.
    #endif // wxCHECK_VERSION

    // On Linux, we must delay delay initialization until the canvas has
    // been full created.  On windows, we can finish now.
    #ifdef __WXMSW__
        InitGL();
    #elif defined(__WXGTK__)
        m_canvas->Bind(wxEVT_CREATE, [this](wxWindowCreateEvent&){InitGL();});
    #endif // defined

    wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
    szr->Add(m_canvas, wxSizerFlags(1).Expand().Border(wxALL));
    bg->SetSizer(szr);
}
Are you sure you're setting the parent for the canvas correctly and adding it to the sizer with the correct flags?
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

New Pagodi wrote: Fri Oct 15, 2021 3:56 pm
apoorv569 wrote: Fri Oct 15, 2021 3:20 pm Thank you for the example code. Its working now. However I was not able to run the application if I set the parent of wxGLCanvas to a wxPanel instead of the top wxFrame. Is it not possible to use a panel for the canvas? Or is the problem was with using a sizer for panel, as I had a sizer for panel as well?
I tried changing the constructor to this and it still works for me.

Code: Select all

wxGlewFrame::wxGlewFrame(wxWindow* parent)
    : wxFrame(parent,  wxID_ANY, wxString())
{
    wxPanel* bg = new wxPanel(this,wxID_ANY);

    // Create the canvas and context.
    #if wxCHECK_VERSION(3,1,0)
        // These settings should work with any GPU from the last 10 years.
        wxGLAttributes dispAttrs;
        dispAttrs.PlatformDefaults().RGBA().DoubleBuffer().EndList();

        wxGLContextAttrs cxtAttrs;
        cxtAttrs.PlatformDefaults().CoreProfile().OGLVersion(3, 3).EndList();

        m_canvas = new wxGLCanvas(bg, dispAttrs);
        m_context = new wxGLContext(m_canvas, NULL, &cxtAttrs);

        if ( !m_context->IsOK() )
        {
            SetTitle("Failed to create context.");
            return;
        }
    #else
        int dispAttrs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_CORE_PROFILE,
                            WX_GL_MAJOR_VERSION ,3, WX_GL_MINOR_VERSION, 3, 0 };

        m_canvas = new wxGLCanvas(this, wxID_ANY, dispAttrs);
        m_context = new wxGLContext(m_canvas, NULL);

        // Unfortunately, there doesn't seem to be any way to check if the
        // context is ok prior to wxWidgets 3.1.0.
    #endif // wxCHECK_VERSION

    // On Linux, we must delay delay initialization until the canvas has
    // been full created.  On windows, we can finish now.
    #ifdef __WXMSW__
        InitGL();
    #elif defined(__WXGTK__)
        m_canvas->Bind(wxEVT_CREATE, [this](wxWindowCreateEvent&){InitGL();});
    #endif // defined

    wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
    szr->Add(m_canvas, wxSizerFlags(1).Expand().Border(wxALL));
    bg->SetSizer(szr);
}
Are you sure you're setting the parent for the canvas correctly and adding it to the sizer with the correct flags?
Ah! I was adding the panel to the sizer not the canvas. It works now. Thanks.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

New Pagodi wrote:
Are you sure you're setting the parent for the canvas correctly and adding it to the sizer with the correct flags?
Hi, Sorry to bother again, I'm having a slight problem. I copied the code to my real application, all is good, the applications open and works fine, except I get error saying,

Code: Select all

15:46:26: Debug: Failed to initialize GLEW.
I have all the code in a class which is inherited from wxPanel . Do by any chance I have to bind the size event to the main wxFrame instead?
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: How to setup wxGLContext properly?

Post by New Pagodi »

You need to have created a context and called SetCurrent with the context or GLEW initialization will fail. The initialization requires reading a bunch of global data that is only set correctly once those two things have been done.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

New Pagodi wrote: Sat Oct 16, 2021 1:51 pm You need to have created a context and called SetCurrent with the context or GLEW initialization will fail. The initialization requires reading a bunch of global data that is only set correctly once those two things have been done.
Yes, I am following the exact steps/code you shared above. Here is the link to the InitGL() on my repository https://gitlab.com/samplehive/sample-hi ... r.cpp#L107
New Pagodi
Super wx Problem Solver
Super wx Problem Solver
Posts: 466
Joined: Tue Jun 20, 2006 6:47 pm
Contact:

Re: How to setup wxGLContext properly?

Post by New Pagodi »

I think line 89

Code: Select all

this->SetDoubleBuffered(true);
needs to be removed (at least on windows - on linux it seems to work even with that line). At least for me on windows, glew initialization seems to succeed but none of the calls actually work.

Also, you never seem to be adding the canvas to a sizer in the wave form viewer panel.
apoorv569
Super wx Problem Solver
Super wx Problem Solver
Posts: 426
Joined: Tue Oct 20, 2020 3:35 pm

Re: How to setup wxGLContext properly?

Post by apoorv569 »

New Pagodi wrote: Sun Oct 17, 2021 5:12 pm I think line 89

Code: Select all

this->SetDoubleBuffered(true);
needs to be removed (at least on windows - on linux it seems to work even with that line). At least for me on windows, glew initialization seems to succeed but none of the calls actually work.

Also, you never seem to be adding the canvas to a sizer in the wave form viewer panel.
I commented out line 89, and added the sizer, but I'm getting the same error still, failed to initialize glew.

Code: Select all

WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataViewListCtrl& library,
                               wxMediaCtrl& mediaCtrl, Database& database,
                               const std::string& configFilepath, const std::string& databaseFilepath)
    : wxPanel(window, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER | wxFULL_REPAINT_ON_RESIZE),
      m_ParentFrame(parentFrame), m_Window(window), m_Database(database), m_Library(library), m_MediaCtrl(mediaCtrl),
      m_ConfigFilepath(configFilepath), m_DatabaseFilepath(databaseFilepath)
{
    m_CanvasSizer = new wxBoxSizer(wxVERTICAL);

    // Create the canvas and context.
    #if wxCHECK_VERSION(3, 1, 0)
        // These settings should work with any GPU from the last 10 years.
        wxGLAttributes display_attributes;
        display_attributes.PlatformDefaults().RGBA().DoubleBuffer().EndList();

        wxGLContextAttrs context_attributes;
        context_attributes.PlatformDefaults().CoreProfile().OGLVersion(3, 3).EndList();

        m_Canvas = new wxGLCanvas(this, display_attributes);
        m_Context = new wxGLContext(m_Canvas, NULL, &context_attributes);

        if (!m_Context->IsOK())
        {
            wxLogDebug("Failed to create context.");
            return;
        }
    #else
        int display_attributes[] =
            { WX_GL_RGBA,
              WX_GL_DOUBLEBUFFER,
              WX_GL_CORE_PROFILE,
              WX_GL_MAJOR_VERSION ,3,
              WX_GL_MINOR_VERSION, 3,
              0 };

        m_Canvas = new wxGLCanvas(this, wxID_ANY, display_attributes);
        m_Context = new wxGLContext(m_Canvas, NULL);

        // Unfortunately, there doesn't seem to be any way to check if the
        // context is ok prior to wxWidgets 3.1.0.
    #endif // wxCHECK_VERSION

    // On Linux, we must delay delay initialization until the canvas has
    // been fully created.  On windows, we can finish now.
    #ifdef __WXMSW__
        InitGL();
    #elif defined(__WXGTK__)
        m_Canvas->Bind(wxEVT_CREATE, [this](wxWindowCreateEvent&){ InitGL(); });
    #endif // defined

    m_CanvasSizer->Add(m_Canvas, wxSizerFlags(1).Expand().Border(wxALL));    <----

    this->SetSizer(m_CanvasSizer);
    m_CanvasSizer->Fit(this);
    m_CanvasSizer->SetSizeHints(this);
    m_CanvasSizer->Layout();

    // this->SetDoubleBuffered(true);

    // Bind(wxEVT_PAINT, &WaveformViewer::OnPaint, this);
    Bind(wxEVT_MOTION, &WaveformViewer::OnMouseMotion, this);
    Bind(wxEVT_LEFT_DOWN, &WaveformViewer::OnMouseLeftButtonDown, this);
    Bind(wxEVT_LEFT_UP, &WaveformViewer::OnMouseLeftButtonUp, this);
    // Bind(wxEVT_KEY_DOWN, &WaveformViewer::OnControlKeyDown, this);
    Bind(wxEVT_KEY_UP, &WaveformViewer::OnControlKeyUp, this);
}
Post Reply