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
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
81 void bind() {
82 glBindTexture(GL_TEXTURE_2D, textureId);
83 }
84
88 void setInterpolation(bool interpolation);
89
90 void setWrapMode(bool wrap);
91
92protected:
93 GLuint textureId;
94
95 friend class FrameBufferObject;
96};
97
98class ColorTexture : public Texture
99{
100public:
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
113private:
114 GLsizei width = 0;
115 GLsizei height = 0;
116};
117
119{
120public:
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
137private:
138 GLuint bufferId = 0; // 0 is not a valid openGL name
139 GLint previousId = 0;
140};
141
151template<typename T> class PixelBuffer
152{
153public:
154 PixelBuffer() = default;
155 //~PixelBuffer();
156 PixelBuffer(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
199private:
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
231template<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
241template<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
251template<typename T>
252void 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
269template<typename T>
271{
272 //if (bufferId != 0) {
273 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferId);
274 //}
275}
276
277template<typename T>
279{
280 //if (bufferId != 0) {
281 // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
282 //}
283}
284
285template<typename T>
286T* 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
298template<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
309template<typename T>
311{
312 //if (bufferId != 0) {
313 // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
314 //}
315}
316
317
318
323{
324public:
327 [[nodiscard]] bool isOK() const;
328
329protected:
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
343private:
344 void init(GLenum type, std::string_view header,
345 std::string_view filename);
346
347 friend class ShaderProgram;
348
349private:
350 GLuint handle;
351};
352
356class VertexShader : public Shader
357{
358public:
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
371class FragmentShader : public Shader
372{
373public:
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{
388public:
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
444private:
445 GLuint handle;
446};
447
449{
450public:
451 BufferObject();
453 BufferObject(BufferObject&& other) noexcept
454 : bufferId(other.bufferId)
455 {
456 other.bufferId = 0;
457 }
459 std::swap(bufferId, other.bufferId);
460 return *this;
461 }
462
463 [[nodiscard]] GLuint get() const { return bufferId; }
464
465private:
466 GLuint bufferId;
467};
468
469} // namespace gl
470
471#endif // COMPONENT_GL
472#endif // GLUTIL_HH
BufferObject & operator=(BufferObject &&other) noexcept
Definition: GLUtil.hh:458
BufferObject(BufferObject &&other) noexcept
Definition: GLUtil.hh:453
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
ShaderProgram & operator=(const ShaderProgram &)=delete
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
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
GLuint textureId
Definition: GLUtil.hh:93
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: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
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202