Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal-apps
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d9981078bf01
Choose a base ref
...
head repository: ngscopeclient/scopehal-apps
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 12e15b3f6bce
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Apr 27, 2021

  1. Initial implementation of spectrogram rendering. Correctly scaled for…

    … X axis, haven't touched Y yet.
    azonenberg committed Apr 27, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8c860b9 View commit details
  2. Copy the full SHA
    12e15b3 View commit details
40 changes: 39 additions & 1 deletion src/glscopeclient/WaveformArea.cpp
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
* *
* glscopeclient *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* Copyright (c) 2012-2021 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
@@ -571,6 +571,7 @@ void WaveformArea::on_realize()
InitializeColormapPass();
InitializeCairoPass();
InitializeEyePass();
InitializeSpectrogramPass();
}

void WaveformArea::on_unrealize()
@@ -590,17 +591,20 @@ void WaveformArea::CleanupGLHandles()
m_analogWaveformComputeProgram.Destroy();
m_colormapProgram.Destroy();
m_eyeProgram.Destroy();
m_spectrogramProgram.Destroy();
m_cairoProgram.Destroy();

//Clean up old VAOs
m_colormapVAO.Destroy();
m_cairoVAO.Destroy();
m_eyeVAO.Destroy();
m_spectrogramVAO.Destroy();

//Clean up old VBOs
m_colormapVBO.Destroy();
m_cairoVBO.Destroy();
m_eyeVBO.Destroy();
m_spectrogramVBO.Destroy();

//Clean up old textures
m_cairoTexture.Destroy();
@@ -762,6 +766,35 @@ void WaveformArea::InitializeEyePass()
}
}

void WaveformArea::InitializeSpectrogramPass()
{
//Set up shaders
VertexShader cvs;
FragmentShader cfs;
if(!cvs.Load("shaders/spectrogram-vertex.glsl", NULL) || !cfs.Load("shaders/spectrogram-fragment.glsl", NULL))
LogFatal("failed to load spectrogram shaders, aborting\n");

m_spectrogramProgram.Add(cvs);
m_spectrogramProgram.Add(cfs);
if(!m_spectrogramProgram.Link())
LogFatal("failed to link shader program, aborting\n");

//Create the VAO/VBO for a fullscreen polygon
float verts[8] =
{
-1, -1,
1, -1,
1, 1,
-1, 1
};
m_spectrogramVBO.Bind();
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

m_spectrogramVAO.Bind();
m_spectrogramProgram.EnableVertexArray("vert");
m_spectrogramProgram.SetVertexAttribPointer("vert", 2, 0);
}

void WaveformArea::InitializeCairoPass()
{
//Set up shaders
@@ -812,6 +845,11 @@ bool WaveformArea::IsEye()
return (m_channel.m_channel->GetType() == OscilloscopeChannel::CHANNEL_TYPE_EYE);
}

bool WaveformArea::IsSpectrogram()
{
return (m_channel.m_channel->GetType() == OscilloscopeChannel::CHANNEL_TYPE_SPECTROGRAM);
}

bool WaveformArea::IsEyeOrBathtub()
{
//TODO: this should really be "is fixed two UI wide plot"
11 changes: 10 additions & 1 deletion src/glscopeclient/WaveformArea.h
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
* *
* glscopeclient *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* Copyright (c) 2012-2021 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
@@ -42,6 +42,7 @@

class WaveformArea;
class EyeWaveform;
class SpectrogramWaveform;
class PacketDecoder;

/**
@@ -153,6 +154,7 @@ class WaveformArea : public Gtk::GLArea
//Helpers for figuring out what kind of signal our primary trace is
bool IsAnalog();
bool IsDigital();
bool IsSpectrogram();
bool IsEye();
bool IsEyeOrBathtub();
bool IsWaterfall();
@@ -331,6 +333,13 @@ class WaveformArea : public Gtk::GLArea
Texture m_eyeTexture;
Texture m_eyeColorRamp[6];

//Spectrogram rendering
void RenderSpectrogram();
void InitializeSpectrogramPass();
VertexArray m_spectrogramVAO;
VertexBuffer m_spectrogramVBO;
Program m_spectrogramProgram;

//Waterfall rendering
void RenderWaterfall();

52 changes: 50 additions & 2 deletions src/glscopeclient/WaveformArea_rendering.cpp
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
* *
* glscopeclient *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* Copyright (c) 2012-2021 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
@@ -40,6 +40,7 @@
#include <map>
#include <immintrin.h>
#include "../../lib/scopeprotocols/EyePattern.h"
#include "../../lib/scopeprotocols/SpectrogramFilter.h"
#include "../../lib/scopeprotocols/Waterfall.h"

using namespace std;
@@ -471,7 +472,9 @@ void WaveformArea::RenderMainTrace()
{
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, m_plotRight, m_height);
if(IsEye())
if(IsSpectrogram())
RenderSpectrogram();
else if(IsEye())
RenderEye();
else if(IsWaterfall())
RenderWaterfall();
@@ -522,6 +525,51 @@ void WaveformArea::RenderEye()
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void WaveformArea::RenderSpectrogram()
{
if(m_channel.m_channel->GetType() != OscilloscopeChannel::CHANNEL_TYPE_SPECTROGRAM)
return;
auto pcap = dynamic_cast<SpectrogramWaveform*>(m_channel.GetData());
if(pcap == NULL)
return;

//Reuse the texture from the eye pattern rendering path
m_eyeTexture.Bind();
ResetTextureFiltering();
m_eyeTexture.SetData(
pcap->GetWidth(),
pcap->GetHeight(),
pcap->GetData(),
GL_RED,
GL_FLOAT,
GL_RGBA32F);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);

//Figure out the X scale and offset factors.
float xpixscale = m_group->m_pixelsPerXUnit / m_width;
float xoff = (m_group->m_xAxisOffset + pcap->GetStartTime()) * xpixscale;
float xscale = pcap->GetDuration() * xpixscale;

//Figure out Y axis scale and offset
float range = m_channel.m_channel->GetVoltageRange();
float yoff = -m_channel.m_channel->GetOffset() / range - 0.5;
float yscale = pcap->GetMaxFrequency() / range;

m_spectrogramProgram.Bind();
m_spectrogramVAO.Bind();
m_spectrogramProgram.SetUniform(xscale, "xscale");
m_spectrogramProgram.SetUniform(xoff, "xoff");
m_spectrogramProgram.SetUniform(yscale, "yscale");
m_spectrogramProgram.SetUniform(yoff, "yoff");
m_spectrogramProgram.SetUniform(m_eyeTexture, "fbtex", 0);
m_spectrogramProgram.SetUniform(m_eyeColorRamp[m_parent->GetEyeColor()], "ramp", 1);

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void WaveformArea::RenderWaterfall()
{
auto pfall = dynamic_cast<Waterfall*>(m_channel.m_channel);
33 changes: 33 additions & 0 deletions src/glscopeclient/shaders/spectrogram-fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#version 130

in vec2 texcoord;
uniform sampler2D fbtex;
uniform sampler2D ramp;

out vec4 finalColor;

void main()
{
if( (texcoord.x < 0) || (texcoord.x > 1) )
discard;

//Look up the intensity value and clamp it
vec4 yvec = texture(fbtex, vec2(texcoord));
float y = yvec.r;
if( (texcoord.x < 0) || (texcoord.y > 1) )
if(y >= 0.99)
y = 0.99;
if(y < 0.001)
discard;

//Look up the actual color
vec2 pos;
pos.x = y;
pos.y = 0.5;
vec4 color = texture(ramp, pos);

finalColor.r = color.r;
finalColor.g = color.g;
finalColor.b = color.b;
finalColor.a = 1;
}
16 changes: 16 additions & 0 deletions src/glscopeclient/shaders/spectrogram-vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#version 130

in vec2 vert;
out vec2 texcoord;

uniform float xscale;
uniform float xoff;

uniform float yscale;
uniform float yoff;

void main()
{
gl_Position = vec4((vert.x+1)*xscale - 2*xoff - 1, (vert.y+1)*yscale - 2*yoff - 1, 0, 1);
texcoord = vec2((vert.x+1)/2, (vert.y + 1)/2 );
}