HQ2xScaler.cc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. Original code: Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
  3. openMSX adaptation by Maarten ter Huurne
  4. License: LGPL
  5. Visit the HiEnd3D site for info:
  6. http://www.hiend3d.com/hq2x.html
  7. */
  8. #include "HQ2xScaler.hh"
  9. #include "HQCommon.hh"
  10. #include "LineScalers.hh"
  11. #include "unreachable.hh"
  12. #include "build-info.hh"
  13. #include <cstdint>
  14. namespace openmsx {
  15. template <typename Pixel> struct HQ_1x1on2x2
  16. {
  17. void operator()(const Pixel* in0, const Pixel* in1, const Pixel* in2,
  18. Pixel* out0, Pixel* out1, unsigned srcWidth,
  19. unsigned* edgeBuf, EdgeHQ edgeOp) __restrict;
  20. };
  21. template <typename Pixel> struct HQ_1x1on1x2
  22. {
  23. void operator()(const Pixel* in0, const Pixel* in1, const Pixel* in2,
  24. Pixel* out0, Pixel* out1, unsigned srcWidth,
  25. unsigned* edgeBuf, EdgeHQ edgeOp) __restrict;
  26. };
  27. template <typename Pixel>
  28. void HQ_1x1on2x2<Pixel>::operator()(
  29. const Pixel* __restrict in0, const Pixel* __restrict in1,
  30. const Pixel* __restrict in2,
  31. Pixel* __restrict out0, Pixel* __restrict out1,
  32. unsigned srcWidth, unsigned* __restrict edgeBuf,
  33. EdgeHQ edgeOp) __restrict
  34. {
  35. unsigned c1, c2, c3, c4, c5, c6, c7, c8, c9;
  36. c2 = c3 = readPixel(in0[0]);
  37. c5 = c6 = readPixel(in1[0]);
  38. c8 = c9 = readPixel(in2[0]);
  39. unsigned pattern = 0;
  40. if (edgeOp(c5, c8)) pattern |= 3 << 6;
  41. if (edgeOp(c5, c2)) pattern |= 3 << 9;
  42. for (unsigned x = 0; x < srcWidth; ++x) {
  43. c1 = c2; c4 = c5; c7 = c8;
  44. c2 = c3; c5 = c6; c8 = c9;
  45. if (x != srcWidth - 1) {
  46. c3 = readPixel(in0[x + 1]);
  47. c6 = readPixel(in1[x + 1]);
  48. c9 = readPixel(in2[x + 1]);
  49. }
  50. pattern = (pattern >> 6) & 0x001F; // left overlap
  51. // overlaps with left
  52. //if (edgeOp(c8, c4)) pattern |= 1 << 0; // B - l: c5-c9 6
  53. //if (edgeOp(c5, c7)) pattern |= 1 << 1; // B - l: c6-c8 7
  54. //if (edgeOp(c5, c4)) pattern |= 1 << 2; // l: c5-c6 8
  55. // overlaps with top and left
  56. //if (edgeOp(c5, c1)) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
  57. //if (edgeOp(c4, c2)) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
  58. // non-overlapping pixels
  59. if (edgeOp(c5, c8)) pattern |= 1 << 5; // B
  60. if (edgeOp(c5, c9)) pattern |= 1 << 6; // BR
  61. if (edgeOp(c6, c8)) pattern |= 1 << 7; // BR
  62. if (edgeOp(c5, c6)) pattern |= 1 << 8; // R
  63. // overlaps with top
  64. //if (edgeOp(c2, c6)) pattern |= 1 << 9; // R - t: c5-c9 6
  65. //if (edgeOp(c5, c3)) pattern |= 1 << 10; // R - t: c6-c8 7
  66. //if (edgeOp(c5, c2)) pattern |= 1 << 11; // t: c5-c8 5
  67. pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
  68. ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
  69. edgeBuf[x] = pattern;
  70. unsigned pixel0, pixel1, pixel2, pixel3;
  71. #include "HQ2xScaler-1x1to2x2.nn"
  72. out0[2 * x + 0] = writePixel<Pixel>(pixel0);
  73. out0[2 * x + 1] = writePixel<Pixel>(pixel1);
  74. out1[2 * x + 0] = writePixel<Pixel>(pixel2);
  75. out1[2 * x + 1] = writePixel<Pixel>(pixel3);
  76. }
  77. }
  78. template <typename Pixel>
  79. void HQ_1x1on1x2<Pixel>::operator()(
  80. const Pixel* __restrict in0, const Pixel* __restrict in1,
  81. const Pixel* __restrict in2,
  82. Pixel* __restrict out0, Pixel* __restrict out1,
  83. unsigned srcWidth, unsigned* __restrict edgeBuf,
  84. EdgeHQ edgeOp) __restrict
  85. {
  86. // +---+---+---+
  87. // | 1 | 2 | 3 |
  88. // +---+---+---+
  89. // | 4 | 5 | 6 |
  90. // +---+---+---+
  91. // | 7 | 8 | 9 |
  92. // +---+---+---+
  93. unsigned c1, c2, c3, c4, c5, c6, c7, c8, c9;
  94. c2 = c3 = readPixel(in0[0]);
  95. c5 = c6 = readPixel(in1[0]);
  96. c8 = c9 = readPixel(in2[0]);
  97. unsigned pattern = 0;
  98. if (edgeOp(c5, c8)) pattern |= 3 << 6;
  99. if (edgeOp(c5, c2)) pattern |= 3 << 9;
  100. for (unsigned x = 0; x < srcWidth; ++x) {
  101. c1 = c2; c4 = c5; c7 = c8;
  102. c2 = c3; c5 = c6; c8 = c9;
  103. if (x != srcWidth - 1) {
  104. c3 = readPixel(in0[x + 1]);
  105. c6 = readPixel(in1[x + 1]);
  106. c9 = readPixel(in2[x + 1]);
  107. }
  108. pattern = (pattern >> 6) & 0x001F; // left overlap
  109. // overlaps with left
  110. //if (edgeOp(c8, c4)) pattern |= 1 << 0; // B - l: c5-c9 6
  111. //if (edgeOp(c5, c7)) pattern |= 1 << 1; // B - l: c6-c8 7
  112. //if (edgeOp(c5, c4)) pattern |= 1 << 2; // l: c5-c6 8
  113. // overlaps with top and left
  114. //if (edgeOp(c5, c1)) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
  115. //if (edgeOp(c4, c2)) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
  116. // non-overlapping pixels
  117. if (edgeOp(c5, c8)) pattern |= 1 << 5; // B
  118. if (edgeOp(c5, c9)) pattern |= 1 << 6; // BR
  119. if (edgeOp(c6, c8)) pattern |= 1 << 7; // BR
  120. if (edgeOp(c5, c6)) pattern |= 1 << 8; // R
  121. // overlaps with top
  122. //if (edgeOp(c2, c6)) pattern |= 1 << 9; // R - t: c5-c9 6
  123. //if (edgeOp(c5, c3)) pattern |= 1 << 10; // R - t: c6-c8 7
  124. //if (edgeOp(c5, c2)) pattern |= 1 << 11; // t: c5-c8 5
  125. pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
  126. ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
  127. edgeBuf[x] = pattern;
  128. unsigned pixel0, pixel1;
  129. #include "HQ2xScaler-1x1to1x2.nn"
  130. out0[x] = writePixel<Pixel>(pixel0);
  131. out1[x] = writePixel<Pixel>(pixel1);
  132. }
  133. }
  134. template <class Pixel>
  135. HQ2xScaler<Pixel>::HQ2xScaler(const PixelOperations<Pixel>& pixelOps_)
  136. : Scaler2<Pixel>(pixelOps_)
  137. , pixelOps(pixelOps_)
  138. {
  139. }
  140. template <class Pixel>
  141. void HQ2xScaler<Pixel>::scale1x1to3x2(FrameSource& src,
  142. unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
  143. ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
  144. {
  145. PolyScale<Pixel, Scale_2on3<Pixel>> postScale(pixelOps);
  146. EdgeHQ edgeOp = createEdgeHQ(pixelOps);
  147. doHQScale2<Pixel>(HQ_1x1on2x2<Pixel>(), edgeOp, postScale,
  148. src, srcStartY, srcEndY, srcWidth,
  149. dst, dstStartY, dstEndY, srcWidth * 3);
  150. }
  151. template <class Pixel>
  152. void HQ2xScaler<Pixel>::scale1x1to2x2(FrameSource& src,
  153. unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
  154. ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
  155. {
  156. PolyScale<Pixel, Scale_1on1<Pixel>> postScale;
  157. EdgeHQ edgeOp = createEdgeHQ(pixelOps);
  158. doHQScale2<Pixel>(HQ_1x1on2x2<Pixel>(), edgeOp, postScale,
  159. src, srcStartY, srcEndY, srcWidth,
  160. dst, dstStartY, dstEndY, srcWidth * 2);
  161. }
  162. template <class Pixel>
  163. void HQ2xScaler<Pixel>::scale2x1to3x2(FrameSource& src,
  164. unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
  165. ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
  166. {
  167. PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
  168. EdgeHQ edgeOp = createEdgeHQ(pixelOps);
  169. doHQScale2<Pixel>(HQ_1x1on2x2<Pixel>(), edgeOp, postScale,
  170. src, srcStartY, srcEndY, srcWidth,
  171. dst, dstStartY, dstEndY, (srcWidth * 3) / 2);
  172. }
  173. template <class Pixel>
  174. void HQ2xScaler<Pixel>::scale1x1to1x2(FrameSource& src,
  175. unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
  176. ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
  177. {
  178. PolyScale<Pixel, Scale_1on1<Pixel>> postScale;
  179. EdgeHQ edgeOp = createEdgeHQ(pixelOps);
  180. doHQScale2<Pixel>(HQ_1x1on1x2<Pixel>(), edgeOp, postScale,
  181. src, srcStartY, srcEndY, srcWidth,
  182. dst, dstStartY, dstEndY, srcWidth);
  183. }
  184. template <class Pixel>
  185. void HQ2xScaler<Pixel>::scale4x1to3x2(FrameSource& src,
  186. unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
  187. ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
  188. {
  189. PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
  190. EdgeHQ edgeOp = createEdgeHQ(pixelOps);
  191. doHQScale2<Pixel>(HQ_1x1on1x2<Pixel>(), edgeOp, postScale,
  192. src, srcStartY, srcEndY, srcWidth,
  193. dst, dstStartY, dstEndY, (srcWidth * 3) / 4);
  194. }
  195. template <class Pixel>
  196. void HQ2xScaler<Pixel>::scale2x1to1x2(FrameSource& src,
  197. unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
  198. ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
  199. {
  200. PolyScale<Pixel, Scale_2on1<Pixel>> postScale(pixelOps);
  201. EdgeHQ edgeOp = createEdgeHQ(pixelOps);
  202. doHQScale2<Pixel>(HQ_1x1on1x2<Pixel>(), edgeOp, postScale,
  203. src, srcStartY, srcEndY, srcWidth,
  204. dst, dstStartY, dstEndY, srcWidth / 2);
  205. }
  206. // Force template instantiation.
  207. #if HAVE_16BPP
  208. template class HQ2xScaler<uint16_t>;
  209. #endif
  210. #if HAVE_32BPP
  211. template class HQ2xScaler<uint32_t>;
  212. #endif
  213. } // namespace openmsx