1. 01 Dec, 2018 7 commits
    • Ell's avatar
    • Ell's avatar
      app: in Luminance mode, cache RGBA -> Y fish · dbab0b55
      Ell authored
    • Ell's avatar
      app: in Luminance mode, replace VLAs with gimp-scratch · 70b7316e
      Ell authored
      In the Luminance layer-mode, use the scratch allocator for
      allocating temporary buffers, instead of using VLAs.
      GimpOperationLayerMode already allocates data on the stack,
      calculated as not to overflow the stack on any platform, so having
      any of its descendants also allocate big buffers on the stack is
    • Ell's avatar
      app: add scratch-total variable to the dashboard · 698d1af7
      Ell authored
      Add a scratch-total variable to the dashboard's misc group, showing
      the total amount of memory used by the scratch allocator.
    • Ell's avatar
      app: add gimp-scratch allocator · a8a86552
      Ell authored
      gimp-scratch is a fast memory allocator (on the order of magnitude
      of alloca()), suitable for small (up to a few megabytes), short-
      lived (usually, bound to the current stack-frame) allocations.
      Unlike alloca(), gimp-scratch doesn't use the stack, and is
      therefore safer, and will also serve bigger requests, by falling-
      back to malloc().
      The allocator itself is very simple:  We keep a per-thread stack of
      cached memory blocks (allocated using the normal allocator).  When
      serving an allocation request, we simply pop the top block off the
      stack, and return it. If the block is too small, we replace it with
      a big-enough block.  When the block is freed, we push it back to
      the top of the stack (note that even though each thread uses a
      separate stack, blocks can be migrated between threads, i.e.,
      allocated on one thread, and freed on another thread, although this
      is not really an intended usage pattern.)  The idea is that the
      stacks will ultimately stabalize to contain blocks that can serve
      all the encountered allocation patterns, without needing to reisze
      any of the blocks; as a consequence, the amount of scratch memory
      allocated at any given time should really be kept to a minimum.
    • Ell's avatar
      app: in GimpBacktrace Linux backend, don't leak backtrace when dropping threads · 01f94099
      Ell authored
      Should have been part of commit
    • Ell's avatar
  2. 30 Nov, 2018 5 commits
    • Ell's avatar
      app: use gimp_async_add_callback_for_object() in the bucket-fill tool · 6103f0e5
      Ell authored
      ... for the same reason as commit
    • Ell's avatar
      app: use gimp_async_add_callback_for_object() in various places · 7c00cf49
      Ell authored
      Use gimp_async_add_callback_for_object(), added in the previous
      commit, instead of gimp_async_add_callback(), in cases where the
      destructor of the object owning the async doesn't wait for the
      async to finish.  This avoids leaking such ongoing asyncs on
      shutdown, during which gimp-parallel either finishes or aborts the
      asyncs: if at this point an async has any registered callbacks, an
      idle source is added for running the callbacks, extending the
      lifetime of the async; however, since we're not getting back into
      the main loop, the idle is never run, and the async (and any
      associated resources) are never freed.
    • Ell's avatar
      app: add gimp_async_add_callback_for_object() · 49fd2847
      Ell authored
      ... which is similar to gimp_async_add_callback(), taking an
      additional GObject argument.  The object is kept alive for the
      duration of the callback, and the callback is automatically removed
      when the object is destroyed (if it hasn't been already called).
      This is analogous to g_signal_connect_object(), compared to
    • Ell's avatar
      app: unref async when removing last callback if idle is pending · a779dd38
      Ell authored
      In gimp_async_remove_callback(), if removing the last callback
      while the callback idle-source is already pending, cancel the idle
      source and unref the async object (the async is reffed when adding
      the idle source.)
    • Øyvind "pippin" Kolås's avatar
      app: cache fishes per operation instance in layer-modes · 4dd3e219
      Øyvind "pippin" Kolås authored
      There was a global 3x3 array of babl fishes used for converting between
      blending and compositing pixel representations, these were all hard-coded to
      operate within the sRGB babl-space family. This commit updates a per-instance
      array during operation prepare instead, that comes preconfigured with fishes
      derived from the correct space. Since the same operation instance might get
      different space input during its life time we store and compare the cached
      fishes with the current format (which is unique depending on space).
      This should address the problem seen in issue #2592
  3. 29 Nov, 2018 2 commits
  4. 28 Nov, 2018 7 commits
    • Ell's avatar
      app: use gimp_tile_handler_validate_validate() in gimp:buffer-source-validate · 83dd94ba
      Ell authored
      Use gimp_tile_handler_validate_validate(), added in the commit
      before last, in gimp:buffer-source-validate, in order to pre-render
      the necessary region of the buffer, instead of performing the
      validation implicitly by iterating over the region.  This is both
      simpler, and, more importantly, allows us to render the entire
      region in a single chunk, instead of tile-by-tile, which can be
      considerably more efficient, especially with high thread counts.
      This essentially extends the dynamic sizing of rendered projection
      chunks to layer groups, which are rendered through
      gimp:buffer-source-validate, rather than just the main image
    • Ell's avatar
      app: use gimp_tile_handler_validate_validate() in GimpProjection · d6f0ca55
      Ell authored
      Use gimp_tile_handler_validate_validate(), added in the last
      commit, in GimpProjection, in order to render the projection,
      instead of separately invalidating the buffer, undoing the
      invalidation, and then rendering the graph.  This is more
      efficient, and more idiomatic.
    • Ell's avatar
      app: add gimp_tile_handler_validate_validate() · 82a60997
      Ell authored
      ... which validates a given rectangle directly into the buffer,
      possibly intersecting it with the dirty region.  This is more
      efficient than either invalidating, un-invalidating, and rendering
      a given rect, as we're doing in GimpProjection, or validating the
      buffer tile-by-tile, as we're doing in gimp:buffer-source-validate.
    • Ell's avatar
      app: add GimpTileHandlerValidate::validate_buffer() vfunc · 0ad41cfe
      Ell authored
      ... which is similar to the ::validate() vfunc, however, it should
      render the result to the provided GeglBuffer, instead of to a
      memory buffer.
      Provide a default implementation, which uses
      gegl_node_blit_buffer() if the default ::validate() implementation
      is used, or, otherwise, calls uses
      gegl_buffer_linear_{open,close}(), and passes the returned memory
      buffer to ::validate().
    • Ell's avatar
      app: add GimpTileHandlerValidate::{begin,end}_validate() vfuncs · 5a623fc5
      Ell authored
      Add begin_validate() and end_validate() virtual functions, and
      corresponding free functions, to GimpTileHandlerValidate.  These
      functions are called before/after validation happens, and should
      perform any necessary steps to prepare for validation.  The default
      implementation suspends validation on tile access, so that the
      assigned buffer may be accessed without causing validation.
      Implement the new functions in GimpTileHandlerProjectable, by
      calling gimp_projectable_begin_render() and
      gimp_projectable_end_render(), respectively, instead of calling
      these functions in the ::validate() implementation (which, in turn,
      allows us to use the default ::validate() implementation.)
      In GimpProjection, use the new functions in place of
    • Ell's avatar
      app: avoid starting the chunk renderer while finishing drawing a projection · 8a47b681
      Ell authored
      In gimp_projection_finish_draw(), make sure we don't accidentally
      re-start the chunk renderer idle source while running the remaining
      iterations, in case the chunk height changes, and we need to reinit
      the renderer state.
    • Ell's avatar
      app: avoid flushing bufferless projections · b07f8102
      Ell authored
      Don't needlessly flush projections whose buffer hasn't been
      allocated yet.  This can happen when opening an image, in which
      case the image is flushed before its projection has a buffer.
  5. 27 Nov, 2018 3 commits
    • Jehan's avatar
      app: make GimpBucketFillTool a GimpColorTool. · 5d428194
      Jehan authored
      In particular, it allows to easily color pick. This just makes sense as
      the bucket fill is definitely what one could call a "color tool", and
      being able to easily change color without having to constantly switch to
      color picker tool nor open a color chooser dialog is a must.
      The fill type option (FG/BG/Pattern) was already mapped to the common
      toggle behavior key (Ctrl on Linux), which is commonly used for
      switching to color picker on paint tools. So I decided to remap the fill
      type switch to GDK_MOD1_MASK (Alt on Linux) to keep consistent with
      other tools (at the price of a change for anyone used to this modifier,
      though I doubt it was that much used).
      I also made possible to combine the 2 modifiers (so you could pick the
      foreground or background color with ctrl and ctrl-alt).
    • Jehan's avatar
      app: flood isolated pixels in smart colorization fill. · 744d6793
      Jehan authored
      The smart colorization was leaving irritating single pixels in between
      colorized regions, after growing and combining. So let's just flood
      these. We don't flood bigger regions (and in particular don't use
      gimp_gegl_apply_flood()) on purpose, because there may be small yet
      actual regions inside regions which we'd want in other colors. 1-pixel
      regions is the extreme case where chances that one wanted it filled are
      just higher.
    • Jehan's avatar
      app: radius map actually not useful during smart colorization grow step. · 6bec0bc8
      Jehan authored
      The distance map has all the information we need already. Also we will
      actually grow up to the max radius pixel (middle pixel of a stroke).
      After discussing with Aryeom, we realized it was better to fill a stroke
      fully (for cases of overflowing, I already added the "Maximum growing
      size" property anyway).
  6. 26 Nov, 2018 4 commits
  7. 24 Nov, 2018 1 commit
  8. 23 Nov, 2018 5 commits
  9. 22 Nov, 2018 4 commits
    • Jehan's avatar
      app: add "line-art-max-grow" property to the bucket fill options. · eb042e6c
      Jehan authored
      When flooding the line art, we may overflood it in sample merge (which
      would use color in the line art computation). And if having all colors
      on the same layer, this would go over other colors (making the wrong
      impression that the line art leaked).
      This new option is mostly to keep some control over the mask growth.
      Usually a few pixels is enough for most styles of drawing (though we
      could technically allow for very wide strokes).
    • Jehan's avatar
      app: make sure we reset tool modifier state before saving options. · dd3d9ab3
      Jehan authored
      I had this funny behavior when I was quitting GIMP with the active tool
      using modifiers (for instance bucket fill). Each time I'd quit with
      ctrl-q (and if the image is not dirty), the options would use the value
      from the modifier state and be saved as-is. Hence at next restart, the
      default value was always different!
    • Jehan's avatar
      app: properly (bucket) fill created splines and segments in line art. · 5a4754f3
      Jehan authored
      For this, I needed distmap of the closed version of the line art (after
      splines and segments are created). This will result in invisible stroke
      borders added when flooding in the end. These invisible borders will
      have a thickness of 0.0, which means that flooding will stop at once
      after these single pixels are filled, which makes it quick, and is
      perfect since created splines and segments are 1-pixel thick anyway.
      Only downside is having to run "gegl:distance-transform" a second time,
      but this still stays fast.
    • Jehan's avatar
      app: replace gegl:watershed-transform with custom algorithm. · 3467acf0
      Jehan authored
      We don't really need to flow every line art pixel and this new
      implementation is simpler (because we don't actually need over-featured
      watershedding), and a lot lot faster, making the line art bucket fill
      now very reactive.
      For this, I am keeping the computed distance map, as well as local
      thickness map around to be used when flooding the line art pixels
      (basically I try to flood half the stroke thickness).
      Note that there are still some issues with this new implementation as it
      doesn't properly flood yet created (i.e. invisible) splines and
      segments, and in particular the ones between 2 colored sections. I am
      going to fix this next.
  10. 21 Nov, 2018 1 commit
  11. 20 Nov, 2018 1 commit
    • Jehan's avatar
      app: fix a line art leak in bucket fill tool. · 36c885a6
      Jehan authored
      Introduced in commit b4e12fbb:
      gimp_pickable_contiguous_region_prepare_line_art_async() was running
      gimp_pickable_flush(), which provokes the "rendered" signal on the
      image projection when a change occured. As a result, it was calling
      gimp_bucket_fill_compute_line_art() within itself and since
      tool->priv->async was not set yet, none of the call were canceled. Hence
      the same line art is computed twice, but one is leaked.
      Make sure we block this signal handler as a solution.