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 <string_view>
19 #include <cassert>
20 
21 // arbitrary but distinct values, (roughly) ordered according to version number
22 #define OPENGL_ES_2_0 1
23 #define OPENGL_2_1 2
24 #define OPENGL_3_3 3
25 #define OPENGL_VERSION OPENGL_2_1
26 
27 namespace gl {
28 
29 void checkGLError(std::string_view prefix);
30 
31 
32 // Dummy object, to be able to construct empty handler objects.
33 struct Null {};
34 
35 
39 class Texture
40 {
41 public:
42  Texture(const Texture&) = delete;
43  Texture& operator=(const Texture&) = delete;
44 
46  explicit Texture(bool interpolation = false, bool wrap = false);
47 
49  explicit Texture(Null) : textureId(0) {}
50 
52  ~Texture() { reset(); }
53 
55  Texture(Texture&& other) noexcept
56  : textureId(other.textureId)
57  {
58  other.textureId = 0; // 0 is not a valid openGL texture name
59  }
60  Texture& operator=(Texture&& other) noexcept {
61  std::swap(textureId, other.textureId);
62  return *this;
63  }
64 
66  void allocate();
67 
69  void reset();
70 
74  [[nodiscard]] GLuint get() const { return textureId; }
75 
81  void bind() {
82  glBindTexture(GL_TEXTURE_2D, textureId);
83  }
84 
88  void setInterpolation(bool interpolation);
89 
90  void setWrapMode(bool wrap);
91 
92 protected:
93  GLuint textureId;
94 
95  friend class FrameBufferObject;
96 };
97 
98 class ColorTexture : public Texture
99 {
100 public:
102  ColorTexture() = default;
103 
107  ColorTexture(GLsizei width, GLsizei height);
108  void resize(GLsizei width, GLsizei height);
109 
110  [[nodiscard]] GLsizei getWidth () const { return width; }
111  [[nodiscard]] GLsizei getHeight() const { return height; }
112 
113 private:
114  GLsizei width = 0;
115  GLsizei height = 0;
116 };
117 
119 {
120 public:
121  FrameBufferObject() = default;
122  explicit FrameBufferObject(Texture& texture);
124  : bufferId(other.bufferId)
125  {
126  other.bufferId = 0;
127  }
129  std::swap(bufferId, other.bufferId);
130  return *this;
131  }
133 
134  void push();
135  void pop();
136 
137 private:
138  GLuint bufferId = 0; // 0 is not a valid openGL name
139  GLint previousId = 0;
140 };
141 
151 template<typename T> class PixelBuffer
152 {
153 public:
154  PixelBuffer() = default;
155  //~PixelBuffer();
156  PixelBuffer(PixelBuffer&& other) noexcept;
157  PixelBuffer& operator=(PixelBuffer&& other) noexcept;
158 
163  void setImage(GLuint width, GLuint height);
164 
169  void bind() const;
170 
173  void unbind() const;
174 
181  [[nodiscard]] T* getOffset(GLuint x, GLuint y);
182 
191  [[nodiscard]] T* mapWrite();
192 
197  void unmap() const;
198 
199 private:
202  openmsx::MemBuffer<T> allocated;
203 
206  //GLuint bufferId;
207 
210  GLuint width = 0;
211 
214  GLuint height = 0;
215 };
216 
217 // class PixelBuffer
218 
219 //template<typename T>
220 //PixelBuffer<T>::PixelBuffer()
221 //{
222 // glGenBuffers(1, &bufferId);
223 //}
224 
225 //template<typename T>
226 //PixelBuffer<T>::~PixelBuffer()
227 //{
228 // glDeleteBuffers(1, &bufferId); // ok to delete '0'
229 //}
230 
231 template<typename T>
233  : allocated(std::move(other.allocated))
234  //, bufferId(other.bufferId)
235  , width(other.width)
236  , height(other.height)
237 {
238  //other.bufferId = 0;
239 }
240 
241 template<typename T>
243 {
244  std::swap(allocated, other.allocated);
245  //std::swap(bufferId, other.bufferId);
246  std::swap(width, other.width);
247  std::swap(height, other.height);
248  return *this;
249 }
250 
251 template<typename T>
252 void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
253 {
254  width = width_;
255  height = height_;
256  //if (bufferId != 0) {
257  // bind();
258  // // TODO make performance hint configurable?
259  // glBufferData(GL_PIXEL_UNPACK_BUFFER,
260  // width * height * 4,
261  // nullptr, // leave data undefined
262  // GL_STREAM_DRAW); // performance hint
263  // unbind();
264  //} else {
265  allocated.resize(width * height);
266  //}
267 }
268 
269 template<typename T>
271 {
272  //if (bufferId != 0) {
273  // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
274  //}
275 }
276 
277 template<typename T>
279 {
280  //if (bufferId != 0) {
281  // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
282  //}
283 }
284 
285 template<typename T>
286 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
287 {
288  assert(x < width);
289  assert(y < height);
290  auto offset = x + size_t(width) * y;
291  //if (bufferId != 0) {
292  // return reinterpret_cast<T*>(offset * sizeof(T));
293  //} else {
294  return &allocated[offset];
295  //}
296 }
297 
298 template<typename T>
300 {
301  //if (bufferId != 0) {
302  // return reinterpret_cast<T*>(glMapBuffer(
303  // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
304  //} else {
305  return allocated.data();
306  //}
307 }
308 
309 template<typename T>
311 {
312  //if (bufferId != 0) {
313  // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
314  //}
315 }
316 
317 
318 
322 class Shader
323 {
324 public:
327  [[nodiscard]] bool isOK() const;
328 
329 protected:
334  Shader(GLenum type, std::string_view filename) {
335  init(type, {}, filename);
336  }
337  Shader(GLenum type, std::string_view header, std::string_view filename) {
338  init(type, header, filename);
339  }
340 
341  ~Shader();
342 
343 private:
344  void init(GLenum type, std::string_view header,
345  std::string_view filename);
346 
347  friend class ShaderProgram;
348 
349 private:
350  GLuint handle;
351 };
352 
356 class VertexShader : public Shader
357 {
358 public:
362  explicit VertexShader(std::string_view filename)
363  : Shader(GL_VERTEX_SHADER, filename) {}
364  VertexShader(std::string_view header, std::string_view filename)
365  : Shader(GL_VERTEX_SHADER, header, filename) {}
366 };
367 
371 class FragmentShader : public Shader
372 {
373 public:
377  explicit FragmentShader(std::string_view filename)
378  : Shader(GL_FRAGMENT_SHADER, filename) {}
379  FragmentShader(std::string_view header, std::string_view filename)
380  : Shader(GL_FRAGMENT_SHADER, header, filename) {}
381 };
382 
387 {
388 public:
389  ShaderProgram(const ShaderProgram&) = delete;
391 
394 
396  explicit ShaderProgram(Null) : handle(0) {}
397 
400 
402  void allocate();
403 
405  void reset();
406 
410  [[nodiscard]] GLuint get() const { return handle; }
411 
415  [[nodiscard]] bool isOK() const;
416 
419  void attach(const Shader& shader);
420 
424  void link();
425 
429  void bindAttribLocation(unsigned index, const char* name);
430 
435  [[nodiscard]] GLint getUniformLocation(const char* name) const;
436 
440  void activate() const;
441 
442  void validate() const;
443 
444 private:
445  GLuint handle;
446 };
447 
449 {
450 public:
451  BufferObject();
452  ~BufferObject();
453  BufferObject(BufferObject&& other) noexcept
454  : bufferId(other.bufferId)
455  {
456  other.bufferId = 0;
457  }
458  BufferObject& operator=(BufferObject&& other) noexcept {
459  std::swap(bufferId, other.bufferId);
460  return *this;
461  }
462 
463  [[nodiscard]] GLuint get() const { return bufferId; }
464 
465 private:
466  GLuint bufferId;
467 };
468 
469 } // namespace gl
470 
471 #endif // COMPONENT_GL
472 #endif // GLUTIL_HH
BufferObject(BufferObject &&other) noexcept
Definition: GLUtil.hh:453
BufferObject & operator=(BufferObject &&other) noexcept
Definition: GLUtil.hh:458
GLuint get() const
Definition: GLUtil.hh:463
GLsizei getHeight() const
Definition: GLUtil.hh:111
GLsizei getWidth() const
Definition: GLUtil.hh:110
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:372
FragmentShader(std::string_view header, std::string_view filename)
Definition: GLUtil.hh:379
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition: GLUtil.hh:377
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:123
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:128
Wrapper around a pixel buffer.
Definition: GLUtil.hh:152
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:242
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:310
PixelBuffer()=default
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:278
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:252
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:286
PixelBuffer(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:232
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:270
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:299
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:387
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:410
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:396
void allocate()
Allocate a shader program handle.
Definition: GLUtil.cc:198
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition: GLUtil.hh:399
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition: GLUtil.hh:393
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:323
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:334
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition: GLUtil.hh:337
Most basic/generic texture: only contains a texture ID.
Definition: GLUtil.hh:40
Texture & operator=(Texture &&other) noexcept
Definition: GLUtil.hh:60
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:52
GLuint get() const
Returns the underlying openGL handler id.
Definition: GLUtil.hh:74
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:81
void allocate()
Allocate an openGL texture name.
Definition: GLUtil.cc:36
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition: GLUtil.hh:55
Texture & operator=(const Texture &)=delete
GLuint textureId
Definition: GLUtil.hh:93
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition: GLUtil.hh:49
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff.
Definition: GLUtil.hh:357
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition: GLUtil.hh:362
VertexShader(std::string_view header, std::string_view filename)
Definition: GLUtil.hh:364
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:127