+def pack_rgba(format, src_channel, r, g, b, a):
+ """Return an expression for packing r, g, b, a into a pixel of the
+ given format. Ex: '(b << 24) | (g << 16) | (r << 8) | (a << 0)'
+ """
+ assert format.colorspace in ('rgb', 'srgb')
+ inv_swizzle = format.inv_swizzles()
+ shift = 0
+ expr = None
+ for i in range(4):
+ # choose r, g, b, or a depending on the inverse swizzle term
+ if inv_swizzle[i] == 0:
+ value = r
+ elif inv_swizzle[i] == 1:
+ value = g
+ elif inv_swizzle[i] == 2:
+ value = b
+ elif inv_swizzle[i] == 3:
+ value = a
+ else:
+ value = None
+
+ if value:
+ dst_channel = format.channels[i]
+ dst_native_type = native_type(format)
+ value = conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=False)
+ term = "((%s) << %d)" % (value, shift)
+ if expr:
+ expr = expr + " | " + term
+ else:
+ expr = term
+
+ width = format.channels[i].size
+ shift = shift + width
+ return expr
+
+
+def emit_unrolled_unswizzle_code(format, src_channel):
+ '''Emit code for writing a block based on unrolled loops.
+ This is considerably faster than the TILE_PIXEL-based code below.
+ '''
+ dst_native_type = 'uint%u_t' % format.block_size()
+ print ' const unsigned dstpix_stride = dst_stride / %d;' % format.stride()
+ print ' %s *dstpix = (%s *) dst;' % (dst_native_type, dst_native_type)
+ print ' unsigned int qx, qy, i;'
+ print
+ print ' for (qy = 0; qy < h; qy += TILE_VECTOR_HEIGHT) {'
+ print ' const unsigned py = y0 + qy;'
+ print ' for (qx = 0; qx < w; qx += TILE_VECTOR_WIDTH) {'
+ print ' const unsigned px = x0 + qx;'
+ print ' const uint8_t *r = src + 0 * TILE_C_STRIDE;'
+ print ' const uint8_t *g = src + 1 * TILE_C_STRIDE;'
+ print ' const uint8_t *b = src + 2 * TILE_C_STRIDE;'
+ print ' const uint8_t *a = src + 3 * TILE_C_STRIDE;'
+ print ' (void) r; (void) g; (void) b; (void) a; /* silence warnings */'
+ print ' for (i = 0; i < TILE_C_STRIDE; i += 2) {'
+ print ' const uint32_t pixel0 = %s;' % pack_rgba(format, src_channel, "r[i+0]", "g[i+0]", "b[i+0]", "a[i+0]")
+ print ' const uint32_t pixel1 = %s;' % pack_rgba(format, src_channel, "r[i+1]", "g[i+1]", "b[i+1]", "a[i+1]")
+ print ' const unsigned offset = (py + tile_y_offset[i]) * dstpix_stride + (px + tile_x_offset[i]);'
+ print ' dstpix[offset + 0] = pixel0;'
+ print ' dstpix[offset + 1] = pixel1;'
+ print ' }'
+ print ' src += TILE_X_STRIDE;'
+ print ' }'
+ print ' }'