0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/string.h>
0013
0014 #include <asm/unaligned.h>
0015
0016 #include "c2p.h"
0017 #include "c2p_core.h"
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 static void c2p_16x8(u32 d[4])
0028 {
0029 transp4(d, 8, 2);
0030 transp4(d, 1, 2);
0031 transp4x(d, 16, 2);
0032 transp4x(d, 2, 2);
0033 transp4(d, 4, 1);
0034 }
0035
0036
0037
0038
0039
0040
0041 static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
0042
0043
0044
0045
0046
0047
0048 static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
0049 {
0050 int i;
0051
0052 for (i = 0; i < bpp/2; i++, dst += 4)
0053 put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
0054 }
0055
0056
0057
0058
0059
0060
0061 static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
0062 {
0063 int i;
0064
0065 for (i = 0; i < bpp/2; i++, dst += 4)
0066 put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
0067 get_unaligned_be32(dst), mask),
0068 dst);
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
0086 u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
0087 {
0088 union {
0089 u8 pixels[16];
0090 u32 words[4];
0091 } d;
0092 u32 dst_idx, first, last, w;
0093 const u8 *c;
0094 void *p;
0095
0096 dst += dy*dst_nextline+(dx & ~15)*bpp;
0097 dst_idx = dx % 16;
0098 first = 0xffffU >> dst_idx;
0099 first |= first << 16;
0100 last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
0101 last |= last << 16;
0102 while (height--) {
0103 c = src;
0104 p = dst;
0105 w = width;
0106 if (dst_idx+width <= 16) {
0107
0108 first &= last;
0109 memset(d.pixels, 0, sizeof(d));
0110 memcpy(d.pixels+dst_idx, c, width);
0111 c += width;
0112 c2p_16x8(d.words);
0113 store_iplan2_masked(p, bpp, d.words, first);
0114 p += bpp*2;
0115 } else {
0116
0117 w = width;
0118
0119 if (dst_idx) {
0120 w = 16 - dst_idx;
0121 memset(d.pixels, 0, dst_idx);
0122 memcpy(d.pixels+dst_idx, c, w);
0123 c += w;
0124 c2p_16x8(d.words);
0125 store_iplan2_masked(p, bpp, d.words, first);
0126 p += bpp*2;
0127 w = width-w;
0128 }
0129
0130 while (w >= 16) {
0131 memcpy(d.pixels, c, 16);
0132 c += 16;
0133 c2p_16x8(d.words);
0134 store_iplan2(p, bpp, d.words);
0135 p += bpp*2;
0136 w -= 16;
0137 }
0138
0139 w %= 16;
0140 if (w > 0) {
0141 memcpy(d.pixels, c, w);
0142 memset(d.pixels+w, 0, 16-w);
0143 c2p_16x8(d.words);
0144 store_iplan2_masked(p, bpp, d.words, last);
0145 }
0146 }
0147 src += src_nextline;
0148 dst += dst_nextline;
0149 }
0150 }
0151 EXPORT_SYMBOL_GPL(c2p_iplan2);
0152
0153 MODULE_LICENSE("GPL");