OXYGENHUB
◆ main openmsx / src / video / scalers / GLScaler.cc
3.7 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "GLScaler.hh"
2
3
#include "GLContext.hh"
4
#include "gl_vec.hh"
5
6
#include "narrow.hh"
7
#include "strCat.hh"
8
#include "xrange.hh"
9
10
using namespace gl;
11
12
namespace openmsx {
13
14
GLScaler::GLScaler(const std::string& progName)
15
{
16
	for (auto i : xrange(2)) {
17
		auto header = tmpStrCat("#define SUPERIMPOSE ", char('0' + i), '\n');
18
		VertexShader   vShader(header, progName + ".vert");
19
		FragmentShader fShader(header, progName + ".frag");
20
		program[i].attach(vShader);
21
		program[i].attach(fShader);
22
		program[i].bindAttribLocation(0, "a_position");
23
		program[i].bindAttribLocation(1, "a_texCoord");
24
		program[i].link();
25
		program[i].activate();
26
		glUniform1i(program[i].getUniformLocation("tex"), 0);
27
		if (i == 1) {
28
			glUniform1i(program[i].getUniformLocation("videoTex"), 1);
29
		}
30
		unifTexSize[i] = program[i].getUniformLocation("texSize");
31
		unifMvpMatrix[i] = program[i].getUniformLocation("u_mvpMatrix");
32
	}
33
}
34
35
void GLScaler::uploadBlock(
36
	unsigned /*srcStartY*/, unsigned /*srcEndY*/,
37
	unsigned /*lineWidth*/, FrameSource& /*paintFrame*/)
38
{
39
}
40
41
void GLScaler::setup(bool superImpose)
42
{
43
	int i = superImpose ? 1 : 0;
44
	program[i].activate();
45
46
	glUniformMatrix4fv(unifMvpMatrix[i], 1, GL_FALSE, gl::context->pixelMvp.data());
47
}
48
49
void GLScaler::execute(
50
	const ColorTexture& src, const ColorTexture* superImpose,
51
	unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
52
	unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
53
	unsigned logSrcHeight, bool textureFromZero)
54
{
55
	auto srcStartYF = narrow<float>(srcStartY);
56
	auto srcEndYF = narrow<float>(srcEndY);
57
	auto dstStartYF = narrow<float>(dstStartY);
58
	auto dstEndYF = narrow<float>(dstEndY);
59
	auto dstWidthF = narrow<float>(dstWidth);
60
	auto srcWidthF = narrow<float>(srcWidth);
61
	auto srcHeightF = narrow<float>(src.getHeight());
62
	auto logSrcHeightF = narrow<float>(logSrcHeight);
63
64
	if (superImpose) {
65
		glActiveTexture(GL_TEXTURE1);
66
		superImpose->bind();
67
		glActiveTexture(GL_TEXTURE0);
68
	}
69
	int i = superImpose ? 1 : 0;
70
	glUniform3f(unifTexSize[i], srcWidthF, srcHeightF, logSrcHeightF);
71
72
	src.bind();
73
	// Note: hShift is pre-divided by srcWidth, while vShift will be divided
74
	//       by srcHeight later on.
75
	// Note: The coordinate is put just past zero, to avoid fract() in the
76
	//       fragment shader to wrap around on rounding errors.
77
	static constexpr float BIAS = 0.001f;
78
	float samplePos = (textureFromZero ? 0.5f : 0.0f) + BIAS;
79
	float hShift = samplePos / dstWidthF;
80
	float yRatio = (srcEndYF - srcStartYF) / (dstEndYF - dstStartYF);
81
	float vShift = samplePos * yRatio;
82
83
	// vertex positions
84
	std::array pos = {
85
		vec2(     0.0f, dstStartYF),
86
		vec2(dstWidthF, dstStartYF),
87
		vec2(dstWidthF, dstEndYF  ),
88
		vec2(     0.0f, dstEndYF  ),
89
	};
90
	// texture coordinates, X-coord shared, Y-coord separate for tex0 and tex1
91
	float tex0StartY = (srcStartYF + vShift) / srcHeightF;
92
	float tex0EndY   = (srcEndYF   + vShift) / srcHeightF;
93
	float tex1StartY = (srcStartYF + vShift) / logSrcHeightF;
94
	float tex1EndY   = (srcEndYF   + vShift) / logSrcHeightF;
95
	std::array tex = {
96
		vec3(0.0f + hShift, tex0StartY, tex1StartY),
97
		vec3(1.0f + hShift, tex0StartY, tex1StartY),
98
		vec3(1.0f + hShift, tex0EndY  , tex1EndY  ),
99
		vec3(0.0f + hShift, tex0EndY  , tex1EndY  ),
100
	};
101
102
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
103
	glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos.data(), GL_STREAM_DRAW);
104
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
105
106
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1].get());
107
	glBufferData(GL_ARRAY_BUFFER, sizeof(tex), tex.data(), GL_STREAM_DRAW);
108
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
109
110
	glEnableVertexAttribArray(0);
111
	glEnableVertexAttribArray(1);
112
113
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
114
115
	glDisableVertexAttribArray(1);
116
	glDisableVertexAttribArray(0);
117
	glBindBuffer(GL_ARRAY_BUFFER, 0);
118
}
119
120
} // namespace openmsx