Changed WaveformViewer from wxPanel to wxGLCanvas.
This commit is contained in:
parent
7174e52c48
commit
b349486eef
|
|
@ -202,7 +202,7 @@ if wx_found
|
|||
sources: src,
|
||||
cpp_args: [wx_cxx_flags],
|
||||
link_args: [wx_libs],
|
||||
dependencies: [wx, taglib, sqlite3, yaml, snd],
|
||||
dependencies: [wx, taglib, sqlite3, yaml, snd, glew],
|
||||
install: true,
|
||||
install_rpath: prefix / 'lib')
|
||||
else
|
||||
|
|
|
|||
130
src/GL.cpp
130
src/GL.cpp
|
|
@ -2,12 +2,36 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "GL.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <wx/event.h>
|
||||
|
||||
#define ASSERT(x) if (!(x)) raise(SIGTRAP);
|
||||
#define GLCall(x) GLClearError(); \
|
||||
x;\
|
||||
ASSERT(GLLogCall(__FUNCTION__, __FILE__, __LINE__))
|
||||
|
||||
static void GLClearError()
|
||||
{
|
||||
while (glGetError() != GL_NO_ERROR);
|
||||
}
|
||||
|
||||
static bool GLLogCall(const char* function, const char* file, int line)
|
||||
{
|
||||
while (GLenum error = glGetError())
|
||||
{
|
||||
std::cout << "[OpenGL Error] (" << error << "): " << function
|
||||
<< " " << file << ":" << line << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string ParseShader(const std::string& filepath)
|
||||
{
|
||||
std::string source;
|
||||
|
|
@ -36,18 +60,18 @@ static unsigned int CompileShader(unsigned int type, const std::string& source)
|
|||
{
|
||||
unsigned int id = glCreateShader(type);
|
||||
const char* src = source.c_str();
|
||||
glShaderSource(id, 1, &src , nullptr);
|
||||
glCompileShader(id);
|
||||
GLCall(glShaderSource(id, 1, &src , nullptr));
|
||||
GLCall(glCompileShader(id));
|
||||
|
||||
int result;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
||||
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
|
||||
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
int length;
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
|
||||
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
|
||||
char message[length];
|
||||
glGetShaderInfoLog(id, length, &length, message);
|
||||
GLCall(glGetShaderInfoLog(id, length, &length, message));
|
||||
|
||||
std::cout << "Failed to compile "
|
||||
<< (type == GL_VERTEX_SHADER ? "vertex" : "fragment")
|
||||
|
|
@ -55,7 +79,7 @@ static unsigned int CompileShader(unsigned int type, const std::string& source)
|
|||
|
||||
std::cout << message << std::endl;
|
||||
|
||||
glDeleteShader(id);
|
||||
GLCall(glDeleteShader(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -63,35 +87,103 @@ static unsigned int CompileShader(unsigned int type, const std::string& source)
|
|||
return id;
|
||||
}
|
||||
|
||||
static unsigned int CreateShader(unsigned int type, const std::string& source)
|
||||
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
|
||||
{
|
||||
unsigned int program = glCreateProgram();
|
||||
GLCall(unsigned int program = glCreateProgram());
|
||||
|
||||
unsigned int shader = CompileShader(type, source);
|
||||
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
|
||||
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
|
||||
|
||||
glAttachShader(program, shader);
|
||||
glLinkProgram(program);
|
||||
glValidateProgram(program);
|
||||
GLCall(glAttachShader(program, vs));
|
||||
GLCall(glAttachShader(program, fs));
|
||||
GLCall(glLinkProgram(program));
|
||||
GLCall(glValidateProgram(program));
|
||||
|
||||
glDeleteShader(shader);
|
||||
GLCall(glDeleteShader(vs));
|
||||
GLCall(glDeleteShader(fs));
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
bool GLHelper::InitGlew()
|
||||
{
|
||||
GLenum initStatus = glewInit();
|
||||
// GLCall(glewExperimental = GL_TRUE);
|
||||
|
||||
return initStatus == GLEW_OK;
|
||||
GLCall(GLenum init_status = glewInit());
|
||||
|
||||
if (init_status != GLEW_OK)
|
||||
{
|
||||
GLCall(const GLubyte* error = glewGetErrorString(init_status));
|
||||
|
||||
std::cout << "GLEW Error: " << error << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLHelper::Render()
|
||||
{
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// 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;
|
||||
// GLCall(glGenVertexArrays(1, &vertex_array_object));
|
||||
// GLCall(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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
GLCall(glClearColor(0.4f, 0.2f, 0.8f, 1.0f));
|
||||
GLCall(glClear(GL_COLOR_BUFFER_BIT));
|
||||
}
|
||||
|
||||
void GLHelper::SetSize(int width, int height)
|
||||
void GLHelper::SetViewport(int x, int y, int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
GLCall(glViewport(x, y, width, height));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ class GLHelper
|
|||
public:
|
||||
bool InitGlew();
|
||||
void Render();
|
||||
void SetSize(int w, int h);
|
||||
void SetViewport(int x, int y, int width, int height);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -404,7 +404,18 @@ MainFrame::MainFrame()
|
|||
m_Database->CreateTableSamples();
|
||||
m_Database->CreateTableHives();
|
||||
|
||||
m_TopWaveformPanel = new WaveformViewer(this, m_TopPanel, *m_Library, *m_MediaCtrl, *m_Database,
|
||||
wxGLAttributes display_attributes;
|
||||
display_attributes.PlatformDefaults().RGBA().DoubleBuffer().EndList();
|
||||
|
||||
// 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_TopWaveformPanel = new WaveformViewer(this, m_TopPanel, display_attributes, *m_Library, *m_MediaCtrl, *m_Database,
|
||||
m_ConfigFilepath, m_DatabaseFilepath);
|
||||
|
||||
// Binding events.
|
||||
|
|
|
|||
|
|
@ -183,7 +183,9 @@ class MainFrame : public wxFrame
|
|||
wxLongLong m_LoopA, m_LoopB;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
#if wxCHECK_VERSION(3, 1, 0)
|
||||
wxSystemAppearance m_Theme = wxSystemSettings::GetAppearance();
|
||||
#endif
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -38,24 +38,27 @@
|
|||
|
||||
#include <sndfile.hh>
|
||||
|
||||
WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataViewListCtrl& library,
|
||||
wxMediaCtrl& mediaCtrl, Database& database,
|
||||
// WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, int* attrs,
|
||||
WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, const wxGLAttributes& attrs,
|
||||
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),
|
||||
: wxGLCanvas(window, attrs),
|
||||
// : wxGLCanvas(window, wxID_ANY, attrs),
|
||||
// : 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)
|
||||
{
|
||||
// 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();
|
||||
// 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);
|
||||
// this = new wxGLCanvas(this, display_attributes);
|
||||
m_Context = new wxGLContext(this, NULL, &context_attributes);
|
||||
|
||||
if (!m_Context->IsOK())
|
||||
{
|
||||
|
|
@ -63,16 +66,16 @@ WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataVi
|
|||
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 };
|
||||
// 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);
|
||||
// this = new wxGLCanvas(this, wxID_ANY, display_attributes);
|
||||
m_Context = new wxGLContext(this, NULL);
|
||||
|
||||
// Unfortunately, there doesn't seem to be any way to check if the
|
||||
// context is ok prior to wxWidgets 3.1.0.
|
||||
|
|
@ -80,15 +83,17 @@ WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataVi
|
|||
|
||||
// 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
|
||||
// #ifdef __WXMSW__
|
||||
// InitGL();
|
||||
// #elif defined(__WXGTK__)
|
||||
// this->Bind(wxEVT_CREATE, [this](wxWindowCreateEvent&){ InitGL(); });
|
||||
// #endif // defined
|
||||
|
||||
this->SetDoubleBuffered(true);
|
||||
// this->SetDoubleBuffered(true);
|
||||
|
||||
// Bind(wxEVT_PAINT, &WaveformViewer::OnPaint, this);
|
||||
Bind(wxEVT_SIZE, &WaveformViewer::OnSize, this);
|
||||
|
||||
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);
|
||||
|
|
@ -101,42 +106,75 @@ WaveformViewer::~WaveformViewer()
|
|||
delete m_Context;
|
||||
}
|
||||
|
||||
void WaveformViewer::InitGL()
|
||||
bool WaveformViewer::InitGL()
|
||||
{
|
||||
if (!m_Context)
|
||||
return false;
|
||||
|
||||
// The current context must be set before we get OGL pointers
|
||||
if (!IsShownOnScreen())
|
||||
return false;
|
||||
// else
|
||||
// SetCurrent(*m_Context);
|
||||
|
||||
// First call SetCurrent or GL initialization will fail.
|
||||
m_Context->SetCurrent(*m_Canvas);
|
||||
if (!m_Context->SetCurrent(*this))
|
||||
{
|
||||
wxLogDebug("Error! Unable to set the context");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize GLEW.
|
||||
bool glewInialized = m_Helper.InitGlew();
|
||||
|
||||
if (!glewInialized)
|
||||
if (!m_GLHelper.InitGlew())
|
||||
{
|
||||
wxLogDebug("Failed to initialize GLEW.");
|
||||
return;
|
||||
wxLogDebug("Error %s()! Failed to initialize GLEW.", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
wxLogDebug("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, &WaveformViewer::OnSize, this);
|
||||
m_Canvas->Bind(wxEVT_PAINT, &WaveformViewer::OnPaint, this);
|
||||
// this->Bind(wxEVT_SIZE, &WaveformViewer::OnSize, this);
|
||||
// this->Bind(wxEVT_PAINT, &WaveformViewer::OnPaint, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaveformViewer::OnSize(wxSizeEvent &event)
|
||||
{
|
||||
wxSize sz = event.GetSize();
|
||||
m_Helper.SetSize(sz.GetWidth(), sz.GetHeight());
|
||||
|
||||
event.Skip();
|
||||
|
||||
// First call SetCurrent or GL initialization will fail.
|
||||
// if (!m_Context->SetCurrent(*this))
|
||||
// wxLogDebug("Error from %s! Unable to set the context", __FUNCTION__);
|
||||
|
||||
// if (!InitGL())
|
||||
// wxLogDebug("Failed to initialize GL");
|
||||
// else
|
||||
// wxLogDebug("Canvas ready, initializing GL..");
|
||||
|
||||
// PostSizeEvent();
|
||||
|
||||
InitGL();
|
||||
|
||||
wxSize size = event.GetSize() * GetContentScaleFactor();
|
||||
m_GLHelper.SetViewport(0, 0, size.x, size.y);
|
||||
|
||||
// Refresh(false);
|
||||
}
|
||||
|
||||
void WaveformViewer::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(m_Canvas);
|
||||
wxPaintDC dc(this);
|
||||
|
||||
m_Helper.Render();
|
||||
m_Canvas->SwapBuffers();
|
||||
// First call SetCurrent or GL initialization will fail.
|
||||
if (!m_Context->SetCurrent(*this))
|
||||
wxLogDebug("Error from %s! Unable to set the context", __FUNCTION__);
|
||||
|
||||
m_GLHelper.Render();
|
||||
|
||||
this->SwapBuffers();
|
||||
|
||||
// wxPaintDC dc(this);
|
||||
|
||||
|
|
|
|||
|
|
@ -37,11 +37,13 @@
|
|||
#include <wx/timer.h>
|
||||
#include <wx/window.h>
|
||||
|
||||
class WaveformViewer : public wxPanel
|
||||
class WaveformViewer : public wxGLCanvas
|
||||
{
|
||||
public:
|
||||
WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataViewListCtrl& library,
|
||||
wxMediaCtrl& mediaCtrl, Database& database,
|
||||
// WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataViewListCtrl& library,
|
||||
// WaveformViewer(wxWindow* parentFrame, wxWindow* window, int* attrs,
|
||||
WaveformViewer(wxWindow* parentFrame, wxWindow* window, const wxGLAttributes& attrs,
|
||||
wxDataViewListCtrl& library, wxMediaCtrl& mediaCtrl, Database& database,
|
||||
const std::string& configFilepath, const std::string& databaseFilepath);
|
||||
~WaveformViewer();
|
||||
|
||||
|
|
@ -74,7 +76,7 @@ class WaveformViewer : public wxPanel
|
|||
// -------------------------------------------------------------------
|
||||
wxGLCanvas* m_Canvas;
|
||||
wxGLContext* m_Context;
|
||||
GLHelper m_Helper;
|
||||
GLHelper m_GLHelper;
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
|
|
@ -85,7 +87,7 @@ class WaveformViewer : public wxPanel
|
|||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
void InitGL();
|
||||
bool InitGL();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void OnSize(wxSizeEvent& event);
|
||||
|
|
|
|||
Loading…
Reference in New Issue