From 94dee0bbebfe1a97f43ea4006c337a7fcc3d1ae9 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Fri, 13 Nov 2020 13:09:51 -0800 Subject: [PATCH] ImageGadget : Fix active not being reset when reverting to stored tile --- Changes.md | 1 + include/GafferImageUI/ImageGadget.h | 2 ++ src/GafferImageUI/ImageGadget.cpp | 52 +++++++++++++++++++---------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Changes.md b/Changes.md index f67334bf228..9e67f916201 100644 --- a/Changes.md +++ b/Changes.md @@ -12,6 +12,7 @@ Fixes - Spreadsheet : Fixed serialisation of default values which do not match those of the default row. - Checkerboard : Checker colors are now exactly equal to the colorA and colorB parameters. Previously, there were very tiny floating point errors which grew larger as the distance from origin increased. - Transform2DPlug : Fixed serialisation of dynamic plugs, such as plugs promoted to a Box. +- Image Viewer : Fix active tile indicators getting stuck when switching back to cached value partway through compute API --- diff --git a/include/GafferImageUI/ImageGadget.h b/include/GafferImageUI/ImageGadget.h index 96e7d784712..0fdbd56450d 100644 --- a/include/GafferImageUI/ImageGadget.h +++ b/include/GafferImageUI/ImageGadget.h @@ -279,6 +279,8 @@ class GAFFERIMAGEUI_API ImageGadget : public GafferUI::Gadget // Called from the UI thread. const IECoreGL::Texture *texture( bool &active ); + void finishedUpdate(); + private : IECore::MurmurHash m_channelDataHash; diff --git a/src/GafferImageUI/ImageGadget.cpp b/src/GafferImageUI/ImageGadget.cpp index fceefbeda0e..1242e8f6367 100644 --- a/src/GafferImageUI/ImageGadget.cpp +++ b/src/GafferImageUI/ImageGadget.cpp @@ -940,6 +940,11 @@ void ImageGadget::Tile::applyUpdates( const std::vector &updates ) } } +void ImageGadget::Tile::finishedUpdate() +{ + m_active = false; +} + const IECoreGL::Texture *ImageGadget::Tile::texture( bool &active ) { const auto now = std::chrono::steady_clock::now(); @@ -1069,27 +1074,40 @@ void ImageGadget::updateTiles() auto tileFunctor = [this, channelsToCompute] ( const ImagePlug *image, const V2i &tileOrigin ) { - vector updates; - ImagePlug::ChannelDataScope channelScope( Context::current() ); - for( auto &channelName : channelsToCompute ) + try { - channelScope.setChannelName( channelName ); - Tile &tile = m_tiles[TileIndex(tileOrigin, channelName)]; - updates.push_back( tile.computeUpdate( image ) ); - } - Tile::applyUpdates( updates ); + vector updates; + ImagePlug::ChannelDataScope channelScope( Context::current() ); + for( auto &channelName : channelsToCompute ) + { + channelScope.setChannelName( channelName ); + Tile &tile = m_tiles[TileIndex(tileOrigin, channelName)]; + updates.push_back( tile.computeUpdate( image ) ); + } + + Tile::applyUpdates( updates ); - if( refCount() && !m_renderRequestPending.exchange( true ) ) + if( refCount() && !m_renderRequestPending.exchange( true ) ) + { + // Must hold a reference to stop us dying before our UI thread call is scheduled. + ImageGadgetPtr thisRef = this; + ParallelAlgo::callOnUIThread( + [thisRef] { + thisRef->m_renderRequestPending = false; + thisRef->Gadget::dirty( DirtyType::Render ); + } + ); + } + } + catch (...) { - // Must hold a reference to stop us dying before our UI thread call is scheduled. - ImageGadgetPtr thisRef = this; - ParallelAlgo::callOnUIThread( - [thisRef] { - thisRef->m_renderRequestPending = false; - thisRef->Gadget::dirty( DirtyType::Render ); - } - ); + // Make sure we don't leave behind active indicators if the computation is cancelled + for( auto &channelName : channelsToCompute ) + { + m_tiles[TileIndex(tileOrigin, channelName)].finishedUpdate(); + } + throw; } };