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