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#include <string_view>
15#include <cassert>
16
17// arbitrary but distinct values, (roughly) ordered according to version number
18#define OPENGL_ES_2_0 1
19#define OPENGL_2_1 2
20#define OPENGL_3_3 3
21#define OPENGL_VERSION OPENGL_2_1
22
23namespace gl {
24
25void checkGLError(std::string_view prefix);
26
27
28// Dummy object, to be able to construct empty handler objects.
29struct Null {};
30
31
36{
37public:
38 Texture(const Texture&) = delete;
39 Texture& operator=(const Texture&) = delete;
40
42 explicit Texture(bool interpolation = false, bool wrap = false);
43
45 explicit Texture(Null) : textureId(0) {}
46
48 ~Texture() { reset(); }
49
51 Texture(Texture&& other) noexcept
52 : textureId(other.textureId)
53 {
54 other.textureId = 0; // 0 is not a valid openGL texture name
55 }
56 Texture& operator=(Texture&& other) noexcept {
57 std::swap(textureId, other.textureId);
58 return *this;
59 }
60
62 void allocate();
63
65 void reset();
66
70 [[nodiscard]] GLuint get() const { return textureId; }
71
77 void bind() {
78 glBindTexture(GL_TEXTURE_2D, textureId);
79 }
80
84 void setInterpolation(bool interpolation);
85
86 void setWrapMode(bool wrap);
87
88protected:
89 GLuint textureId;
90
91 friend class FrameBufferObject;
92};
93
94class ColorTexture : public Texture
95{
96public:
98 ColorTexture() = default;
99
103 ColorTexture(GLsizei width, GLsizei height);
104 void resize(GLsizei width, GLsizei height);
105
106 [[nodiscard]] GLsizei getWidth () const { return width; }
107 [[nodiscard]] GLsizei getHeight() const { return height; }
108
109private:
110 GLsizei width = 0;
111 GLsizei height = 0;
112};
113
115{
116public:
117 FrameBufferObject() = default;
118 explicit FrameBufferObject(Texture& texture);
120 : bufferId(other.bufferId)
121 {
122 other.bufferId = 0;
123 }
125 std::swap(bufferId, other.bufferId);
126 return *this;
127 }
129
130 void push();
131 void pop();
132
133private:
134 GLuint bufferId = 0; // 0 is not a valid openGL name
135 GLint previousId = 0;
136};
137
147template<typename T> class PixelBuffer
148{
149public:
150 PixelBuffer() = default;
151 //~PixelBuffer();
152 PixelBuffer(PixelBuffer&& other) noexcept;
154
159 void setImage(GLuint width, GLuint height);
160
165 void bind() const;
166
169 void unbind() const;
170
177 [[nodiscard]] T* getOffset(GLuint x, GLuint y);
178
187 [[nodiscard]] T* mapWrite();
188
193 void unmap() const;
194
195private:
198 openmsx::MemBuffer<T> allocated;
199
202 //GLuint bufferId;
203
206 GLuint width = 0;
207
210 GLuint height = 0;
211};
212
213// class PixelBuffer
214
215//template<typename T>
216//PixelBuffer<T>::PixelBuffer()
217//{
218// glGenBuffers(1, &bufferId);
219//}
220
221//template<typename T>
222//PixelBuffer<T>::~PixelBuffer()
223//{
224// glDeleteBuffers(1, &bufferId); // ok to delete '0'
225//}
226
227template<typename T>
229 : allocated(std::move(other.allocated))
230 //, bufferId(other.bufferId)
231 , width(other.width)
232 , height(other.height)
233{
234 //other.bufferId = 0;
235}
236
237template<typename T>
239{
240 std::swap(allocated, other.allocated);
241 //std::swap(bufferId, other.bufferId);
242 std::swap(width, other.width);
243 std::swap(height, other.height);
244 return *this;
245}
246
247template<typename T>
248void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
249{
250 width = width_;
251 height = height_;
252 //if (bufferId != 0) {
253 // bind();
254 // // TODO make performance hint configurable?
255 // glBufferData(GL_PIXEL_UNPACK_BUFFER,
256 // width * height * 4,
257 // nullptr, // leave data undefined
258 // GL_STREAM_DRAW); // performance hint
259 // unbind();
260 //} else {
261 allocated.resize(width * height);
262 //}
263}
264
265template<typename T>
267{
268 //if (bufferId != 0) {
269 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
270 //}
271}
272
273template<typename T>
275{
276 //if (bufferId != 0) {
277 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
278 //}
279}
280
281template<typename T>
282T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
283{
284 assert(x < width);
285 assert(y < height);
286 auto offset = x + size_t(width) * y;
287 //if (bufferId != 0) {
288 // return reinterpret_cast<T*>(offset * sizeof(T));
289 //} else {
290 return &allocated[offset];
291 //}
292}
293
294template<typename T>
296{
297 //if (bufferId != 0) {
298 // return reinterpret_cast<T*>(glMapBuffer(
299 // GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
300 //} else {
301 return allocated.data();
302 //}
303}
304
305template<typename T>
307{
308 //if (bufferId != 0) {
309 // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
310 //}
311}
312
313
314
319{
320public:
323 [[nodiscard]] bool isOK() const;
324
325protected:
330 Shader(GLenum type, std::string_view filename) {
331 init(type, {}, filename);
332 }
333 Shader(GLenum type, std::string_view header, std::string_view filename) {
334 init(type, header, filename);
335 }
336
337 ~Shader();
338
339private:
340 void init(GLenum type, std::string_view header,
341 std::string_view filename);
342
343 friend class ShaderProgram;
344
345private:
346 GLuint handle;
347};
348
352class VertexShader : public Shader
353{
354public:
358 explicit VertexShader(std::string_view filename)
359 : Shader(GL_VERTEX_SHADER, filename) {}
360 VertexShader(std::string_view header, std::string_view filename)
361 : Shader(GL_VERTEX_SHADER, header, filename) {}
362};
363
367class FragmentShader : public Shader
368{
369public:
373 explicit FragmentShader(std::string_view filename)
374 : Shader(GL_FRAGMENT_SHADER, filename) {}
375 FragmentShader(std::string_view header, std::string_view filename)
376 : Shader(GL_FRAGMENT_SHADER, header, filename) {}
377};
378
383{
384public:
385 ShaderProgram(const ShaderProgram&) = delete;
387
390
392 explicit ShaderProgram(Null) : handle(0) {}
393
396
398 void allocate();
399
401 void reset();
402
406 [[nodiscard]] GLuint get() const { return handle; }
407
411 [[nodiscard]] bool isOK() const;
412
415 void attach(const Shader& shader);
416
420 void link();
421
425 void bindAttribLocation(unsigned index, const char* name);
426
431 [[nodiscard]] GLint getUniformLocation(const char* name) const;
432
436 void activate() const;
437
438 void validate() const;
439
440private:
441 GLuint handle;
442};
443
445{
446public:
447 BufferObject();
449 BufferObject(BufferObject&& other) noexcept
450 : bufferId(other.bufferId)
451 {
452 other.bufferId = 0;
453 }
455 std::swap(bufferId, other.bufferId);
456 return *this;
457 }
458
459 [[nodiscard]] GLuint get() const { return bufferId; }
460
461private:
462 GLuint bufferId;
463};
464
465} // namespace gl
466
467#endif // GLUTIL_HH
BufferObject & operator=(BufferObject &&other) noexcept
Definition GLUtil.hh:454
BufferObject(BufferObject &&other) noexcept
Definition GLUtil.hh:449
GLuint get() const
Definition GLUtil.hh:459
GLsizei getHeight() const
Definition GLUtil.hh:107
GLsizei getWidth() const
Definition GLUtil.hh:106
void resize(GLsizei width, GLsizei height)
Definition GLUtil.cc:82
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:368
FragmentShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:375
FragmentShader(std::string_view filename)
Instantiates a fragment shader.
Definition GLUtil.hh:373
FrameBufferObject()=default
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:119
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition GLUtil.hh:124
Wrapper around a pixel buffer.
Definition GLUtil.hh:148
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition GLUtil.hh:238
void unmap() const
Unmaps the contents of this buffer.
Definition GLUtil.hh:306
PixelBuffer()=default
void unbind() const
Unbind this buffer.
Definition GLUtil.hh:274
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition GLUtil.hh:248
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition GLUtil.hh:282
PixelBuffer(PixelBuffer &&other) noexcept
Definition GLUtil.hh:228
void bind() const
Bind this PixelBuffer.
Definition GLUtil.hh:266
T * mapWrite()
Maps the contents of this buffer into memory.
Definition GLUtil.hh:295
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition GLUtil.hh:383
ShaderProgram & operator=(const ShaderProgram &)=delete
void activate() const
Makes this program the active shader program.
Definition GLUtil.cc:279
GLuint get() const
Returns the underlying openGL handler id.
Definition GLUtil.hh:406
bool isOK() const
Returns true iff this program was linked without errors.
Definition GLUtil.cc:226
void attach(const Shader &shader)
Adds a given shader to this program.
Definition GLUtil.cc:234
void validate() const
Definition GLUtil.cc:285
ShaderProgram(Null)
Create null handler (don't yet allocate a openGL object).
Definition GLUtil.hh:392
void allocate()
Allocate a shader program handle.
Definition GLUtil.cc:209
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition GLUtil.hh:395
ShaderProgram(const ShaderProgram &)=delete
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition GLUtil.hh:389
void reset()
Release the shader program handle.
Definition GLUtil.cc:217
void link()
Links all attached shaders together into one program.
Definition GLUtil.cc:246
void bindAttribLocation(unsigned index, const char *name)
Bind the given name for a vertex shader attribute to the given location.
Definition GLUtil.cc:266
GLint getUniformLocation(const char *name) const
Gets a reference to a uniform variable declared in the shader source.
Definition GLUtil.cc:271
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition GLUtil.hh:319
bool isOK() const
Returns true iff this shader is loaded and compiled without errors.
Definition GLUtil.cc:198
Shader(GLenum type, std::string_view filename)
Instantiates a shader.
Definition GLUtil.hh:330
Shader(GLenum type, std::string_view header, std::string_view filename)
Definition GLUtil.hh:333
Most basic/generic texture: only contains a texture ID.
Definition GLUtil.hh:36
Texture & operator=(Texture &&other) noexcept
Definition GLUtil.hh:56
void reset()
Release openGL texture name.
Definition GLUtil.cc:41
Texture(const Texture &)=delete
void setWrapMode(bool wrap)
Definition GLUtil.cc:66
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition GLUtil.cc:58
~Texture()
Release openGL texture name.
Definition GLUtil.hh:48
GLuint get() const
Returns the underlying openGL handler id.
Definition GLUtil.hh:70
void bind()
Makes this texture the active GL texture.
Definition GLUtil.hh:77
void allocate()
Allocate an openGL texture name.
Definition GLUtil.cc:36
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition GLUtil.hh:51
GLuint textureId
Definition GLUtil.hh:89
Texture & operator=(const Texture &)=delete
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition GLUtil.hh:45
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff.
Definition GLUtil.hh:353
VertexShader(std::string_view filename)
Instantiates a vertex shader.
Definition GLUtil.hh:358
VertexShader(std::string_view header, std::string_view filename)
Definition GLUtil.hh:360
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