openMSX
GLHQLiteScaler.cc
Go to the documentation of this file.
1#include "GLHQLiteScaler.hh"
2#include "GLUtil.hh"
3#include "HQCommon.hh"
4#include "FrameSource.hh"
5#include "FileContext.hh"
6#include "File.hh"
7#include "narrow.hh"
8#include "ranges.hh"
9#include "vla.hh"
10#include <array>
11#include <cstring>
12#include <utility>
13
14namespace openmsx {
15
17 : GLScaler("hqlite")
18 , fallback(fallback_)
19{
20 for (auto& p : program) {
21 p.activate();
22 glUniform1i(p.getUniformLocation("edgeTex"), 2);
23 glUniform1i(p.getUniformLocation("offsetTex"), 3);
24 }
25
26 // GL_LUMINANCE_ALPHA is no longer supported in newer openGL versions
27 auto format = (OPENGL_VERSION >= OPENGL_3_3) ? GL_RG : GL_LUMINANCE_ALPHA;
28 edgeTexture.bind();
29 glTexImage2D(GL_TEXTURE_2D, // target
30 0, // level
31 format, // internal format
32 320, // width
33 240, // height
34 0, // border
35 format, // format
36 GL_UNSIGNED_BYTE, // type
37 nullptr); // data
38#if OPENGL_VERSION >= OPENGL_3_3
39 GLint swizzleMask1[] = {GL_RED, GL_RED, GL_RED, GL_GREEN};
40 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask1);
41#endif
42 edgeBuffer.setImage(320, 240);
43
44 const auto& context = systemFileContext();
45 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
46 std::string offsetName = "shaders/HQ_xLiteOffsets.dat";
47 for (auto i : xrange(3)) {
48 int n = i + 2;
49 offsetName[10] = narrow<char>('0' + n);
50 File offsetFile(context.resolve(offsetName));
51 offsetTexture[i].bind();
52 glTexImage2D(GL_TEXTURE_2D, // target
53 0, // level
54 format, // internal format
55 n * 64, // width
56 n * 64, // height
57 0, // border
58 format, // format
59 GL_UNSIGNED_BYTE, // type
60 offsetFile.mmap().data());// data
61#if OPENGL_VERSION >= OPENGL_3_3
62 GLint swizzleMask2[] = {GL_RED, GL_RED, GL_RED, GL_GREEN};
63 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask2);
64#endif
65 }
66 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
67}
68
70 gl::ColorTexture& src, gl::ColorTexture* superImpose,
71 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
72 unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
73 unsigned logSrcHeight)
74{
75 unsigned factorX = dstWidth / srcWidth; // 1 - 4
76 unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY);
77
78 if ((srcWidth == 320) && (factorX > 1) && (factorX == factorY)) {
79 setup(superImpose != nullptr);
80 src.setInterpolation(true);
81 glActiveTexture(GL_TEXTURE3);
82 offsetTexture[factorX - 2].bind();
83 glActiveTexture(GL_TEXTURE2);
84 edgeTexture.bind();
85 glActiveTexture(GL_TEXTURE0);
86 execute(src, superImpose,
87 srcStartY, srcEndY, srcWidth,
88 dstStartY, dstEndY, dstWidth,
89 logSrcHeight);
90 src.setInterpolation(false);
91 } else {
92 fallback.scaleImage(src, superImpose,
93 srcStartY, srcEndY, srcWidth,
94 dstStartY, dstEndY, dstWidth,
95 logSrcHeight);
96 }
97}
98
99using Pixel = uint32_t;
101 unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
102 FrameSource& paintFrame)
103{
104 if ((lineWidth != 320) || (srcEndY > 240)) return;
105
106 std::array<Endian::L32, 320 / 2> tmpBuf2; // 2 x uint16_t
107 #ifndef NDEBUG
108 // Avoid UMR. In optimized mode we don't care.
109 ranges::fill(tmpBuf2, 0);
110 #endif
111
112 VLA_SSE_ALIGNED(Pixel, buf1, lineWidth);
113 VLA_SSE_ALIGNED(Pixel, buf2, lineWidth);
114 auto curr = paintFrame.getLine(narrow<int>(srcStartY) - 1, buf1);
115 auto next = paintFrame.getLine(narrow<int>(srcStartY) + 0, buf2);
116 calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
117
118 edgeBuffer.bind();
119 if (auto* mapped = edgeBuffer.mapWrite()) {
120 for (auto y : xrange(srcStartY, srcEndY)) {
121 curr = next;
122 std::swap(buf1, buf2);
123 next = paintFrame.getLine(narrow<int>(y + 1), buf2);
124 calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
125 memcpy(mapped + 320 * size_t(y), tmpBuf2.data(), 320 * sizeof(uint16_t));
126 }
127 edgeBuffer.unmap();
128
129 auto format = (OPENGL_VERSION >= OPENGL_3_3) ? GL_RG : GL_LUMINANCE_ALPHA;
130 edgeTexture.bind();
131 glTexSubImage2D(GL_TEXTURE_2D, // target
132 0, // level
133 0, // offset x
134 narrow<GLint>(srcStartY), // offset y
135 narrow<GLint>(lineWidth), // width
136 narrow<GLint>(srcEndY - srcStartY), // height
137 format, // format
138 GL_UNSIGNED_BYTE, // type
139 edgeBuffer.getOffset(0, srcStartY));// data
140 }
141 edgeBuffer.unbind();
142}
143
144} // namespace openmsx
#define OPENGL_3_3
Definition GLUtil.hh:20
#define OPENGL_VERSION
Definition GLUtil.hh:21
void unmap() const
Unmaps the contents of this buffer.
Definition GLUtil.hh:306
void unbind() const
Unbind this buffer.
Definition GLUtil.hh:274
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition GLUtil.hh:248
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition GLUtil.hh:282
void bind() const
Bind this PixelBuffer.
Definition GLUtil.hh:266
T * mapWrite()
Maps the contents of this buffer into memory.
Definition GLUtil.hh:295
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition GLUtil.cc:58
void bind()
Makes this texture the active GL texture.
Definition GLUtil.hh:77
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
GLHQLiteScaler(GLScaler &fallback)
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.
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(gl::ColorTexture &src, 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:121
void format(SectorAccessibleDisk &disk, MSXBootSectorType bootType)
Format the given disk (= a single partition).
This file implemented 3 utility functions:
Definition Autofire.cc:9
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:63
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:305
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition vla.hh:50
constexpr auto xrange(T e)
Definition xrange.hh:132