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 "openmsx.hh"
9 #include "memory.hh"
10 #include <cstring>
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 #ifdef GL_VERSION_2_0
27  if (GLEW_VERSION_2_0) {
28  scalerProgram[i].activate();
29  glUniform1i(scalerProgram[i].getUniformLocation("colorTex"), 0);
30  if (i == 1) {
31  glUniform1i(scalerProgram[i].getUniformLocation("videoTex"), 1);
32  }
33  glUniform1i(scalerProgram[i].getUniformLocation("edgeTex"), 2);
34  glUniform1i(scalerProgram[i].getUniformLocation("offsetTex"), 3);
35  glUniform2f(scalerProgram[i].getUniformLocation("texSize"),
36  320.0f, 240.0f);
37  }
38 #endif
39  }
40 
41  edgeTexture.bind();
42  edgeTexture.setWrapMode(false);
43  glTexImage2D(GL_TEXTURE_2D, // target
44  0, // level
45  GL_LUMINANCE16, // internal format
46  320, // width
47  240, // height
48  0, // border
49  GL_LUMINANCE, // format
50  GL_UNSIGNED_SHORT,// type
51  nullptr); // data
52  edgeBuffer.setImage(320, 240);
53 
54  SystemFileContext context;
55  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
56  for (int i = 0; i < 3; ++i) {
57  int n = i + 2;
58  string offsetName = StringOp::Builder() <<
59  "shaders/HQ" << n << "xLiteOffsets.dat";
60  File offsetFile(context.resolve(offsetName));
61  offsetTexture[i].setWrapMode(false);
62  offsetTexture[i].bind();
63  size_t size; // dummy
64  glTexImage2D(GL_TEXTURE_2D, // target
65  0, // level
66  GL_LUMINANCE8_ALPHA8, // internal format
67  n * 64, // width
68  n * 64, // height
69  0, // border
70  GL_LUMINANCE_ALPHA, // format
71  GL_UNSIGNED_BYTE, // type
72  offsetFile.mmap(size));// data
73  }
74  glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
75 }
76 
78  ColorTexture& src, ColorTexture* superImpose,
79  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
80  unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
81  unsigned logSrcHeight)
82 {
83  unsigned factorX = dstWidth / srcWidth; // 1 - 4
84  unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY);
85 
86  auto& prog = scalerProgram[superImpose ? 1 : 0];
87  if ((srcWidth == 320) && (factorX > 1) && (factorX == factorY)) {
88  src.enableInterpolation();
89  glActiveTexture(GL_TEXTURE3);
90  offsetTexture[factorX - 2].bind();
91  glActiveTexture(GL_TEXTURE2);
92  edgeTexture.bind();
93  if (superImpose) {
94  glActiveTexture(GL_TEXTURE1);
95  superImpose->bind();
96  }
97  glActiveTexture(GL_TEXTURE0);
98  prog.activate();
99  //prog.validate();
100  drawMultiTex(src, srcStartY, srcEndY, src.getHeight(), logSrcHeight,
101  dstStartY, dstEndY, dstWidth);
102  src.disableInterpolation();
103  } else {
104  GLScaler::scaleImage(src, superImpose,
105  srcStartY, srcEndY, srcWidth,
106  dstStartY, dstEndY, dstWidth,
107  logSrcHeight);
108  }
109 }
110 
111 typedef unsigned Pixel;
113  unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
114  FrameSource& paintFrame)
115 {
116  if (lineWidth != 320) return;
117 
118  unsigned tmpBuf2[320 / 2];
119  #ifndef NDEBUG
120  // Avoid UMR. In optimized mode we don't care.
121  memset(tmpBuf2, 0, sizeof(tmpBuf2));
122  #endif
123 
124  const Pixel* curr = paintFrame.getLinePtr<Pixel>(srcStartY - 1, lineWidth);
125  const Pixel* next = paintFrame.getLinePtr<Pixel>(srcStartY + 0, lineWidth);
126  calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
127 
128  edgeBuffer.bind();
129  if (unsigned short* mapped = edgeBuffer.mapWrite()) {
130  for (unsigned y = srcStartY; y < srcEndY; ++y) {
131  curr = next;
132  next = paintFrame.getLinePtr<Pixel>(y + 1, lineWidth);
133  calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
134  memcpy(mapped + 320 * y, tmpBuf2, 320 * sizeof(unsigned short));
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