Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19. /*
  20.  *
  21.  * Protypes for rle functions.
  22.  *
  23.  */
  24.  
  25. #pragma once
  26.  
  27. #include "pstypes.h"
  28. #include "gr.h"
  29.  
  30. #include <cstdint>
  31. #include "dxxsconf.h"
  32. #include "dsx-ns.h"
  33. #include "compiler-poison.h"
  34. #include <iterator>
  35.  
  36. struct rle_position_t
  37. {
  38.         const uint8_t *src;
  39.         uint8_t *dst;
  40. };
  41.  
  42. static inline const uint8_t *end(const grs_bitmap &b)
  43. {
  44.         return &b.bm_data[b.bm_h * b.bm_w];
  45. }
  46.  
  47. static inline uint8_t *end(grs_bitmap &b)
  48. {
  49.         return &b.get_bitmap_data()[b.bm_h * b.bm_w];
  50. }
  51.  
  52. template <typename T1, typename T2>
  53. static inline rle_position_t rle_end(const T1 &src, T2 &dst)
  54. {
  55.         return {end(src), end(dst)};
  56. }
  57.  
  58. namespace dcx {
  59. uint8_t *gr_rle_decode(const uint8_t *sb, uint8_t *db, rle_position_t e);
  60. int gr_bitmap_rle_compress(grs_bitmap &bmp);
  61. #if !DXX_USE_OGL
  62. void gr_rle_expand_scanline_masked(uint8_t *dest, const uint8_t *src, int x1, int x2);
  63. #endif
  64. void gr_rle_expand_scanline(uint8_t *dest, const uint8_t *src, int x1, int x2);
  65. grs_bitmap *_rle_expand_texture(const grs_bitmap &bmp);
  66. static inline const grs_bitmap *rle_expand_texture(const grs_bitmap &bmp) __attribute_warn_unused_result;
  67. static inline const grs_bitmap *rle_expand_texture(const grs_bitmap &bmp)
  68. {
  69.         if (bmp.get_flag_mask(BM_FLAG_RLE))
  70.                 return _rle_expand_texture(bmp);
  71.         return &bmp;
  72. }
  73. void rle_cache_close();
  74. void rle_cache_flush();
  75. void rle_swap_0_255(grs_bitmap &bmp);
  76. void rle_remap(grs_bitmap &bmp, std::array<color_palette_index, 256> &colormap);
  77. #if !DXX_USE_OGL
  78. #define gr_rle_expand_scanline_generic(C,D,DX,DY,S,X1,X2) gr_rle_expand_scanline_generic(D,DX,DY,S,X1,X2)
  79. void gr_rle_expand_scanline_generic(grs_canvas &, grs_bitmap &dest, int dx, int dy, const ubyte *src, int x1, int x2 );
  80. #endif
  81.  
  82. class bm_rle_expand_range
  83. {
  84.         uint8_t *iter_dbits;
  85.         uint8_t *const end_dbits;
  86. public:
  87.         bm_rle_expand_range(uint8_t *const i, uint8_t *const e) :
  88.                 iter_dbits(i), end_dbits(e)
  89.         {
  90.         }
  91.         template <std::size_t N>
  92.                 bm_rle_expand_range(std::array<uint8_t, N> &a) :
  93.                         iter_dbits(a.data()), end_dbits(std::next(iter_dbits, N))
  94.         {
  95.         }
  96.         uint8_t *get_begin_dbits() const
  97.         {
  98.                 return iter_dbits;
  99.         }
  100.         uint8_t *get_end_dbits() const
  101.         {
  102.                 return end_dbits;
  103.         }
  104.         void consume_dbits(const unsigned w)
  105.         {
  106.                 iter_dbits += w;
  107.         }
  108. };
  109.  
  110. class bm_rle_src_stride
  111. {
  112.         /* Width of an individual element of the table of row lengths.  This
  113.          * is sizeof(uint8_t) if the bitmap is not RLE_BIG, or is
  114.          * sizeof(uint16_t) otherwise.
  115.          */
  116.         const unsigned src_bit_stride_size;
  117.         /* Bitmask used for filtering the table load.  To minimize
  118.          * branching, the code always loads two bytes from the table of row
  119.          * lengths.  If the bitmap is not RLE_BIG, then `src_bit_load_mask`
  120.          * will be 0xff and will be used to mask out the high byte from the
  121.          * load.  Otherwise, `src_bit_load_mask` will be 0xffff and the mask
  122.          * operation will leave the loaded value unchanged.
  123.          */
  124.         const unsigned src_bit_load_mask;
  125. protected:
  126.         /* Pointer to the table of row lengths.  The table is uint8_t[] if
  127.          * the bitmap is not RLE_BIG, or is uint16_t[] otherwise.  The table
  128.          * is not required to be aligned.
  129.          */
  130.         const uint8_t *ptr_src_bit_lengths;
  131.         /* Pointer to the table of RLE-encoded bitmap elements.
  132.          */
  133.         const uint8_t *src_bits;
  134. public:
  135.         bm_rle_src_stride(const grs_bitmap &src, const unsigned rle_big) :
  136.                 /* Jump threading should collapse the separate ?: uses */
  137.                 src_bit_stride_size(rle_big ? sizeof(uint16_t) : sizeof(uint8_t)),
  138.                 src_bit_load_mask(rle_big ? 0xffff : 0xff),
  139.                 ptr_src_bit_lengths(&src.bm_data[4]),
  140.                 src_bits(&ptr_src_bit_lengths[rle_big ? src.bm_h * 2 : src.bm_h])
  141.         {
  142.         }
  143.         void advance_src_bits();
  144. };
  145.  
  146. class bm_rle_expand : bm_rle_src_stride
  147. {
  148.         /* Pointer to the first byte that is not part of the table of row
  149.          * lengths.  When `ptr_src_bit_lengths` == `end_src_bit_lengths`, no
  150.          * further rows are available.
  151.          */
  152.         const uint8_t *const end_src_bit_lengths;
  153.         /* Pointer to the first byte that is not part of the bitmap data.
  154.          * When `end_src_bm` == `src_bits`, no further bitmap elements are
  155.          * available.
  156.          */
  157.         const uint8_t *const end_src_bm;
  158. public:
  159.         enum step_result
  160.         {
  161.                 /* A row decoded successfully.  Act on the decoded buffer as
  162.                  * necessary, then call this class again.
  163.                  *
  164.                  * This result is returned even if the returned row is the last
  165.                  * row.  The first call after the last row will return
  166.                  * src_exhausted, which is the trigger to stop calling the
  167.                  * class.
  168.                  */
  169.                 again,
  170.                 /* The source was exhausted before any work was done.  No data
  171.                  * is available.  No further calls should be made with this
  172.                  * source.
  173.                  */
  174.                 src_exhausted,
  175.                 /* The destination was exhausted before decoding completed.  The
  176.                  * source is left at the beginning of the row which failed to
  177.                  * decode.  The caller may try again with a larger destination
  178.                  * buffer or may abandon the attempt.  Further calls with the
  179.                  * same source and destination will continue to return
  180.                  * `dst_exhausted`.
  181.                  */
  182.                 dst_exhausted,
  183.         };
  184.         bm_rle_expand(const grs_bitmap &src) :
  185.                 bm_rle_src_stride(src, src.get_flag_mask(BM_FLAG_RLE_BIG)),
  186.                 end_src_bit_lengths(src_bits),
  187.                 end_src_bm(end(src))
  188.         {
  189.         }
  190.         template <typename T>
  191.                 /* Decode one row of the bitmap, then return control to the
  192.                  * caller.  If the return value is `again`, then the caller
  193.                  * should perform any per-row processing, then call step()
  194.                  * again.  If the return value is not `again`, then the
  195.                  * destination buffer is undefined and the caller should not
  196.                  * access it or call step().
  197.                  *
  198.                  * `const T &` to ensure that t is only modified by the caller
  199.                  * and that the caller does not accidentally provide an
  200.                  * implementation of `get_begin_dbits` that moves the
  201.                  * destination pointer.
  202.                  */
  203.                 step_result step(const T &t)
  204.                 {
  205.                         /* Poison the memory first, so that it is undefined even if
  206.                          * the source is exhausted.
  207.                          */
  208.                         const auto b = t.get_begin_dbits();
  209.                         const auto e = t.get_end_dbits();
  210.                         DXX_MAKE_MEM_UNDEFINED(b, e);
  211.                         /* Check for source exhaustion, so that empty bitmaps are
  212.                          * not read at all.  This allows callers to treat
  213.                          * src_exhausted as a definitive end-of-record with no data
  214.                          * available.
  215.                          */
  216.                         if (ptr_src_bit_lengths == end_src_bit_lengths)
  217.                                 return src_exhausted;
  218.                         return step_internal(b, e);
  219.                 }
  220.         template <typename T>
  221.                 /* Decode until source or destination is exhausted.  The
  222.                  * destination position is updated automatically as each row is
  223.                  * decoded.  There is no opportunity for callers to perform
  224.                  * per-row processing.  Callers should call step() directly if
  225.                  * per-row processing is required.
  226.                  *
  227.                  * `T &&` since some callers may not care about the state of `t`
  228.                  * afterward; `T &&` lets them pass an anonymous temporary.
  229.                  */
  230.                 bool loop(const unsigned bm_w, T &&t)
  231.                 {
  232.                         for (;;)
  233.                         {
  234.                                 switch (step(t))
  235.                                 {
  236.                                         case again:
  237.                                                 /* Step succeeded.  Notify `t` to update its
  238.                                                  * dbits position, then loop around.
  239.                                                  */
  240.                                                 t.consume_dbits(bm_w);
  241.                                                 break;
  242.                                         case src_exhausted:
  243.                                                 /* Success: source buffer exhausted and no error
  244.                                                  * conditions detected.
  245.                                                  */
  246.                                                 return true;
  247.                                         case dst_exhausted:
  248.                                                 /* Failure: destination buffer too small to hold
  249.                                                  * expanded source.
  250.                                                  */
  251.                                                 return false;
  252.                                 }
  253.                         }
  254.                 }
  255. private:
  256.         step_result step_internal(uint8_t *begin_dbits, uint8_t *end_dbits);
  257. };
  258.  
  259. }
  260.