Trying out OpenGL to render waveform.
This commit is contained in:
parent
0ecf694997
commit
7174e52c48
13
meson.build
13
meson.build
|
|
@ -121,6 +121,7 @@ src = [
|
|||
'src/Serialize.cpp',
|
||||
'src/Tags.cpp',
|
||||
'src/WaveformViewer.cpp',
|
||||
'src/GL.cpp',
|
||||
'src/SH_Event.cpp',
|
||||
|
||||
]
|
||||
|
|
@ -137,12 +138,14 @@ if not wx.found()
|
|||
wx_base = wx_subproject.dependency('wxbase')
|
||||
wx_core = wx_subproject.dependency('wxcore')
|
||||
wx_media = wx_subproject.dependency('wxmedia')
|
||||
wx = [wx_core, wx_base, wx_media]
|
||||
wx_gl = wx_subproject.dependency('wxgl')
|
||||
|
||||
wx = [wx_core, wx_base, wx_media, wx_gl]
|
||||
else
|
||||
wx_found = true
|
||||
|
||||
wxconfig = find_program(['wx-config-gtk3', 'wx-config'])
|
||||
wx_modules = ['media', 'std']
|
||||
wxconfig = find_program(['wx-config', 'wx-config-gtk3', 'wx-config-3.1'])
|
||||
wx_modules = ['gl', 'media', 'std']
|
||||
wx_cxx_flags = []
|
||||
wx_libs = []
|
||||
|
||||
|
|
@ -183,6 +186,8 @@ if not snd.found()
|
|||
snd = snd_subproject.dependency('sndfile')
|
||||
endif
|
||||
|
||||
glew = dependency('glew')
|
||||
|
||||
# Create samplehive-config.h based on configuration
|
||||
config_h = configure_file(output: 'SampleHiveConfig.hpp',
|
||||
configuration: config_data,)
|
||||
|
|
@ -203,7 +208,7 @@ if wx_found
|
|||
else
|
||||
executable('SampleHive',
|
||||
sources: src,
|
||||
dependencies: [wx, taglib, sqlite3, yaml, snd],
|
||||
dependencies: [wx, taglib, sqlite3, yaml, snd, glew],
|
||||
install: true,
|
||||
install_rpath: prefix / 'lib')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "GL.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <wx/event.h>
|
||||
|
||||
static std::string ParseShader(const std::string& filepath)
|
||||
{
|
||||
std::string source;
|
||||
|
||||
std::ifstream stream(filepath);
|
||||
std::stringstream shader_stream;
|
||||
|
||||
stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
|
||||
try
|
||||
{
|
||||
shader_stream << stream.rdbuf();
|
||||
stream.close();
|
||||
|
||||
source = shader_stream.str();
|
||||
}
|
||||
catch(std::ifstream::failure e)
|
||||
{
|
||||
std::cout << "Error! Could not parse shader file." << e.code() << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int result;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
||||
|
||||
if (result == GL_FALSE)
|
||||
{
|
||||
int length;
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
|
||||
char message[length];
|
||||
glGetShaderInfoLog(id, length, &length, message);
|
||||
|
||||
std::cout << "Failed to compile "
|
||||
<< (type == GL_VERTEX_SHADER ? "vertex" : "fragment")
|
||||
<< "shader" << std::endl;
|
||||
|
||||
std::cout << message << std::endl;
|
||||
|
||||
glDeleteShader(id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static unsigned int CreateShader(unsigned int type, const std::string& source)
|
||||
{
|
||||
unsigned int program = glCreateProgram();
|
||||
|
||||
unsigned int shader = CompileShader(type, source);
|
||||
|
||||
glAttachShader(program, shader);
|
||||
glLinkProgram(program);
|
||||
glValidateProgram(program);
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
class GLHelper
|
||||
{
|
||||
public:
|
||||
bool InitGlew();
|
||||
void Render();
|
||||
void SetSize(int w, int h);
|
||||
};
|
||||
|
|
@ -45,9 +45,50 @@ WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataVi
|
|||
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();
|
||||
|
||||
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
|
||||
|
||||
this->SetDoubleBuffered(true);
|
||||
|
||||
Bind(wxEVT_PAINT, &WaveformViewer::OnPaint, 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);
|
||||
|
|
@ -57,55 +98,90 @@ WaveformViewer::WaveformViewer(wxWindow* parentFrame, wxWindow* window, wxDataVi
|
|||
|
||||
WaveformViewer::~WaveformViewer()
|
||||
{
|
||||
delete m_Context;
|
||||
}
|
||||
|
||||
void WaveformViewer::InitGL()
|
||||
{
|
||||
// First call SetCurrent or GL initialization will fail.
|
||||
m_Context->SetCurrent(*m_Canvas);
|
||||
|
||||
// Initialize GLEW.
|
||||
bool glewInialized = m_Helper.InitGlew();
|
||||
|
||||
if (!glewInialized)
|
||||
{
|
||||
wxLogDebug("Failed to initialize GLEW.");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void WaveformViewer::OnSize(wxSizeEvent &event)
|
||||
{
|
||||
wxSize sz = event.GetSize();
|
||||
m_Helper.SetSize(sz.GetWidth(), sz.GetHeight());
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void WaveformViewer::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
wxPaintDC dc(m_Canvas);
|
||||
|
||||
const wxSize& size = m_Window->GetClientSize();
|
||||
m_Helper.Render();
|
||||
m_Canvas->SwapBuffers();
|
||||
|
||||
if (!m_WaveformBitmap.IsOk()
|
||||
|| m_WaveformBitmap.GetWidth() != size.x
|
||||
|| m_WaveformBitmap.GetHeight() != size.y
|
||||
|| bBitmapDirty)
|
||||
{
|
||||
wxLogDebug("Updating waveform bitmap..");
|
||||
// wxPaintDC dc(this);
|
||||
|
||||
m_WaveformBitmap = wxBitmap(wxImage(size.x, size.y), 32);
|
||||
// const wxSize& size = m_Window->GetClientSize();
|
||||
|
||||
UpdateWaveformBitmap();
|
||||
// if (!m_WaveformBitmap.IsOk()
|
||||
// || m_WaveformBitmap.GetWidth() != size.x
|
||||
// || m_WaveformBitmap.GetHeight() != size.y
|
||||
// || bBitmapDirty)
|
||||
// {
|
||||
// wxLogDebug("Updating waveform bitmap..");
|
||||
|
||||
bBitmapDirty = false;
|
||||
}
|
||||
// m_WaveformBitmap = wxBitmap(wxImage(size.x, size.y), 32);
|
||||
|
||||
dc.DrawBitmap(m_WaveformBitmap, 0, 0, false);
|
||||
// UpdateWaveformBitmap();
|
||||
|
||||
RenderPlayhead(dc);
|
||||
// bBitmapDirty = false;
|
||||
// }
|
||||
|
||||
// Draw selection range
|
||||
if (bSelectRange)
|
||||
{
|
||||
wxRect rect(m_CurrentPoint, m_AnchorPoint);
|
||||
// dc.DrawBitmap(m_WaveformBitmap, 0, 0, false);
|
||||
|
||||
dc.SetPen(wxPen(wxColour(200, 200, 200), 2, wxPENSTYLE_SOLID));
|
||||
dc.SetBrush(wxBrush(wxColour(200, 200, 200, 80), wxBRUSHSTYLE_SOLID));
|
||||
dc.DrawRectangle(rect);
|
||||
}
|
||||
// RenderPlayhead(dc);
|
||||
|
||||
// Draw selected area
|
||||
if (!bSelectRange && bDrawSelectedArea && !bBitmapDirty)
|
||||
{
|
||||
dc.SetPen(wxPen(wxColour(200, 200, 200, 255), 4, wxPENSTYLE_SOLID));
|
||||
dc.SetBrush(wxBrush(wxColour(200, 200, 200, 80), wxBRUSHSTYLE_SOLID));
|
||||
dc.DrawRectangle(wxRect(m_AnchorPoint.x, -2, m_CurrentPoint.x - m_AnchorPoint.x, this->GetSize().GetHeight() + 5));
|
||||
// // Draw selection range
|
||||
// if (bSelectRange)
|
||||
// {
|
||||
// wxRect rect(m_CurrentPoint, m_AnchorPoint);
|
||||
|
||||
bAreaSelected = true;
|
||||
SendLoopPoints();
|
||||
}
|
||||
else
|
||||
bAreaSelected = false;
|
||||
// dc.SetPen(wxPen(wxColour(200, 200, 200), 2, wxPENSTYLE_SOLID));
|
||||
// dc.SetBrush(wxBrush(wxColour(200, 200, 200, 80), wxBRUSHSTYLE_SOLID));
|
||||
// dc.DrawRectangle(rect);
|
||||
// }
|
||||
|
||||
// // Draw selected area
|
||||
// if (!bSelectRange && bDrawSelectedArea && !bBitmapDirty)
|
||||
// {
|
||||
// dc.SetPen(wxPen(wxColour(200, 200, 200, 255), 4, wxPENSTYLE_SOLID));
|
||||
// dc.SetBrush(wxBrush(wxColour(200, 200, 200, 80), wxBRUSHSTYLE_SOLID));
|
||||
// dc.DrawRectangle(wxRect(m_AnchorPoint.x, -2, m_CurrentPoint.x - m_AnchorPoint.x, this->GetSize().GetHeight() + 5));
|
||||
|
||||
// bAreaSelected = true;
|
||||
// SendLoopPoints();
|
||||
// }
|
||||
// else
|
||||
// bAreaSelected = false;
|
||||
}
|
||||
|
||||
void WaveformViewer::RenderPlayhead(wxDC& dc)
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "Database.hpp"
|
||||
#include "GL.hpp"
|
||||
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/infobar.h>
|
||||
#include <wx/mediactrl.h>
|
||||
#include <wx/panel.h>
|
||||
|
|
@ -48,10 +50,12 @@ class WaveformViewer : public wxPanel
|
|||
wxWindow* m_ParentFrame;
|
||||
wxWindow* m_Window;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
Database& m_Database;
|
||||
wxDataViewListCtrl& m_Library;
|
||||
wxMediaCtrl& m_MediaCtrl;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
const std::string& m_ConfigFilepath;
|
||||
const std::string& m_DatabaseFilepath;
|
||||
|
||||
|
|
@ -66,6 +70,12 @@ class WaveformViewer : public wxPanel
|
|||
wxPoint m_AnchorPoint;
|
||||
wxPoint m_CurrentPoint;
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
wxGLCanvas* m_Canvas;
|
||||
wxGLContext* m_Context;
|
||||
GLHelper m_Helper;
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
bool bBitmapDirty = false;
|
||||
|
|
@ -75,6 +85,10 @@ class WaveformViewer : public wxPanel
|
|||
|
||||
private:
|
||||
// -------------------------------------------------------------------
|
||||
void InitGL();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void OnSize(wxSizeEvent& event);
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void RenderPlayhead(wxDC& dc);
|
||||
void UpdateWaveformBitmap();
|
||||
|
|
|
|||
Loading…
Reference in New Issue