openMSX
GLScaler.cc
Go to the documentation of this file.
1#include "GLScaler.hh"
2#include "GLContext.hh"
3#include "gl_transform.hh"
4#include "gl_vec.hh"
5#include "narrow.hh"
6#include "strCat.hh"
7#include "xrange.hh"
8
9using namespace gl;
10
11namespace openmsx {
12
13GLScaler::GLScaler(const std::string& progName)
14{
15 for (auto i : xrange(2)) {
16 auto header = tmpStrCat("#define SUPERIMPOSE ", char('0' + i), '\n');
17 VertexShader vShader(header, progName + ".vert");
18 FragmentShader fShader(header, progName + ".frag");
19 program[i].attach(vShader);
20 program[i].attach(fShader);
21 program[i].bindAttribLocation(0, "a_position");
22 program[i].bindAttribLocation(1, "a_texCoord");
23 program[i].link();
24 program[i].activate();
25 glUniform1i(program[i].getUniformLocation("tex"), 0);
26 if (i == 1) {
27 glUniform1i(program[i].getUniformLocation("videoTex"), 1);
28 }
29 unifTexSize[i] = program[i].getUniformLocation("texSize");
30 unifMvpMatrix[i] = program[i].getUniformLocation("u_mvpMatrix");
31 }
32}
33
35 unsigned /*srcStartY*/, unsigned /*srcEndY*/,
36 unsigned /*lineWidth*/, FrameSource& /*paintFrame*/)
37{
38}
39
40void GLScaler::setup(bool superImpose)
41{
42 int i = superImpose ? 1 : 0;
43 program[i].activate();
44
45 glUniformMatrix4fv(unifMvpMatrix[i], 1, GL_FALSE, gl::context->pixelMvp.data());
46}
47
49 const ColorTexture& src, const ColorTexture* superImpose,
50 unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
51 unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
52 unsigned logSrcHeight, bool textureFromZero)
53{
54 auto srcStartYF = narrow<float>(srcStartY);
55 auto srcEndYF = narrow<float>(srcEndY);
56 auto dstStartYF = narrow<float>(dstStartY);
57 auto dstEndYF = narrow<float>(dstEndY);
58 auto dstWidthF = narrow<float>(dstWidth);
59 auto srcWidthF = narrow<float>(srcWidth);
60 auto srcHeightF = narrow<float>(src.getHeight());
61 auto logSrcHeightF = narrow<float>(logSrcHeight);
62
63 if (superImpose) {
64 glActiveTexture(GL_TEXTURE1);
65 superImpose->bind();
66 glActiveTexture(GL_TEXTURE0);
67 }
68 int i = superImpose ? 1 : 0;
69 glUniform3f(unifTexSize[i], srcWidthF, srcHeightF, logSrcHeightF);
70
71 src.bind();
72 // Note: hShift is pre-divided by srcWidth, while vShift will be divided
73 // by srcHeight later on.
74 // Note: The coordinate is put just past zero, to avoid fract() in the
75 // fragment shader to wrap around on rounding errors.
76 static constexpr float BIAS = 0.001f;
77 float samplePos = (textureFromZero ? 0.5f : 0.0f) + BIAS;
78 float hShift = samplePos / dstWidthF;
79 float yRatio = (srcEndYF - srcStartYF) / (dstEndYF - dstStartYF);
80 float vShift = samplePos * yRatio;
81
82 // vertex positions
83 std::array pos = {
84 vec2( 0.0f, dstStartYF),
85 vec2(dstWidthF, dstStartYF),
86 vec2(dstWidthF, dstEndYF ),
87 vec2( 0.0f, dstEndYF ),
88 };
89 // texture coordinates, X-coord shared, Y-coord separate for tex0 and tex1
90 float tex0StartY = (srcStartYF + vShift) / srcHeightF;
91 float tex0EndY = (srcEndYF + vShift) / srcHeightF;
92 float tex1StartY = (srcStartYF + vShift) / logSrcHeightF;
93 float tex1EndY = (srcEndYF + vShift) / logSrcHeightF;
94 std::array tex = {
95 vec3(0.0f + hShift, tex0StartY, tex1StartY),
96 vec3(1.0f + hShift, tex0StartY, tex1StartY),
97 vec3(1.0f + hShift, tex0EndY , tex1EndY ),
98 vec3(0.0f + hShift, tex0EndY , tex1EndY ),
99 };
100
101 glBindBuffer(GL_ARRAY_BUFFER, vbo[0].get());
102 glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos.data(), GL_STREAM_DRAW);
103 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
104
105 glBindBuffer(GL_ARRAY_BUFFER, vbo[1].get());
106 glBufferData(GL_ARRAY_BUFFER, sizeof(tex), tex.data(), GL_STREAM_DRAW);
107 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
108
109 glEnableVertexAttribArray(0);
110 glEnableVertexAttribArray(1);
111
112 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
113
114 glDisableVertexAttribArray(1);
115 glDisableVertexAttribArray(0);
116 glBindBuffer(GL_ARRAY_BUFFER, 0);
117}
118
119} // namespace openmsx
GLsizei getHeight() const
Definition GLUtil.hh:118
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition GLUtil.hh:348
void bind() const
Makes this texture the active GL texture.
Definition GLUtil.hh:88
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff.
Definition GLUtil.hh:333
Interface for getting lines from a video frame.
void setup(bool superImpose)
Setup scaler.
Definition GLScaler.cc:40
GLScaler(const std::string &progName)
Definition GLScaler.cc:13
std::array< gl::ShaderProgram, 2 > program
Definition GLScaler.hh:85
std::array< GLint, 2 > unifTexSize
Definition GLScaler.hh:86
std::array< GLint, 2 > unifMvpMatrix
Definition GLScaler.hh:87
std::array< gl::BufferObject, 2 > vbo
Definition GLScaler.hh:84
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 uploadBlock(unsigned srcStartY, unsigned srcEndY, unsigned lineWidth, FrameSource &paintFrame)
Definition GLScaler.cc:34
Definition gl_mat.hh:23
vecN< 3, float > vec3
Definition gl_vec.hh:383
vecN< 2, float > vec2
Definition gl_vec.hh:382
std::optional< Context > context
Definition GLContext.cc:10
This file implemented 3 utility functions:
Definition Autofire.cc:11
TemporaryString tmpStrCat(Ts &&... ts)
Definition strCat.hh:742
constexpr auto xrange(T e)
Definition xrange.hh:132