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 "StringOp.hh"
8 #include "vla.hh"
9 #include <cstring>
10 #include <algorithm>
11 
12 using std::string;
13 
14 namespace openmsx {
15 
17 {
18  for (int i = 0; i < 2; ++i) {
19  string header = string("#define SUPERIMPOSE ")
20  + char('0' + i) + '\n';
21  VertexShader vertexShader (header, "hqlite.vert");
22  FragmentShader fragmentShader(header, "hqlite.frag");
23  scalerProgram[i].attach(vertexShader);
24  scalerProgram[i].attach(fragmentShader);
25  scalerProgram[i].link();
26 
27  scalerProgram[i].activate();
28  glUniform1i(scalerProgram[i].getUniformLocation("colorTex"), 0);
29  if (i == 1) {
30  glUniform1i(scalerProgram[i].getUniformLocation("videoTex"), 1);
31  }
32  glUniform1i(scalerProgram[i].getUniformLocation("edgeTex"), 2);
33  glUniform1i(scalerProgram[i].getUniformLocation("offsetTex"), 3);
34  glUniform2f(scalerProgram[i].getUniformLocation("texSize"),
35  320.0f, 240.0f);
36  }
37 
38  edgeTexture.bind();
39  edgeTexture.setWrapMode(false);
40  glTexImage2D(GL_TEXTURE_2D, // target
41  0, // level
42  GL_LUMINANCE16, // internal format
43  320, // width
44  240, // height
45  0, // border
46  GL_LUMINANCE, // format
47  GL_UNSIGNED_SHORT,// type
48  nullptr); // data
49  edgeBuffer.setImage(320, 240);
50 
51  SystemFileContext context;
52  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
53  for (int i = 0; i < 3; ++i) {
54  int n = i + 2;
55  string offsetName = StringOp::Builder() <<
56  "shaders/HQ" << n << "xLiteOffsets.dat";
57  File offsetFile(context.resolve(offsetName));
58  offsetTexture[i].setWrapMode(false);
59  offsetTexture[i].bind();
60  size_t size; // dummy
61  glTexImage2D(GL_TEXTURE_2D, // target
62  0, // level
63  GL_LUMINANCE8_ALPHA8, // internal format
64  n * 64, // width
65  n * 64, // height
66  0, // border
67  GL_LUMINANCE_ALPHA, // format
68  GL_UNSIGNED_BYTE, // type
69  offsetFile.mmap(size));// data
70  }
71  glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
72 }
73 
75  ColorTexture& src, ColorTexture* superImpose,
76  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
77  unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
78  unsigned logSrcHeight)
79 {
80  unsigned factorX = dstWidth / srcWidth; // 1 - 4
81  unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY);
82 
83  auto& prog = scalerProgram[superImpose ? 1 : 0];
84  if ((srcWidth == 320) && (factorX > 1) && (factorX == factorY)) {
85  src.enableInterpolation();
86  glActiveTexture(GL_TEXTURE3);
87  offsetTexture[factorX - 2].bind();
88  glActiveTexture(GL_TEXTURE2);
89  edgeTexture.bind();
90  if (superImpose) {
91  glActiveTexture(GL_TEXTURE1);
92  superImpose->bind();
93  }
94  glActiveTexture(GL_TEXTURE0);
95  prog.activate();
96  //prog.validate();
97  drawMultiTex(src, srcStartY, srcEndY, src.getHeight(), logSrcHeight,
98  dstStartY, dstEndY, dstWidth);
100  } else {
101  GLScaler::scaleImage(src, superImpose,
102  srcStartY, srcEndY, srcWidth,
103  dstStartY, dstEndY, dstWidth,
104  logSrcHeight);
105  }
106 }
107 
108 typedef unsigned Pixel;
110  unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
111  FrameSource& paintFrame)
112 {
113  if (lineWidth != 320) return;
114 
115  uint32_t tmpBuf2[320 / 2]; // 2 x uint16_t
116  #ifndef NDEBUG
117  // Avoid UMR. In optimized mode we don't care.
118  memset(tmpBuf2, 0, sizeof(tmpBuf2));
119  #endif
120 
121  VLA_SSE_ALIGNED(Pixel, buf1_, lineWidth); auto* buf1 = buf1_;
122  VLA_SSE_ALIGNED(Pixel, buf2_, lineWidth); auto* buf2 = buf2_;
123  auto* curr = paintFrame.getLinePtr(srcStartY - 1, lineWidth, buf1);
124  auto* next = paintFrame.getLinePtr(srcStartY + 0, lineWidth, buf2);
125  calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
126 
127  edgeBuffer.bind();
128  if (auto* mapped = edgeBuffer.mapWrite()) {
129  for (unsigned y = srcStartY; y < srcEndY; ++y) {
130  curr = next;
131  std::swap(buf1, buf2);
132  next = paintFrame.getLinePtr(y + 1, lineWidth, buf2);
133  calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
134  memcpy(mapped + 320 * y, tmpBuf2, 320 * sizeof(uint16_t));
135  }
136  edgeBuffer.unmap();
137 
138  edgeTexture.bind();
139  glTexSubImage2D(GL_TEXTURE_2D, // target
140  0, // level
141  0, // offset x
142  srcStartY, // offset y
143  lineWidth, // width
144  srcEndY - srcStartY, // height
145  GL_LUMINANCE, // format
146  GL_UNSIGNED_SHORT, // type
147  edgeBuffer.getOffset(0, srcStartY)); // data
148  }
149  edgeBuffer.unbind();
150 }
151 
152 } // namespace openmsx
virtual void uploadBlock(unsigned srcStartY, unsigned srcEndY, unsigned lineWidth, FrameSource &paintFrame)
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition: GLUtil.hh:426
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:340
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff...
Definition: GLUtil.hh:413
virtual void scaleImage(ColorTexture &src, 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...
Definition: GLScaler.cc:29
void drawMultiTex(ColorTexture &src, unsigned srcStartY, unsigned srcEndY, float physSrcHeight, float logSrcHeight, unsigned dstStartY, unsigned dstEndY, unsigned dstWidth, bool textureFromZero=false)
Helper method to draw a rectangle with multiple texture coordinates.
Definition: GLScaler.cc:48
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:348
void activate() const
Makes this program the active shader program.
Definition: GLUtil.cc:383
void link()
Links all attached shaders together into one program.
Definition: GLUtil.cc:346
virtual void scaleImage(ColorTexture &src, ColorTexture *superImpose, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, unsigned dstStartY, unsigned dstEndY, unsigned dstWidth, unsigned logSrcHeight)
Scales the image in the given area, which must consist of lines which are all equally wide...
Interface for getting lines from a video frame.
Definition: FrameSource.hh:15
void disableInterpolation()
Disables bilinear interpolation for this texture and uses nearest neighbour instead.
Definition: GLUtil.cc:56
void calcEdgesGL(const uint32_t *curr, const uint32_t *next, uint32_t *edges2, EdgeOp edgeOp)
Definition: HQCommon.hh:104
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:61
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:314
const std::string resolve(string_ref filename) const
Definition: FileContext.cc:73
unsigned Pixel
GLsizei getHeight() const
Definition: GLUtil.hh:119
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:332
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:372
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:361
void attach(const Shader &shader)
Adds a given shader to this program.
Definition: GLUtil.cc:334
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:95
size_t size() const
void setWrapMode(bool wrap)
Definition: GLUtil.cc:63
void enableInterpolation()
Enables bilinear interpolation for this texture.
Definition: GLUtil.cc:49
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44