1. 19 Aug, 2018 7 commits
    • Ell's avatar
      buffer: add gegl_tile_backend_command(); pre-0.4.10 compatibility · 30047e65
      Ell authored
      Tile backends currently assert in their command handlers that the
      input command is between 0 and GEGL_TILE_LAST_COMMAND (this is true
      for the built-in backends, but we can assume it's also true for
      custom backends.)  This prevents us from adding new tile commands
      without breaking the ABI.
      Instead, add a new gegl_tile_backend_command() function, which acts
      as a default command handler for tile backends, and to which their
      handlers should forward unhandled commands (this function currently
      simply performs the range check for the command -- however, against
      the GEGL_TILE_LAST_COMMAND value of the runtime GEGL -- and returns
      NULL; we can add differet default behaviors for different commands
      as necessary.)
      In order to remain backward compatible with tile backends compiled
      against older versions of GEGL, which still contain the above
      assertion, we replace the subclass's command handler with a thunk
      upon construction, which tests whether the original handler
      forwards unhandled commands to gegl_tile_backend_command(), and re-
      replaces the handler with either the original handler if it does,
      or a compatibility shim, which only forwards pre-0.4.10 commands to
      the original handler, if it doesn't.
    • Ell's avatar
      buffer, stats: limit maximal pending data size in the swap backend queue · 64021786
      Ell authored
      In GeglTileBackendSwap, limit the maximal data size allowed to be
      pending in the queue at any given time.  The limit is currently set
      to 10% of the cache size.  If data is attempted to be written to
      the swap while the queue is full, the operation blocks until the
      queued data size drops below the limit.
      Add new "swap-queue-total", "swap-queue-full", and "swap-queue-
      stalls" properties to GeglStats, reporting the total queued data
      size, whether or not the queue is full, and the number of times a
      write operation has been blocked due to a full queue, respectively.
    • Ell's avatar
      buffer: implement TILE_COPY in the buffer backend · 04011ae6
      Ell authored
      In GeglTileBackendBuffer, implement the TILE_COPY command, by
      simply forwarding it to the underlying buffer (unless the
      underlying buffer has user-provided tile handlers, in which case we
      can't use TILE_COPY for the same reason as in gegl_buffer_copy()).
    • Ell's avatar
      buffer, stats: implement TILE_COPY in the swap backend; cleanup; new stat · 185f4450
      Ell authored
      In GeglTileBackendSwap, implement the TILE_COPY command between a
      pair of swap backends, but decoupling swap data blocks,
      representing an allocated block in the common swap file, from swap
      entries, representing stored tiles in an individual swap backend.
      Have data blocks be ref-counted, such that each swap entry
      corresponds to a single data block, but each data block may be
      shared among multiple entries.  When copying a tile, we simply
      assign the data block of the source entry to the destination entry,
      and increment its reference count.  When modifying a tile, upon a
      TILE_SET command, if the corresponding data block isn't uniquely
      owned by the entry (i.e., if its ref-count is greater than 1), we
      allocate a new data block for the tile.
      Some all-around cleanup in gegl-tile-backend-swap.c.
      In GeglStats, add a "swap-total-uncloned" stat, analogous to
      "cache-total-uncloned", reporting the total size of the data that
      would have been stored in the swap, if each tile occupied a unique
      data block.
    • Ell's avatar
      buffer: implement TILE_COPY in the cache handler · e9dce12c
      Ell authored
      If the tile exists in the cache, we start by copying it directly to
      the destination.  Then, if the tile doesn't exist in the cache, or
      if it's already stored -- i.e., if it might exist in the backend in
      an up-to-date state -- we try letting the backend copy the tile as
      well, and, if this succeeds, we either mark the tile copied from
      the cache as stored, or void any existing tile in the destination
      cache.  The copy is considered successful if either the cache or
      the backend copied the tile.
    • Ell's avatar
      buffer: use TILE_COPY in gegl_buffer_copy() · 44c258bf
      Ell authored
      In gegl_buffer_copy(), use the TILE_COPY command, added in the
      previous commit, when copying tiles directly between the buffers,
      and fall back to a simple TILE_GET + cache_insert() if the
      TILE_COPY command fails.  See the previous commit for a rationale.
      We currently avoid this optimization for source buffers that have
      user-provided tile handlers, since they might interfere with the
      TILE_COPY mechanism.  See the comment in the code for more
      Additionally, lock/unlock the source buffer's tile-storage mutex
      before/after copying the entire set of tiles, and use an unlocked
      gegl_tile_source_get_tile() call to fetch the tiles, instead of
      locking the mutex once per tile.  In addition to being more
      efficient, this allows us to properly order the source/destination
      buffer locks, to avoid a potential deadlock when copying between
      two swapped pairs of buffers concurrently.
    • Ell's avatar
      buffer: add GEGL_TILE_COPY tile-source command · c5045711
      Ell authored
      GEGL_TILE_COPY requests a tile source to copy a tile to a given
      destination buffer (or to the same buffer to which the tile source
      belongs), at given destination tile coordinates.  The tile source
      and the destination buffer are assumed to be tile-compatible (i.e.,
      having the same tile dimensions and format).  The tile source
      should return a boolean value, indicating whether the tile has been
      This is mostly meant to be implemented by the cache handler, and by
      tile backends (the swap backend, in particular).  It allows
      backends to implement a cheap copy operation, avoiding the need to
      actually fetch the tile.  For example, at the moment, copying a
      swapped-out tile between two buffers, both of which are using the
      swap backend, requires reading the tile from disk into memory
      first, only to COW the result.  This might not be an issue if the
      same tile is known to be accessed shortly after, but when doing a
      tentative copy, usually of an entire buffer (as is done in GIMP in
      several cases), this incurs a very noticeable overhead.
  2. 18 Aug, 2018 4 commits
  3. 17 Aug, 2018 4 commits
  4. 16 Aug, 2018 3 commits
  5. 14 Aug, 2018 3 commits
    • Øyvind "pippin" Kolås's avatar
      configure: depend on babl 0.1.56 · 7ab21c10
      Øyvind "pippin" Kolås authored
    • Ell's avatar
      buffer: don't store empty tiles in the swap · f6b5b17a
      Ell authored
      In GeglTileBackendSwap, void any existing tile upon SETting an
      empty tile, instead of writing the empty tile data to disk.  The
      empty tile will be recreated by the empty-tile handler upon
    • Ell's avatar
      buffer: always increase revision of duplicate tiles, even empty · 5a8c84e7
      Ell authored
      In gegl_tile_dup(), increate the revision of the newly-created
      duplicate tile unconditionally, even if it's empty, so that it gets
      Instead of special-casing empty tiles in the above function, mark
      newly-craeted empty tiles as stored in the empty-tile handler.
      This way, newly-created empty tiles are not stored, but copied
      empty tiles are, since we might need them to replace outdated data
      in the tile backend.  Tile backends may, in turn, test for empty
      tiles upon a SET command, and drop the existing tile instead of
      storing the empty tile.
      Remove the now-unnecessary revision bump in gegl_buffer_copy().
  6. 11 Aug, 2018 2 commits
    • Ell's avatar
      buffer: in GeglTileBackendSwap, move reused OP_DESTROY to the top · 3275239e
      Ell authored
      In gegl_tile_backend_swap_entry_destroy(), when reusing an existing
      queued op as an OP_DESTROY, move the op to the top of the queue, so
      that the corresponding storage is reclaimed before any pending
      WRITE ops.  This used to be the behavior before last commit, which
      accidentally removed it.
    • Ell's avatar
      buffer: fix potential race condition during tile-swap entry destruction · 4241b0fd
      Ell authored
      In gegl_tile_backend_swap_entry_destroy(), don't free the entry in
      the calling thread when it has a pending op in the queue, but no
      allocated storage, since the test for whether the entry has
      allocated storage introduces a race condition between the calling
      thread and the writer thread, where storage allocation happens.
      Instead, always convert the existing op to an OP_DESTROY.
      In particular, this could lead to a use-after-free and/or swap-
      space leak, if a TILE_SET command is issued for a tile while it is
      being written to the swap by the writer thread (after the
      corresponding OP_WRITE has been dequeued).  In this case, another
      OP_WRITE is pushed to the queue.  If the corresponding entry
      doesn't have storage allocated yet, and is then destroyed, the
      entry will be freed while the writer thread is still potentially
      using it while serving the earlier OP_WRITE, and the storage
      subsequently allocated for it will never be reclaimed.
  7. 10 Aug, 2018 2 commits
  8. 09 Aug, 2018 5 commits
  9. 06 Aug, 2018 3 commits
  10. 05 Aug, 2018 1 commit
  11. 03 Aug, 2018 1 commit
  12. 02 Aug, 2018 1 commit
  13. 31 Jul, 2018 2 commits
    • Ell's avatar
      long-shadow: fix finite shadow accumulation · da936ece
      Ell authored
      For finite shadows, when replacing the current shadow value of a
      screen pixel, clear the pixel's now-irrelevant shadow queue, and
      correct the active-pixel count.  Note that failing to do either of
      these doesn't actually produce wrong results, but performance
      should be better in some cases now.
    • Rodrigo Lledó Milanca's avatar
      Update Spanish translation · e4ac3f45
      Rodrigo Lledó Milanca authored
  14. 30 Jul, 2018 2 commits
    • Ell's avatar
    • Ell's avatar
      long-shadow: add new operation to workshop · ef6a3e94
      Ell authored
      Add a gegl:long-shadow operation, which (surprise surprise) creates
      a long-shadow effect.  The operation supports three shadow styles:
      finite, infinite, and fading.  The shadow's color, angle, length
      (for finite shadows), and midpoint (for fading shadows) are
      Additionally, the output composition is also controllable, and can
      be one of:
        - Shadow plus image:  Both the shadow and the input image are
          included in the output.
        - Shadow only:  Only the shadow is included in the output.
        - Shadow minus image:  Only the parts of the shadow that aren't
          obscured by the input image are included in the input.  In
          GIMP, such output can be combined with the original layer using
          "Merge" layer mode, to achieve the same result as "Shadow plus
          image", using separate layers for the image and the shadow.
      The operation preserves partial-transparency, and produces anti-
      aliased results.