LCOV - code coverage report
Current view: top level - common - quic_tmpl.c (source / functions) Hit Total Coverage
Test: out.info Lines: 175 197 88.8 %
Date: 2022-01-27 10:43:00 Functions: 40 44 90.9 %

          Line data    Source code
       1             : /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
       2             : /*
       3             :    Copyright (C) 2009 Red Hat, Inc.
       4             : 
       5             :    This library is free software; you can redistribute it and/or
       6             :    modify it under the terms of the GNU Lesser General Public
       7             :    License as published by the Free Software Foundation; either
       8             :    version 2.1 of the License, or (at your option) any later version.
       9             : 
      10             :    This library is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :    Lesser General Public License for more details.
      14             : 
      15             :    You should have received a copy of the GNU Lesser General Public
      16             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      17             : */
      18             : #include <config.h>
      19             : 
      20             : #define COMPRESS_IMP
      21             : 
      22             : #if defined(ONE_BYTE) || defined(FOUR_BYTE)
      23             : #  define FARGS_DECL(...) (Encoder *encoder, Channel *channel_a, __VA_ARGS__)
      24             : #  define FARGS_CALL(...) (encoder, channel_a, __VA_ARGS__)
      25             : #  define UNCOMPRESS_PIX_START(row) do { } while (0)
      26             : #  define SET_a(pix, val) ((pix)->a = val)
      27             : #  define GET_a(pix) ((pix)->a)
      28             : #  define SAME_PIXEL(p1, p2) (GET_a(p1) == GET_a(p2))
      29             : #  define COPY_PIXEL(dest, src) \
      30             :     SET_a(dest, GET_a(src));
      31             : #  define DECLARE_STATE_VARIABLES \
      32             :     CommonState *state = &channel_a->state
      33             : #  define DECLARE_CHANNEL_VARIABLES \
      34             :     BYTE * const correlate_row_a = channel_a->correlate_row
      35             : #  define APPLY_ALL_COMP(macro, ...) \
      36             :     macro(a, ## __VA_ARGS__)
      37             : #else
      38             : #  define FARGS_DECL(...) (Encoder *encoder, __VA_ARGS__)
      39             : #  define FARGS_CALL(...) (encoder, __VA_ARGS__)
      40             : #  define SAME_PIXEL(p1, p2)                               \
      41             :     (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) &&   \
      42             :      GET_b(p1) == GET_b(p2))
      43             : #  define COPY_PIXEL(dest, src) \
      44             :     SET_r(dest, GET_r(src)); \
      45             :     SET_g(dest, GET_g(src)); \
      46             :     SET_b(dest, GET_b(src))
      47             : #  define DECLARE_STATE_VARIABLES \
      48             :     CommonState *state = &encoder->rgb_state
      49             : #  define DECLARE_CHANNEL_VARIABLES \
      50             :     Channel * const channel_r = encoder->channels; \
      51             :     Channel * const channel_g = channel_r + 1; \
      52             :     Channel * const channel_b = channel_g + 1; \
      53             :     BYTE * const correlate_row_r = channel_r->correlate_row; \
      54             :     BYTE * const correlate_row_g = channel_g->correlate_row; \
      55             :     BYTE * const correlate_row_b = channel_b->correlate_row
      56             : #  define APPLY_ALL_COMP(macro, ...) \
      57             :     macro(r, ## __VA_ARGS__); \
      58             :     macro(g, ## __VA_ARGS__); \
      59             :     macro(b, ## __VA_ARGS__)
      60             : #endif
      61             : 
      62             : #ifdef ONE_BYTE
      63             : #undef ONE_BYTE
      64             : #define FNAME(name) quic_one_##name
      65             : #define PIXEL one_byte_t
      66             : #define BPC 8
      67             : #endif
      68             : 
      69             : #ifdef FOUR_BYTE
      70             : #undef FOUR_BYTE
      71             : #define FNAME(name) quic_four_##name
      72             : #define PIXEL four_bytes_t
      73             : #define BPC 8
      74             : #endif
      75             : 
      76             : #ifdef QUIC_RGB32
      77             : #undef QUIC_RGB32
      78             : #define PIXEL rgb32_pixel_t
      79             : #define FNAME(name) quic_rgb32_##name
      80             : #define BPC 8
      81             : #define SET_r(pix, val) ((pix)->r = val)
      82             : #define GET_r(pix) ((pix)->r)
      83             : #define SET_g(pix, val) ((pix)->g = val)
      84             : #define GET_g(pix) ((pix)->g)
      85             : #define SET_b(pix, val) ((pix)->b = val)
      86             : #define GET_b(pix) ((pix)->b)
      87             : #define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0)
      88             : #endif
      89             : 
      90             : #ifdef QUIC_RGB24
      91             : #undef QUIC_RGB24
      92             : #define PIXEL rgb24_pixel_t
      93             : #define FNAME(name) quic_rgb24_##name
      94             : #define BPC 8
      95             : #define SET_r(pix, val) ((pix)->r = val)
      96             : #define GET_r(pix) ((pix)->r)
      97             : #define SET_g(pix, val) ((pix)->g = val)
      98             : #define GET_g(pix) ((pix)->g)
      99             : #define SET_b(pix, val) ((pix)->b = val)
     100             : #define GET_b(pix) ((pix)->b)
     101             : #define UNCOMPRESS_PIX_START(pix)
     102             : #endif
     103             : 
     104             : #ifdef QUIC_RGB16
     105             : #undef QUIC_RGB16
     106             : #define PIXEL rgb16_pixel_t
     107             : #define FNAME(name) quic_rgb16_##name
     108             : #define BPC 5
     109             : #define SET_r(pix, val) (*(pix) = (*(pix) & ~(0x1f << 10)) | ((val) << 10))
     110             : #define GET_r(pix) ((*(pix) >> 10) & 0x1f)
     111             : #define SET_g(pix, val) (*(pix) = (*(pix) & ~(0x1f << 5)) | ((val) << 5))
     112             : #define GET_g(pix) ((*(pix) >> 5) & 0x1f)
     113             : #define SET_b(pix, val) (*(pix) = (*(pix) & ~0x1f) | (val))
     114             : #define GET_b(pix) (*(pix) & 0x1f)
     115             : #define UNCOMPRESS_PIX_START(pix) (*(pix) = 0)
     116             : #endif
     117             : 
     118             : #ifdef QUIC_RGB16_TO_32
     119             : #undef QUIC_RGB16_TO_32
     120             : #define PIXEL rgb32_pixel_t
     121             : #define FNAME(name) quic_rgb16_to_32_##name
     122             : #define BPC 5
     123             : #undef COMPRESS_IMP
     124             : #define SET_r(pix, val) ((pix)->r = ((val) << 3) | (((val) & 0x1f) >> 2))
     125             : #define GET_r(pix) ((pix)->r >> 3)
     126             : #define SET_g(pix, val) ((pix)->g = ((val) << 3) | (((val) & 0x1f) >> 2))
     127             : #define GET_g(pix) ((pix)->g >> 3)
     128             : #define SET_b(pix, val) ((pix)->b = ((val) << 3) | (((val) & 0x1f) >> 2))
     129             : #define GET_b(pix) ((pix)->b >> 3)
     130             : #define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0)
     131             : #endif
     132             : 
     133             : #define FNAME_DECL(name) FNAME(name) FARGS_DECL
     134             : #define FNAME_CALL(name) FNAME(name) FARGS_CALL
     135             : 
     136             : #if BPC == 5
     137             : #  define golomb_coding golomb_coding_5bpc
     138             : #  define golomb_decoding golomb_decoding_5bpc
     139             : #  define update_model update_model_5bpc
     140             : #  define find_bucket find_bucket_5bpc
     141             : #  define family family_5bpc
     142             : #  define BPC_MASK 0x1fU
     143             : #elif BPC == 8
     144             : #  define golomb_coding golomb_coding_8bpc
     145             : #  define golomb_decoding golomb_decoding_8bpc
     146             : #  define update_model update_model_8bpc
     147             : #  define find_bucket find_bucket_8bpc
     148             : #  define family family_8bpc
     149             : #  define BPC_MASK 0xffU
     150             : #else
     151             : #  error BPC must be 5 or 8
     152             : #endif
     153             : 
     154             : #define _PIXEL_A(channel, curr) ((unsigned int)GET_##channel((curr) - 1))
     155             : #define _PIXEL_B(channel, prev) ((unsigned int)GET_##channel(prev))
     156             : 
     157             : /*  a  */
     158             : 
     159             : #define DECORRELATE_0(channel, curr, bpc_mask)\
     160             :     family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)_PIXEL_A(channel, curr)) & bpc_mask]
     161             : 
     162             : #define CORRELATE_0(channel, curr, correlate, bpc_mask)\
     163             :     ((family.xlatL2U[correlate] + _PIXEL_A(channel, curr)) & bpc_mask)
     164             : 
     165             : 
     166             : /*  (a+b)/2  */
     167             : #define DECORRELATE(channel, prev, curr, bpc_mask, r)                                          \
     168             :     r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)((_PIXEL_A(channel, curr) +  \
     169             :     _PIXEL_B(channel, prev)) >> 1)) & bpc_mask]
     170             : 
     171             : #define CORRELATE(channel, prev, curr, correlate, bpc_mask, r)                                  \
     172             :     SET_##channel(r, ((family.xlatL2U[correlate] +                                              \
     173             :          (int)((_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev)) >> 1)) & bpc_mask))
     174             : 
     175             : 
     176             : #define COMPRESS_ONE_ROW0_0(channel)                                    \
     177             :     correlate_row_##channel[0] = family.xlatU2L[GET_##channel(cur_row)];\
     178             :     golomb_coding(encoder, correlate_row_##channel[0],                  \
     179             :                   find_bucket(channel_##channel,                        \
     180             :                               correlate_row_##channel[-1])->bestcode)
     181             : 
     182             : #define COMPRESS_ONE_ROW0(channel, index)                                               \
     183             :     correlate_row_##channel[index] = DECORRELATE_0(channel, &cur_row[index], bpc_mask); \
     184             :     golomb_coding(encoder, correlate_row_##channel[index],                              \
     185             :                   find_bucket(channel_##channel,                                        \
     186             :                               correlate_row_##channel[index - 1])->bestcode)
     187             : 
     188             : #define UPDATE_MODEL_COMP(channel, index)                                                   \
     189             :     update_model(state, find_bucket(channel_##channel, correlate_row_##channel[index - 1]), \
     190             :                  correlate_row_##channel[index])
     191             : #define UPDATE_MODEL(index) APPLY_ALL_COMP(UPDATE_MODEL_COMP, index)
     192             : 
     193             : #define RLE_PRED_IMP                                                                \
     194             : if (SAME_PIXEL(&prev_row[i - 1], &prev_row[i])) {                                   \
     195             :     if (run_index != i && i > 2 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2])) {  \
     196             :         goto do_run;                                                                \
     197             :     }                                                                               \
     198             : }
     199             : 
     200             : #ifdef COMPRESS_IMP
     201             : 
     202          10 : static void FNAME_DECL(compress_row0_seg)(int i,
     203             :                                           const PIXEL * const cur_row,
     204             :                                           const int end,
     205             :                                           const unsigned int waitmask,
     206             :                                           const unsigned int bpc_mask)
     207             : {
     208          10 :     DECLARE_STATE_VARIABLES;
     209          10 :     DECLARE_CHANNEL_VARIABLES;
     210             :     int stopidx;
     211             : 
     212          10 :     spice_assert(end - i > 0);
     213             : 
     214          10 :     if (i == 0) {
     215          10 :         APPLY_ALL_COMP(COMPRESS_ONE_ROW0_0);
     216             : 
     217          10 :         if (state->waitcnt) {
     218           0 :             state->waitcnt--;
     219             :         } else {
     220          10 :             state->waitcnt = (tabrand(&state->tabrand_seed) & waitmask);
     221          10 :             UPDATE_MODEL(0);
     222             :         }
     223          10 :         stopidx = ++i + state->waitcnt;
     224             :     } else {
     225           0 :         stopidx = i + state->waitcnt;
     226             :     }
     227             : 
     228        7052 :     while (stopidx < end) {
     229       14084 :         for (; i <= stopidx; i++) {
     230        7042 :             APPLY_ALL_COMP(COMPRESS_ONE_ROW0, i);
     231             :         }
     232             : 
     233        7042 :         UPDATE_MODEL(stopidx);
     234        7042 :         stopidx = i + (tabrand(&state->tabrand_seed) & waitmask);
     235             :     }
     236             : 
     237          10 :     for (; i < end; i++) {
     238           0 :         APPLY_ALL_COMP(COMPRESS_ONE_ROW0, i);
     239             :     }
     240          10 :     state->waitcnt = stopidx - end;
     241          10 : }
     242             : 
     243             : #undef COMPRESS_ONE_ROW0_0
     244             : #undef COMPRESS_ONE_ROW0
     245             : 
     246          10 : static void FNAME_DECL(compress_row0)(const PIXEL *cur_row, unsigned int width)
     247             : {
     248          10 :     DECLARE_STATE_VARIABLES;
     249          10 :     const unsigned int bpc_mask = BPC_MASK;
     250          10 :     int pos = 0;
     251             : 
     252          10 :     while ((DEFwmimax > (int)state->wmidx) && (state->wmileft <= width)) {
     253           0 :         if (state->wmileft) {
     254           0 :             FNAME_CALL(compress_row0_seg)(pos, cur_row, pos + state->wmileft,
     255             :                                           bppmask[state->wmidx], bpc_mask);
     256           0 :             width -= state->wmileft;
     257           0 :             pos += state->wmileft;
     258             :         }
     259             : 
     260           0 :         state->wmidx++;
     261           0 :         set_wm_trigger(state);
     262           0 :         state->wmileft = DEFwminext;
     263             :     }
     264             : 
     265          10 :     if (width) {
     266          10 :         FNAME_CALL(compress_row0_seg)(pos, cur_row, pos + width,
     267             :                                       bppmask[state->wmidx], bpc_mask);
     268          10 :         if (DEFwmimax > (int)state->wmidx) {
     269          10 :             state->wmileft -= width;
     270             :         }
     271             :     }
     272             : 
     273          10 :     spice_assert((int)state->wmidx <= DEFwmimax);
     274          10 :     spice_assert(state->wmidx <= 32);
     275             :     spice_assert(DEFwminext > 0);
     276          10 : }
     277             : 
     278             : #define COMPRESS_ONE_0(channel) \
     279             :     correlate_row_##channel[0] = family.xlatU2L[(unsigned)((int)GET_##channel(cur_row) -              \
     280             :                                                           (int)GET_##channel(prev_row) ) & bpc_mask]; \
     281             :     golomb_coding(encoder, correlate_row_##channel[0],                                                \
     282             :                   find_bucket(channel_##channel, correlate_row_##channel[-1])->bestcode)
     283             : 
     284             : #define COMPRESS_ONE(channel, index)                                                                   \
     285             :      DECORRELATE(channel, &prev_row[index], &cur_row[index],bpc_mask, correlate_row_##channel[index]); \
     286             :      golomb_coding(encoder, correlate_row_##channel[index],                                            \
     287             :                    find_bucket(channel_##channel, correlate_row_##channel[index - 1])->bestcode)
     288             : 
     289        2230 : static void FNAME_DECL(compress_row_seg)(int i,
     290             :                                          const PIXEL * const prev_row,
     291             :                                          const PIXEL * const cur_row,
     292             :                                          const int end,
     293             :                                          const unsigned int waitmask,
     294             :                                          const unsigned int bpc_mask)
     295             : {
     296        2230 :     DECLARE_STATE_VARIABLES;
     297        2230 :     DECLARE_CHANNEL_VARIABLES;
     298             :     int stopidx;
     299        2230 :     int run_index = 0;
     300             :     int run_size;
     301             : 
     302        2230 :     spice_assert(end - i > 0);
     303             : 
     304        2230 :     if (i == 0) {
     305        2170 :         APPLY_ALL_COMP(COMPRESS_ONE_0);
     306             : 
     307        2170 :         if (state->waitcnt) {
     308        2034 :             state->waitcnt--;
     309             :         } else {
     310         136 :             state->waitcnt = (tabrand(&state->tabrand_seed) & waitmask);
     311         136 :             UPDATE_MODEL(0);
     312             :         }
     313        2170 :         stopidx = ++i + state->waitcnt;
     314             :     } else {
     315          60 :         stopidx = i + state->waitcnt;
     316             :     }
     317             :     for (;;) {
     318       51567 :         while (stopidx < end) {
     319      997014 :             for (; i <= stopidx; i++) {
     320      947679 :                 RLE_PRED_IMP;
     321      946521 :                 APPLY_ALL_COMP(COMPRESS_ONE, i);
     322             :             }
     323             : 
     324       49335 :             UPDATE_MODEL(stopidx);
     325       49335 :             stopidx = i + (tabrand(&state->tabrand_seed) & waitmask);
     326             :         }
     327             : 
     328       20243 :         for (; i < end; i++) {
     329       19169 :             RLE_PRED_IMP;
     330       19169 :             APPLY_ALL_COMP(COMPRESS_ONE, i);
     331             :         }
     332        1074 :         state->waitcnt = stopidx - end;
     333             : 
     334        1074 :         return;
     335             : 
     336        1158 : do_run:
     337        1158 :         run_index = i;
     338        1158 :         state->waitcnt = stopidx - i;
     339        1158 :         run_size = 0;
     340             : 
     341      823340 :         while (SAME_PIXEL(&cur_row[i], &cur_row[i - 1])) {
     342      823338 :             run_size++;
     343      823338 :             if (++i == end) {
     344        1156 :                 encode_state_run(encoder, state, run_size);
     345        1156 :                 return;
     346             :             }
     347             :         }
     348           2 :         encode_state_run(encoder, state, run_size);
     349           2 :         stopidx = i + state->waitcnt;
     350             :     }
     351             : }
     352             : 
     353        2170 : static void FNAME_DECL(compress_row)(const PIXEL * const prev_row,
     354             :                                      const PIXEL * const cur_row,
     355             :                                      unsigned int width)
     356             : 
     357             : {
     358        2170 :     DECLARE_STATE_VARIABLES;
     359        2170 :     const unsigned int bpc_mask = BPC_MASK;
     360        2170 :     unsigned int pos = 0;
     361             : 
     362        2230 :     while ((DEFwmimax > (int)state->wmidx) && (state->wmileft <= width)) {
     363          60 :         if (state->wmileft) {
     364          60 :             FNAME_CALL(compress_row_seg)(pos, prev_row, cur_row,
     365             :                                          pos + state->wmileft, bppmask[state->wmidx],
     366             :                                          bpc_mask);
     367          60 :             width -= state->wmileft;
     368          60 :             pos += state->wmileft;
     369             :         }
     370             : 
     371          60 :         state->wmidx++;
     372          60 :         set_wm_trigger(state);
     373          60 :         state->wmileft = DEFwminext;
     374             :     }
     375             : 
     376        2170 :     if (width) {
     377        2170 :         FNAME_CALL(compress_row_seg)(pos, prev_row, cur_row, pos + width,
     378             :                                      bppmask[state->wmidx], bpc_mask);
     379        2170 :         if (DEFwmimax > (int)state->wmidx) {
     380         209 :             state->wmileft -= width;
     381             :         }
     382             :     }
     383             : 
     384        2170 :     spice_assert((int)state->wmidx <= DEFwmimax);
     385        2170 :     spice_assert(state->wmidx <= 32);
     386             :     spice_assert(DEFwminext > 0);
     387        2170 : }
     388             : 
     389             : #endif
     390             : 
     391             : #define UNCOMPRESS_ONE_ROW0_0(channel)                                                                      \
     392             :     correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel,                       \
     393             :                                                                    correlate_row_##channel[-1])->bestcode,  \
     394             :                                                        encoder->io_word, &codewordlen);                     \
     395             :     SET_##channel(&cur_row[0], (BYTE)family.xlatL2U[correlate_row_##channel[0]]);                           \
     396             :     decode_eatbits(encoder, codewordlen);
     397             : 
     398             : #define UNCOMPRESS_ONE_ROW0(channel)                                                                           \
     399             :     correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel,                          \
     400             :                                                                    correlate_row_##channel[i - 1])->bestcode,  \
     401             :                                                        encoder->io_word, &codewordlen);                        \
     402             :     SET_##channel(&cur_row[i], CORRELATE_0(channel, &cur_row[i], correlate_row_##channel[i],                   \
     403             :                   bpc_mask));                                                                                  \
     404             :     decode_eatbits(encoder, codewordlen);
     405             : 
     406          10 : static void FNAME_DECL(uncompress_row0_seg)(int i,
     407             :                                             PIXEL * const cur_row,
     408             :                                             const int end,
     409             :                                             const unsigned int waitmask,
     410             :                                             const unsigned int bpc_mask)
     411             : {
     412          10 :     DECLARE_STATE_VARIABLES;
     413          10 :     DECLARE_CHANNEL_VARIABLES;
     414             :     int stopidx;
     415             : 
     416          10 :     spice_assert(end - i > 0);
     417             : 
     418          10 :     if (i == 0) {
     419             :         unsigned int codewordlen;
     420             : 
     421           4 :         UNCOMPRESS_PIX_START(&cur_row[i]);
     422          10 :         APPLY_ALL_COMP(UNCOMPRESS_ONE_ROW0_0);
     423             : 
     424          10 :         if (state->waitcnt) {
     425           0 :             --state->waitcnt;
     426             :         } else {
     427          10 :             state->waitcnt = (tabrand(&state->tabrand_seed) & waitmask);
     428          10 :             UPDATE_MODEL(0);
     429             :         }
     430          10 :         stopidx = ++i + state->waitcnt;
     431             :     } else {
     432           0 :         stopidx = i + state->waitcnt;
     433             :     }
     434             : 
     435        7052 :     while (stopidx < end) {
     436       14084 :         for (; i <= stopidx; i++) {
     437             :             unsigned int codewordlen;
     438             : 
     439        2171 :             UNCOMPRESS_PIX_START(&cur_row[i]);
     440        7042 :             APPLY_ALL_COMP(UNCOMPRESS_ONE_ROW0);
     441             :         }
     442        7042 :         UPDATE_MODEL(stopidx);
     443        7042 :         stopidx = i + (tabrand(&state->tabrand_seed) & waitmask);
     444             :     }
     445             : 
     446          10 :     for (; i < end; i++) {
     447             :         unsigned int codewordlen;
     448             : 
     449           0 :         UNCOMPRESS_PIX_START(&cur_row[i]);
     450           0 :         APPLY_ALL_COMP(UNCOMPRESS_ONE_ROW0);
     451             :     }
     452          10 :     state->waitcnt = stopidx - end;
     453          10 : }
     454             : 
     455          10 : static void FNAME_DECL(uncompress_row0)(PIXEL * const cur_row,
     456             :                                         unsigned int width)
     457             : 
     458             : {
     459          10 :     DECLARE_STATE_VARIABLES;
     460          10 :     const unsigned int bpc_mask = BPC_MASK;
     461          10 :     unsigned int pos = 0;
     462             : 
     463          10 :     while ((DEFwmimax > (int)state->wmidx) && (state->wmileft <= width)) {
     464           0 :         if (state->wmileft) {
     465           0 :             FNAME_CALL(uncompress_row0_seg)(pos, cur_row,
     466             :                                             pos + state->wmileft,
     467             :                                             bppmask[state->wmidx],
     468             :                                             bpc_mask);
     469           0 :             pos += state->wmileft;
     470           0 :             width -= state->wmileft;
     471             :         }
     472             : 
     473           0 :         state->wmidx++;
     474           0 :         set_wm_trigger(state);
     475           0 :         state->wmileft = DEFwminext;
     476             :     }
     477             : 
     478          10 :     if (width) {
     479          10 :         FNAME_CALL(uncompress_row0_seg)(pos, cur_row, pos + width,
     480             :                                         bppmask[state->wmidx], bpc_mask);
     481          10 :         if (DEFwmimax > (int)state->wmidx) {
     482          10 :             state->wmileft -= width;
     483             :         }
     484             :     }
     485             : 
     486          10 :     spice_assert((int)state->wmidx <= DEFwmimax);
     487          10 :     spice_assert(state->wmidx <= 32);
     488             :     spice_assert(DEFwminext > 0);
     489          10 : }
     490             : 
     491             : #define UNCOMPRESS_ONE_0(channel)                                                                          \
     492             :     correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel,                      \
     493             :                                                                    correlate_row_##channel[-1])->bestcode, \
     494             :                                                        encoder->io_word, &codewordlen);                    \
     495             :     SET_##channel(&cur_row[0], (family.xlatL2U[correlate_row_##channel[0]] +                               \
     496             :                   GET_##channel(prev_row)) & bpc_mask);                                                    \
     497             :     decode_eatbits(encoder, codewordlen);
     498             : 
     499             : #define UNCOMPRESS_ONE(channel)                                                                               \
     500             :     correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel,                         \
     501             :                                                                    correlate_row_##channel[i - 1])->bestcode, \
     502             :                                                        encoder->io_word, &codewordlen);                       \
     503             :     CORRELATE(channel, &prev_row[i], &cur_row[i], correlate_row_##channel[i], bpc_mask,                       \
     504             :               &cur_row[i]);                                                                                   \
     505             :     decode_eatbits(encoder, codewordlen);
     506             : 
     507        2230 : static void FNAME_DECL(uncompress_row_seg)(const PIXEL * const prev_row,
     508             :                                            PIXEL * const cur_row,
     509             :                                            int i,
     510             :                                            const int end,
     511             :                                            const unsigned int bpc_mask)
     512             : {
     513        2230 :     DECLARE_STATE_VARIABLES;
     514        2230 :     DECLARE_CHANNEL_VARIABLES;
     515        2230 :     const unsigned int waitmask = bppmask[state->wmidx];
     516             :     int stopidx;
     517        2230 :     int run_index = 0;
     518             :     int run_end;
     519             : 
     520        2230 :     spice_assert(end - i > 0);
     521             : 
     522        2230 :     if (i == 0) {
     523             :         unsigned int codewordlen;
     524             : 
     525         667 :         UNCOMPRESS_PIX_START(&cur_row[i]);
     526        2170 :         APPLY_ALL_COMP(UNCOMPRESS_ONE_0);
     527             : 
     528        2170 :         if (state->waitcnt) {
     529        2034 :             --state->waitcnt;
     530             :         } else {
     531         136 :             state->waitcnt = (tabrand(&state->tabrand_seed) & waitmask);
     532         136 :             UPDATE_MODEL(0);
     533             :         }
     534        2170 :         stopidx = ++i + state->waitcnt;
     535             :     } else {
     536          60 :         stopidx = i + state->waitcnt;
     537             :     }
     538             :     for (;;) {
     539       51567 :         while (stopidx < end) {
     540      997014 :             for (; i <= stopidx; i++) {
     541             :                 unsigned int codewordlen;
     542      947679 :                 RLE_PRED_IMP;
     543      132179 :                 UNCOMPRESS_PIX_START(&cur_row[i]);
     544      946521 :                 APPLY_ALL_COMP(UNCOMPRESS_ONE);
     545             :             }
     546             : 
     547       49335 :             UPDATE_MODEL(stopidx);
     548             : 
     549       49335 :             stopidx = i + (tabrand(&state->tabrand_seed) & waitmask);
     550             :         }
     551             : 
     552       20243 :         for (; i < end; i++) {
     553             :             unsigned int codewordlen;
     554       19169 :             RLE_PRED_IMP;
     555        4605 :             UNCOMPRESS_PIX_START(&cur_row[i]);
     556       19169 :             APPLY_ALL_COMP(UNCOMPRESS_ONE);
     557             :         }
     558             : 
     559        1074 :         state->waitcnt = stopidx - end;
     560             : 
     561        1074 :         return;
     562             : 
     563        1158 : do_run:
     564        1158 :         state->waitcnt = stopidx - i;
     565        1158 :         run_index = i;
     566        1158 :         run_end = decode_state_run(encoder, state);
     567        1158 :         if (run_end < 0 || run_end > (end - i)) {
     568           0 :             encoder->usr->error(encoder->usr, "wrong RLE\n");
     569             :         }
     570        1158 :         run_end += i;
     571             : 
     572      824496 :         for (; i < run_end; i++) {
     573      212376 :             UNCOMPRESS_PIX_START(&cur_row[i]);
     574      823338 :             COPY_PIXEL(&cur_row[i], &cur_row[i - 1]);
     575             :         }
     576             : 
     577        1158 :         if (i == end) {
     578        1156 :             return;
     579             :         }
     580             : 
     581           2 :         stopidx = i + state->waitcnt;
     582             :     }
     583             : }
     584             : 
     585        2170 : static void FNAME_DECL(uncompress_row)(const PIXEL * const prev_row,
     586             :                                        PIXEL * const cur_row,
     587             :                                        unsigned int width)
     588             : 
     589             : {
     590        2170 :     DECLARE_STATE_VARIABLES;
     591        2170 :     const unsigned int bpc_mask = BPC_MASK;
     592        2170 :     unsigned int pos = 0;
     593             : 
     594        2230 :     while ((DEFwmimax > (int)state->wmidx) && (state->wmileft <= width)) {
     595          60 :         if (state->wmileft) {
     596          60 :             FNAME_CALL(uncompress_row_seg)(prev_row, cur_row, pos,
     597             :                                            pos + state->wmileft, bpc_mask);
     598          60 :             pos += state->wmileft;
     599          60 :             width -= state->wmileft;
     600             :         }
     601             : 
     602          60 :         state->wmidx++;
     603          60 :         set_wm_trigger(state);
     604          60 :         state->wmileft = DEFwminext;
     605             :     }
     606             : 
     607        2170 :     if (width) {
     608        2170 :         FNAME_CALL(uncompress_row_seg)(prev_row, cur_row, pos,
     609             :                                        pos + width, bpc_mask);
     610        2170 :         if (DEFwmimax > (int)state->wmidx) {
     611         209 :             state->wmileft -= width;
     612             :         }
     613             :     }
     614             : 
     615        2170 :     spice_assert((int)state->wmidx <= DEFwmimax);
     616        2170 :     spice_assert(state->wmidx <= 32);
     617             :     spice_assert(DEFwminext > 0);
     618        2170 : }
     619             : 
     620             : #undef PIXEL
     621             : #undef FARGS_CALL
     622             : #undef FARGS_DECL
     623             : #undef FNAME
     624             : #undef FNAME_CALL
     625             : #undef FNAME_DECL
     626             : #undef _PIXEL_A
     627             : #undef _PIXEL_B
     628             : #undef SAME_PIXEL
     629             : #undef RLE_PRED_IMP
     630             : #undef UPDATE_MODEL
     631             : #undef DECORRELATE_0
     632             : #undef DECORRELATE
     633             : #undef COMPRESS_ONE_0
     634             : #undef COMPRESS_ONE
     635             : #undef CORRELATE_0
     636             : #undef CORRELATE
     637             : #undef UNCOMPRESS_ONE_ROW0_0
     638             : #undef UNCOMPRESS_ONE_ROW0
     639             : #undef UNCOMPRESS_ONE_0
     640             : #undef UNCOMPRESS_ONE
     641             : #undef golomb_coding
     642             : #undef golomb_decoding
     643             : #undef update_model
     644             : #undef find_bucket
     645             : #undef family
     646             : #undef BPC
     647             : #undef BPC_MASK
     648             : #undef COMPRESS_IMP
     649             : #undef SET_r
     650             : #undef GET_r
     651             : #undef SET_g
     652             : #undef GET_g
     653             : #undef SET_b
     654             : #undef GET_b
     655             : #undef SET_a
     656             : #undef GET_a
     657             : #undef UNCOMPRESS_PIX_START
     658             : #undef UPDATE_MODEL_COMP
     659             : #undef APPLY_ALL_COMP
     660             : #undef DECLARE_STATE_VARIABLES
     661             : #undef DECLARE_CHANNEL_VARIABLES
     662             : #undef COPY_PIXEL

Generated by: LCOV version 1.14