[Mesa-dev] [PATCH 1/3] vl: Only initialize vlc once

Maarten Lankhorst m.b.lankhorst at gmail.com
Fri Dec 23 00:58:53 PST 2011


On 12/22/2011 02:25 PM, Christian König wrote:
> Hi Maarten,
>
> On 21.12.2011 21:52, Maarten Lankhorst wrote:
>> It would be nice if you inlined patches for easier reviewing. :)
> Well I can try, but I can't promise that Thunderbird isn't badly fucking up all whitespaces, newest version of the patch is in-lined below.
http://www.mjmwired.net/kernel/Documentation/email-clients.txt
has some info on how to set things up. It mangles pretty badly by
default. Oddly enough enabling HTML format can help, I always
paste in my text in the preformat style, but send it as text.

+      vlc->buffer |= (uint64_t)*data<<  (24 + vlc->invalid_bits);
I have no idea how your mailer comes up with such weird spaces
in the if statements though, might be the server rather than client.
:(

>> I'm spotting an overflow that could be triggered with 64 single-byte unaligned buffers, maybe this is better:
> Should be fixed.
>> With all the pointer math, maybe change the type for 'end' and 'data' to
>> uint8_t? Then you would only need that single cast in fillbits (which
>> I did above) and you can kill all the casts everywhere.
> Yeah, we now use it as int8_t more often, that saves at least some casts.
>
>> Another thought, this would prevent the need to read past end of file which could show up erroneously in valgrind, with something like this: if (end-data>= 4) { // Nom nom 4 bytes } else { // Read at most 3 bytes }
> Ok, take a look below. I now use if(bytes_left ==0) {...} else if (bytes_left >= 4) {...} else {...} construct, should this work or do you see any more corner cases I missed?
>
> I also inverted the valid_bits handling to invalid_bits and moved range where invalid_bits is now moving in between to -32 and 32, that should save a few more CPU cycles.
>
> Last but not least I added at least one sentence of documentation to each function. Any more thoughts or should we commit that now?
>

> diff --git a/src/gallium/auxiliary/vl/vl_vlc.h b/src/gallium/auxiliary/vl/vl_vlc.h
> index dc4faed..5e5e64c 100644
> --- a/src/gallium/auxiliary/vl/vl_vlc.h
> +++ b/src/gallium/auxiliary/vl/vl_vlc.h
> ...
>  static INLINE void
>  vl_vlc_fillbits(struct vl_vlc *vlc)
>  {
> -   if (vlc->valid_bits<  32) {
> -      uint32_t value = *vlc->data;
> +   assert(vlc);
>
> -      //assert(vlc->data<= vlc->end);
> +   /* as long as the buffer needs to be filled */
> +   while (vlc->invalid_bits>  0) {
> +      unsigned bytes_left = vlc->end - vlc->data;
> +
> +      /* if this input is depleted */
> +      if (bytes_left == 0) {
> +
> +         if (vlc->num_inputs)
> +            /* go on to next input */
> +            vl_vlc_next_input(vlc);
> +         else
> +            /* or give up since we don't have anymore inputs */
> +            return;
> +
> +      } else if (bytes_left>= 4) {
> +
> +         /* enough bytes in buffer, read in a whole dword */
> +         uint32_t value = *(const uint32_t*)vlc->data;
Change type to uint64_t and get rid of cast?
>
>  #ifndef PIPE_ARCH_BIG_ENDIAN
> -      value = util_bswap32(value);
> +         value = util_bswap32(value);
>  #endif
>
> -      vlc->buffer |= (uint64_t)value<<  (32 - vlc->valid_bits);
> -      ++vlc->data;
> -      vlc->valid_bits += 32;
> +         vlc->buffer |= (uint64_t)value<<  vlc->invalid_bits;
> +         vlc->data += 4;
> +         vlc->invalid_bits -= 32;
> +
> +         /* buffer is now definitely filled up avoid the loop test */
> +         break;
> +
> +      } else while (vlc->data<  vlc->end) {
> +
> +         /* not enough bytes left in buffer, read single bytes */
> +         vlc->buffer |= (uint64_t)*vlc->data<<  (24 + vlc->invalid_bits);
> +         ++vlc->data;
> +         vlc->invalid_bits -= 8;
> +      }
>     }
>  }
>
> +/*
> + * initialize vlc structure and start reading from first input buffer
> + */
>  static INLINE void
> -vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len)
> +vl_vlc_init(struct vl_vlc *vlc, unsigned num_inputs,
> +            const void *const *inputs, const unsigned *sizes)
>  {
> +   unsigned i;
> +
>     assert(vlc);
> -   assert(data&&  len);
> +   assert(num_inputs);
>
>     vlc->buffer = 0;
> -   vlc->valid_bits = 0;
> +   vlc->invalid_bits = 32;
> +   vlc->num_inputs = num_inputs;
> +   vlc->inputs = inputs;
> +   vlc->sizes = sizes;
> +   vlc->bytes_left = 0;
>
> -   /* align the data pointer */
> -   while (pointer_to_uintptr(data)&  3) {
> -      vlc->buffer |= (uint64_t)*data<<  (56 - vlc->valid_bits);
> -      ++data;
> -      --len;
> -      vlc->valid_bits += 8;
> -   }
> -   vlc->data = (uint32_t*)data;
> -   vlc->end = (uint32_t*)(data + len);
> +   for (i = 0; i<  num_inputs; ++i)
> +      vlc->bytes_left += sizes[i];
>
> +   vl_vlc_next_input(vlc);
>     vl_vlc_fillbits(vlc);
>     vl_vlc_fillbits(vlc);
Second fillbits is a noop now?
>  }
>
> +/*
> + * number of bits still valid in bit buffer
> + */
> +static INLINE unsigned
> +vl_vlc_valid_bits(struct vl_vlc *vlc)
> +{
> +   return 32 - vlc->invalid_bits;
> +}
Since all the 1 liner comments can already be implied from the function
name, I dont think it adds much. You might want to kill the comments entirely.
Personally I only prefer to add comments when I'm doing something that's not
clear from the code. If you want to make it part of doxygen you would need
to start with /** instead of /*. Up to you if you want to remove them or change
to /**.

Feel free to commit the result with those 3 changes without further review. :)

~Maarten


More information about the mesa-dev mailing list