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 "vla.hh"
8 #include <cstring>
9 #include <utility>
10 
11 using std::string;
12 
13 namespace openmsx {
14 
16  : GLScaler("hq")
17  , fallback(fallback_)
18 {
19  for (auto& p : program) {
20  p.activate();
21  glUniform1i(p.getUniformLocation("edgeTex"), 2);
22  glUniform1i(p.getUniformLocation("offsetTex"), 3);
23  glUniform1i(p.getUniformLocation("weightTex"), 4);
24  }
25 
26  // GL_LUMINANCE_ALPHA is no longer supported in newer openGL versions
27  auto format = (OPENGL_VERSION >= OPENGL_3_3) ? GL_RG : GL_LUMINANCE_ALPHA;
28  edgeTexture.bind();
29  glTexImage2D(GL_TEXTURE_2D, // target
30  0, // level
31  format, // internal format
32  320, // width
33  240, // height
34  0, // border
35  format, // format
36  GL_UNSIGNED_BYTE, // type
37  nullptr); // data
38 #if OPENGL_VERSION >= OPENGL_3_3
39  GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE};
40  glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
41 #endif
42  edgeBuffer.setImage(320, 240);
43 
44  auto context = systemFileContext();
45  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
46  string offsetsName = "shaders/HQ_xOffsets.dat";
47  string weightsName = "shaders/HQ_xWeights.dat";
48  for (int i = 0; i < 3; ++i) {
49  int n = i + 2;
50  offsetsName[10] = char('0') + n;
51  File offsetsFile(context.resolve(offsetsName));
52  offsetTexture[i].bind();
53  glTexImage2D(GL_TEXTURE_2D, // target
54  0, // level
55  GL_RGBA, // internal format
56  n * 64, // width
57  n * 64, // height
58  0, // border
59  GL_RGBA, // format
60  GL_UNSIGNED_BYTE, // type
61  offsetsFile.mmap().data());// data
62 
63  weightsName[10] = char('0') + n;
64  File weightsFile(context.resolve(weightsName));
65  weightTexture[i].bind();
66  glTexImage2D(GL_TEXTURE_2D, // target
67  0, // level
68  GL_RGB, // internal format
69  n * 64, // width
70  n * 64, // height
71  0, // border
72  GL_RGB, // format
73  GL_UNSIGNED_BYTE, // type
74  weightsFile.mmap().data());// data
75  }
76  glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore to default
77 }
78 
80  gl::ColorTexture& src, gl::ColorTexture* superImpose,
81  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
82  unsigned dstStartY, unsigned dstEndY, unsigned dstWidth,
83  unsigned logSrcHeight)
84 {
85  unsigned factorX = dstWidth / srcWidth; // 1 - 4
86  unsigned factorY = (dstEndY - dstStartY) / (srcEndY - srcStartY);
87 
88  if ((srcWidth == 320) && (factorX > 1) && (factorX == factorY)) {
89  assert(src.getHeight() == 2 * 240);
90  setup(superImpose != nullptr);
91  glActiveTexture(GL_TEXTURE4);
92  weightTexture[factorX - 2].bind();
93  glActiveTexture(GL_TEXTURE3);
94  offsetTexture[factorX - 2].bind();
95  glActiveTexture(GL_TEXTURE2);
96  edgeTexture.bind();
97  glActiveTexture(GL_TEXTURE0);
98  execute(src, superImpose,
99  srcStartY, srcEndY, srcWidth,
100  dstStartY, dstEndY, dstWidth,
101  logSrcHeight);
102  } else {
103  fallback.scaleImage(src, superImpose,
104  srcStartY, srcEndY, srcWidth,
105  dstStartY, dstEndY, dstWidth,
106  logSrcHeight);
107  }
108 }
109 
110 using Pixel = uint32_t;
112  unsigned srcStartY, unsigned srcEndY, unsigned lineWidth,
113  FrameSource& paintFrame)
114 {
115  if ((lineWidth != 320) || (srcEndY > 240)) return;
116 
117  Endian::L32 tmpBuf2[320 / 2]; // 2 x uint16_t
118  #ifndef NDEBUG
119  // Avoid UMR. In optimized mode we don't care.
120  memset(tmpBuf2, 0, sizeof(tmpBuf2));
121  #endif
122 
123  VLA_SSE_ALIGNED(Pixel, buf1_, lineWidth); auto* buf1 = buf1_;
124  VLA_SSE_ALIGNED(Pixel, buf2_, lineWidth); auto* buf2 = buf2_;
125  const auto* curr = paintFrame.getLinePtr(srcStartY - 1, lineWidth, buf1);
126  const auto* next = paintFrame.getLinePtr(srcStartY + 0, lineWidth, buf2);
127  EdgeHQ edgeOp(0, 8, 16);
128  calcEdgesGL(curr, next, tmpBuf2, edgeOp);
129 
130  edgeBuffer.bind();
131  if (auto* mapped = edgeBuffer.mapWrite()) {
132  for (unsigned y = srcStartY; y < srcEndY; ++y) {
133  curr = next;
134  std::swap(buf1, buf2);
135  next = paintFrame.getLinePtr(y + 1, lineWidth, buf2);
136  calcEdgesGL(curr, next, tmpBuf2, edgeOp);
137  memcpy(mapped + 320 * y, tmpBuf2, 320 * sizeof(uint16_t));
138  }
139  edgeBuffer.unmap();
140 
141  auto format = (OPENGL_VERSION >= OPENGL_3_3) ? GL_RG : GL_LUMINANCE_ALPHA;
142  edgeTexture.bind();
143  glTexSubImage2D(GL_TEXTURE_2D, // target
144  0, // level
145  0, // offset x
146  srcStartY, // offset y
147  lineWidth, // width
148  srcEndY - srcStartY, // height
149  format, // format
150  GL_UNSIGNED_BYTE, // type
151  edgeBuffer.getOffset(0, srcStartY)); // data
152  }
153  edgeBuffer.unbind();
154 }
155 
156 } // namespace openmsx
openmsx::GLScaler::scaleImage
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.
openmsx::EdgeHQ
Definition: HQCommon.hh:44
openmsx::DiskImageUtils::format
void format(SectorAccessibleDisk &disk, bool dos1)
Format the given disk (= a single partition).
Definition: DiskImageUtils.cc:188
openmsx::calcEdgesGL
void calcEdgesGL(const uint32_t *curr, const uint32_t *next, Endian::L32 *edges2, EdgeOp edgeOp)
Definition: HQCommon.hh:105
openmsx::File::mmap
span< uint8_t > mmap()
Map file in memory.
Definition: File.cc:93
openmsx::GLScaler::program
gl::ShaderProgram program[2]
Definition: GLScaler.hh:78
gl::ColorTexture
Definition: GLUtil.hh:100
FrameSource.hh
gl::PixelBuffer::mapWrite
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:300
openmsx::FrameSource::getLinePtr
const Pixel * getLinePtr(int line, unsigned width, Pixel *buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:90
gl::Texture::bind
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:82
openmsx::GLScaler::execute
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
gl::ColorTexture::getHeight
GLsizei getHeight() const
Definition: GLUtil.hh:112
GLHQScaler.hh
gl::PixelBuffer::setImage
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:253
gl::PixelBuffer::unmap
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:311
openmsx::GLScaler::setup
void setup(bool superImpose)
Definition: GLScaler.cc:39
vla.hh
openmsx::Pixel
uint32_t Pixel
Definition: GLHQLiteScaler.cc:98
File.hh
FileContext.hh
Endian::EndianT
Definition: endian.hh:71
gl::PixelBuffer::unbind
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:279
gl::context
std::unique_ptr< Context > context
Definition: GLContext.cc:9
openmsx::File
Definition: File.hh:16
openmsx::FrameSource
Interface for getting lines from a video frame.
Definition: FrameSource.hh:14
openmsx::GLScaler
Abstract base class for OpenGL scalers.
Definition: GLScaler.hh:14
openmsx::GLHQScaler::scaleImage
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.
Definition: GLHQScaler.cc:79
OPENGL_VERSION
#define OPENGL_VERSION
Definition: GLUtil.hh:26
gl::PixelBuffer::bind
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:271
GLUtil.hh
gl::PixelBuffer::getOffset
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:287
VLA_SSE_ALIGNED
#define VLA_SSE_ALIGNED(TYPE, NAME, LENGTH)
Definition: vla.hh:44
openmsx::GLHQScaler::GLHQScaler
GLHQScaler(GLScaler &fallback)
Definition: GLHQScaler.cc:15
openmsx::GLHQScaler::uploadBlock
void uploadBlock(unsigned srcStartY, unsigned srcEndY, unsigned lineWidth, FrameSource &paintFrame) override
Definition: GLHQScaler.cc:111
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
OPENGL_3_3
#define OPENGL_3_3
Definition: GLUtil.hh:25
HQCommon.hh
openmsx::systemFileContext
FileContext systemFileContext()
Definition: FileContext.cc:152