openMSX
HQ3xScaler.cc
Go to the documentation of this file.
1 /*
2 Original code: Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
3 openMSX adaptation by Wouter Vermaelen
4 
5 License: LGPL
6 
7 Visit the HiEnd3D site for info:
8  http://www.hiend3d.com/hq2x.html
9 */
10 
11 #include "HQ3xScaler.hh"
12 #include "HQCommon.hh"
13 #include "LineScalers.hh"
14 #include "openmsx.hh"
15 #include "unreachable.hh"
16 #include "build-info.hh"
17 
18 namespace openmsx {
19 
20 template <typename Pixel> struct HQ_1x1on3x3
21 {
22  void operator()(const Pixel* in0, const Pixel* in1, const Pixel* in2,
23  Pixel* out0, Pixel* out1, Pixel* out2,
24  unsigned srcWidth, unsigned* edgeBuf, EdgeHQ edgeOp);
25 };
26 
27 template <typename Pixel>
29  const Pixel* __restrict in0, const Pixel* __restrict in1,
30  const Pixel* __restrict in2,
31  Pixel* __restrict out0, Pixel* __restrict out1,
32  Pixel* __restrict out2,
33  unsigned srcWidth, unsigned* __restrict edgeBuf,
34  EdgeHQ edgeOp) __restrict
35 {
36  unsigned c1, c2, c3, c4, c5, c6, c7, c8, c9;
37  c2 = c3 = readPixel(in0[0]);
38  c5 = c6 = readPixel(in1[0]);
39  c8 = c9 = readPixel(in2[0]);
40 
41  unsigned pattern = 0;
42  if (edgeOp(c5, c8)) pattern |= 3 << 6;
43  if (edgeOp(c5, c2)) pattern |= 3 << 9;
44 
45  for (unsigned x = 0; x < srcWidth; ++x) {
46  c1 = c2; c4 = c5; c7 = c8;
47  c2 = c3; c5 = c6; c8 = c9;
48  if (x != srcWidth - 1) {
49  c3 = readPixel(in0[x + 1]);
50  c6 = readPixel(in1[x + 1]);
51  c9 = readPixel(in2[x + 1]);
52  }
53 
54  pattern = (pattern >> 6) & 0x001F; // left overlap
55  // overlaps with left
56  //if (edgeOp(c8, c4)) pattern |= 1 << 0; // B - l: c5-c9 6
57  //if (edgeOp(c5, c7)) pattern |= 1 << 1; // B - l: c6-c8 7
58  //if (edgeOp(c5, c4)) pattern |= 1 << 2; // l: c5-c6 8
59  // overlaps with top and left
60  //if (edgeOp(c5, c1)) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
61  //if (edgeOp(c4, c2)) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
62  // non-overlapping pixels
63  if (edgeOp(c5, c8)) pattern |= 1 << 5; // B
64  if (edgeOp(c5, c9)) pattern |= 1 << 6; // BR
65  if (edgeOp(c6, c8)) pattern |= 1 << 7; // BR
66  if (edgeOp(c5, c6)) pattern |= 1 << 8; // R
67  // overlaps with top
68  //if (edgeOp(c2, c6)) pattern |= 1 << 9; // R - t: c5-c9 6
69  //if (edgeOp(c5, c3)) pattern |= 1 << 10; // R - t: c6-c8 7
70  //if (edgeOp(c5, c2)) pattern |= 1 << 11; // t: c5-c8 5
71  pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
72  ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
73  edgeBuf[x] = pattern;
74 
75  unsigned pixel0, pixel1, pixel2, pixel3, pixel4,
76  pixel5, pixel6, pixel7, pixel8;
77 
78 #include "HQ3xScaler-1x1to3x3.nn"
79 
80  out0[3 * x + 0] = writePixel<Pixel>(pixel0);
81  out0[3 * x + 1] = writePixel<Pixel>(pixel1);
82  out0[3 * x + 2] = writePixel<Pixel>(pixel2);
83  out1[3 * x + 0] = writePixel<Pixel>(pixel3);
84  out1[3 * x + 1] = writePixel<Pixel>(pixel4);
85  out1[3 * x + 2] = writePixel<Pixel>(pixel5);
86  out2[3 * x + 0] = writePixel<Pixel>(pixel6);
87  out2[3 * x + 1] = writePixel<Pixel>(pixel7);
88  out2[3 * x + 2] = writePixel<Pixel>(pixel8);
89  }
90 }
91 
92 
93 
94 template <class Pixel>
96  : Scaler3<Pixel>(pixelOps_)
97  , pixelOps(pixelOps_)
98 {
99 }
100 
101 template <class Pixel>
103  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
104  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
105 {
106  PolyScale<Pixel, Scale_2on3<Pixel>> postScale(pixelOps);
107  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
108  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
109  src, srcStartY, srcEndY, srcWidth,
110  dst, dstStartY, dstEndY, (srcWidth * 9) / 2);
111 }
112 
113 template <class Pixel>
115  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
116  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
117 {
119  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
120  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
121  src, srcStartY, srcEndY, srcWidth,
122  dst, dstStartY, dstEndY, srcWidth * 3);
123 }
124 
125 template <class Pixel>
127  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
128  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
129 {
130  PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
131  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
132  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
133  src, srcStartY, srcEndY, srcWidth,
134  dst, dstStartY, dstEndY, (srcWidth * 9) / 4);
135 }
136 
137 template <class Pixel>
139  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
140  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
141 {
142  PolyScale<Pixel, Scale_2on1<Pixel>> postScale(pixelOps);
143  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
144  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
145  src, srcStartY, srcEndY, srcWidth,
146  dst, dstStartY, dstEndY, (srcWidth * 3) / 2);
147 }
148 
149 template <class Pixel>
151  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
152  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
153 {
154  PolyScale<Pixel, Scale_8on3<Pixel>> postScale(pixelOps);
155  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
156  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
157  src, srcStartY, srcEndY, srcWidth,
158  dst, dstStartY, dstEndY, (srcWidth * 9) / 8);
159 }
160 
161 template <class Pixel>
163  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
164  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
165 {
166  PolyScale<Pixel, Scale_4on1<Pixel>> postScale(pixelOps);
167  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
168  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
169  src, srcStartY, srcEndY, srcWidth,
170  dst, dstStartY, dstEndY, (srcWidth * 3) / 4);
171 }
172 
173 // Force template instantiation.
174 #if HAVE_16BPP
175 template class HQ3xScaler<word>;
176 #endif
177 #if HAVE_32BPP
178 template class HQ3xScaler<unsigned>;
179 #endif
180 
181 } // namespace openmsx