openMSX
GLUtil.hh
Go to the documentation of this file.
1 #ifndef GLUTIL_HH
2 #define GLUTIL_HH
3 
4 // Check for availability of OpenGL.
5 #include "components.hh"
6 #if COMPONENT_GL
7 
8 // Include GLEW headers.
9 #include <GL/glew.h>
10 // Include OpenGL headers.
11 #ifdef __APPLE__
12 #include <OpenGL/gl.h>
13 #else
14 #include <GL/gl.h>
15 #endif
16 
17 #include "MemBuffer.hh"
18 #include "build-info.hh"
19 #include <string_view>
20 #include <cassert>
21 
22 // arbitrary but distinct values, (roughly) ordered according to version number
23 #define OPENGL_ES_2_0 1
24 #define OPENGL_2_1 2
25 #define OPENGL_3_3 3
26 #define OPENGL_VERSION OPENGL_2_1
27 
28 namespace gl {
29 
30 void checkGLError(std::string_view prefix);
31 
32 
33 // Dummy object, to be able to construct empty handler objects.
34 struct Null {};
35 
36 
40 class Texture
41 {
42 public:
43  Texture(const Texture&) = delete;
44  Texture& operator=(const Texture&) = delete;
45 
47  explicit Texture(bool interpolation = false, bool wrap = false);
48 
50  explicit Texture(Null) : textureId(0) {}
51 
53  ~Texture() { reset(); }
54 
56  Texture(Texture&& other) noexcept
57  : textureId(other.textureId)
58  {
59  other.textureId = 0; // 0 is not a valid openGL texture name
60  }
61  Texture& operator=(Texture&& other) noexcept {
62  std::swap(textureId, other.textureId);
63  return *this;
64  }
65 
67  void allocate();
68 
70  void reset();
71 
75  [[nodiscard]] GLuint get() const { return textureId; }
76 
82  void bind() {
83  glBindTexture(GL_TEXTURE_2D, textureId);
84  }
85 
89  void setInterpolation(bool interpolation);
90 
91  void setWrapMode(bool wrap);
92 
93 protected:
94  GLuint textureId;
95 
96  friend class FrameBufferObject;
97 };
98 
99 class ColorTexture : public Texture
100 {
101 public:
103  ColorTexture() = default;
104 
108  ColorTexture(GLsizei width, GLsizei height);
109  void resize(GLsizei width, GLsizei height);
110 
111  [[nodiscard]] GLsizei getWidth () const { return width; }
112  [[nodiscard]] GLsizei getHeight() const { return height; }
113 
114 private:
115  GLsizei width = 0;
116  GLsizei height = 0;
117 };
118 
120 {
121 public:
122  FrameBufferObject() = default;
123  explicit FrameBufferObject(Texture& texture);
125  : bufferId(other.bufferId)
126  {
127  other.bufferId = 0;
128  }
130  std::swap(bufferId, other.bufferId);
131  return *this;
132  }
134 
135  void push();
136  void pop();
137 
138 private:
139  GLuint bufferId = 0; // 0 is not a valid openGL name
140  GLint previousId = 0;
141 };
142 
152 template<typename T> class PixelBuffer
153 {
154 public:
155  PixelBuffer() = default;
156  //~PixelBuffer();
157  PixelBuffer(PixelBuffer&& other) noexcept;
158  PixelBuffer& operator=(PixelBuffer&& other) noexcept;
159 
164  void setImage(GLuint width, GLuint height);
165 
170  void bind() const;
171 
174  void unbind() const;
175 
182  [[nodiscard]] T* getOffset(GLuint x, GLuint y);
183 
192  [[nodiscard]] T* mapWrite();
193 
198  void unmap() const;
199 
200 private:
203  openmsx::MemBuffer<T> allocated;
204 
207  //GLuint bufferId;
208 
211  GLuint width = 0;
212 
215  GLuint height = 0;
216 };
217 
218 // class PixelBuffer
219 
220 //template<typename T>
221 //PixelBuffer<T>::PixelBuffer()
222 //{
223 // glGenBuffers(1, &bufferId);
224 //}
225 
226 //template<typename T>
227 //PixelBuffer<T>::~PixelBuffer()
228 //{
229 // glDeleteBuffers(1, &bufferId); // ok to delete '0'
230 //}
231 
232 template<typename T>
234  : allocated(std::move(other.allocated))
235  //, bufferId(other.bufferId)
236  , width(other.width)
237  , height(other.height)
238 {
239  //other.bufferId = 0;
240 }
241 
242 template<typename T>
244 {
245  std::swap(allocated, other.allocated);
246  //std::swap(bufferId, other.bufferId);
247  std::swap(width, other.width);
248  std::swap(height, other.height);
249  return *this;
250 }
251 
252 template<typename T>
253 void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
254 {
255  width = width_;
256  height = height_;
257  //if (bufferId != 0) {
258  // bind();
259  // // TODO make performance hint configurable?
260  // glBufferData(GL_PIXEL_UNPACK_BUFFER,
261  // width * height * 4,
262  // nullptr, // leave data undefined
263  // GL_STREAM_DRAW); // performance hint
264  // unbind();
265  //} else {
266  allocated.resize(width * height);
267  //}
268 }
269 
270 template<typename T>
272 {
273  //if (bufferId != 0) {
274  // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
275  //}
276 }
277 
278 template<typename T>
280 {
281  //if (bufferId != 0) {
282  // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
283  //}
284 }
285 
286 template<typename T>
287 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
288 {
289  assert(x < width);
290  assert(y < height);
291  auto offset = x + size_t(width) * y;
292  //if (bufferId != 0) {
293  // return reinterpret_cast<T*>(offset * sizeof(T));
294  //} else {
295  return &allocated[offset];
296  //}
297 }
298 
299 template<typename T>
301 {
302  //if (bufferId != 0) {
303  // return reinterpret_cast<T*>(glMapBuffer(
304  // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
305  //} else {
306  return allocated.data();
307  //}
308 }
309 
310 template<typename T>
312 {
313  //if (bufferId != 0) {
314  // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
315  //}
316 }
317 
318 
319 
323 class Shader
324 {
325 public:
328  [[nodiscard]] bool isOK() const;
329 
330 protected:
335  Shader(GLenum type, std::string_view filename) {
336  init(type, {}, filename);
337  }
338  Shader(GLenum type, std::string_view header, std::string_view filename) {
339  init(type, header, filename);
340  }
341 
342  ~Shader();
343 
344 private:
345  void init(GLenum type, std::string_view header,
346  std::string_view filename);
347 
348  friend class ShaderProgram;
349 
350 private:
351  GLuint handle;
352 };
353 
357 class VertexShader : public Shader
358 {
359 public:
363  explicit VertexShader(std::string_view filename)
364  : Shader(GL_VERTEX_SHADER, filename) {}
365  VertexShader(std::string_view header, std::string_view filename)
366  : Shader(GL_VERTEX_SHADER, header, filename) {}
367 };
368 
372 class FragmentShader : public Shader
373 {
374 public:
378  explicit FragmentShader(std::string_view filename)
379  : Shader(GL_FRAGMENT_SHADER, filename) {}
380  FragmentShader(std::string_view header, std::string_view filename)
381  : Shader(GL_FRAGMENT_SHADER, header, filename) {}
382 };
383 
388 {
389 public:
390  ShaderProgram(const ShaderProgram&) = delete;
392 
395 
397  explicit ShaderProgram(Null) : handle(0) {}
398 
401 
403  void allocate();
404 
406  void reset();
407 
411  [[nodiscard]] GLuint get() const { return handle; }
412 
416  [[nodiscard]] bool isOK() const;
417 
420  void attach(const Shader& shader);
421 
425  void link();
426 
430  void bindAttribLocation(unsigned index, const char* name);
431 
436  [[nodiscard]] GLint getUniformLocation(const char* name) const;
437 
441  void activate() const;
442 
443  void validate() const;
444 
445 private:
446  GLuint handle;
447 };
448 
450 {
451 public:
452  BufferObject();
453  ~BufferObject();
454  BufferObject(BufferObject&& other) noexcept
455  : bufferId(other.bufferId)
456  {
457  other.bufferId = 0;
458  }
459  BufferObject& operator=(BufferObject&& other) noexcept {
460  std::swap(bufferId, other.bufferId);
461  return *this;
462  }
463 
464  [[nodiscard]] GLuint get() const { return bufferId; }
465 
466 private:
467  GLuint bufferId;
468 };
469 
470 } // namespace gl
471 
472 #endif // COMPONENT_GL
473 #endif // GLUTIL_HH
BufferObject(BufferObject &&other) noexcept
Definition: GLUtil.hh:454
BufferObject & operator=(BufferObject &&other) noexcept
Definition: GLUtil.hh:459
GLuint get() const
Definition: GLUtil.hh:464
GLsizei getHeight() const
Definition: GLUtil.hh:112
GLsizei getWidth() const
Definition: GLUtil.hh:111
void resize(GLsizei width, GLsizei height)
Definition: GLUtil.cc:71
ColorTexture()=default
Default constructor, zero-sized texture.
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition: GLUtil.hh:373
FragmentShader(std::string_view header, std::string_view filename)
Definition: GLUtil.hh:380
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition: GLUtil.hh:378
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:124
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:129
Wrapper around a pixel buffer.
Definition: GLUtil.hh:153
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:243
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:311
PixelBuffer()=default
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:279
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:253
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:287
PixelBuffer(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:233
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:271
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:300
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:388
void activate() const
Makes this program the active shader program.
Definition: GLUtil.cc:265
GLuint get() const
Returns the underlying openGL handler id.
Definition: GLUtil.hh:411
bool isOK() const
Returns true iff this program was linked without errors.
Definition: GLUtil.cc:212
void attach(const Shader &shader)
Adds a given shader to this program.
Definition: GLUtil.cc:220
void validate() const
Definition: GLUtil.cc:271
ShaderProgram(Null)
Create null handler (don't yet allocate a openGL object).
Definition: GLUtil.hh:397
void allocate()
Allocate a shader program handle.
Definition: GLUtil.cc:198
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition: GLUtil.hh:400
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition: GLUtil.hh:394
void reset()
Release the shader program handle.
Definition: GLUtil.cc:206
void link()
Links all attached shaders together into one program.
Definition: GLUtil.cc:232
void bindAttribLocation(unsigned index, const char *name)
Bind the given name for a vertex shader attribute to the given location.
Definition: GLUtil.cc:252
GLint getUniformLocation(const char *name) const
Gets a reference to a uniform variable declared in the shader source.
Definition: GLUtil.cc:257
ShaderProgram & operator=(const ShaderProgram &)=delete
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition: GLUtil.hh:324
bool isOK() const
Returns true iff this shader is loaded and compiled without errors.
Definition: GLUtil.cc:187
Shader(GLenum type, std::string_view filename)
Instantiates a shader.
Definition: GLUtil.hh:335
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition: GLUtil.hh:338
Most basic/generic texture: only contains a texture ID.
Definition: GLUtil.hh:41
Texture & operator=(Texture &&other) noexcept
Definition: GLUtil.hh:61
void reset()
Release openGL texture name.
Definition: GLUtil.cc:41
Texture(const Texture &)=delete
void setWrapMode(bool wrap)
Definition: GLUtil.cc:55
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition: GLUtil.cc:47
~Texture()
Release openGL texture name.
Definition: GLUtil.hh:53
GLuint get() const
Returns the underlying openGL handler id.
Definition: GLUtil.hh:75
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:82
void allocate()
Allocate an openGL texture name.
Definition: GLUtil.cc:36
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition: GLUtil.hh:56
Texture & operator=(const Texture &)=delete
GLuint textureId
Definition: GLUtil.hh:94
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition: GLUtil.hh:50
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff.
Definition: GLUtil.hh:358
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition: GLUtil.hh:363
VertexShader(std::string_view header, std::string_view filename)
Definition: GLUtil.hh:365
This class manages the lifetime of a block of memory.
Definition: MemBuffer.hh:29
Definition: gl_mat.hh:23
void checkGLError(std::string_view prefix)
Definition: GLUtil.cc:15
constexpr const char *const filename
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118