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: 7742f53ec359
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: 6c1977a26fe6
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Feb 24, 2020

  1. Copy the full SHA
    6c1977a View commit details
Showing with 105 additions and 106 deletions.
  1. +3 −3 glscopeclient/WaveformArea.h
  2. +12 −55 glscopeclient/WaveformArea_cairo.cpp
  3. +9 −1 glscopeclient/WaveformArea_events.cpp
  4. +81 −47 glscopeclient/WaveformArea_rendering.cpp
6 changes: 3 additions & 3 deletions glscopeclient/WaveformArea.h
Original file line number Diff line number Diff line change
@@ -254,17 +254,17 @@ class WaveformArea : public Gtk::GLArea
//Trace rendering
void RenderTrace(WaveformRenderData* wdata);
void InitializeWaveformPass();
void PrepareAnalogGeometry(WaveformRenderData* wdata);
void PrepareDigitalGeometry(WaveformRenderData* wdata);
void PrepareGeometry(WaveformRenderData* wdata);
Program m_waveformComputeProgram;
WaveformRenderData* m_waveformRenderData;
std::map<ProtocolDecoder*, WaveformRenderData*> m_overlayRenderData;

//Final compositing
void RenderMainTrace();
void RenderOverlayTraces();

//Color correction
void RenderTraceColorCorrection();
void RenderTraceColorCorrection(WaveformRenderData* wdata);
void InitializeColormapPass();
VertexArray m_colormapVAO;
VertexBuffer m_colormapVBO;
67 changes: 12 additions & 55 deletions glscopeclient/WaveformArea_cairo.cpp
Original file line number Diff line number Diff line change
@@ -281,17 +281,22 @@ void WaveformArea::RenderDecodeOverlays(Cairo::RefPtr< Cairo::Context > cr)
auto render = o->CreateRenderer();
auto data = o->GetData();

bool digital = dynamic_cast<DigitalRenderer*>(render) != NULL;

double ymid = m_overlayPositions[o];
double ytop = ymid - height/2;
double ybot = ymid + height/2;

//Render the grayed-out background
cr->set_source_rgba(0,0,0, 0.6);
cr->move_to(0, ytop);
cr->line_to(m_plotRight, ytop);
cr->line_to(m_plotRight, ybot);
cr->line_to(0, ybot);
cr->fill();
if(!digital)
{
//Render the grayed-out background
cr->set_source_rgba(0,0,0, 0.6);
cr->move_to(0, ytop);
cr->line_to(m_plotRight, ytop);
cr->line_to(m_plotRight, ybot);
cr->line_to(0, ybot);
cr->fill();
}

Rect chanbox;
RenderChannelInfoBox(o, cr, ybot, o->m_displayname, chanbox, 2);
@@ -330,54 +335,6 @@ void WaveformArea::RenderDecodeOverlays(Cairo::RefPtr< Cairo::Context > cr)
}
}

//Handle digital
auto dr = dynamic_cast<DigitalRenderer*>(render);
Gdk::Color color(o->m_displaycolor);
cr->set_source_rgb(color.get_red_p(), color.get_green_p(), color.get_blue_p());
bool first = true;
double last_end = -100;
if(dr != NULL)
{
auto ddat = dynamic_cast<DigitalCapture*>(data);
for(size_t i=0; i<data->GetDepth(); i++)
{
double start = (data->GetSampleStart(i) * data->m_timescale) + data->m_triggerPhase;
double end = start + (data->GetSampleLen(i) * data->m_timescale);

double xs = XAxisUnitsToXPosition(start);
double xe = XAxisUnitsToXPosition(end);

if( (xe < textright) || (xs > m_plotRight) )
continue;

//Clamp
if(xe > m_plotRight)
xe = m_plotRight;

double y = ybot;
if((*ddat)[i])
y = ytop;

//Handle gaps between samples
if( (xs - last_end) > 2)
first = true;
last_end = xe;

//start of sample
if(first)
{
cr->move_to(xs, y);
first = false;
}
else
cr->line_to(xs, y);

//end of sample
cr->line_to(xe, y);
}
cr->stroke();
}

delete render;
}
}
10 changes: 9 additions & 1 deletion glscopeclient/WaveformArea_events.cpp
Original file line number Diff line number Diff line change
@@ -70,11 +70,19 @@ void WaveformArea::on_resize(int width, int height)
if(err != 0)
LogNotice("resize 2, err = %x\n", err);

//Allocate waveform texture
//Reallocate waveform texture
m_waveformRenderData->m_waveformTexture.Bind();
m_waveformRenderData->m_waveformTexture.SetData(width, height, NULL, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA32F);
ResetTextureFiltering();

//Reallocate textures for overlays
for(auto it : m_overlayRenderData)
{
it.second->m_waveformTexture.Bind();
it.second->m_waveformTexture.SetData(width, height, NULL, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA32F);
ResetTextureFiltering();
}

SetGeometryDirty();

err = glGetError();
128 changes: 81 additions & 47 deletions glscopeclient/WaveformArea_rendering.cpp
Original file line number Diff line number Diff line change
@@ -50,25 +50,37 @@ using namespace glm;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rendering

void WaveformArea::PrepareAnalogGeometry(WaveformRenderData* wdata)
void WaveformArea::PrepareGeometry(WaveformRenderData* wdata)
{
double start = GetTime();

//TODO: support digital channels
auto channel = wdata->m_channel;
auto pdat = dynamic_cast<AnalogCapture*>(channel->GetData());
if(!pdat || (pdat->size() == 0))
auto pdat = channel->GetData();
auto andat = dynamic_cast<AnalogCapture*>(pdat);
auto digdat = dynamic_cast<DigitalCapture*>(pdat);
if( !(andat && andat->GetDepth()) && !(digdat && digdat->GetDepth()))
{
wdata->m_geometryOK = false;
return;
}

size_t count = pdat->size();
size_t count;
if(andat)
count = andat->size();
else
count = digdat->size();
double xscale = pdat->m_timescale * m_group->m_pixelsPerXUnit;
float xoff = (pdat->m_triggerPhase - m_group->m_xAxisOffset) * m_group->m_pixelsPerXUnit;

bool fft = IsFFT();

//Zero voltage level
//TODO: don't assume all digital data is a protocol decode, logic analyzers are a thing!
//TODO: properly calculate decoder positions once RenderDecodeOverlays() isn't doing that anymore
float ybase = m_height/2;
if(digdat)
ybase = m_height - (m_overlayPositions[dynamic_cast<ProtocolDecoder*>(channel)] + 15);

//Calculate X/Y coordinate of each sample point
//TODO: some of this can probably move to GPU too?
vector<float> traceBuffer;
@@ -82,10 +94,15 @@ void WaveformArea::PrepareAnalogGeometry(WaveformRenderData* wdata)
traceBuffer[j*2] = pdat->GetSampleStart(j) * xscale + xoff;

float y;
if(fft)
y = DbToYPosition(-70 - (20 * log10((*pdat)[j]))); //TODO: don't hard code plot limits
if(digdat)
{
//TODO: digital overlay stuff
y = ybase + 5 + ( (*digdat)[j] ? 20: 0 );
}
else if(fft)
y = DbToYPosition(-70 - (20 * log10((*andat)[j]))); //TODO: don't hard code plot limits
else
y = (m_pixelsPerVolt * ((*pdat)[j] + offset)) + m_height/2;
y = (m_pixelsPerVolt * ((*andat)[j] + offset)) + ybase;

traceBuffer[j*2 + 1] = y;
}
@@ -145,11 +162,6 @@ void WaveformArea::PrepareAnalogGeometry(WaveformRenderData* wdata)
wdata->m_geometryOK = true;
}

void WaveformArea::PrepareDigitalGeometry(WaveformRenderData* wdata)
{
//TODO
}

void WaveformArea::ResetTextureFiltering()
{
//No texture filtering
@@ -199,35 +211,46 @@ bool WaveformArea::on_render(const Glib::RefPtr<Gdk::GLContext>& /*context*/)
RenderPersistenceOverlay();
*/

//Download the waveform to the GPU and kick off the compute shader for rendering it
//Download the main waveform to the GPU and kick off the compute shader for rendering it
if(IsAnalog())
{
PrepareAnalogGeometry(m_waveformRenderData);
PrepareGeometry(m_waveformRenderData);
RenderTrace(m_waveformRenderData);
}

//Launch software rendering passes and push the resulting data to the GPU
ComputeAndDownloadCairoUnderlays();
ComputeAndDownloadCairoOverlays();

//Do compute shader rendering for digital waveforms
for(auto overlay : m_overlays)
{
if(overlay->GetType() != OscilloscopeChannel::CHANNEL_TYPE_DIGITAL)
continue;

//Create render data if needed
//(can't do this when m_waveformRenderData is created because decoders are added later on)
if(m_overlayRenderData.find(overlay) == m_overlayRenderData.end())
m_overlayRenderData[overlay] = new WaveformRenderData(overlay);

//PrepareDigitalGeometry(m_overlayRenderData[overlay]);
//RenderTrace(m_overlayRenderData[overlay]);
}
//Create the texture
auto wdat = m_overlayRenderData[overlay];
wdat->m_waveformTexture.Bind();
wdat->m_waveformTexture.SetData(m_width, m_height, NULL, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA32F);
ResetTextureFiltering();

//Launch software rendering passes and push the resulting data to the GPU
ComputeAndDownloadCairoUnderlays();
ComputeAndDownloadCairoOverlays();
PrepareGeometry(wdat);
RenderTrace(wdat);
}

//
//Make sure all compute shaders are done before we composite
m_waveformComputeProgram.MemoryBarrier();

//Final compositing of data being drawn to the screen
m_windowFramebuffer.Bind(GL_FRAMEBUFFER);
RenderCairoUnderlays();
RenderMainTrace();
RenderOverlayTraces();
RenderCairoOverlays();

//Sanity check
@@ -243,17 +266,25 @@ bool WaveformArea::on_render(const Glib::RefPtr<Gdk::GLContext>& /*context*/)

void WaveformArea::RenderMainTrace()
{
//Make sure all compute shaders are done
m_waveformComputeProgram.MemoryBarrier();

glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, m_plotRight, m_height);
if(IsEye())
RenderEye();
else if(IsWaterfall())
RenderWaterfall();
else if(m_waveformRenderData->m_geometryOK)
RenderTraceColorCorrection();
else
RenderTraceColorCorrection(m_waveformRenderData);
glDisable(GL_SCISSOR_TEST);
}

void WaveformArea::RenderOverlayTraces()
{
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, m_plotRight, m_height);

for(auto it : m_overlayRenderData)
RenderTraceColorCorrection(it.second);

glDisable(GL_SCISSOR_TEST);
}

@@ -366,6 +397,29 @@ void WaveformArea::RenderTrace(WaveformRenderData* data)
m_waveformComputeProgram.DispatchCompute(numGroups, 1, 1);
}

void WaveformArea::RenderTraceColorCorrection(WaveformRenderData* data)
{
if(!data->m_geometryOK)
return;

//Prepare to render
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
m_colormapProgram.Bind();
m_colormapVAO.Bind();

//Draw the offscreen buffer to the onscreen buffer
//as a textured quad. Apply color correction as we do this.
Gdk::Color color(data->m_channel->m_displaycolor);
m_colormapProgram.SetUniform(data->m_waveformTexture, "fbtex");
m_colormapProgram.SetUniform(color.get_red_p(), "r");
m_colormapProgram.SetUniform(color.get_green_p(), "g");
m_colormapProgram.SetUniform(color.get_blue_p(), "b");

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void WaveformArea::ComputeAndDownloadCairoUnderlays()
{
double tstart = GetTime();
@@ -418,26 +472,6 @@ void WaveformArea::RenderCairoUnderlays()
m_compositeTime += (GetTime() - tstart);
}

void WaveformArea::RenderTraceColorCorrection()
{
//Prepare to render
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
m_colormapProgram.Bind();
m_colormapVAO.Bind();

//Draw the offscreen buffer to the onscreen buffer
//as a textured quad. Apply color correction as we do this.
Gdk::Color color(m_channel->m_displaycolor);
m_colormapProgram.SetUniform(m_waveformRenderData->m_waveformTexture, "fbtex");
m_colormapProgram.SetUniform(color.get_red_p(), "r");
m_colormapProgram.SetUniform(color.get_green_p(), "g");
m_colormapProgram.SetUniform(color.get_blue_p(), "b");

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

void WaveformArea::ComputeAndDownloadCairoOverlays()
{
double tstart = GetTime();