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 <span>
19#include <string_view>
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
27namespace gl {
28
29void checkGLError(std::string_view prefix);
30
31
32// Dummy object, to be able to construct empty handler objects.
33struct Null {};
34
35
40{
41public:
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
78 [[nodiscard]] void* getImGui() const {
79 assert(textureId);
80 return std::bit_cast<void*>(uintptr_t(textureId));
81 }
82
88 void bind() const {
89 glBindTexture(GL_TEXTURE_2D, textureId);
90 }
91
95 void setInterpolation(bool interpolation);
96
97 void setWrapMode(bool wrap);
98
99protected:
100 GLuint textureId;
101
102 friend class FrameBufferObject;
103};
104
105class ColorTexture : public Texture
106{
107public:
109 ColorTexture() = default;
110
114 ColorTexture(GLsizei width, GLsizei height);
115 void resize(GLsizei width, GLsizei height);
116
117 [[nodiscard]] GLsizei getWidth () const { return width; }
118 [[nodiscard]] GLsizei getHeight() const { return height; }
119
120private:
121 GLsizei width = 0;
122 GLsizei height = 0;
123};
124
126{
127public:
128 FrameBufferObject() = default;
129 explicit FrameBufferObject(Texture& texture);
131 : bufferId(other.bufferId)
132 {
133 other.bufferId = 0;
134 }
136 std::swap(bufferId, other.bufferId);
137 return *this;
138 }
140
141 void push();
142 void pop();
143
144private:
145 GLuint bufferId = 0; // 0 is not a valid openGL name
146 GLint previousId = 0;
147};
148
158template<typename T> class PixelBuffer
159{
160public:
162 PixelBuffer(const PixelBuffer& other) = delete;
163 PixelBuffer(PixelBuffer&& other) noexcept;
164 PixelBuffer& operator=(const PixelBuffer& other) = delete;
167
170 void allocate(GLuint size);
171
176 void bind() const;
177
180 void unbind() const;
181
190 [[nodiscard]] std::span<T> mapWrite();
191
196 void unmap() const;
197
198private:
201 openmsx::MemBuffer<T> allocated;
202
205 GLuint size = 0;
206
209 //GLuint bufferId;
210};
211
212// class PixelBuffer
213
214template<typename T>
216{
217 //glGenBuffers(1, &bufferId);
218}
219
220template<typename T>
222{
223 //glDeleteBuffers(1, &bufferId); // ok to delete '0'
224}
225
226template<typename T>
228 : allocated(std::move(other.allocated))
229 , size(other.size)
230 //, bufferId(other.bufferId)
231{
232 other.size = 0;
233 //other.bufferId = 0;
234}
235
236template<typename T>
238{
239 std::swap(allocated, other.allocated);
240 std::swap(size, other.size);
241 //std::swap(bufferId, other.bufferId);
242 return *this;
243}
244
245template<typename T>
246void PixelBuffer<T>::allocate(GLuint size_)
247{
248 size = size_;
249 //if (bufferId != 0) {
250 // bind();
251 // // TODO make performance hint configurable?
252 // glBufferData(GL_PIXEL_UNPACK_BUFFER,
253 // size * 4,
254 // nullptr, // leave data undefined
255 // GL_STREAM_DRAW); // performance hint
256 // unbind();
257 //} else {
258 allocated.resize(size);
259 //}
260}
261
262template<typename T>
264{
265 //if (bufferId != 0) {
266 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
267 //}
268}
269
270template<typename T>
272{
273 //if (bufferId != 0) {
274 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
275 //}
276}
277
278template<typename T>
280{
281 //if (bufferId != 0) {
282 // return std::bit_cast<T*>(glMapBuffer(
283 // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
284 //} else {
285 return {allocated.data(), size};
286 //}
287}
288
289template<typename T>
291{
292 //if (bufferId != 0) {
293 // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
294 //}
295}
296
297
298
303{
304public:
305 Shader(const Shader&) = delete;
306 Shader(Shader&&) = delete;
307 Shader& operator=(const Shader&) = delete;
308 Shader& operator=(Shader&&) = delete;
309
312 [[nodiscard]] bool isOK() const;
313
314protected:
319 Shader(GLenum type, std::string_view filename) {
320 init(type, {}, filename);
321 }
322 Shader(GLenum type, std::string_view header, std::string_view filename) {
323 init(type, header, filename);
324 }
325 ~Shader();
326
327private:
328 void init(GLenum type, std::string_view header,
329 std::string_view filename);
330
331 friend class ShaderProgram;
332
333private:
334 GLuint handle;
335};
336
340class VertexShader : public Shader
341{
342public:
346 explicit VertexShader(std::string_view filename)
347 : Shader(GL_VERTEX_SHADER, filename) {}
348 VertexShader(std::string_view header, std::string_view filename)
349 : Shader(GL_VERTEX_SHADER, header, filename) {}
350};
351
355class FragmentShader : public Shader
356{
357public:
361 explicit FragmentShader(std::string_view filename)
362 : Shader(GL_FRAGMENT_SHADER, filename) {}
363 FragmentShader(std::string_view header, std::string_view filename)
364 : Shader(GL_FRAGMENT_SHADER, header, filename) {}
365};
366
371{
372public:
373 ShaderProgram(const ShaderProgram&) = delete;
377
380
382 explicit ShaderProgram(Null) : handle(0) {}
383
386
388 void allocate();
389
391 void reset();
392
396 [[nodiscard]] GLuint get() const { return handle; }
397
401 [[nodiscard]] bool isOK() const;
402
405 void attach(const Shader& shader);
406
410 void link();
411
415 void bindAttribLocation(unsigned index, const char* name);
416
421 [[nodiscard]] GLint getUniformLocation(const char* name) const;
422
426 void activate() const;
427
428 void validate() const;
429
430private:
431 GLuint handle;
432};
433
435{
436public:
437 BufferObject();
438 BufferObject(const BufferObject&) = delete;
441
442 BufferObject(BufferObject&& other) noexcept
443 : bufferId(other.bufferId)
444 {
445 other.bufferId = 0;
446 }
448 std::swap(bufferId, other.bufferId);
449 return *this;
450 }
451
452 [[nodiscard]] GLuint get() const { return bufferId; }
453
454private:
455 GLuint bufferId;
456};
457
458} // namespace gl
459
460#endif // GLUTIL_HH
BufferObject & operator=(BufferObject &&other) noexcept
Definition GLUtil.hh:447
BufferObject(BufferObject &&other) noexcept
Definition GLUtil.hh:442
BufferObject & operator=(const BufferObject &)=delete
GLuint get() const
Definition GLUtil.hh:452
BufferObject(const BufferObject &)=delete
GLsizei getHeight() const
Definition GLUtil.hh:118
GLsizei getWidth() const
Definition GLUtil.hh:117
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:356
FragmentShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:363
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition GLUtil.hh:361
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:130
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:135
Wrapper around a pixel buffer.
Definition GLUtil.hh:159
PixelBuffer(const PixelBuffer &other)=delete
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition GLUtil.hh:237
void allocate(GLuint size)
Allocate the maximum required size for this buffer.
Definition GLUtil.hh:246
void unmap() const
Unmaps the contents of this buffer.
Definition GLUtil.hh:290
void unbind() const
Unbind this buffer.
Definition GLUtil.hh:271
PixelBuffer(PixelBuffer &&other) noexcept
Definition GLUtil.hh:227
void bind() const
Bind this PixelBuffer.
Definition GLUtil.hh:263
PixelBuffer & operator=(const PixelBuffer &other)=delete
std::span< T > mapWrite()
Maps the contents of this buffer into memory.
Definition GLUtil.hh:279
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition GLUtil.hh:371
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:396
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:382
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:385
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition GLUtil.hh:379
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:303
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:319
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition GLUtil.hh:322
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:45
Texture(const Texture &)=delete
void bind() const
Makes this texture the active GL texture.
Definition GLUtil.hh:88
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:52
GLuint get() const
Returns the underlying openGL handler id.
Definition GLUtil.hh:74
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:78
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition GLUtil.hh:55
GLuint textureId
Definition GLUtil.hh:100
Texture & operator=(const Texture &)=delete
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:341
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition GLUtil.hh:346
VertexShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:348
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