openMSX
Scale3xScaler.cc
Go to the documentation of this file.
1 /*
2 Original code: Copyright (C) 2001-2003 Andrea Mazzoleni
3 openMSX adaptation by Maarten ter Huurne
4 
5 This file is based on code from the Scale2x project.
6 This modified version is licensed under GPL; the original code is dual-licensed
7 under GPL and under a custom license.
8 
9 Visit the Scale2x site for info:
10  http://scale2x.sourceforge.net/
11 */
12 
13 #include "Scale3xScaler.hh"
14 #include "FrameSource.hh"
15 #include "ScalerOutput.hh"
16 #include "vla.hh"
17 #include "xrange.hh"
18 #include "build-info.hh"
19 #include <cstdint>
20 
21 namespace openmsx {
22 
23 template<typename Pixel>
25  : Scaler3<Pixel>(pixelOps_)
26 {
27 }
28 
29 template<typename Pixel>
31  Pixel* __restrict dst, const Pixel* __restrict src0,
32  const Pixel* __restrict src1, const Pixel* __restrict src2,
33  unsigned srcWidth) __restrict
34 {
35  /* A B C
36  * D E F
37  * G H I
38  *
39  * E0 = D == B && B != F && D != H ? D : E;
40  * E1 = (D == B && B != F && D != H && E != C) ||
41  * (B == F && B != D && F != H && E != A) ? B : E;
42  * E2 = B == F && B != D && F != H ? F : E;
43  */
44 
45  // First pixel.
46  Pixel top = src0[0];
47  Pixel mid = src1[0];
48  Pixel right = src1[1];
49  Pixel bot = src2[0];
50 
51  dst[0] = mid;
52  dst[1] = (mid != right) && (top != bot) &&
53  (((top == mid) && (mid != src0[1])) ||
54  ((top == right) && (mid != top)))
55  ? top : mid;
56  dst[2] = (mid != right) && (top != bot) && (top == right)
57  ? top : mid;
58 
59  // Central pixels.
60  for (auto x : xrange(1u, srcWidth - 1)) {
61  Pixel left = mid;
62  mid = right;
63  right = src1[x + 1];
64  top = src0[x];
65  bot = src2[x];
66  dst[3 * x + 0] = (left != right) && (top != bot) &&
67  (top == left)
68  ? top : mid;
69  dst[3 * x + 1] = (left != right) && (top != bot) &&
70  (((top == left ) && (mid != src0[x + 1])) ||
71  ((top == right) && (mid != src0[x - 1])))
72  ? top : mid;
73  dst[3 * x + 2] = (left != right) && (top != bot) &&
74  (top == right)
75  ? top : mid;
76  }
77 
78  // Last pixel.
79  Pixel left = mid;
80  mid = right;
81  top = src0[srcWidth - 1];
82  bot = src2[srcWidth - 1];
83  dst[3 * srcWidth - 3] = (left != mid) && (top != bot) && (top ==left)
84  ? top : mid;
85  dst[3 * srcWidth - 2] = (left != mid) && (top != bot) &&
86  (((top == left) && (mid != top)) ||
87  ((top == mid ) && (mid != src0[srcWidth - 2])))
88  ? top : mid;
89  dst[3 * srcWidth - 1] = mid;
90 }
91 
92 template<typename Pixel>
93 void Scale3xScaler<Pixel>::scaleLine1on3Mid(
94  Pixel* __restrict dst, const Pixel* __restrict src0,
95  const Pixel* __restrict src1, const Pixel* __restrict src2,
96  unsigned srcWidth) __restrict
97 {
98  /*
99  * A B C
100  * D E F
101  * G H I
102  *
103  * E3 = (D == B && B != F && D != H && E != G) ||
104  * (D == H && D != B && H != F && E != A) ? D : E;
105  * E4 = E
106  * E5 = (B == F && B != D && F != H && E != I) ||
107  * (H == F && D != H && B != F && E != C) ? F : E;
108  */
109 
110  // First pixel.
111  Pixel mid = src1[0];
112  Pixel right = src1[1];
113  Pixel top = src0[0];
114  Pixel bot = src2[0];
115  dst[0] = mid;
116  dst[1] = mid;
117  dst[2] = (mid != right) && (top != bot) &&
118  (((right == top) && (mid != src2[1])) ||
119  ((right == bot) && (mid != src0[1])))
120  ? right : mid;
121 
122  // Central pixels.
123  for (auto x : xrange(1u, srcWidth - 1)) {
124  Pixel left = mid;
125  mid = right;
126  right = src1[x + 1];
127  top = src0[x];
128  bot = src2[x];
129  dst[3 * x + 0] = (left != right) && (top != bot) &&
130  (((left == top) && (mid != src2[x - 1])) ||
131  ((left == bot) && (mid != src0[x - 1])))
132  ? left : mid;
133  dst[3 * x + 1] = mid;
134  dst[3 * x + 2] = (left != right) && (top != bot) &&
135  (((right == top) && (mid != src2[x + 1])) ||
136  ((right == bot) && (mid != src0[x + 1])))
137  ? right : mid;
138  }
139 
140  // Last pixel.
141  Pixel left = mid;
142  mid = right;
143  top = src0[srcWidth - 1];
144  bot = src2[srcWidth - 1];
145  dst[3 * srcWidth - 3] = (left != mid) && (top != bot) &&
146  (((left == top) && (mid != src2[srcWidth - 2])) ||
147  ((left == bot) && (mid != src0[srcWidth - 2])))
148  ? left : mid;
149  dst[3 * srcWidth - 2] = mid;
150  dst[3 * srcWidth - 1] = mid;
151 }
152 
153 template<typename Pixel>
155  unsigned srcStartY, unsigned /*srcEndY*/, unsigned srcWidth,
156  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
157 {
158  VLA_SSE_ALIGNED(Pixel, buf0_, srcWidth); auto* buf0 = buf0_;
159  VLA_SSE_ALIGNED(Pixel, buf1_, srcWidth); auto* buf1 = buf1_;
160  VLA_SSE_ALIGNED(Pixel, buf2_, srcWidth); auto* buf2 = buf2_;
161 
162  int srcY = srcStartY;
163  auto* srcPrev = src.getLinePtr(srcY - 1, srcWidth, buf0);
164  auto* srcCurr = src.getLinePtr(srcY + 0, srcWidth, buf1);
165 
166  for (unsigned dstY = dstStartY; dstY < dstEndY; srcY += 1, dstY += 3) {
167  auto* srcNext = src.getLinePtr(srcY + 1, srcWidth, buf2);
168 
169  auto* dstUpper = dst.acquireLine(dstY + 0);
170  scaleLine1on3Half(dstUpper, srcPrev, srcCurr, srcNext, srcWidth);
171  dst.releaseLine(dstY + 0, dstUpper);
172 
173  auto* dstMiddle = dst.acquireLine(dstY + 1);
174  scaleLine1on3Mid(dstMiddle, srcPrev, srcCurr, srcNext, srcWidth);
175  dst.releaseLine(dstY + 1, dstMiddle);
176 
177  auto* dstLower = dst.acquireLine(dstY + 2);
178  scaleLine1on3Half(dstLower, srcNext, srcCurr, srcPrev, srcWidth);
179  dst.releaseLine(dstY + 2, dstLower);
180 
181  srcPrev = srcCurr;
182  srcCurr = srcNext;
183  std::swap(buf0, buf1);
184  std::swap(buf1, buf2);
185  }
186 }
187 
188 // Force template instantiation.
189 #if HAVE_16BPP
190 template class Scale3xScaler<uint16_t>;
191 #endif
192 #if HAVE_32BPP
193 template class Scale3xScaler<uint32_t>;
194 #endif
195 
196 } // namespace openmsx
Interface for getting lines from a video frame.
Definition: FrameSource.hh:16
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:92
Runs the Scale3x scaler algorithm.
void scale1x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Scale3xScaler(const PixelOperations< Pixel > &pixelOps)
Base class for 3x scalers.
Definition: Scaler3.hh:12
virtual Pixel * acquireLine(unsigned y)=0
virtual void releaseLine(unsigned y, Pixel *buf)=0
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint32_t Pixel
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44
constexpr auto xrange(T e)
Definition: xrange.hh:155