Dunny said:
I should know better than to doubt you in areas of code, but to my mind twiddling RGB values will be faster in 32bpp than in 16bpp.
It depends what you mean by twiddling values. Blending, for instance, is faster in 16bpp than what you have in mind. I imagine you're referring to the savings gained by byte addressing vs packing and unpacking values. We'll assume that packing 32bpp is never faster than packing 16bpp, at least on "normal" architectures (let's ignore the byte segmentation of registers on x86, because using them actually tends to be a pipeline hazard).
Consider the following blending example:
Code:
// Blend (pixel_a * blend_a) + (pixel_b * blend_B), blend_a and blend_b are 0 to 16, result is assumed to not saturate
// 16-bit RGB 565 version:
// source_a, source_b, and dest are u16 *
pixel_a = *source_a;
pixel_b = *source_b;
pixel_a_expand = (pixel_a & (0x1F | (0x1F << 11)) | ((pixel_a & (0x3F << 5)) << 16);
pixel_b_expand = (pixel_b & (0x1F | (0x1F << 11)) | ((pixel_b & (0x3F << 5)) << 16);
pixel = ((pixel_a_expand * blend_a) + (pixel_b_expand * blend_B) >> 4) & (0x1F | (0x1F << 11) | (0x3F << (5 + 16)));
*dest = pixel | (pixel >> 16);
// 8-bit 0RGB 8888 version, using byte addressing:
// source_a, source_b, and dest are u8 *
dest[0] = ((source_a[0] * blend) + (source_b[0] * blend)) >> 4;
dest[1] = ((source_a[1] * blend) + (source_b[1] * blend)) >> 4;
dest[2] = ((source_a[2] * blend) + (source_b[2] * blend)) >> 4;
16-bit version is 2 loads, 5 ands, 3 ors, 3 shifts, 2 32x8 multiplies, and 1 store.
32-bit version is 6 loads, 3 adds, 3 shifts, 6 8x8 multiplies, and 3 stores.
On ARM two of the shifts in the 16-bit version can be folded. Of course, which one is faster depends on the architecture, but generally it'll be the 16-bit version, especially if the arch can't issue multiplies every cycle (although, you might get some faster issues multiplies down the 8x8 path). I won't look into data dependencies because you're probably not only doing one pixel in isolation.
Dunny said:
Copying pixels from one area to another would be quicker in 16bpp (Assuming you're copying an even number of pixels in each row), unless the rep instructions have gotten a lot more efficient in the last few years.
Any realistic case is going to be memory bandwidth bound (hopefully not memory latency bound, if the write buffering is any good). Block transfer instructions only really help you if there's no write combining on the write buffering.