From d3584b4e85ee984c35c1e152af6c7b4dbc34b7c2 Mon Sep 17 00:00:00 2001 From: Charlie Brej Date: Mon, 27 Oct 2008 12:49:06 -0400 Subject: [PATCH] Dither colors in non-default low depth color path This patch modifies the low color mode (slow) path to dither the colors before flushing them to the scanout buffer. This improves the output quality in those corner cases. --- src/libply/ply-frame-buffer.c | 41 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/libply/ply-frame-buffer.c b/src/libply/ply-frame-buffer.c index d80a6cdb..dd266469 100644 --- a/src/libply/ply-frame-buffer.c +++ b/src/libply/ply-frame-buffer.c @@ -68,6 +68,10 @@ struct _ply_frame_buffer uint32_t bits_for_blue; uint32_t bits_for_alpha; + int32_t dither_red; + int32_t dither_green; + int32_t dither_blue; + unsigned int bytes_per_pixel; unsigned int row_stride; @@ -315,6 +319,10 @@ ply_frame_buffer_query_device (ply_frame_buffer_t *buffer) buffer->bytes_per_pixel = variable_screen_info.bits_per_pixel >> 3; buffer->row_stride = fixed_screen_info.line_length / buffer->bytes_per_pixel; buffer->size = buffer->area.height * buffer->row_stride * buffer->bytes_per_pixel; + + buffer->dither_red = 0; + buffer->dither_green = 0; + buffer->dither_blue = 0; if (buffer->bytes_per_pixel == 4 && buffer->red_bit_position == 16 && buffer->bits_for_red == 8 && @@ -340,24 +348,37 @@ ply_frame_buffer_map_to_device (ply_frame_buffer_t *buffer) return buffer->map_address != MAP_FAILED; } -__attribute__((__pure__)) static inline uint_fast32_t ply_frame_buffer_pixel_value_to_device_pixel_value (ply_frame_buffer_t *buffer, uint32_t pixel_value) { uint8_t r, g, b, a; + int orig_r, orig_g, orig_b, orig_a; + int i; + + orig_a = pixel_value >> 24; + a = orig_a >> (8 - buffer->bits_for_alpha); - a = pixel_value >> 24; - a >>= (8 - buffer->bits_for_alpha); + orig_r = ((pixel_value >> 16) & 0xff) - buffer->dither_red; + r = CLAMP(orig_r, 0, 255) >> (8 - buffer->bits_for_red); - r = (pixel_value >> 16) & 0xff; - r >>= (8 - buffer->bits_for_red); + orig_g = ((pixel_value >> 8) & 0xff) - buffer->dither_green; + g = CLAMP(orig_g, 0, 255) >> (8 - buffer->bits_for_green); - g = (pixel_value >> 8) & 0xff; - g >>= (8 - buffer->bits_for_green); - - b = pixel_value & 0xff; - b >>= (8 - buffer->bits_for_blue); + orig_b = (pixel_value & 0xff) - buffer->dither_blue; + b = CLAMP(orig_b, 0, 255) >> (8 - buffer->bits_for_blue); + + uint8_t new_r = r << (8 - buffer->bits_for_red); + uint8_t new_g = g << (8 - buffer->bits_for_green); + uint8_t new_b = b << (8 - buffer->bits_for_blue); + for (i=buffer->bits_for_red; i<8; i*=2) new_r |= new_r >> i; + for (i=buffer->bits_for_green; i<8; i*=2) new_g |= new_g >> i; + for (i=buffer->bits_for_blue; i<8; i*=2) new_b |= new_b >> i; + + buffer->dither_red = new_r - orig_r; + buffer->dither_green = new_g - orig_g; + buffer->dither_blue = new_b - orig_b; + return ((a << buffer->alpha_bit_position) | (r << buffer->red_bit_position)