Path: blob/21.2-virgl/src/gallium/auxiliary/vl/vl_vlc.h
4565 views
/**************************************************************************1*2* Copyright 2011 Christian König.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/*28* Functions for fast bitwise access to multiple probably unaligned input buffers29*/3031#ifndef vl_vlc_h32#define vl_vlc_h3334#include "pipe/p_compiler.h"3536#include "util/u_math.h"37#include "util/u_pointer.h"38#include "util/u_debug.h"3940struct vl_vlc41{42uint64_t buffer;43signed invalid_bits;44const uint8_t *data;45const uint8_t *end;4647const void *const *inputs;48const unsigned *sizes;49unsigned bytes_left;50};5152struct vl_vlc_entry53{54int8_t length;55int8_t value;56};5758struct vl_vlc_compressed59{60uint16_t bitcode;61struct vl_vlc_entry entry;62};6364/**65* initalize and decompress a lookup table66*/67static inline void68vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size)69{70unsigned i, bits = util_logbase2(dst_size);7172assert(dst && dst_size);73assert(src && src_size);7475for (i=0;i<dst_size;++i) {76dst[i].length = 0;77dst[i].value = 0;78}7980for(; src_size > 0; --src_size, ++src) {81for(i = 0; i < (1u << (bits - src->entry.length)); ++i)82dst[src->bitcode >> (16 - bits) | i] = src->entry;83}84}8586/**87* switch over to next input buffer88*/89static inline void90vl_vlc_next_input(struct vl_vlc *vlc)91{92unsigned len = vlc->sizes[0];9394assert(vlc);95assert(vlc->bytes_left);9697if (len < vlc->bytes_left)98vlc->bytes_left -= len;99else {100len = vlc->bytes_left;101vlc->bytes_left = 0;102}103104vlc->data = vlc->inputs[0];105vlc->end = vlc->data + len;106107++vlc->inputs;108++vlc->sizes;109}110111/**112* align the data pointer to the next dword113*/114static inline void115vl_vlc_align_data_ptr(struct vl_vlc *vlc)116{117/* align the data pointer */118while (vlc->data != vlc->end && pointer_to_uintptr(vlc->data) & 3) {119vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits);120++vlc->data;121vlc->invalid_bits -= 8;122}123}124125/**126* fill the bit buffer, so that at least 32 bits are valid127*/128static inline void129vl_vlc_fillbits(struct vl_vlc *vlc)130{131assert(vlc);132133/* as long as the buffer needs to be filled */134while (vlc->invalid_bits > 0) {135unsigned bytes_left = vlc->end - vlc->data;136137/* if this input is depleted */138if (bytes_left == 0) {139140if (vlc->bytes_left) {141/* go on to next input */142vl_vlc_next_input(vlc);143vl_vlc_align_data_ptr(vlc);144} else145/* or give up since we don't have anymore inputs */146return;147148} else if (bytes_left >= 4) {149150/* enough bytes in buffer, read in a whole dword */151uint64_t value = *(const uint32_t*)vlc->data;152153#if !UTIL_ARCH_BIG_ENDIAN154value = util_bswap32(value);155#endif156157vlc->buffer |= value << vlc->invalid_bits;158vlc->data += 4;159vlc->invalid_bits -= 32;160161/* buffer is now definitely filled up avoid the loop test */162break;163164} else while (vlc->data < vlc->end) {165166/* not enough bytes left in buffer, read single bytes */167vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits);168++vlc->data;169vlc->invalid_bits -= 8;170}171}172}173174/**175* initialize vlc structure and start reading from first input buffer176*/177static inline void178vl_vlc_init(struct vl_vlc *vlc, unsigned num_inputs,179const void *const *inputs, const unsigned *sizes)180{181unsigned i;182183assert(vlc);184assert(num_inputs);185186vlc->buffer = 0;187vlc->invalid_bits = 32;188vlc->inputs = inputs;189vlc->sizes = sizes;190vlc->bytes_left = 0;191192for (i = 0; i < num_inputs; ++i)193vlc->bytes_left += sizes[i];194195if (vlc->bytes_left) {196vl_vlc_next_input(vlc);197vl_vlc_align_data_ptr(vlc);198vl_vlc_fillbits(vlc);199}200}201202/**203* number of bits still valid in bit buffer204*/205static inline unsigned206vl_vlc_valid_bits(struct vl_vlc *vlc)207{208return 32 - vlc->invalid_bits;209}210211/**212* number of bits left over all inbut buffers213*/214static inline unsigned215vl_vlc_bits_left(struct vl_vlc *vlc)216{217signed bytes_left = vlc->end - vlc->data;218bytes_left += vlc->bytes_left;219return bytes_left * 8 + vl_vlc_valid_bits(vlc);220}221222/**223* get num_bits from bit buffer without removing them224*/225static inline unsigned226vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)227{228assert(vl_vlc_valid_bits(vlc) >= num_bits || vlc->data >= vlc->end);229return vlc->buffer >> (64 - num_bits);230}231232/**233* remove num_bits from bit buffer234*/235static inline void236vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)237{238assert(vl_vlc_valid_bits(vlc) >= num_bits);239240vlc->buffer <<= num_bits;241vlc->invalid_bits += num_bits;242}243244/**245* get num_bits from bit buffer with removing them246*/247static inline unsigned248vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)249{250unsigned value;251252assert(vl_vlc_valid_bits(vlc) >= num_bits);253254value = vlc->buffer >> (64 - num_bits);255vl_vlc_eatbits(vlc, num_bits);256257return value;258}259260/**261* treat num_bits as signed value and remove them from bit buffer262*/263static inline signed264vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)265{266signed value;267268assert(vl_vlc_valid_bits(vlc) >= num_bits);269270value = ((int64_t)vlc->buffer) >> (64 - num_bits);271vl_vlc_eatbits(vlc, num_bits);272273return value;274}275276/**277* lookup a value and length in a decompressed table278*/279static inline int8_t280vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits)281{282tbl += vl_vlc_peekbits(vlc, num_bits);283vl_vlc_eatbits(vlc, tbl->length);284return tbl->value;285}286287/**288* fast forward search for a specific byte value289*/290static inline boolean291vl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value)292{293/* make sure we are on a byte boundary */294assert((vl_vlc_valid_bits(vlc) % 8) == 0);295assert(num_bits == ~0u || (num_bits % 8) == 0);296297/* deplete the bit buffer */298while (vl_vlc_valid_bits(vlc) > 0) {299300if (vl_vlc_peekbits(vlc, 8) == value) {301vl_vlc_fillbits(vlc);302return TRUE;303}304305vl_vlc_eatbits(vlc, 8);306307if (num_bits != ~0u) {308num_bits -= 8;309if (num_bits == 0)310return FALSE;311}312}313314/* deplete the byte buffers */315while (1) {316317/* if this input is depleted */318if (vlc->data == vlc->end) {319if (vlc->bytes_left)320/* go on to next input */321vl_vlc_next_input(vlc);322else323/* or give up since we don't have anymore inputs */324return FALSE;325}326327if (*vlc->data == value) {328vl_vlc_align_data_ptr(vlc);329vl_vlc_fillbits(vlc);330return TRUE;331}332333++vlc->data;334if (num_bits != ~0u) {335num_bits -= 8;336if (num_bits == 0) {337vl_vlc_align_data_ptr(vlc);338return FALSE;339}340}341}342}343344/**345* remove num_bits bits starting at pos from the bitbuffer346*/347static inline void348vl_vlc_removebits(struct vl_vlc *vlc, unsigned pos, unsigned num_bits)349{350uint64_t lo = (vlc->buffer & (~0UL >> (pos + num_bits))) << num_bits;351uint64_t hi = (vlc->buffer & (~0UL << (64 - pos)));352vlc->buffer = lo | hi;353vlc->invalid_bits += num_bits;354}355356/**357* limit the number of bits left for fetching358*/359static inline void360vl_vlc_limit(struct vl_vlc *vlc, unsigned bits_left)361{362assert(bits_left <= vl_vlc_bits_left(vlc));363364vl_vlc_fillbits(vlc);365if (bits_left < vl_vlc_valid_bits(vlc)) {366vlc->invalid_bits = 32 - bits_left;367vlc->buffer &= ~0L << (vlc->invalid_bits + 32);368vlc->end = vlc->data;369vlc->bytes_left = 0;370} else {371assert((bits_left - vl_vlc_valid_bits(vlc)) % 8 == 0);372vlc->bytes_left = (bits_left - vl_vlc_valid_bits(vlc)) / 8;373if (vlc->bytes_left < (vlc->end - vlc->data)) {374vlc->end = vlc->data + vlc->bytes_left;375vlc->bytes_left = 0;376} else377vlc->bytes_left -= vlc->end - vlc->data;378}379}380381#endif /* vl_vlc_h */382383384