1 // SPDX-License-Identifier: Zlib
3 #include "../zlib_deflate/defutil.h"
4 #include "dfltcc_util.h"
7 #include <linux/zutil.h>
12 int dfltcc_can_deflate(
16 deflate_state
*state
= (deflate_state
*)strm
->state
;
17 struct dfltcc_state
*dfltcc_state
= GET_DFLTCC_STATE(state
);
19 /* Check for kernel dfltcc command line parameter */
20 if (zlib_dfltcc_support
== ZLIB_DFLTCC_DISABLED
||
21 zlib_dfltcc_support
== ZLIB_DFLTCC_INFLATE_ONLY
)
24 /* Unsupported compression settings */
25 if (!dfltcc_are_params_ok(state
->level
, state
->w_bits
, state
->strategy
,
26 dfltcc_state
->level_mask
))
29 /* Unsupported hardware */
30 if (!is_bit_set(dfltcc_state
->af
.fns
, DFLTCC_GDHT
) ||
31 !is_bit_set(dfltcc_state
->af
.fns
, DFLTCC_CMPR
) ||
32 !is_bit_set(dfltcc_state
->af
.fmts
, DFLTCC_FMT0
))
38 static void dfltcc_gdht(
42 deflate_state
*state
= (deflate_state
*)strm
->state
;
43 struct dfltcc_param_v0
*param
= &GET_DFLTCC_STATE(state
)->param
;
44 size_t avail_in
= avail_in
= strm
->avail_in
;
48 &strm
->next_in
, &avail_in
, NULL
);
51 static dfltcc_cc
dfltcc_cmpr(
55 deflate_state
*state
= (deflate_state
*)strm
->state
;
56 struct dfltcc_param_v0
*param
= &GET_DFLTCC_STATE(state
)->param
;
57 size_t avail_in
= strm
->avail_in
;
58 size_t avail_out
= strm
->avail_out
;
61 cc
= dfltcc(DFLTCC_CMPR
| HBT_CIRCULAR
,
62 param
, &strm
->next_out
, &avail_out
,
63 &strm
->next_in
, &avail_in
, state
->window
);
64 strm
->total_in
+= (strm
->avail_in
- avail_in
);
65 strm
->total_out
+= (strm
->avail_out
- avail_out
);
66 strm
->avail_in
= avail_in
;
67 strm
->avail_out
= avail_out
;
71 static void send_eobs(
73 const struct dfltcc_param_v0
*param
76 deflate_state
*state
= (deflate_state
*)strm
->state
;
80 bi_reverse(param
->eobs
>> (15 - param
->eobl
), param
->eobl
),
83 if (state
->pending
!= 0) {
84 /* The remaining data is located in pending_out[0:pending]. If someone
85 * calls put_byte() - this might happen in deflate() - the byte will be
86 * placed into pending_buf[pending], which is incorrect. Move the
87 * remaining data to the beginning of pending_buf so that put_byte() is
90 memmove(state
->pending_buf
, state
->pending_out
, state
->pending
);
91 state
->pending_out
= state
->pending_buf
;
94 state
->compressed_len
+= param
->eobl
;
104 deflate_state
*state
= (deflate_state
*)strm
->state
;
105 struct dfltcc_state
*dfltcc_state
= GET_DFLTCC_STATE(state
);
106 struct dfltcc_param_v0
*param
= &dfltcc_state
->param
;
107 uInt masked_avail_in
;
109 int need_empty_block
;
113 if (!dfltcc_can_deflate(strm
))
119 no_flush
= flush
== Z_NO_FLUSH
;
121 /* Trailing empty block. Switch to software, except when Continuation Flag
122 * is set, which means that DFLTCC has buffered some output in the
123 * parameter block and needs to be called again in order to flush it.
125 if (flush
== Z_FINISH
&& strm
->avail_in
== 0 && !param
->cf
) {
127 /* A block is still open, and the hardware does not support closing
128 * blocks without adding data. Thus, close it manually.
130 send_eobs(strm
, param
);
136 if (strm
->avail_in
== 0 && !param
->cf
) {
141 /* There is an open non-BFINAL block, we are not going to close it just
142 * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
143 * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
144 * DHT in order to adapt to a possibly changed input data distribution.
146 if (param
->bcf
&& no_flush
&&
147 strm
->total_in
> dfltcc_state
->block_threshold
&&
148 strm
->avail_in
>= dfltcc_state
->dht_threshold
) {
150 /* We need to flush the DFLTCC buffer before writing the
151 * End-of-block Symbol. Mask the input data and proceed as usual.
153 masked_avail_in
+= strm
->avail_in
;
157 /* DFLTCC buffer is empty, so we can manually write the
158 * End-of-block Symbol right away.
160 send_eobs(strm
, param
);
162 dfltcc_state
->block_threshold
=
163 strm
->total_in
+ dfltcc_state
->block_size
;
164 if (strm
->avail_out
== 0) {
171 /* The caller gave us too much data. Pass only one block worth of
172 * uncompressed data to DFLTCC and mask the rest, so that on the next
173 * iteration we start a new block.
175 if (no_flush
&& strm
->avail_in
> dfltcc_state
->block_size
) {
176 masked_avail_in
+= (strm
->avail_in
- dfltcc_state
->block_size
);
177 strm
->avail_in
= dfltcc_state
->block_size
;
180 /* When we have an open non-BFINAL deflate block and caller indicates that
181 * the stream is ending, we need to close an open deflate block and open a
184 need_empty_block
= flush
== Z_FINISH
&& param
->bcf
&& !param
->bhf
;
186 /* Translate stream to parameter block */
187 param
->cvt
= CVT_ADLER32
;
189 /* We need to close a block. Always do this in software - when there is
190 * no input data, the hardware will not nohor BCC. */
192 if (flush
== Z_FINISH
&& !param
->bcf
)
193 /* We are about to open a BFINAL block, set Block Header Final bit
194 * until the stream ends.
197 /* DFLTCC-CMPR will write to next_out, so make sure that buffers with
198 * higher precedence are empty.
200 Assert(state
->pending
== 0, "There must be no pending bytes");
201 Assert(state
->bi_valid
< 8, "There must be less than 8 pending bits");
202 param
->sbb
= (unsigned int)state
->bi_valid
;
204 *strm
->next_out
= (Byte
)state
->bi_buf
;
206 param
->nt
= 0; /* Honor history */
207 param
->cv
= strm
->adler
;
209 /* When opening a block, choose a Huffman-Table Type */
211 if (strm
->total_in
== 0 && dfltcc_state
->block_threshold
> 0) {
212 param
->htt
= HTT_FIXED
;
215 param
->htt
= HTT_DYNAMIC
;
222 cc
= dfltcc_cmpr(strm
);
223 if (strm
->avail_in
< 4096 && masked_avail_in
> 0)
224 /* We are about to call DFLTCC with a small input buffer, which is
225 * inefficient. Since there is masked data, there will be at least
226 * one more DFLTCC call, so skip the current one and make the next
227 * one handle more data.
230 } while (cc
== DFLTCC_CC_AGAIN
);
232 /* Translate parameter block to stream */
233 strm
->msg
= oesc_msg(dfltcc_state
->msg
, param
->oesc
);
234 state
->bi_valid
= param
->sbb
;
235 if (state
->bi_valid
== 0)
236 state
->bi_buf
= 0; /* Avoid accessing next_out */
238 state
->bi_buf
= *strm
->next_out
& ((1 << state
->bi_valid
) - 1);
239 strm
->adler
= param
->cv
;
241 /* Unmask the input data */
242 strm
->avail_in
+= masked_avail_in
;
245 /* If we encounter an error, it means there is a bug in DFLTCC call */
246 Assert(cc
!= DFLTCC_CC_OP2_CORRUPT
|| param
->oesc
== 0, "BUG");
248 /* Update Block-Continuation Flag. It will be used to check whether to call
249 * GDHT the next time.
251 if (cc
== DFLTCC_CC_OK
) {
253 send_eobs(strm
, param
);
255 dfltcc_state
->block_threshold
=
256 strm
->total_in
+ dfltcc_state
->block_size
;
259 if (flush
== Z_FINISH
) {
260 if (need_empty_block
)
261 /* Make the current deflate() call also close the stream */
265 *result
= finish_done
;
268 if (flush
== Z_FULL_FLUSH
)
269 param
->hl
= 0; /* Clear history */
270 *result
= flush
== Z_NO_FLUSH
? need_more
: block_done
;
276 if (strm
->avail_in
!= 0 && strm
->avail_out
!= 0)
277 goto again
; /* deflate() must use all input or all output */