openMSX
GLUtil.hh
Go to the documentation of this file.
1#ifndef GLUTIL_HH
2#define GLUTIL_HH
3
4// Include GLEW headers.
5#include <GL/glew.h>
6// Include OpenGL headers.
7#ifdef __APPLE__
8#include <OpenGL/gl.h>
9#else
10#include <GL/gl.h>
11#endif
12
13#include "MemBuffer.hh"
14
15#include <bit>
16#include <cassert>
17#include <cstdint>
18#include <string_view>
19
20// arbitrary but distinct values, (roughly) ordered according to version number
21#define OPENGL_ES_2_0 1
22#define OPENGL_2_1 2
23#define OPENGL_3_3 3
24#define OPENGL_VERSION OPENGL_2_1
25
26namespace gl {
27
28void checkGLError(std::string_view prefix);
29
30
31// Dummy object, to be able to construct empty handler objects.
32struct Null {};
33
34
39{
40public:
41 Texture(const Texture&) = delete;
42 Texture& operator=(const Texture&) = delete;
43
45 explicit Texture(bool interpolation = false, bool wrap = false);
46
48 explicit Texture(Null) : textureId(0) {}
49
51 ~Texture() { reset(); }
52
54 Texture(Texture&& other) noexcept
55 : textureId(other.textureId)
56 {
57 other.textureId = 0; // 0 is not a valid openGL texture name
58 }
59 Texture& operator=(Texture&& other) noexcept {
60 std::swap(textureId, other.textureId);
61 return *this;
62 }
63
65 void allocate();
66
68 void reset();
69
73 [[nodiscard]] GLuint get() const { return textureId; }
74
77 [[nodiscard]] void* getImGui() const { return std::bit_cast<void*>(uintptr_t(textureId)); }
78
84 void bind() const {
85 glBindTexture(GL_TEXTURE_2D, textureId);
86 }
87
91 void setInterpolation(bool interpolation);
92
93 void setWrapMode(bool wrap);
94
95protected:
96 GLuint textureId;
97
98 friend class FrameBufferObject;
99};
100
101class ColorTexture : public Texture
102{
103public:
105 ColorTexture() = default;
106
110 ColorTexture(GLsizei width, GLsizei height);
111 void resize(GLsizei width, GLsizei height);
112
113 [[nodiscard]] GLsizei getWidth () const { return width; }
114 [[nodiscard]] GLsizei getHeight() const { return height; }
115
116private:
117 GLsizei width = 0;
118 GLsizei height = 0;
119};
120
122{
123public:
124 FrameBufferObject() = default;
125 explicit FrameBufferObject(Texture& texture);
127 : bufferId(other.bufferId)
128 {
129 other.bufferId = 0;
130 }
132 std::swap(bufferId, other.bufferId);
133 return *this;
134 }
136
137 void push();
138 void pop();
139
140private:
141 GLuint bufferId = 0; // 0 is not a valid openGL name
142 GLint previousId = 0;
143};
144
154template<typename T> class PixelBuffer
155{
156public:
158 PixelBuffer(const PixelBuffer& other) = delete;
159 PixelBuffer(PixelBuffer&& other) noexcept;
160 PixelBuffer& operator=(const PixelBuffer& other) = delete;
163
168 void setImage(GLuint width, GLuint height);
169
174 void bind() const;
175
178 void unbind() const;
179
186 [[nodiscard]] T* getOffset(GLuint x, GLuint y);
187
196 [[nodiscard]] T* mapWrite();
197
202 void unmap() const;
203
204private:
207 openmsx::MemBuffer<T> allocated;
208
211 //GLuint bufferId;
212
215 GLuint width = 0;
216
219 GLuint height = 0;
220};
221
222// class PixelBuffer
223
224template<typename T>
226{
227 //glGenBuffers(1, &bufferId);
228}
229
230template<typename T>
232{
233 //glDeleteBuffers(1, &bufferId); // ok to delete '0'
234}
235
236template<typename T>
238 : allocated(std::move(other.allocated))
239 //, bufferId(other.bufferId)
240 , width(other.width)
241 , height(other.height)
242{
243 //other.bufferId = 0;
244}
245
246template<typename T>
248{
249 std::swap(allocated, other.allocated);
250 //std::swap(bufferId, other.bufferId);
251 std::swap(width, other.width);
252 std::swap(height, other.height);
253 return *this;
254}
255
256template<typename T>
257void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
258{
259 width = width_;
260 height = height_;
261 //if (bufferId != 0) {
262 // bind();
263 // // TODO make performance hint configurable?
264 // glBufferData(GL_PIXEL_UNPACK_BUFFER,
265 // width * height * 4,
266 // nullptr, // leave data undefined
267 // GL_STREAM_DRAW); // performance hint
268 // unbind();
269 //} else {
270 allocated.resize(width * height);
271 //}
272}
273
274template<typename T>
276{
277 //if (bufferId != 0) {
278 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
279 //}
280}
281
282template<typename T>
284{
285 //if (bufferId != 0) {
286 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
287 //}
288}
289
290template<typename T>
291T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
292{
293 assert(x < width);
294 assert(y < height);
295 auto offset = x + size_t(width) * y;
296 //if (bufferId != 0) {
297 // return std::bit_cast<T*>(offset * sizeof(T));
298 //} else {
299 return &allocated[offset];
300 //}
301}
302
303template<typename T>
305{
306 //if (bufferId != 0) {
307 // return std::bit_cast<T*>(glMapBuffer(
308 // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
309 //} else {
310 return allocated.data();
311 //}
312}
313
314template<typename T>
316{
317 //if (bufferId != 0) {
318 // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
319 //}
320}
321
322
323
328{
329public:
330 Shader(const Shader&) = delete;
331 Shader(Shader&&) = delete;
332 Shader& operator=(const Shader&) = delete;
333 Shader& operator=(Shader&&) = delete;
334
337 [[nodiscard]] bool isOK() const;
338
339protected:
344 Shader(GLenum type, std::string_view filename) {
345 init(type, {}, filename);
346 }
347 Shader(GLenum type, std::string_view header, std::string_view filename) {
348 init(type, header, filename);
349 }
350 ~Shader();
351
352private:
353 void init(GLenum type, std::string_view header,
354 std::string_view filename);
355
356 friend class ShaderProgram;
357
358private:
359 GLuint handle;
360};
361
365class VertexShader : public Shader
366{
367public:
371 explicit VertexShader(std::string_view filename)
372 : Shader(GL_VERTEX_SHADER, filename) {}
373 VertexShader(std::string_view header, std::string_view filename)
374 : Shader(GL_VERTEX_SHADER, header, filename) {}
375};
376
380class FragmentShader : public Shader
381{
382public:
386 explicit FragmentShader(std::string_view filename)
387 : Shader(GL_FRAGMENT_SHADER, filename) {}
388 FragmentShader(std::string_view header, std::string_view filename)
389 : Shader(GL_FRAGMENT_SHADER, header, filename) {}
390};
391
396{
397public:
398 ShaderProgram(const ShaderProgram&) = delete;
402
405
407 explicit ShaderProgram(Null) : handle(0) {}
408
411
413 void allocate();
414
416 void reset();
417
421 [[nodiscard]] GLuint get() const { return handle; }
422
426 [[nodiscard]] bool isOK() const;
427
430 void attach(const Shader& shader);
431
435 void link();
436
440 void bindAttribLocation(unsigned index, const char* name);
441
446 [[nodiscard]] GLint getUniformLocation(const char* name) const;
447
451 void activate() const;
452
453 void validate() const;
454
455private:
456 GLuint handle;
457};
458
460{
461public:
462 BufferObject();
463 BufferObject(const BufferObject&) = delete;
466
467 BufferObject(BufferObject&& other) noexcept
468 : bufferId(other.bufferId)
469 {
470 other.bufferId = 0;
471 }
473 std::swap(bufferId, other.bufferId);
474 return *this;
475 }
476
477 [[nodiscard]] GLuint get() const { return bufferId; }
478
479private:
480 GLuint bufferId;
481};
482
483} // namespace gl
484
485#endif // GLUTIL_HH
BufferObject & operator=(BufferObject &&other) noexcept
Definition GLUtil.hh:472
BufferObject(BufferObject &&other) noexcept
Definition GLUtil.hh:467
BufferObject & operator=(const BufferObject &)=delete
GLuint get() const
Definition GLUtil.hh:477
BufferObject(const BufferObject &)=delete
GLsizei getHeight() const
Definition GLUtil.hh:114
GLsizei getWidth() const
Definition GLUtil.hh:113
void resize(GLsizei width, GLsizei height)
Definition GLUtil.cc:86
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:381
FragmentShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:388
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition GLUtil.hh:386
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:126
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:131
Wrapper around a pixel buffer.
Definition GLUtil.hh:155
PixelBuffer(const PixelBuffer &other)=delete
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition GLUtil.hh:247
void unmap() const
Unmaps the contents of this buffer.
Definition GLUtil.hh:315
void unbind() const
Unbind this buffer.
Definition GLUtil.hh:283
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition GLUtil.hh:257
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition GLUtil.hh:291
PixelBuffer(PixelBuffer &&other) noexcept
Definition GLUtil.hh:237
void bind() const
Bind this PixelBuffer.
Definition GLUtil.hh:275
PixelBuffer & operator=(const PixelBuffer &other)=delete
T * mapWrite()
Maps the contents of this buffer into memory.
Definition GLUtil.hh:304
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition GLUtil.hh:396
ShaderProgram & operator=(const ShaderProgram &)=delete
void activate() const
Makes this program the active shader program.
Definition GLUtil.cc:283
GLuint get() const
Returns the underlying openGL handler id.
Definition GLUtil.hh:421
bool isOK() const
Returns true iff this program was linked without errors.
Definition GLUtil.cc:230
void attach(const Shader &shader)
Adds a given shader to this program.
Definition GLUtil.cc:238
ShaderProgram(ShaderProgram &&)=delete
void validate() const
Definition GLUtil.cc:289
ShaderProgram(Null)
Create null handler (don't yet allocate a openGL object).
Definition GLUtil.hh:407
void allocate()
Allocate a shader program handle.
Definition GLUtil.cc:213
ShaderProgram & operator=(ShaderProgram &&)=delete
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition GLUtil.hh:410
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition GLUtil.hh:404
void reset()
Release the shader program handle.
Definition GLUtil.cc:221
void link()
Links all attached shaders together into one program.
Definition GLUtil.cc:250
void bindAttribLocation(unsigned index, const char *name)
Bind the given name for a vertex shader attribute to the given location.
Definition GLUtil.cc:270
GLint getUniformLocation(const char *name) const
Gets a reference to a uniform variable declared in the shader source.
Definition GLUtil.cc:275
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition GLUtil.hh:328
Shader & operator=(Shader &&)=delete
Shader(const Shader &)=delete
Shader(Shader &&)=delete
Shader & operator=(const Shader &)=delete
bool isOK() const
Returns true iff this shader is loaded and compiled without errors.
Definition GLUtil.cc:202
Shader(GLenum type, std::string_view filename)
Instantiates a shader.
Definition GLUtil.hh:344
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition GLUtil.hh:347
Most basic/generic texture: only contains a texture ID.
Definition GLUtil.hh:39
Texture & operator=(Texture &&other) noexcept
Definition GLUtil.hh:59
void reset()
Release openGL texture name.
Definition GLUtil.cc:45
Texture(const Texture &)=delete
void bind() const
Makes this texture the active GL texture.
Definition GLUtil.hh:84
void setWrapMode(bool wrap)
Definition GLUtil.cc:70
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition GLUtil.cc:62
~Texture()
Release openGL texture name.
Definition GLUtil.hh:51
GLuint get() const
Returns the underlying openGL handler id.
Definition GLUtil.hh:73
void allocate()
Allocate an openGL texture name.
Definition GLUtil.cc:40
void * getImGui() const
Return as a 'void*' (needed for 'Dear ImGui').
Definition GLUtil.hh:77
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition GLUtil.hh:54
GLuint textureId
Definition GLUtil.hh:96
Texture & operator=(const Texture &)=delete
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition GLUtil.hh:48
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff.
Definition GLUtil.hh:366
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition GLUtil.hh:371
VertexShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:373
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:19