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 {
78 assert(textureId);
79 return std::bit_cast<void*>(uintptr_t(textureId));
80 }
81
87 void bind() const {
88 glBindTexture(GL_TEXTURE_2D, textureId);
89 }
90
94 void setInterpolation(bool interpolation);
95
96 void setWrapMode(bool wrap);
97
98protected:
99 GLuint textureId;
100
101 friend class FrameBufferObject;
102};
103
104class ColorTexture : public Texture
105{
106public:
108 ColorTexture() = default;
109
113 ColorTexture(GLsizei width, GLsizei height);
114 void resize(GLsizei width, GLsizei height);
115
116 [[nodiscard]] GLsizei getWidth () const { return width; }
117 [[nodiscard]] GLsizei getHeight() const { return height; }
118
119private:
120 GLsizei width = 0;
121 GLsizei height = 0;
122};
123
125{
126public:
127 FrameBufferObject() = default;
128 explicit FrameBufferObject(Texture& texture);
130 : bufferId(other.bufferId)
131 {
132 other.bufferId = 0;
133 }
135 std::swap(bufferId, other.bufferId);
136 return *this;
137 }
139
140 void push();
141 void pop();
142
143private:
144 GLuint bufferId = 0; // 0 is not a valid openGL name
145 GLint previousId = 0;
146};
147
157template<typename T> class PixelBuffer
158{
159public:
161 PixelBuffer(const PixelBuffer& other) = delete;
162 PixelBuffer(PixelBuffer&& other) noexcept;
163 PixelBuffer& operator=(const PixelBuffer& other) = delete;
166
171 void setImage(GLuint width, GLuint height);
172
177 void bind() const;
178
181 void unbind() const;
182
189 [[nodiscard]] T* getOffset(GLuint x, GLuint y);
190
199 [[nodiscard]] T* mapWrite();
200
205 void unmap() const;
206
207private:
210 openmsx::MemBuffer<T> allocated;
211
214 //GLuint bufferId;
215
218 GLuint width = 0;
219
222 GLuint height = 0;
223};
224
225// class PixelBuffer
226
227template<typename T>
229{
230 //glGenBuffers(1, &bufferId);
231}
232
233template<typename T>
235{
236 //glDeleteBuffers(1, &bufferId); // ok to delete '0'
237}
238
239template<typename T>
241 : allocated(std::move(other.allocated))
242 //, bufferId(other.bufferId)
243 , width(other.width)
244 , height(other.height)
245{
246 //other.bufferId = 0;
247}
248
249template<typename T>
251{
252 std::swap(allocated, other.allocated);
253 //std::swap(bufferId, other.bufferId);
254 std::swap(width, other.width);
255 std::swap(height, other.height);
256 return *this;
257}
258
259template<typename T>
260void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
261{
262 width = width_;
263 height = height_;
264 //if (bufferId != 0) {
265 // bind();
266 // // TODO make performance hint configurable?
267 // glBufferData(GL_PIXEL_UNPACK_BUFFER,
268 // width * height * 4,
269 // nullptr, // leave data undefined
270 // GL_STREAM_DRAW); // performance hint
271 // unbind();
272 //} else {
273 allocated.resize(width * height);
274 //}
275}
276
277template<typename T>
279{
280 //if (bufferId != 0) {
281 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
282 //}
283}
284
285template<typename T>
287{
288 //if (bufferId != 0) {
289 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
290 //}
291}
292
293template<typename T>
294T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
295{
296 assert(x < width);
297 assert(y < height);
298 auto offset = x + size_t(width) * y;
299 //if (bufferId != 0) {
300 // return std::bit_cast<T*>(offset * sizeof(T));
301 //} else {
302 return &allocated[offset];
303 //}
304}
305
306template<typename T>
308{
309 //if (bufferId != 0) {
310 // return std::bit_cast<T*>(glMapBuffer(
311 // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
312 //} else {
313 return allocated.data();
314 //}
315}
316
317template<typename T>
319{
320 //if (bufferId != 0) {
321 // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
322 //}
323}
324
325
326
331{
332public:
333 Shader(const Shader&) = delete;
334 Shader(Shader&&) = delete;
335 Shader& operator=(const Shader&) = delete;
336 Shader& operator=(Shader&&) = delete;
337
340 [[nodiscard]] bool isOK() const;
341
342protected:
347 Shader(GLenum type, std::string_view filename) {
348 init(type, {}, filename);
349 }
350 Shader(GLenum type, std::string_view header, std::string_view filename) {
351 init(type, header, filename);
352 }
353 ~Shader();
354
355private:
356 void init(GLenum type, std::string_view header,
357 std::string_view filename);
358
359 friend class ShaderProgram;
360
361private:
362 GLuint handle;
363};
364
368class VertexShader : public Shader
369{
370public:
374 explicit VertexShader(std::string_view filename)
375 : Shader(GL_VERTEX_SHADER, filename) {}
376 VertexShader(std::string_view header, std::string_view filename)
377 : Shader(GL_VERTEX_SHADER, header, filename) {}
378};
379
383class FragmentShader : public Shader
384{
385public:
389 explicit FragmentShader(std::string_view filename)
390 : Shader(GL_FRAGMENT_SHADER, filename) {}
391 FragmentShader(std::string_view header, std::string_view filename)
392 : Shader(GL_FRAGMENT_SHADER, header, filename) {}
393};
394
399{
400public:
401 ShaderProgram(const ShaderProgram&) = delete;
405
408
410 explicit ShaderProgram(Null) : handle(0) {}
411
414
416 void allocate();
417
419 void reset();
420
424 [[nodiscard]] GLuint get() const { return handle; }
425
429 [[nodiscard]] bool isOK() const;
430
433 void attach(const Shader& shader);
434
438 void link();
439
443 void bindAttribLocation(unsigned index, const char* name);
444
449 [[nodiscard]] GLint getUniformLocation(const char* name) const;
450
454 void activate() const;
455
456 void validate() const;
457
458private:
459 GLuint handle;
460};
461
463{
464public:
465 BufferObject();
466 BufferObject(const BufferObject&) = delete;
469
470 BufferObject(BufferObject&& other) noexcept
471 : bufferId(other.bufferId)
472 {
473 other.bufferId = 0;
474 }
476 std::swap(bufferId, other.bufferId);
477 return *this;
478 }
479
480 [[nodiscard]] GLuint get() const { return bufferId; }
481
482private:
483 GLuint bufferId;
484};
485
486} // namespace gl
487
488#endif // GLUTIL_HH
BufferObject & operator=(BufferObject &&other) noexcept
Definition GLUtil.hh:475
BufferObject(BufferObject &&other) noexcept
Definition GLUtil.hh:470
BufferObject & operator=(const BufferObject &)=delete
GLuint get() const
Definition GLUtil.hh:480
BufferObject(const BufferObject &)=delete
GLsizei getHeight() const
Definition GLUtil.hh:117
GLsizei getWidth() const
Definition GLUtil.hh:116
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:384
FragmentShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:391
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition GLUtil.hh:389
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:129
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:134
Wrapper around a pixel buffer.
Definition GLUtil.hh:158
PixelBuffer(const PixelBuffer &other)=delete
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition GLUtil.hh:250
void unmap() const
Unmaps the contents of this buffer.
Definition GLUtil.hh:318
void unbind() const
Unbind this buffer.
Definition GLUtil.hh:286
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition GLUtil.hh:260
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition GLUtil.hh:294
PixelBuffer(PixelBuffer &&other) noexcept
Definition GLUtil.hh:240
void bind() const
Bind this PixelBuffer.
Definition GLUtil.hh:278
PixelBuffer & operator=(const PixelBuffer &other)=delete
T * mapWrite()
Maps the contents of this buffer into memory.
Definition GLUtil.hh:307
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition GLUtil.hh:399
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:424
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:410
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:413
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition GLUtil.hh:407
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:331
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:347
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition GLUtil.hh:350
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:87
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:99
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:369
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition GLUtil.hh:374
VertexShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:376
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