openMSX
Scale3xScaler.cc
Go to the documentation of this file.
1/*
2Original code: Copyright (C) 2001-2003 Andrea Mazzoleni
3openMSX adaptation by Maarten ter Huurne
4
5This file is based on code from the Scale2x project.
6This modified version is licensed under GPL; the original code is dual-licensed
7under GPL and under a custom license.
8
9Visit 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
21namespace openmsx {
22
23template<std::unsigned_integral Pixel>
25 : Scaler3<Pixel>(pixelOps_)
26{
27}
28
29template<std::unsigned_integral 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
92template<std::unsigned_integral Pixel>
93void 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
153template<std::unsigned_integral 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
190template class Scale3xScaler<uint16_t>;
191#endif
192#if HAVE_32BPP
193template class Scale3xScaler<uint32_t>;
194#endif
195
196} // namespace openmsx
Interface for getting lines from a video frame.
Definition: FrameSource.hh:17
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:93
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:127
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44
constexpr auto xrange(T e)
Definition: xrange.hh:133