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>
20 #include <string_view>
21 #include <cassert>
22 
23 // arbitrary but distinct values, (roughly) ordered according to version number
24 #define OPENGL_ES_2_0 1
25 #define OPENGL_2_1 2
26 #define OPENGL_3_3 3
27 #define OPENGL_VERSION OPENGL_2_1
28 
29 namespace gl {
30 
31 void checkGLError(std::string_view prefix);
32 
33 
34 // Dummy object, to be able to construct empty handler objects.
35 struct Null {};
36 
37 
41 class Texture
42 {
43 public:
44  Texture(const Texture&) = delete;
45  Texture& operator=(const Texture&) = delete;
46 
48  explicit Texture(bool interpolation = false, bool wrap = false);
49 
51  explicit Texture(Null) : textureId(0) {}
52 
54  ~Texture() { reset(); }
55 
57  Texture(Texture&& other) noexcept
58  : textureId(other.textureId)
59  {
60  other.textureId = 0; // 0 is not a valid openGL texture name
61  }
62  Texture& operator=(Texture&& other) noexcept {
63  std::swap(textureId, other.textureId);
64  return *this;
65  }
66 
68  void allocate();
69 
71  void reset();
72 
76  [[nodiscard]] GLuint get() const { return textureId; }
77 
83  void bind() {
84  glBindTexture(GL_TEXTURE_2D, textureId);
85  }
86 
90  void setInterpolation(bool interpolation);
91 
92  void setWrapMode(bool wrap);
93 
94 protected:
95  GLuint textureId;
96 
97  friend class FrameBufferObject;
98 };
99 
100 class ColorTexture : public Texture
101 {
102 public:
104  ColorTexture() = default;
105 
109  ColorTexture(GLsizei width, GLsizei height);
110  void resize(GLsizei width, GLsizei height);
111 
112  [[nodiscard]] GLsizei getWidth () const { return width; }
113  [[nodiscard]] GLsizei getHeight() const { return height; }
114 
115 private:
116  GLsizei width = 0;
117  GLsizei height = 0;
118 };
119 
121 {
122 public:
123  FrameBufferObject() = default;
124  explicit FrameBufferObject(Texture& texture);
126  : bufferId(other.bufferId)
127  {
128  other.bufferId = 0;
129  }
131  std::swap(bufferId, other.bufferId);
132  return *this;
133  }
135 
136  void push();
137  void pop();
138 
139 private:
140  GLuint bufferId = 0; // 0 is not a valid openGL name
141  GLint previousId = 0;
142 };
143 
153 template<typename T> class PixelBuffer
154 {
155 public:
156  PixelBuffer() = default;
157  //~PixelBuffer();
158  PixelBuffer(PixelBuffer&& other) noexcept;
159  PixelBuffer& operator=(PixelBuffer&& other) noexcept;
160 
165  void setImage(GLuint width, GLuint height);
166 
171  void bind() const;
172 
175  void unbind() const;
176 
183  [[nodiscard]] T* getOffset(GLuint x, GLuint y);
184 
193  [[nodiscard]] T* mapWrite();
194 
199  void unmap() const;
200 
201 private:
204  openmsx::MemBuffer<T> allocated;
205 
208  //GLuint bufferId;
209 
212  GLuint width = 0;
213 
216  GLuint height = 0;
217 };
218 
219 // class PixelBuffer
220 
221 //template<typename T>
222 //PixelBuffer<T>::PixelBuffer()
223 //{
224 // glGenBuffers(1, &bufferId);
225 //}
226 
227 //template<typename T>
228 //PixelBuffer<T>::~PixelBuffer()
229 //{
230 // glDeleteBuffers(1, &bufferId); // ok to delete '0'
231 //}
232 
233 template<typename T>
235  : allocated(std::move(other.allocated))
236  //, bufferId(other.bufferId)
237  , width(other.width)
238  , height(other.height)
239 {
240  //other.bufferId = 0;
241 }
242 
243 template<typename T>
245 {
246  std::swap(allocated, other.allocated);
247  //std::swap(bufferId, other.bufferId);
248  std::swap(width, other.width);
249  std::swap(height, other.height);
250  return *this;
251 }
252 
253 template<typename T>
254 void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
255 {
256  width = width_;
257  height = height_;
258  //if (bufferId != 0) {
259  // bind();
260  // // TODO make performance hint configurable?
261  // glBufferData(GL_PIXEL_UNPACK_BUFFER,
262  // width * height * 4,
263  // nullptr, // leave data undefined
264  // GL_STREAM_DRAW); // performance hint
265  // unbind();
266  //} else {
267  allocated.resize(width * height);
268  //}
269 }
270 
271 template<typename T>
273 {
274  //if (bufferId != 0) {
275  // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
276  //}
277 }
278 
279 template<typename T>
281 {
282  //if (bufferId != 0) {
283  // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
284  //}
285 }
286 
287 template<typename T>
288 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
289 {
290  assert(x < width);
291  assert(y < height);
292  auto offset = x + size_t(width) * y;
293  //if (bufferId != 0) {
294  // return reinterpret_cast<T*>(offset * sizeof(T));
295  //} else {
296  return &allocated[offset];
297  //}
298 }
299 
300 template<typename T>
302 {
303  //if (bufferId != 0) {
304  // return reinterpret_cast<T*>(glMapBuffer(
305  // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
306  //} else {
307  return allocated.data();
308  //}
309 }
310 
311 template<typename T>
313 {
314  //if (bufferId != 0) {
315  // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
316  //}
317 }
318 
319 
320 
324 class Shader
325 {
326 public:
329  [[nodiscard]] bool isOK() const;
330 
331 protected:
336  Shader(GLenum type, std::string_view filename) {
337  init(type, {}, filename);
338  }
339  Shader(GLenum type, std::string_view header, std::string_view filename) {
340  init(type, header, filename);
341  }
342 
343  ~Shader();
344 
345 private:
346  void init(GLenum type, std::string_view header,
347  std::string_view filename);
348 
349  friend class ShaderProgram;
350 
351 private:
352  GLuint handle;
353 };
354 
358 class VertexShader : public Shader
359 {
360 public:
364  explicit VertexShader(std::string_view filename)
365  : Shader(GL_VERTEX_SHADER, filename) {}
366  VertexShader(std::string_view header, std::string_view filename)
367  : Shader(GL_VERTEX_SHADER, header, filename) {}
368 };
369 
373 class FragmentShader : public Shader
374 {
375 public:
379  explicit FragmentShader(std::string_view filename)
380  : Shader(GL_FRAGMENT_SHADER, filename) {}
381  FragmentShader(std::string_view header, std::string_view filename)
382  : Shader(GL_FRAGMENT_SHADER, header, filename) {}
383 };
384 
389 {
390 public:
391  ShaderProgram(const ShaderProgram&) = delete;
393 
396 
398  explicit ShaderProgram(Null) : handle(0) {}
399 
402 
404  void allocate();
405 
407  void reset();
408 
412  [[nodiscard]] GLuint get() const { return handle; }
413 
417  [[nodiscard]] bool isOK() const;
418 
421  void attach(const Shader& shader);
422 
426  void link();
427 
431  void bindAttribLocation(unsigned index, const char* name);
432 
437  [[nodiscard]] GLint getUniformLocation(const char* name) const;
438 
442  void activate() const;
443 
444  void validate() const;
445 
446 private:
447  GLuint handle;
448 };
449 
451 {
452 public:
453  BufferObject();
454  ~BufferObject();
455  BufferObject(BufferObject&& other) noexcept
456  : bufferId(other.bufferId)
457  {
458  other.bufferId = 0;
459  }
460  BufferObject& operator=(BufferObject&& other) noexcept {
461  std::swap(bufferId, other.bufferId);
462  return *this;
463  }
464 
465  [[nodiscard]] GLuint get() const { return bufferId; }
466 
467 private:
468  GLuint bufferId;
469 };
470 
471 } // namespace gl
472 
473 #endif // COMPONENT_GL
474 #endif // GLUTIL_HH
BufferObject(BufferObject &&other) noexcept
Definition: GLUtil.hh:455
BufferObject & operator=(BufferObject &&other) noexcept
Definition: GLUtil.hh:460
GLuint get() const
Definition: GLUtil.hh:465
GLsizei getHeight() const
Definition: GLUtil.hh:113
GLsizei getWidth() const
Definition: GLUtil.hh:112
void resize(GLsizei width, GLsizei height)
Definition: GLUtil.cc:73
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:374
FragmentShader(std::string_view header, std::string_view filename)
Definition: GLUtil.hh:381
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition: GLUtil.hh:379
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:125
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:130
Wrapper around a pixel buffer.
Definition: GLUtil.hh:154
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:244
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:312
PixelBuffer()=default
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:280
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:254
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:288
PixelBuffer(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:234
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:272
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:301
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:389
void activate() const
Makes this program the active shader program.
Definition: GLUtil.cc:267
GLuint get() const
Returns the underlying openGL handler id.
Definition: GLUtil.hh:412
bool isOK() const
Returns true iff this program was linked without errors.
Definition: GLUtil.cc:214
void attach(const Shader &shader)
Adds a given shader to this program.
Definition: GLUtil.cc:222
void validate() const
Definition: GLUtil.cc:273
ShaderProgram(Null)
Create null handler (don't yet allocate a openGL object).
Definition: GLUtil.hh:398
void allocate()
Allocate a shader program handle.
Definition: GLUtil.cc:200
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition: GLUtil.hh:401
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition: GLUtil.hh:395
void reset()
Release the shader program handle.
Definition: GLUtil.cc:208
void link()
Links all attached shaders together into one program.
Definition: GLUtil.cc:234
void bindAttribLocation(unsigned index, const char *name)
Bind the given name for a vertex shader attribute to the given location.
Definition: GLUtil.cc:254
GLint getUniformLocation(const char *name) const
Gets a reference to a uniform variable declared in the shader source.
Definition: GLUtil.cc:259
ShaderProgram & operator=(const ShaderProgram &)=delete
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition: GLUtil.hh:325
bool isOK() const
Returns true iff this shader is loaded and compiled without errors.
Definition: GLUtil.cc:189
Shader(GLenum type, std::string_view filename)
Instantiates a shader.
Definition: GLUtil.hh:336
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition: GLUtil.hh:339
Most basic/generic texture: only contains a texture ID.
Definition: GLUtil.hh:42
Texture & operator=(Texture &&other) noexcept
Definition: GLUtil.hh:62
void reset()
Release openGL texture name.
Definition: GLUtil.cc:43
Texture(const Texture &)=delete
void setWrapMode(bool wrap)
Definition: GLUtil.cc:57
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition: GLUtil.cc:49
~Texture()
Release openGL texture name.
Definition: GLUtil.hh:54
GLuint get() const
Returns the underlying openGL handler id.
Definition: GLUtil.hh:76
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:83
void allocate()
Allocate an openGL texture name.
Definition: GLUtil.cc:38
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition: GLUtil.hh:57
Texture & operator=(const Texture &)=delete
GLuint textureId
Definition: GLUtil.hh:95
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition: GLUtil.hh:51
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff.
Definition: GLUtil.hh:359
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition: GLUtil.hh:364
VertexShader(std::string_view header, std::string_view filename)
Definition: GLUtil.hh:366
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:17
constexpr const char *const filename
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:124