Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/udl: optimize udl_compress_hline16 (v2)

The run-length encoding algorithm should compare 16-bit encoded pixel
values instead of comparing raw pixel values. It allows pixels
with similar but different colors to be encoded as repeat pixels, and
thus potentially save USB bandwidth.

Signed-off-by: Haixia Shi <hshi@chromium.org>
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
Tested-by: Haixia Shi <hshi@chromium.org>
Signed-off-by: Dave Airlie <airlied@gmail.com>

authored by

Haixia Shi and committed by
Dave Airlie
86584444 e4100553

+18 -19
+18 -19
drivers/gpu/drm/udl/udl_transfer.c
··· 82 82 ((pixel >> 8) & 0xf800)); 83 83 } 84 84 85 - static bool pixel_repeats(const void *pixel, const uint32_t repeat, int bpp) 85 + static inline u16 get_pixel_val16(const uint8_t *pixel, int bpp) 86 86 { 87 + u16 pixel_val16 = 0; 87 88 if (bpp == 2) 88 - return *(const uint16_t *)pixel == repeat; 89 - else 90 - return *(const uint32_t *)pixel == repeat; 89 + pixel_val16 = *(const uint16_t *)pixel; 90 + else if (bpp == 4) 91 + pixel_val16 = pixel32_to_be16(*(const uint32_t *)pixel); 92 + return pixel_val16; 91 93 } 92 94 93 95 /* ··· 136 134 uint8_t *cmd_pixels_count_byte = NULL; 137 135 const u8 *raw_pixel_start = NULL; 138 136 const u8 *cmd_pixel_start, *cmd_pixel_end = NULL; 137 + uint16_t pixel_val16; 139 138 140 139 prefetchw((void *) cmd); /* pull in one cache line at least */ 141 140 ··· 157 154 (int)(cmd_buffer_end - cmd) / 2))) * bpp; 158 155 159 156 prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); 157 + pixel_val16 = get_pixel_val16(pixel, bpp); 160 158 161 159 while (pixel < cmd_pixel_end) { 162 160 const u8 *const start = pixel; 163 - u32 repeating_pixel; 161 + const uint16_t repeating_pixel_val16 = pixel_val16; 164 162 165 - if (bpp == 2) { 166 - repeating_pixel = *(uint16_t *)pixel; 167 - *(uint16_t *)cmd = cpu_to_be16(repeating_pixel); 168 - } else { 169 - repeating_pixel = *(uint32_t *)pixel; 170 - *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16(repeating_pixel)); 171 - } 163 + *(uint16_t *)cmd = cpu_to_be16(pixel_val16); 172 164 173 165 cmd += 2; 174 166 pixel += bpp; 175 167 176 - if (unlikely((pixel < cmd_pixel_end) && 177 - (pixel_repeats(pixel, repeating_pixel, bpp)))) { 168 + while (pixel < cmd_pixel_end) { 169 + pixel_val16 = get_pixel_val16(pixel, bpp); 170 + if (pixel_val16 != repeating_pixel_val16) 171 + break; 172 + pixel += bpp; 173 + } 174 + 175 + if (unlikely(pixel > start + bpp)) { 178 176 /* go back and fill in raw pixel count */ 179 177 *raw_pixels_count_byte = (((start - 180 178 raw_pixel_start) / bpp) + 1) & 0xFF; 181 - 182 - while ((pixel < cmd_pixel_end) && 183 - (pixel_repeats(pixel, repeating_pixel, bpp))) { 184 - pixel += bpp; 185 - } 186 179 187 180 /* immediately after raw data is repeat byte */ 188 181 *cmd++ = (((pixel - start) / bpp) - 1) & 0xFF;