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  : GLScaler("hqlite")
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  }
25 
26  edgeTexture.bind();
27  glTexImage2D(GL_TEXTURE_2D, // target
28  0, // level
29  GL_LUMINANCE16, // internal format
30  320, // width
31  240, // height
32  0, // border
33  GL_LUMINANCE, // format
34  GL_UNSIGNED_SHORT,// type
35  nullptr); // data
36  edgeBuffer.setImage(320, 240);
37 
39  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
40  for (int i = 0; i < 3; ++i) {
41  int n = i + 2;
42  string offsetName = StringOp::Builder() <<
43  "shaders/HQ" << n << "xLiteOffsets.dat";
44  File offsetFile(context.resolve(offsetName));
45  offsetTexture[i].bind();
46  size_t size; // dummy
47  glTexImage2D(GL_TEXTURE_2D, // target
48  0, // level
49  GL_LUMINANCE8_ALPHA8, // internal format
50  n * 64, // width
51  n * 64, // height
52  0, // border
53  GL_LUMINANCE_ALPHA, // format
54  GL_UNSIGNED_BYTE, // type
55  offsetFile.mmap(size));// data
56  }
57  glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
58 }
59 
61  gl::ColorTexture& src, gl::ColorTexture* superImpose,
62  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
63  unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
64  unsigned logSrcHeight)
65 {
66  unsigned factorX = dstWidth / srcWidth; // 1 - 4
67  unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY);
68 
69  if ((srcWidth == 320) && (factorX > 1) && (factorX == factorY)) {
70  setup(superImpose != nullptr);
71  src.setInterpolation(true);
72  glActiveTexture(GL_TEXTURE3);
73  offsetTexture[factorX - 2].bind();
74  glActiveTexture(GL_TEXTURE2);
75  edgeTexture.bind();
76  glActiveTexture(GL_TEXTURE0);
77  execute(src, superImpose,
78  srcStartY, srcEndY, srcWidth,
79  dstStartY, dstEndY, dstWidth,
80  logSrcHeight);
81  src.setInterpolation(false);
82  } else {
83  fallback.scaleImage(src, superImpose,
84  srcStartY, srcEndY, srcWidth,
85  dstStartY, dstEndY, dstWidth,
86  logSrcHeight);
87  }
88 }
89 
90 typedef unsigned Pixel;
92  unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
93  FrameSource& paintFrame)
94 {
95  if (lineWidth != 320) return;
96 
97  uint32_t tmpBuf2[320 / 2]; // 2 x uint16_t
98  #ifndef NDEBUG
99  // Avoid UMR. In optimized mode we don't care.
100  memset(tmpBuf2, 0, sizeof(tmpBuf2));
101  #endif
102 
103  VLA_SSE_ALIGNED(Pixel, buf1_, lineWidth); auto* buf1 = buf1_;
104  VLA_SSE_ALIGNED(Pixel, buf2_, lineWidth); auto* buf2 = buf2_;
105  auto* curr = paintFrame.getLinePtr(srcStartY - 1, lineWidth, buf1);
106  auto* next = paintFrame.getLinePtr(srcStartY + 0, lineWidth, buf2);
107  calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
108 
109  edgeBuffer.bind();
110  if (auto* mapped = edgeBuffer.mapWrite()) {
111  for (unsigned y = srcStartY; y < srcEndY; ++y) {
112  curr = next;
113  std::swap(buf1, buf2);
114  next = paintFrame.getLinePtr(y + 1, lineWidth, buf2);
115  calcEdgesGL(curr, next, tmpBuf2, EdgeHQLite());
116  memcpy(mapped + 320 * y, tmpBuf2, 320 * sizeof(uint16_t));
117  }
118  edgeBuffer.unmap();
119 
120  edgeTexture.bind();
121  glTexSubImage2D(GL_TEXTURE_2D, // target
122  0, // level
123  0, // offset x
124  srcStartY, // offset y
125  lineWidth, // width
126  srcEndY - srcStartY, // height
127  GL_LUMINANCE, // format
128  GL_UNSIGNED_SHORT, // type
129  edgeBuffer.getOffset(0, srcStartY)); // data
130  }
131  edgeBuffer.unbind();
132 }
133 
134 } // 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
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
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
GLHQLiteScaler(GLScaler &fallback)
void uploadBlock(unsigned srcStartY, unsigned srcEndY, unsigned lineWidth, FrameSource &paintFrame) override
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:289
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition: GLUtil.cc:55
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:93
Abstract base class for OpenGL scalers.
Definition: GLScaler.hh:13
size_t size() const
gl::ShaderProgram program[2]
Definition: GLScaler.hh:77
void scaleImage(gl::ColorTexture &src, gl::ColorTexture *superImpose, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, unsigned dstStartY, unsigned dstEndY, unsigned dstWidth, unsigned logSrcHeight) override
Scales the image in the given area, which must consist of lines which are all equally wide...
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