openMSX
GLHQScaler.cc
Go to the documentation of this file.
1#include "GLHQScaler.hh"
2
3#include "File.hh"
4#include "FileContext.hh"
5#include "FrameSource.hh"
6#include "GLUtil.hh"
7#include "HQCommon.hh"
8
9#include "inplace_buffer.hh"
10#include "narrow.hh"
11#include "ranges.hh"
12
13#include <array>
14#include <cstring>
15#include <utility>
16
17namespace openmsx {
18
19GLHQScaler::GLHQScaler(GLScaler& fallback_, unsigned maxWidth_, unsigned maxHeight_)
20 : GLScaler("hq")
21 , fallback(fallback_)
22 , maxWidth(maxWidth_), maxHeight(maxHeight_)
23{
24 for (auto i : xrange(2)) {
25 auto& p = program[i];
26 p.activate();
27 glUniform1i(p.getUniformLocation("edgeTex"), 2);
28 glUniform1i(p.getUniformLocation("offsetTex"), 3);
29 glUniform1i(p.getUniformLocation("weightTex"), 4);
30 edgePosScaleUnif[i] = p.getUniformLocation("edgePosScale");
31 }
32
33 // GL_LUMINANCE_ALPHA is no longer supported in newer openGL versions
34 auto format = (OPENGL_VERSION >= OPENGL_3_3) ? GL_RG : GL_LUMINANCE_ALPHA;
35 edgeTexture.bind();
36 glTexImage2D(GL_TEXTURE_2D, // target
37 0, // level
38 format, // internal format
39 maxWidth, // width
40 maxHeight, // height
41 0, // border
42 format, // format
43 GL_UNSIGNED_BYTE, // type
44 nullptr); // data
45#if OPENGL_VERSION >= OPENGL_3_3
46 GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE};
47 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
48#endif
49 edgeBuffer.allocate(maxWidth * maxHeight);
50
51 const auto& context = systemFileContext();
52 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
53 std::string offsetsName = "shaders/HQ_xOffsets.dat";
54 std::string weightsName = "shaders/HQ_xWeights.dat";
55 for (auto i : xrange(3)) {
56 int n = i + 2;
57 offsetsName[10] = narrow<char>('0' + n);
58 File offsetsFile(context.resolve(offsetsName));
59 offsetTexture[i].bind();
60 glTexImage2D(GL_TEXTURE_2D, // target
61 0, // level
62 GL_RGBA, // internal format
63 n * 64, // width
64 n * 64, // height
65 0, // border
66 GL_RGBA, // format
67 GL_UNSIGNED_BYTE, // type
68 offsetsFile.mmap().data());// data
69
70 weightsName[10] = narrow<char>('0' + n);
71 File weightsFile(context.resolve(weightsName));
72 weightTexture[i].bind();
73 glTexImage2D(GL_TEXTURE_2D, // target
74 0, // level
75 GL_RGB, // internal format
76 n * 64, // width
77 n * 64, // height
78 0, // border
79 GL_RGB, // format
80 GL_UNSIGNED_BYTE, // type
81 weightsFile.mmap().data());// data
82 }
83 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
84}
85
87 gl::ColorTexture& src, gl::ColorTexture* superImpose,
88 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
89 unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
90 unsigned logSrcHeight)
91{
92 unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY); // 1 - 4
93
94 if ((factorY >= 2) && ((srcWidth % 320) == 0)) {
95 assert(src.getHeight() == 2 * 240);
96 setup(superImpose != nullptr);
97 glActiveTexture(GL_TEXTURE4);
98 weightTexture[factorY - 2].bind();
99 glActiveTexture(GL_TEXTURE3);
100 offsetTexture[factorY - 2].bind();
101 glActiveTexture(GL_TEXTURE2);
102 edgeTexture.bind();
103 glActiveTexture(GL_TEXTURE0);
104
105 int i = superImpose ? 1 : 0;
106 glUniform2f(edgePosScaleUnif[i],
107 float(src.getWidth()) / float(maxWidth),
108 float(src.getHeight()) / float(maxHeight));
109
110 execute(src, superImpose,
111 srcStartY, srcEndY, srcWidth,
112 dstStartY, dstEndY, dstWidth,
113 logSrcHeight);
114 } else {
115 fallback.scaleImage(src, superImpose,
116 srcStartY, srcEndY, srcWidth,
117 dstStartY, dstEndY, dstWidth,
118 logSrcHeight);
119 }
120}
121
122using Pixel = uint32_t;
124 unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
125 FrameSource& paintFrame)
126{
127 if ((lineWidth % 320) != 0) return;
128
129 assert(maxWidth <= 1280);
130 inplace_buffer<Endian::L32, 1280 / 2> tmpBuf2(uninitialized_tag{}, lineWidth / 2); // 2 x uint16_t
131 #ifndef NDEBUG
132 // Avoid UMR. In optimized mode we don't care.
133 ranges::fill(tmpBuf2, 0);
134 #endif
135
138 auto curr = paintFrame.getLine(narrow<int>(srcStartY) - 1, buf1);
139 auto next = paintFrame.getLine(narrow<int>(srcStartY) + 0, buf2);
140 EdgeHQ edgeOp;
141 calcEdgesGL(curr, next, tmpBuf2, edgeOp);
142
143 edgeBuffer.bind();
144 auto mapped = edgeBuffer.mapWrite();
145 auto numLines = srcEndY - srcStartY;
146 for (auto yy : xrange(numLines)) {
147 curr = next;
148 std::swap(buf1, buf2);
149 next = paintFrame.getLine(narrow<int>(yy + srcStartY + 1), buf2);
150 calcEdgesGL(curr, next, tmpBuf2, edgeOp);
151 auto dest = mapped.subspan(yy * size_t(lineWidth), lineWidth);
152 assert(dest.size_bytes() == std::span{tmpBuf2}.size_bytes()); // note: convert L32 -> 2 x uint16_t
153 memcpy(dest.data(), tmpBuf2.data(), std::span{tmpBuf2}.size_bytes());
154 }
155 edgeBuffer.unmap();
156
157 auto format = (OPENGL_VERSION >= OPENGL_3_3) ? GL_RG : GL_LUMINANCE_ALPHA;
158 edgeTexture.bind();
159 glTexSubImage2D(GL_TEXTURE_2D, // target
160 0, // level
161 0, // offset x
162 narrow<GLint>(srcStartY), // offset y
163 narrow<GLint>(lineWidth), // width
164 narrow<GLint>(numLines), // height
165 format, // format
166 GL_UNSIGNED_BYTE, // type
167 mapped.data()); // data
168 edgeBuffer.unbind();
169}
170
171} // namespace openmsx
#define OPENGL_3_3
Definition GLUtil.hh:24
#define OPENGL_VERSION
Definition GLUtil.hh:25
GLsizei getHeight() const
Definition GLUtil.hh:118
GLsizei getWidth() const
Definition GLUtil.hh:117
void allocate(GLuint size)
Allocate the maximum required size for this buffer.
Definition GLUtil.hh:239
void unmap() const
Unmaps the contents of this buffer.
Definition GLUtil.hh:282
void unbind() const
Unbind this buffer.
Definition GLUtil.hh:263
void bind() const
Bind this PixelBuffer.
Definition GLUtil.hh:255
std::span< T > mapWrite()
Maps the contents of this buffer into memory.
Definition GLUtil.hh:271
void bind() const
Makes this texture the active GL texture.
Definition GLUtil.hh:88
std::span< const uint8_t > mmap()
Map file in memory.
Definition File.cc:102
Interface for getting lines from a video frame.
std::span< const Pixel > getLine(int line, std::span< Pixel > buf) const
Gets a pointer to the pixels of the given line number.
void uploadBlock(unsigned srcStartY, unsigned srcEndY, unsigned lineWidth, FrameSource &paintFrame) override
GLHQScaler(GLScaler &fallback, unsigned maxWidth, unsigned maxHeight)
Definition GLHQScaler.cc:19
void scaleImage(gl::ColorTexture &src, gl::ColorTexture *superImpose, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, unsigned dstStartY, unsigned dstEndY, unsigned dstWidth, unsigned logSrcHeight) override
Scales the image in the given area, which must consist of lines which are all equally wide.
Definition GLHQScaler.cc:86
Abstract base class for OpenGL scalers.
Definition GLScaler.hh:16
void setup(bool superImpose)
Setup scaler.
Definition GLScaler.cc:40
std::array< gl::ShaderProgram, 2 > program
Definition GLScaler.hh:85
void execute(const gl::ColorTexture &src, const gl::ColorTexture *superImpose, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, unsigned dstStartY, unsigned dstEndY, unsigned dstWidth, unsigned logSrcHeight, bool textureFromZero=false)
Helper method to draw a rectangle with multiple texture coordinates.
Definition GLScaler.cc:48
virtual void scaleImage(gl::ColorTexture &src, gl::ColorTexture *superImpose, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, unsigned dstStartY, unsigned dstEndY, unsigned dstWidth, unsigned logSrcHeight)=0
Scales the image in the given area, which must consist of lines which are all equally wide.
EndianT< uint32_t, ConvLittle< BIG > > L32
Definition endian.hh:122
void format(SectorAccessibleDisk &disk, MSXBootSectorType bootType)
Format the given disk (= a single partition).
This file implemented 3 utility functions:
Definition Autofire.cc:11
const FileContext & systemFileContext()
CharacterConverter::Pixel Pixel
void calcEdgesGL(std::span< const uint32_t > curr, std::span< const uint32_t > next, std::span< Endian::L32 > edges2, EdgeOp edgeOp)
Definition HQCommon.hh:53
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:315
constexpr auto xrange(T e)
Definition xrange.hh:132