c2p_iplan2.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Fast C2P (Chunky-to-Planar) Conversion
  3. *
  4. * Copyright (C) 2003-2008 Geert Uytterhoeven
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file COPYING in the main directory of this archive
  8. * for more details.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/string.h>
  12. #include <asm/unaligned.h>
  13. #include "c2p.h"
  14. #include "c2p_core.h"
  15. /*
  16. * Perform a full C2P step on 16 8-bit pixels, stored in 4 32-bit words
  17. * containing
  18. * - 16 8-bit chunky pixels on input
  19. * - permutated planar data (2 planes per 32-bit word) on output
  20. */
  21. static void c2p_16x8(u32 d[4])
  22. {
  23. transp4(d, 8, 2);
  24. transp4(d, 1, 2);
  25. transp4x(d, 16, 2);
  26. transp4x(d, 2, 2);
  27. transp4(d, 4, 1);
  28. }
  29. /*
  30. * Array containing the permutation indices of the planar data after c2p
  31. */
  32. static const int perm_c2p_16x8[4] = { 1, 3, 0, 2 };
  33. /*
  34. * Store a full block of iplan2 data after c2p conversion
  35. */
  36. static inline void store_iplan2(void *dst, u32 bpp, u32 d[4])
  37. {
  38. int i;
  39. for (i = 0; i < bpp/2; i++, dst += 4)
  40. put_unaligned_be32(d[perm_c2p_16x8[i]], dst);
  41. }
  42. /*
  43. * Store a partial block of iplan2 data after c2p conversion
  44. */
  45. static inline void store_iplan2_masked(void *dst, u32 bpp, u32 d[4], u32 mask)
  46. {
  47. int i;
  48. for (i = 0; i < bpp/2; i++, dst += 4)
  49. put_unaligned_be32(comp(d[perm_c2p_16x8[i]],
  50. get_unaligned_be32(dst), mask),
  51. dst);
  52. }
  53. /*
  54. * c2p_iplan2 - Copy 8-bit chunky image data to an interleaved planar
  55. * frame buffer with 2 bytes of interleave
  56. * @dst: Starting address of the planar frame buffer
  57. * @dx: Horizontal destination offset (in pixels)
  58. * @dy: Vertical destination offset (in pixels)
  59. * @width: Image width (in pixels)
  60. * @height: Image height (in pixels)
  61. * @dst_nextline: Frame buffer offset to the next line (in bytes)
  62. * @src_nextline: Image offset to the next line (in bytes)
  63. * @bpp: Bits per pixel of the planar frame buffer (2, 4, or 8)
  64. */
  65. void c2p_iplan2(void *dst, const void *src, u32 dx, u32 dy, u32 width,
  66. u32 height, u32 dst_nextline, u32 src_nextline, u32 bpp)
  67. {
  68. union {
  69. u8 pixels[16];
  70. u32 words[4];
  71. } d;
  72. u32 dst_idx, first, last, w;
  73. const u8 *c;
  74. void *p;
  75. dst += dy*dst_nextline+(dx & ~15)*bpp;
  76. dst_idx = dx % 16;
  77. first = 0xffffU >> dst_idx;
  78. first |= first << 16;
  79. last = 0xffffU ^ (0xffffU >> ((dst_idx+width) % 16));
  80. last |= last << 16;
  81. while (height--) {
  82. c = src;
  83. p = dst;
  84. w = width;
  85. if (dst_idx+width <= 16) {
  86. /* Single destination word */
  87. first &= last;
  88. memset(d.pixels, 0, sizeof(d));
  89. memcpy(d.pixels+dst_idx, c, width);
  90. c += width;
  91. c2p_16x8(d.words);
  92. store_iplan2_masked(p, bpp, d.words, first);
  93. p += bpp*2;
  94. } else {
  95. /* Multiple destination words */
  96. w = width;
  97. /* Leading bits */
  98. if (dst_idx) {
  99. w = 16 - dst_idx;
  100. memset(d.pixels, 0, dst_idx);
  101. memcpy(d.pixels+dst_idx, c, w);
  102. c += w;
  103. c2p_16x8(d.words);
  104. store_iplan2_masked(p, bpp, d.words, first);
  105. p += bpp*2;
  106. w = width-w;
  107. }
  108. /* Main chunk */
  109. while (w >= 16) {
  110. memcpy(d.pixels, c, 16);
  111. c += 16;
  112. c2p_16x8(d.words);
  113. store_iplan2(p, bpp, d.words);
  114. p += bpp*2;
  115. w -= 16;
  116. }
  117. /* Trailing bits */
  118. w %= 16;
  119. if (w > 0) {
  120. memcpy(d.pixels, c, w);
  121. memset(d.pixels+w, 0, 16-w);
  122. c2p_16x8(d.words);
  123. store_iplan2_masked(p, bpp, d.words, last);
  124. }
  125. }
  126. src += src_nextline;
  127. dst += dst_nextline;
  128. }
  129. }
  130. EXPORT_SYMBOL_GPL(c2p_iplan2);
  131. MODULE_LICENSE("GPL");