xref: /aosp_15_r20/external/virglrenderer/src/venus/vkr_cs.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker /*
2*bbecb9d1SAndroid Build Coastguard Worker  * Copyright 2021 Google LLC
3*bbecb9d1SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*bbecb9d1SAndroid Build Coastguard Worker  */
5*bbecb9d1SAndroid Build Coastguard Worker 
6*bbecb9d1SAndroid Build Coastguard Worker #include "vkr_cs.h"
7*bbecb9d1SAndroid Build Coastguard Worker 
8*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_iov.h"
9*bbecb9d1SAndroid Build Coastguard Worker 
10*bbecb9d1SAndroid Build Coastguard Worker #include "vkr_context.h"
11*bbecb9d1SAndroid Build Coastguard Worker 
12*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_encoder_set_stream(struct vkr_cs_encoder * enc,const struct vkr_resource_attachment * att,size_t offset,size_t size)13*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_set_stream(struct vkr_cs_encoder *enc,
14*bbecb9d1SAndroid Build Coastguard Worker                           const struct vkr_resource_attachment *att,
15*bbecb9d1SAndroid Build Coastguard Worker                           size_t offset,
16*bbecb9d1SAndroid Build Coastguard Worker                           size_t size)
17*bbecb9d1SAndroid Build Coastguard Worker {
18*bbecb9d1SAndroid Build Coastguard Worker    if (!att) {
19*bbecb9d1SAndroid Build Coastguard Worker       memset(&enc->stream, 0, sizeof(enc->stream));
20*bbecb9d1SAndroid Build Coastguard Worker       enc->remaining_size = 0;
21*bbecb9d1SAndroid Build Coastguard Worker       enc->next_iov = 0;
22*bbecb9d1SAndroid Build Coastguard Worker       enc->cur = NULL;
23*bbecb9d1SAndroid Build Coastguard Worker       enc->end = NULL;
24*bbecb9d1SAndroid Build Coastguard Worker       return;
25*bbecb9d1SAndroid Build Coastguard Worker    }
26*bbecb9d1SAndroid Build Coastguard Worker 
27*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.attachment = att;
28*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.iov = att->iov;
29*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.iov_count = att->iov_count;
30*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.offset = offset;
31*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.size = size;
32*bbecb9d1SAndroid Build Coastguard Worker    /* clear cache */
33*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.cached_index = 0;
34*bbecb9d1SAndroid Build Coastguard Worker    enc->stream.cached_offset = 0;
35*bbecb9d1SAndroid Build Coastguard Worker 
36*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_encoder_seek_stream(enc, 0);
37*bbecb9d1SAndroid Build Coastguard Worker }
38*bbecb9d1SAndroid Build Coastguard Worker 
39*bbecb9d1SAndroid Build Coastguard Worker static bool
vkr_cs_encoder_translate_stream_offset(struct vkr_cs_encoder * enc,size_t offset,int * iov_index,size_t * iov_offset)40*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_translate_stream_offset(struct vkr_cs_encoder *enc,
41*bbecb9d1SAndroid Build Coastguard Worker                                        size_t offset,
42*bbecb9d1SAndroid Build Coastguard Worker                                        int *iov_index,
43*bbecb9d1SAndroid Build Coastguard Worker                                        size_t *iov_offset)
44*bbecb9d1SAndroid Build Coastguard Worker {
45*bbecb9d1SAndroid Build Coastguard Worker    int idx = 0;
46*bbecb9d1SAndroid Build Coastguard Worker 
47*bbecb9d1SAndroid Build Coastguard Worker    /* use or clear cache */
48*bbecb9d1SAndroid Build Coastguard Worker    if (offset >= enc->stream.cached_offset) {
49*bbecb9d1SAndroid Build Coastguard Worker       offset -= enc->stream.cached_offset;
50*bbecb9d1SAndroid Build Coastguard Worker       idx = enc->stream.cached_index;
51*bbecb9d1SAndroid Build Coastguard Worker    } else {
52*bbecb9d1SAndroid Build Coastguard Worker       enc->stream.cached_index = 0;
53*bbecb9d1SAndroid Build Coastguard Worker       enc->stream.cached_offset = 0;
54*bbecb9d1SAndroid Build Coastguard Worker    }
55*bbecb9d1SAndroid Build Coastguard Worker 
56*bbecb9d1SAndroid Build Coastguard Worker    while (true) {
57*bbecb9d1SAndroid Build Coastguard Worker       if (idx >= enc->stream.iov_count)
58*bbecb9d1SAndroid Build Coastguard Worker          return false;
59*bbecb9d1SAndroid Build Coastguard Worker 
60*bbecb9d1SAndroid Build Coastguard Worker       const struct iovec *iov = &enc->stream.iov[idx];
61*bbecb9d1SAndroid Build Coastguard Worker       if (offset < iov->iov_len)
62*bbecb9d1SAndroid Build Coastguard Worker          break;
63*bbecb9d1SAndroid Build Coastguard Worker 
64*bbecb9d1SAndroid Build Coastguard Worker       idx++;
65*bbecb9d1SAndroid Build Coastguard Worker       offset -= iov->iov_len;
66*bbecb9d1SAndroid Build Coastguard Worker 
67*bbecb9d1SAndroid Build Coastguard Worker       /* update cache */
68*bbecb9d1SAndroid Build Coastguard Worker       enc->stream.cached_index++;
69*bbecb9d1SAndroid Build Coastguard Worker       enc->stream.cached_offset += iov->iov_len;
70*bbecb9d1SAndroid Build Coastguard Worker    }
71*bbecb9d1SAndroid Build Coastguard Worker 
72*bbecb9d1SAndroid Build Coastguard Worker    *iov_index = idx;
73*bbecb9d1SAndroid Build Coastguard Worker    *iov_offset = offset;
74*bbecb9d1SAndroid Build Coastguard Worker 
75*bbecb9d1SAndroid Build Coastguard Worker    return true;
76*bbecb9d1SAndroid Build Coastguard Worker }
77*bbecb9d1SAndroid Build Coastguard Worker 
78*bbecb9d1SAndroid Build Coastguard Worker static void
vkr_cs_encoder_update_end(struct vkr_cs_encoder * enc)79*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_update_end(struct vkr_cs_encoder *enc)
80*bbecb9d1SAndroid Build Coastguard Worker {
81*bbecb9d1SAndroid Build Coastguard Worker    const struct iovec *iov = &enc->stream.iov[enc->next_iov - 1];
82*bbecb9d1SAndroid Build Coastguard Worker    const size_t iov_offset = enc->cur - (uint8_t *)iov->iov_base;
83*bbecb9d1SAndroid Build Coastguard Worker    const size_t iov_remain = iov->iov_len - iov_offset;
84*bbecb9d1SAndroid Build Coastguard Worker 
85*bbecb9d1SAndroid Build Coastguard Worker    if (enc->remaining_size >= iov_remain) {
86*bbecb9d1SAndroid Build Coastguard Worker       enc->end = enc->cur + iov_remain;
87*bbecb9d1SAndroid Build Coastguard Worker       enc->remaining_size -= iov_remain;
88*bbecb9d1SAndroid Build Coastguard Worker    } else {
89*bbecb9d1SAndroid Build Coastguard Worker       enc->end = enc->cur + enc->remaining_size;
90*bbecb9d1SAndroid Build Coastguard Worker       enc->remaining_size = 0;
91*bbecb9d1SAndroid Build Coastguard Worker    }
92*bbecb9d1SAndroid Build Coastguard Worker }
93*bbecb9d1SAndroid Build Coastguard Worker 
94*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_encoder_seek_stream(struct vkr_cs_encoder * enc,size_t pos)95*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_seek_stream(struct vkr_cs_encoder *enc, size_t pos)
96*bbecb9d1SAndroid Build Coastguard Worker {
97*bbecb9d1SAndroid Build Coastguard Worker    const size_t offset = enc->stream.offset + pos;
98*bbecb9d1SAndroid Build Coastguard Worker    int iov_index;
99*bbecb9d1SAndroid Build Coastguard Worker    size_t iov_offset;
100*bbecb9d1SAndroid Build Coastguard Worker    if (pos > enc->stream.size ||
101*bbecb9d1SAndroid Build Coastguard Worker        !vkr_cs_encoder_translate_stream_offset(enc, offset, &iov_index, &iov_offset)) {
102*bbecb9d1SAndroid Build Coastguard Worker       vkr_log("failed to seek the reply stream to %zu", pos);
103*bbecb9d1SAndroid Build Coastguard Worker       vkr_cs_encoder_set_fatal(enc);
104*bbecb9d1SAndroid Build Coastguard Worker       return;
105*bbecb9d1SAndroid Build Coastguard Worker    }
106*bbecb9d1SAndroid Build Coastguard Worker 
107*bbecb9d1SAndroid Build Coastguard Worker    enc->remaining_size = enc->stream.size - pos;
108*bbecb9d1SAndroid Build Coastguard Worker    enc->next_iov = iov_index + 1;
109*bbecb9d1SAndroid Build Coastguard Worker 
110*bbecb9d1SAndroid Build Coastguard Worker    const struct iovec *iov = &enc->stream.iov[iov_index];
111*bbecb9d1SAndroid Build Coastguard Worker    enc->cur = iov->iov_base;
112*bbecb9d1SAndroid Build Coastguard Worker    enc->cur += iov_offset;
113*bbecb9d1SAndroid Build Coastguard Worker 
114*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_encoder_update_end(enc);
115*bbecb9d1SAndroid Build Coastguard Worker }
116*bbecb9d1SAndroid Build Coastguard Worker 
117*bbecb9d1SAndroid Build Coastguard Worker static bool
vkr_cs_encoder_next_iov(struct vkr_cs_encoder * enc)118*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_next_iov(struct vkr_cs_encoder *enc)
119*bbecb9d1SAndroid Build Coastguard Worker {
120*bbecb9d1SAndroid Build Coastguard Worker    if (enc->next_iov >= enc->stream.iov_count)
121*bbecb9d1SAndroid Build Coastguard Worker       return false;
122*bbecb9d1SAndroid Build Coastguard Worker 
123*bbecb9d1SAndroid Build Coastguard Worker    const struct iovec *iov = &enc->stream.iov[enc->next_iov++];
124*bbecb9d1SAndroid Build Coastguard Worker    enc->cur = iov->iov_base;
125*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_encoder_update_end(enc);
126*bbecb9d1SAndroid Build Coastguard Worker 
127*bbecb9d1SAndroid Build Coastguard Worker    return true;
128*bbecb9d1SAndroid Build Coastguard Worker }
129*bbecb9d1SAndroid Build Coastguard Worker 
130*bbecb9d1SAndroid Build Coastguard Worker static uint8_t *
vkr_cs_encoder_get_ptr(struct vkr_cs_encoder * enc,size_t size,size_t * ptr_size)131*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_get_ptr(struct vkr_cs_encoder *enc, size_t size, size_t *ptr_size)
132*bbecb9d1SAndroid Build Coastguard Worker {
133*bbecb9d1SAndroid Build Coastguard Worker    while (true) {
134*bbecb9d1SAndroid Build Coastguard Worker       uint8_t *ptr = enc->cur;
135*bbecb9d1SAndroid Build Coastguard Worker       const size_t avail = enc->end - enc->cur;
136*bbecb9d1SAndroid Build Coastguard Worker 
137*bbecb9d1SAndroid Build Coastguard Worker       if (avail) {
138*bbecb9d1SAndroid Build Coastguard Worker          *ptr_size = MIN2(size, avail);
139*bbecb9d1SAndroid Build Coastguard Worker          enc->cur += *ptr_size;
140*bbecb9d1SAndroid Build Coastguard Worker          return ptr;
141*bbecb9d1SAndroid Build Coastguard Worker       }
142*bbecb9d1SAndroid Build Coastguard Worker 
143*bbecb9d1SAndroid Build Coastguard Worker       if (!vkr_cs_encoder_next_iov(enc)) {
144*bbecb9d1SAndroid Build Coastguard Worker          *ptr_size = 0;
145*bbecb9d1SAndroid Build Coastguard Worker          return size ? NULL : ptr;
146*bbecb9d1SAndroid Build Coastguard Worker       }
147*bbecb9d1SAndroid Build Coastguard Worker    }
148*bbecb9d1SAndroid Build Coastguard Worker }
149*bbecb9d1SAndroid Build Coastguard Worker 
150*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_encoder_write_internal(struct vkr_cs_encoder * enc,size_t size,const void * val,size_t val_size)151*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_encoder_write_internal(struct vkr_cs_encoder *enc,
152*bbecb9d1SAndroid Build Coastguard Worker                               size_t size,
153*bbecb9d1SAndroid Build Coastguard Worker                               const void *val,
154*bbecb9d1SAndroid Build Coastguard Worker                               size_t val_size)
155*bbecb9d1SAndroid Build Coastguard Worker {
156*bbecb9d1SAndroid Build Coastguard Worker    size_t pad_size = size - val_size;
157*bbecb9d1SAndroid Build Coastguard Worker 
158*bbecb9d1SAndroid Build Coastguard Worker    do {
159*bbecb9d1SAndroid Build Coastguard Worker       size_t ptr_size;
160*bbecb9d1SAndroid Build Coastguard Worker       uint8_t *ptr = vkr_cs_encoder_get_ptr(enc, val_size, &ptr_size);
161*bbecb9d1SAndroid Build Coastguard Worker       if (unlikely(!ptr)) {
162*bbecb9d1SAndroid Build Coastguard Worker          vkr_log("failed to write value to the reply stream");
163*bbecb9d1SAndroid Build Coastguard Worker          vkr_cs_encoder_set_fatal(enc);
164*bbecb9d1SAndroid Build Coastguard Worker          return;
165*bbecb9d1SAndroid Build Coastguard Worker       }
166*bbecb9d1SAndroid Build Coastguard Worker 
167*bbecb9d1SAndroid Build Coastguard Worker       memcpy(ptr, val, ptr_size);
168*bbecb9d1SAndroid Build Coastguard Worker       val = (const uint8_t *)val + ptr_size;
169*bbecb9d1SAndroid Build Coastguard Worker       val_size -= ptr_size;
170*bbecb9d1SAndroid Build Coastguard Worker    } while (val_size);
171*bbecb9d1SAndroid Build Coastguard Worker 
172*bbecb9d1SAndroid Build Coastguard Worker    while (pad_size) {
173*bbecb9d1SAndroid Build Coastguard Worker       size_t ptr_size;
174*bbecb9d1SAndroid Build Coastguard Worker       const void *ptr = vkr_cs_encoder_get_ptr(enc, pad_size, &ptr_size);
175*bbecb9d1SAndroid Build Coastguard Worker       if (unlikely(!ptr)) {
176*bbecb9d1SAndroid Build Coastguard Worker          vkr_log("failed to write padding to the reply stream");
177*bbecb9d1SAndroid Build Coastguard Worker          vkr_cs_encoder_set_fatal(enc);
178*bbecb9d1SAndroid Build Coastguard Worker          return;
179*bbecb9d1SAndroid Build Coastguard Worker       }
180*bbecb9d1SAndroid Build Coastguard Worker       pad_size -= ptr_size;
181*bbecb9d1SAndroid Build Coastguard Worker    }
182*bbecb9d1SAndroid Build Coastguard Worker }
183*bbecb9d1SAndroid Build Coastguard Worker 
184*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_decoder_init(struct vkr_cs_decoder * dec,const struct hash_table * object_table)185*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_init(struct vkr_cs_decoder *dec, const struct hash_table *object_table)
186*bbecb9d1SAndroid Build Coastguard Worker {
187*bbecb9d1SAndroid Build Coastguard Worker    memset(dec, 0, sizeof(*dec));
188*bbecb9d1SAndroid Build Coastguard Worker    dec->object_table = object_table;
189*bbecb9d1SAndroid Build Coastguard Worker }
190*bbecb9d1SAndroid Build Coastguard Worker 
191*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_decoder_fini(struct vkr_cs_decoder * dec)192*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_fini(struct vkr_cs_decoder *dec)
193*bbecb9d1SAndroid Build Coastguard Worker {
194*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
195*bbecb9d1SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pool->buffer_count; i++)
196*bbecb9d1SAndroid Build Coastguard Worker       free(pool->buffers[i]);
197*bbecb9d1SAndroid Build Coastguard Worker    if (pool->buffers)
198*bbecb9d1SAndroid Build Coastguard Worker       free(pool->buffers);
199*bbecb9d1SAndroid Build Coastguard Worker }
200*bbecb9d1SAndroid Build Coastguard Worker 
201*bbecb9d1SAndroid Build Coastguard Worker static void
vkr_cs_decoder_sanity_check(const struct vkr_cs_decoder * dec)202*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_sanity_check(const struct vkr_cs_decoder *dec)
203*bbecb9d1SAndroid Build Coastguard Worker {
204*bbecb9d1SAndroid Build Coastguard Worker    const struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
205*bbecb9d1SAndroid Build Coastguard Worker    assert(pool->buffer_count <= pool->buffer_max);
206*bbecb9d1SAndroid Build Coastguard Worker    if (pool->buffer_count) {
207*bbecb9d1SAndroid Build Coastguard Worker       assert(pool->buffers[pool->buffer_count - 1] <= pool->reset_to);
208*bbecb9d1SAndroid Build Coastguard Worker       assert(pool->reset_to <= pool->cur);
209*bbecb9d1SAndroid Build Coastguard Worker       assert(pool->cur <= pool->end);
210*bbecb9d1SAndroid Build Coastguard Worker    }
211*bbecb9d1SAndroid Build Coastguard Worker 
212*bbecb9d1SAndroid Build Coastguard Worker    assert(dec->cur <= dec->end);
213*bbecb9d1SAndroid Build Coastguard Worker }
214*bbecb9d1SAndroid Build Coastguard Worker 
215*bbecb9d1SAndroid Build Coastguard Worker static void
vkr_cs_decoder_gc_temp_pool(struct vkr_cs_decoder * dec)216*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_gc_temp_pool(struct vkr_cs_decoder *dec)
217*bbecb9d1SAndroid Build Coastguard Worker {
218*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
219*bbecb9d1SAndroid Build Coastguard Worker    if (!pool->buffer_count)
220*bbecb9d1SAndroid Build Coastguard Worker       return;
221*bbecb9d1SAndroid Build Coastguard Worker 
222*bbecb9d1SAndroid Build Coastguard Worker    /* free all but the last buffer */
223*bbecb9d1SAndroid Build Coastguard Worker    if (pool->buffer_count > 1) {
224*bbecb9d1SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pool->buffer_count - 1; i++)
225*bbecb9d1SAndroid Build Coastguard Worker          free(pool->buffers[i]);
226*bbecb9d1SAndroid Build Coastguard Worker 
227*bbecb9d1SAndroid Build Coastguard Worker       pool->buffers[0] = pool->buffers[pool->buffer_count - 1];
228*bbecb9d1SAndroid Build Coastguard Worker       pool->buffer_count = 1;
229*bbecb9d1SAndroid Build Coastguard Worker    }
230*bbecb9d1SAndroid Build Coastguard Worker 
231*bbecb9d1SAndroid Build Coastguard Worker    pool->reset_to = pool->buffers[0];
232*bbecb9d1SAndroid Build Coastguard Worker    pool->cur = pool->buffers[0];
233*bbecb9d1SAndroid Build Coastguard Worker 
234*bbecb9d1SAndroid Build Coastguard Worker    pool->total_size = pool->end - pool->cur;
235*bbecb9d1SAndroid Build Coastguard Worker 
236*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_decoder_sanity_check(dec);
237*bbecb9d1SAndroid Build Coastguard Worker }
238*bbecb9d1SAndroid Build Coastguard Worker 
239*bbecb9d1SAndroid Build Coastguard Worker /**
240*bbecb9d1SAndroid Build Coastguard Worker  * Reset a decoder for reuse.
241*bbecb9d1SAndroid Build Coastguard Worker  */
242*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_decoder_reset(struct vkr_cs_decoder * dec)243*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_reset(struct vkr_cs_decoder *dec)
244*bbecb9d1SAndroid Build Coastguard Worker {
245*bbecb9d1SAndroid Build Coastguard Worker    /* dec->fatal_error is sticky */
246*bbecb9d1SAndroid Build Coastguard Worker 
247*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_decoder_gc_temp_pool(dec);
248*bbecb9d1SAndroid Build Coastguard Worker 
249*bbecb9d1SAndroid Build Coastguard Worker    dec->saved_state_count = 0;
250*bbecb9d1SAndroid Build Coastguard Worker    dec->cur = NULL;
251*bbecb9d1SAndroid Build Coastguard Worker    dec->end = NULL;
252*bbecb9d1SAndroid Build Coastguard Worker }
253*bbecb9d1SAndroid Build Coastguard Worker 
254*bbecb9d1SAndroid Build Coastguard Worker bool
vkr_cs_decoder_push_state(struct vkr_cs_decoder * dec)255*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_push_state(struct vkr_cs_decoder *dec)
256*bbecb9d1SAndroid Build Coastguard Worker {
257*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
258*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_saved_state *saved;
259*bbecb9d1SAndroid Build Coastguard Worker 
260*bbecb9d1SAndroid Build Coastguard Worker    if (dec->saved_state_count >= ARRAY_SIZE(dec->saved_states))
261*bbecb9d1SAndroid Build Coastguard Worker       return false;
262*bbecb9d1SAndroid Build Coastguard Worker 
263*bbecb9d1SAndroid Build Coastguard Worker    saved = &dec->saved_states[dec->saved_state_count++];
264*bbecb9d1SAndroid Build Coastguard Worker    saved->cur = dec->cur;
265*bbecb9d1SAndroid Build Coastguard Worker    saved->end = dec->end;
266*bbecb9d1SAndroid Build Coastguard Worker 
267*bbecb9d1SAndroid Build Coastguard Worker    saved->pool_buffer_count = pool->buffer_count;
268*bbecb9d1SAndroid Build Coastguard Worker    saved->pool_reset_to = pool->reset_to;
269*bbecb9d1SAndroid Build Coastguard Worker    /* avoid temp data corruption */
270*bbecb9d1SAndroid Build Coastguard Worker    pool->reset_to = pool->cur;
271*bbecb9d1SAndroid Build Coastguard Worker 
272*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_decoder_sanity_check(dec);
273*bbecb9d1SAndroid Build Coastguard Worker 
274*bbecb9d1SAndroid Build Coastguard Worker    return true;
275*bbecb9d1SAndroid Build Coastguard Worker }
276*bbecb9d1SAndroid Build Coastguard Worker 
277*bbecb9d1SAndroid Build Coastguard Worker void
vkr_cs_decoder_pop_state(struct vkr_cs_decoder * dec)278*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_pop_state(struct vkr_cs_decoder *dec)
279*bbecb9d1SAndroid Build Coastguard Worker {
280*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
281*bbecb9d1SAndroid Build Coastguard Worker    const struct vkr_cs_decoder_saved_state *saved;
282*bbecb9d1SAndroid Build Coastguard Worker 
283*bbecb9d1SAndroid Build Coastguard Worker    assert(dec->saved_state_count);
284*bbecb9d1SAndroid Build Coastguard Worker    saved = &dec->saved_states[--dec->saved_state_count];
285*bbecb9d1SAndroid Build Coastguard Worker    dec->cur = saved->cur;
286*bbecb9d1SAndroid Build Coastguard Worker    dec->end = saved->end;
287*bbecb9d1SAndroid Build Coastguard Worker 
288*bbecb9d1SAndroid Build Coastguard Worker    /* restore only if pool->reset_to points to the same buffer */
289*bbecb9d1SAndroid Build Coastguard Worker    if (pool->buffer_count == saved->pool_buffer_count)
290*bbecb9d1SAndroid Build Coastguard Worker       pool->reset_to = saved->pool_reset_to;
291*bbecb9d1SAndroid Build Coastguard Worker 
292*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_decoder_sanity_check(dec);
293*bbecb9d1SAndroid Build Coastguard Worker }
294*bbecb9d1SAndroid Build Coastguard Worker 
295*bbecb9d1SAndroid Build Coastguard Worker static uint32_t
next_array_size(uint32_t cur_size,uint32_t min_size)296*bbecb9d1SAndroid Build Coastguard Worker next_array_size(uint32_t cur_size, uint32_t min_size)
297*bbecb9d1SAndroid Build Coastguard Worker {
298*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t next_size = cur_size ? cur_size * 2 : min_size;
299*bbecb9d1SAndroid Build Coastguard Worker    return next_size > cur_size ? next_size : 0;
300*bbecb9d1SAndroid Build Coastguard Worker }
301*bbecb9d1SAndroid Build Coastguard Worker 
302*bbecb9d1SAndroid Build Coastguard Worker static size_t
next_buffer_size(size_t cur_size,size_t min_size,size_t need)303*bbecb9d1SAndroid Build Coastguard Worker next_buffer_size(size_t cur_size, size_t min_size, size_t need)
304*bbecb9d1SAndroid Build Coastguard Worker {
305*bbecb9d1SAndroid Build Coastguard Worker    size_t next_size = cur_size ? cur_size * 2 : min_size;
306*bbecb9d1SAndroid Build Coastguard Worker    while (next_size < need) {
307*bbecb9d1SAndroid Build Coastguard Worker       next_size *= 2;
308*bbecb9d1SAndroid Build Coastguard Worker       if (!next_size)
309*bbecb9d1SAndroid Build Coastguard Worker          return 0;
310*bbecb9d1SAndroid Build Coastguard Worker    }
311*bbecb9d1SAndroid Build Coastguard Worker    return next_size;
312*bbecb9d1SAndroid Build Coastguard Worker }
313*bbecb9d1SAndroid Build Coastguard Worker 
314*bbecb9d1SAndroid Build Coastguard Worker static bool
vkr_cs_decoder_grow_temp_pool(struct vkr_cs_decoder * dec)315*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_grow_temp_pool(struct vkr_cs_decoder *dec)
316*bbecb9d1SAndroid Build Coastguard Worker {
317*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
318*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t buf_max = next_array_size(pool->buffer_max, 4);
319*bbecb9d1SAndroid Build Coastguard Worker    if (!buf_max)
320*bbecb9d1SAndroid Build Coastguard Worker       return false;
321*bbecb9d1SAndroid Build Coastguard Worker 
322*bbecb9d1SAndroid Build Coastguard Worker    uint8_t **bufs = realloc(pool->buffers, sizeof(*pool->buffers) * buf_max);
323*bbecb9d1SAndroid Build Coastguard Worker    if (!bufs)
324*bbecb9d1SAndroid Build Coastguard Worker       return false;
325*bbecb9d1SAndroid Build Coastguard Worker 
326*bbecb9d1SAndroid Build Coastguard Worker    pool->buffers = bufs;
327*bbecb9d1SAndroid Build Coastguard Worker    pool->buffer_max = buf_max;
328*bbecb9d1SAndroid Build Coastguard Worker 
329*bbecb9d1SAndroid Build Coastguard Worker    return true;
330*bbecb9d1SAndroid Build Coastguard Worker }
331*bbecb9d1SAndroid Build Coastguard Worker 
332*bbecb9d1SAndroid Build Coastguard Worker bool
vkr_cs_decoder_alloc_temp_internal(struct vkr_cs_decoder * dec,size_t size)333*bbecb9d1SAndroid Build Coastguard Worker vkr_cs_decoder_alloc_temp_internal(struct vkr_cs_decoder *dec, size_t size)
334*bbecb9d1SAndroid Build Coastguard Worker {
335*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_cs_decoder_temp_pool *pool = &dec->temp_pool;
336*bbecb9d1SAndroid Build Coastguard Worker 
337*bbecb9d1SAndroid Build Coastguard Worker    if (pool->buffer_count >= pool->buffer_max) {
338*bbecb9d1SAndroid Build Coastguard Worker       if (!vkr_cs_decoder_grow_temp_pool(dec))
339*bbecb9d1SAndroid Build Coastguard Worker          return false;
340*bbecb9d1SAndroid Build Coastguard Worker       assert(pool->buffer_count < pool->buffer_max);
341*bbecb9d1SAndroid Build Coastguard Worker    }
342*bbecb9d1SAndroid Build Coastguard Worker 
343*bbecb9d1SAndroid Build Coastguard Worker    const size_t cur_buf_size =
344*bbecb9d1SAndroid Build Coastguard Worker       pool->buffer_count ? pool->end - pool->buffers[pool->buffer_count - 1] : 0;
345*bbecb9d1SAndroid Build Coastguard Worker    const size_t buf_size = next_buffer_size(cur_buf_size, 4096, size);
346*bbecb9d1SAndroid Build Coastguard Worker    if (!buf_size)
347*bbecb9d1SAndroid Build Coastguard Worker       return false;
348*bbecb9d1SAndroid Build Coastguard Worker 
349*bbecb9d1SAndroid Build Coastguard Worker    if (buf_size > VKR_CS_DECODER_TEMP_POOL_MAX_SIZE - pool->total_size)
350*bbecb9d1SAndroid Build Coastguard Worker       return false;
351*bbecb9d1SAndroid Build Coastguard Worker 
352*bbecb9d1SAndroid Build Coastguard Worker    uint8_t *buf = malloc(buf_size);
353*bbecb9d1SAndroid Build Coastguard Worker    if (!buf)
354*bbecb9d1SAndroid Build Coastguard Worker       return false;
355*bbecb9d1SAndroid Build Coastguard Worker 
356*bbecb9d1SAndroid Build Coastguard Worker    pool->total_size += buf_size;
357*bbecb9d1SAndroid Build Coastguard Worker    pool->buffers[pool->buffer_count++] = buf;
358*bbecb9d1SAndroid Build Coastguard Worker    pool->reset_to = buf;
359*bbecb9d1SAndroid Build Coastguard Worker    pool->cur = buf;
360*bbecb9d1SAndroid Build Coastguard Worker    pool->end = buf + buf_size;
361*bbecb9d1SAndroid Build Coastguard Worker 
362*bbecb9d1SAndroid Build Coastguard Worker    vkr_cs_decoder_sanity_check(dec);
363*bbecb9d1SAndroid Build Coastguard Worker 
364*bbecb9d1SAndroid Build Coastguard Worker    return true;
365*bbecb9d1SAndroid Build Coastguard Worker }
366