From cecb753595d850bfaab0e827384bf8ae5f918f62 Mon Sep 17 00:00:00 2001 From: Lawrence Lee Date: Sat, 26 Sep 2020 16:30:51 -0700 Subject: [PATCH] Increase performance of some scopes --- rtgui/histogrampanel.cc | 116 +++++++++++++++++++++++----------------- rtgui/histogrampanel.h | 4 +- 2 files changed, 70 insertions(+), 50 deletions(-) diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 93091733c..0df6496c7 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -1093,7 +1093,8 @@ HistogramArea::HistogramArea (DrawModeListener *fml) : vect_hc_buffer_dirty(true), vect_hs_buffer_dirty(true), waveform_scale(0), rwave(0, 0), gwave(0, 0),bwave(0, 0), lwave(0, 0), - parade_buffer_dirty(true), wave_buffer_dirty(true), + parade_buffer_r_dirty(true), parade_buffer_g_dirty(true), parade_buffer_b_dirty(true), + wave_buffer_dirty(true), wave_buffer_luma_dirty(true), valid(false), drawMode(options.histogramDrawMode), myDrawModeListener(fml), scopeType(options.histogramScopeType), oldwidth(-1), oldheight(-1), @@ -1166,6 +1167,7 @@ void HistogramArea::get_preferred_width_for_height_vfunc (int height, int &minim void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool c, int mode, ScopeType type, bool pointer) { + wave_buffer_dirty = wave_buffer_dirty || needRed != r || needGreen != g || needBlue != b; options.histogramRed = needRed = r; options.histogramGreen = needGreen = g; @@ -1175,8 +1177,6 @@ void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool c, int m options.histogramDrawMode = drawMode = mode; options.histogramScopeType = scopeType = type; options.histogramBar = needPointer = pointer; - - wave_buffer_dirty = true; } bool HistogramArea::updatePending(void) @@ -1224,7 +1224,7 @@ void HistogramArea::update( gwave = waveformGreen; bwave = waveformBlue; lwave = waveformLuma; - parade_buffer_dirty = wave_buffer_dirty = true; + parade_buffer_r_dirty = parade_buffer_g_dirty = parade_buffer_b_dirty = wave_buffer_dirty = wave_buffer_luma_dirty = true; break; case ScopeType::VECTORSCOPE_HS: vectorscope_scale = vectorscopeScale; @@ -1556,49 +1556,67 @@ void HistogramArea::drawParade(Cairo::RefPtr &cr, int w, int h) // See Cairo documentation on stride. const int cairo_stride = Cairo::ImageSurface::format_stride_for_width(Cairo::FORMAT_ARGB32, rwave.getWidth()); + const auto buffer_size = static_cast::size_type>(wave_height) * cairo_stride; - if (parade_buffer_dirty) { - const auto buffer_size = static_cast::size_type>(wave_height) * cairo_stride; + if (parade_buffer_r_dirty && needRed) { parade_buffer_r.assign(buffer_size, 0); - parade_buffer_g.assign(buffer_size, 0); - parade_buffer_b.assign(buffer_size, 0); - wave_buffer_luma.assign(buffer_size, 0); - assert(parade_buffer_r.size() % 4 == 0); - assert(parade_buffer_g.size() % 4 == 0); - assert(parade_buffer_b.size() % 4 == 0); - assert(wave_buffer_luma.size() % 4 == 0); for (int val = 0; val < wave_height; val++) { const int* const r_row = rwave[val]; - const int* const g_row = gwave[val]; - const int* const b_row = bwave[val]; std::uint32_t* const buffer_r_row = reinterpret_cast(parade_buffer_r.data() + (255 - val) * cairo_stride); - std::uint32_t* const buffer_g_row = reinterpret_cast(parade_buffer_g.data() + (255 - val) * cairo_stride); - std::uint32_t* const buffer_b_row = reinterpret_cast(parade_buffer_b.data() + (255 - val) * cairo_stride); for (int col = 0; col < wave_width; col++) { const unsigned char r = std::min(scale * r_row[col], 0xff); - const unsigned char g = std::min(scale * g_row[col], 0xff); - const unsigned char b = std::min(scale * b_row[col], 0xff); - if (r == 0) { - buffer_r_row[col] = 0; - } else { + if (r != 0) { buffer_r_row[col] = (r << 16) | (r << 24); } - if (g == 0) { - buffer_g_row[col] = 0; - } else { + } + } + + parade_buffer_r_dirty = false; + } + + if (parade_buffer_g_dirty && needGreen) { + parade_buffer_g.assign(buffer_size, 0); + assert(parade_buffer_g.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const g_row = gwave[val]; + std::uint32_t* const buffer_g_row = reinterpret_cast(parade_buffer_g.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char g = std::min(scale * g_row[col], 0xff); + if (g != 0) { buffer_g_row[col] = (g << 8) | (g << 24); } - if (b == 0) { - buffer_b_row[col] = 0; - } else { + } + } + + parade_buffer_g_dirty = false; + } + + if (parade_buffer_b_dirty && needBlue) { + parade_buffer_b.assign(buffer_size, 0); + assert(parade_buffer_b.size() % 4 == 0); + + for (int val = 0; val < wave_height; val++) { + const int* const b_row = bwave[val]; + std::uint32_t* const buffer_b_row = reinterpret_cast(parade_buffer_b.data() + (255 - val) * cairo_stride); + for (int col = 0; col < wave_width; col++) { + const unsigned char b = std::min(scale * b_row[col], 0xff); + if (b != 0) { const unsigned char green = b / 2; // Make blue easier to see. buffer_b_row[col] = b | (green << 8) | (b << 24); } } } + parade_buffer_b_dirty = false; + } + + if (wave_buffer_luma_dirty && needLuma) { + wave_buffer_luma.assign(buffer_size, 0); + assert(wave_buffer_luma.size() % 4 == 0); + for (int val = 0; val < wave_height; val++) { const int* const l_row = lwave[val]; std::uint32_t* const buffer_row = @@ -1609,7 +1627,7 @@ void HistogramArea::drawParade(Cairo::RefPtr &cr, int w, int h) } } - parade_buffer_dirty = false; + wave_buffer_luma_dirty = false; } std::vector buffers; @@ -1668,7 +1686,6 @@ void HistogramArea::drawVectorscope(Cairo::RefPtr &cr, int w, in assert(vect_buffer.size() % 4 == 0); - // TODO: Optimize. for (int y = 0; y < vect_height; y++) { const int* const vect_row = vect[y]; std::uint32_t* const buffer_row = @@ -1834,16 +1851,12 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h // See Cairo documentation on stride. const int cairo_stride = Cairo::ImageSurface::format_stride_for_width(Cairo::FORMAT_ARGB32, rwave.getWidth()); + const auto buffer_size = static_cast::size_type>(wave_height) * cairo_stride; - if (wave_buffer_dirty) { - const auto buffer_size = static_cast::size_type>(wave_height) * cairo_stride; + if (wave_buffer_dirty && (needRed || needGreen || needBlue)) { wave_buffer.assign(buffer_size, 0); - wave_buffer_luma.assign(buffer_size, 0); - assert(wave_buffer.size() % 4 == 0); - assert(wave_buffer_luma.size() % 4 == 0); - // TODO: Optimize. for (int val = 0; val < wave_height; val++) { const int* const r_row = rwave[val]; const int* const g_row = gwave[val]; @@ -1854,15 +1867,20 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h const unsigned char g = needGreen ? std::min(scale * g_row[col], 0xff) : 0; const unsigned char b = needBlue ? std::min(scale * b_row[col], 0xff) : 0; const unsigned char value = rtengine::max(r, g, b); - if (value == 0) { - buffer_row[col] = 0; - } else { - // Speedup with one memory access instead of four. + if (value != 0) { + // Ensures correct order regardless of endianness. buffer_row[col] = b | (g << 8) | (r << 16) | (value << 24); } } } + wave_buffer_dirty = false; + } + + if (wave_buffer_luma_dirty && needLuma) { + wave_buffer_luma.assign(buffer_size, 0); + assert(wave_buffer_luma.size() % 4 == 0); + for (int val = 0; val < wave_height; val++) { const int* const l_row = lwave[val]; std::uint32_t* const buffer_row = @@ -1873,7 +1891,7 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h } } - wave_buffer_dirty = false; + wave_buffer_luma_dirty = false; } Cairo::RefPtr surface; @@ -1888,12 +1906,14 @@ void HistogramArea::drawWaveform(Cairo::RefPtr &cr, int w, int h cr->paint(); surface->finish(); } - surface = Cairo::ImageSurface::create( - wave_buffer.data(), Cairo::FORMAT_ARGB32, wave_width, wave_height, cairo_stride); - cr->set_source(surface, 0, 0); - cr->set_operator(Cairo::OPERATOR_OVER); - cr->paint(); - surface->finish(); + if (needRed || needGreen || needBlue) { + surface = Cairo::ImageSurface::create( + wave_buffer.data(), Cairo::FORMAT_ARGB32, wave_width, wave_height, cairo_stride); + cr->set_source(surface, 0, 0); + cr->set_operator(Cairo::OPERATOR_OVER); + cr->paint(); + surface->finish(); + } cr->set_matrix(orig_matrix); } @@ -1980,7 +2000,7 @@ bool HistogramArea::on_motion_notify_event (GdkEventMotion* event) double dx = (event->x - movingPosition) / get_width(); float new_brightness = LIM(trace_brightness * pow(RANGE, dx), MIN_BRIGHT, MAX_BRIGHT); if (new_brightness != trace_brightness) { - parade_buffer_dirty = wave_buffer_dirty = vect_hc_buffer_dirty = vect_hs_buffer_dirty = true; + parade_buffer_r_dirty = parade_buffer_g_dirty = parade_buffer_b_dirty = wave_buffer_dirty = wave_buffer_luma_dirty = vect_hc_buffer_dirty = vect_hs_buffer_dirty = true; trace_brightness = new_brightness; setDirty(true); queue_draw(); diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index cca27a0d9..fdce93d00 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -169,10 +169,10 @@ protected: std::vector parade_buffer_r; std::vector parade_buffer_g; std::vector parade_buffer_b; - bool parade_buffer_dirty; + bool parade_buffer_r_dirty, parade_buffer_g_dirty, parade_buffer_b_dirty; std::vector wave_buffer; std::vector wave_buffer_luma; - bool wave_buffer_dirty; + bool wave_buffer_dirty, wave_buffer_luma_dirty; bool valid; int drawMode;