| e8555c89 Andy McCall |
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 , unsigned , |
| 37 |
unsigned , FrameSource& ) |
| 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 |
|
| 74 |
|
| 75 |
|
| 76 |
|
| 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 |
|
| 84 |
std::array pos = { |
| 85 |
vec2( 0.0f, dstStartYF), |
| 86 |
vec2(dstWidthF, dstStartYF), |
| 87 |
vec2(dstWidthF, dstEndYF ), |
| 88 |
vec2( 0.0f, dstEndYF ), |
| 89 |
}; |
| 90 |
|
| 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 |
} |