openMSX
GLHQScaler.cc
Go to the documentation of this file.
1 #include "GLHQScaler.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  : GLScaler("hq")
18  , fallback(fallback_)
19 {
20  for (int i = 0; i < 2; ++i) {
21  program[i].activate();
22  glUniform1i(program[i].getUniformLocation("edgeTex"), 2);
23  glUniform1i(program[i].getUniformLocation("offsetTex"), 3);
24  glUniform1i(program[i].getUniformLocation("weightTex"), 4);
25  }
26 
27  edgeTexture.bind();
28  glTexImage2D(GL_TEXTURE_2D, // target
29  0, // level
30  GL_LUMINANCE16, // internal format
31  320, // width
32  240, // height
33  0, // border
34  GL_LUMINANCE, // format
35  GL_UNSIGNED_SHORT,// type
36  nullptr); // data
37  edgeBuffer.setImage(320, 240);
38 
40  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
41  for (int i = 0; i < 3; ++i) {
42  int n = i + 2;
43  string offsetsName = StringOp::Builder() <<
44  "shaders/HQ" << n << "xOffsets.dat";
45  File offsetsFile(context.resolve(offsetsName));
46  offsetTexture[i].bind();
47  size_t size; // dummy
48  glTexImage2D(GL_TEXTURE_2D, // target
49  0, // level
50  GL_RGBA8, // internal format
51  n * 64, // width
52  n * 64, // height
53  0, // border
54  GL_RGBA, // format
55  GL_UNSIGNED_BYTE, // type
56  offsetsFile.mmap(size));// data
57 
58  string weightsName = StringOp::Builder() <<
59  "shaders/HQ" << n << "xWeights.dat";
60  File weightsFile(context.resolve(weightsName));
61  weightTexture[i].bind();
62  glTexImage2D(GL_TEXTURE_2D, // target
63  0, // level
64  GL_RGB8, // internal format
65  n * 64, // width
66  n * 64, // height
67  0, // border
68  GL_RGB, // format
69  GL_UNSIGNED_BYTE, // type
70  weightsFile.mmap(size));// data
71  }
72  glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
73 }
74 
76  gl::ColorTexture& src, gl::ColorTexture* superImpose,
77  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
78  unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
79  unsigned logSrcHeight)
80 {
81  unsigned factorX = dstWidth / srcWidth; // 1 - 4
82  unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY);
83 
84  if ((srcWidth == 320) && (factorX > 1) && (factorX == factorY)) {
85  assert(src.getHeight() == 2 * 240);
86  setup(superImpose);
87  glActiveTexture(GL_TEXTURE4);
88  weightTexture[factorX - 2].bind();
89  glActiveTexture(GL_TEXTURE3);
90  offsetTexture[factorX - 2].bind();
91  glActiveTexture(GL_TEXTURE2);
92  edgeTexture.bind();
93  glActiveTexture(GL_TEXTURE0);
94  execute(src, superImpose,
95  srcStartY, srcEndY, srcWidth,
96  dstStartY, dstEndY, dstWidth,
97  logSrcHeight);
98  } else {
99  fallback.scaleImage(src, superImpose,
100  srcStartY, srcEndY, srcWidth,
101  dstStartY, dstEndY, dstWidth,
102  logSrcHeight);
103  }
104 }
105 
106 typedef unsigned Pixel;
108  unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
109  FrameSource& paintFrame)
110 {
111  if (lineWidth != 320) return;
112 
113  uint32_t tmpBuf2[320 / 2]; // 2 x uint16_t
114  #ifndef NDEBUG
115  // Avoid UMR. In optimized mode we don't care.
116  memset(tmpBuf2, 0, sizeof(tmpBuf2));
117  #endif
118 
119  VLA_SSE_ALIGNED(Pixel, buf1_, lineWidth); auto* buf1 = buf1_;
120  VLA_SSE_ALIGNED(Pixel, buf2_, lineWidth); auto* buf2 = buf2_;
121  auto* curr = paintFrame.getLinePtr(srcStartY - 1, lineWidth, buf1);
122  auto* next = paintFrame.getLinePtr(srcStartY + 0, lineWidth, buf2);
123  EdgeHQ edgeOp(0, 8, 16);
124  calcEdgesGL(curr, next, tmpBuf2, edgeOp);
125 
126  edgeBuffer.bind();
127  if (auto* mapped = edgeBuffer.mapWrite()) {
128  for (unsigned y = srcStartY; y < srcEndY; ++y) {
129  curr = next;
130  std::swap(buf1, buf2);
131  next = paintFrame.getLinePtr(y + 1, lineWidth, buf2);
132  calcEdgesGL(curr, next, tmpBuf2, edgeOp);
133  memcpy(mapped + 320 * y, tmpBuf2, 320 * sizeof(uint16_t));
134  }
135  edgeBuffer.unmap();
136 
137  edgeTexture.bind();
138  glTexSubImage2D(GL_TEXTURE_2D, // target
139  0, // level
140  0, // offset x
141  srcStartY, // offset y
142  lineWidth, // width
143  srcEndY - srcStartY, // height
144  GL_LUMINANCE, // format
145  GL_UNSIGNED_SHORT, // type
146  edgeBuffer.getOffset(0, srcStartY)); // data
147  }
148  edgeBuffer.unbind();
149 }
150 
151 } // namespace openmsx
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:336
void setup(bool superImpose)
Definition: GLScaler.cc:39
void activate() const
Makes this program the active shader program.
Definition: GLUtil.cc:324
virtual void uploadBlock(unsigned srcStartY, unsigned srcEndY, unsigned lineWidth, FrameSource &paintFrame)
Definition: GLHQScaler.cc:107
Interface for getting lines from a video frame.
Definition: FrameSource.hh:15
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:75
virtual void scaleImage(gl::ColorTexture &src, gl::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...
Definition: GLHQScaler.cc:75
void calcEdgesGL(const uint32_t *curr, const uint32_t *next, uint32_t *edges2, EdgeOp edgeOp)
Definition: HQCommon.hh:104
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:307
void execute(gl::ColorTexture &src, 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:45
const std::string resolve(string_ref filename) const
Definition: FileContext.cc:74
unsigned Pixel
std::unique_ptr< Context > context
Definition: GLContext.cc:9
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:289
GLsizei getHeight() const
Definition: GLUtil.hh:124
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
Abstract base class for OpenGL scalers.
Definition: GLScaler.hh:13
size_t size() const
gl::ShaderProgram program[2]
Definition: GLScaler.hh:77
GLHQScaler(GLScaler &fallback)
Definition: GLHQScaler.cc:16
virtual void scaleImage(gl::ColorTexture &src, gl::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...
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:323
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:315
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:347
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44