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 "build-info.hh"
19 #include <string>
20 #include <cassert>
21 
22 namespace gl {
23 
24 // TODO this needs glu, but atm we don't link against glu (in windows)
25 //void checkGLError(const std::string& prefix);
26 
27 
28 // Dummy object, to be able to construct empty handler objects.
29 struct Null {};
30 
31 
35 class Texture
36 {
37 public:
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  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 
88 protected:
89  GLuint textureId;
90 
91  friend class FrameBufferObject;
92 };
93 
94 class ColorTexture : public Texture
95 {
96 public:
98  ColorTexture() : width(0), height(0) {}
99 
103  ColorTexture(GLsizei width, GLsizei height);
104  void resize(GLsizei width, GLsizei height);
105 
106  GLsizei getWidth () const { return width; }
107  GLsizei getHeight() const { return height; }
108 
109 private:
110  GLsizei width;
111  GLsizei height;
112 };
113 
115 {
116 public:
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 
133 private:
134  GLuint bufferId;
135 };
136 
138 {
141  static bool enabled;
142 };
143 
149 template <typename T> class PixelBuffer
150 {
151 public:
152  PixelBuffer();
153  PixelBuffer(PixelBuffer&& other) noexcept;
154  PixelBuffer& operator=(PixelBuffer&& other) noexcept;
155  ~PixelBuffer();
156 
162  bool openGLSupported() const;
163 
168  void setImage(GLuint width, GLuint height);
169 
174  void bind() const;
175 
178  void unbind() const;
179 
186  T* getOffset(GLuint x, GLuint y);
187 
196  T* mapWrite();
197 
202  void unmap() const;
203 
204 private:
207  openmsx::MemBuffer<T> allocated;
208 
211  GLuint bufferId;
212 
215  GLuint width;
216 
219  GLuint height;
220 };
221 
222 // class PixelBuffer
223 
224 template <typename T>
226 {
227  if (PixelBuffers::enabled && GLEW_ARB_pixel_buffer_object) {
228  glGenBuffers(1, &bufferId);
229  } else {
230  //std::cerr << "OpenGL pixel buffers are not available" << std::endl;
231  bufferId = 0;
232  }
233 }
234 
235 template <typename T>
237  : allocated(std::move(other.allocated))
238  , bufferId(other.bufferId)
239  , width(other.width)
240  , height(other.height)
241 {
242  other.bufferId = 0;
243 }
244 
245 template <typename T>
247 {
248  std::swap(allocated, other.allocated);
249  std::swap(bufferId, other.bufferId);
250  std::swap(width, other.width);
251  std::swap(height, other.height);
252  return *this;
253 }
254 
255 template <typename T>
257 {
258  glDeleteBuffers(1, &bufferId); // ok to delete '0'
259 }
260 
261 template <typename T>
263 {
264  return bufferId != 0;
265 }
266 
267 template <typename T>
268 void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
269 {
270  width = width_;
271  height = height_;
272  if (bufferId != 0) {
273  bind();
274  // TODO make performance hint configurable?
275  glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
276  width * height * 4,
277  nullptr, // leave data undefined
278  GL_STREAM_DRAW); // performance hint
279  unbind();
280  } else {
281  allocated.resize(width * height);
282  }
283 }
284 
285 template <typename T>
287 {
288  if (bufferId != 0) {
289  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferId);
290  }
291 }
292 
293 template <typename T>
295 {
296  if (bufferId != 0) {
297  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
298  }
299 }
300 
301 template <typename T>
302 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
303 {
304  assert(x < width);
305  assert(y < height);
306  unsigned offset = x + width * y;
307  if (bufferId != 0) {
308  return static_cast<T*>(nullptr) + offset;
309  } else {
310  return &allocated[offset];
311  }
312 }
313 
314 template <typename T>
316 {
317  if (bufferId != 0) {
318  return reinterpret_cast<T*>(glMapBuffer(
319  GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY));
320  } else {
321  return allocated.data();
322  }
323 }
324 
325 template <typename T>
327 {
328  if (bufferId != 0) {
329  glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
330  }
331 }
332 
333 
334 
338 class Shader
339 {
340 public:
343  bool isOK() const;
344 
345 protected:
350  Shader(GLenum type, const std::string& filename);
351  Shader(GLenum type, const std::string& header,
352  const std::string& filename);
353  ~Shader();
354 
355 private:
356  void init(GLenum type, const std::string& header,
357  const std::string& filename);
358 
359  friend class ShaderProgram;
360 
361  GLuint handle;
362 };
363 
367 class VertexShader : public Shader
368 {
369 public:
373  explicit VertexShader(const std::string& filename);
374  VertexShader(const std::string& header, const std::string& filename);
375 };
376 
380 class FragmentShader : public Shader
381 {
382 public:
386  explicit FragmentShader(const std::string& filename);
387  FragmentShader(const std::string& header, const std::string& filename);
388 };
389 
394 {
395 public:
396  ShaderProgram(const ShaderProgram&) = delete;
397  ShaderProgram& operator=(const ShaderProgram&) = delete;
398 
401 
403  explicit ShaderProgram(Null) : handle(0) {}
404 
407 
409  void allocate();
410 
412  void reset();
413 
417  GLuint get() const { return handle; }
418 
422  bool isOK() const;
423 
426  void attach(const Shader& shader);
427 
431  void link();
432 
436  void bindAttribLocation(unsigned index, const char* name);
437 
442  GLint getUniformLocation(const char* name) const;
443 
447  void activate() const;
448 
449  void validate();
450 
451 private:
452  GLuint handle;
453 };
454 
456 {
457 public:
458  BufferObject();
459  ~BufferObject();
460  BufferObject(BufferObject&& other) noexcept
461  : bufferId(other.bufferId)
462  {
463  other.bufferId = 0;
464  }
465  BufferObject& operator=(BufferObject&& other) noexcept {
466  std::swap(bufferId, other.bufferId);
467  return *this;
468  }
469 
470  GLuint get() const { return bufferId; }
471 
472 private:
473  GLuint bufferId;
474 };
475 
476 } // namespace gl
477 
478 #endif // COMPONENT_GL
479 #endif // GLUTIL_HH
Shader(GLenum type, const std::string &filename)
Instantiates a shader.
Definition: GLUtil.cc:167
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:315
void allocate()
Allocate a shader program handle.
Definition: GLUtil.cc:257
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition: GLUtil.hh:406
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition: GLUtil.hh:380
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:119
void activate() const
Makes this program the active shader program.
Definition: GLUtil.cc:324
void allocate()
Allocate an openGL texture name.
Definition: GLUtil.cc:44
Most basic/generic texture: only contains a texture ID.
Definition: GLUtil.hh:35
BufferObject(BufferObject &&other) noexcept
Definition: GLUtil.hh:460
Texture(const Texture &)=delete
GLsizei getWidth() const
Definition: GLUtil.hh:106
Texture & operator=(const Texture &)=delete
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff...
Definition: GLUtil.hh:367
STL namespace.
ColorTexture()
Default constructor, zero-sized texture.
Definition: GLUtil.hh:98
ShaderProgram & operator=(const ShaderProgram &)=delete
ShaderProgram(Null)
Create null handler (don't yet allocate a openGL object).
Definition: GLUtil.hh:403
bool openGLSupported() const
Are PBOs supported by this openGL implementation? This class implements a SW fallback in case PBOs ar...
Definition: GLUtil.hh:262
void validate()
Definition: GLUtil.cc:330
FragmentShader(const std::string &filename)
Instantiates a fragment shader.
Definition: GLUtil.cc:244
void reset()
Release openGL texture name.
Definition: GLUtil.cc:49
bool isOK() const
Returns true iff this shader is loaded and compiled without errors.
Definition: GLUtil.cc:220
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:77
void attach(const Shader &shader)
Adds a given shader to this program.
Definition: GLUtil.cc:279
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:286
FrameBufferObject & operator=(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:124
Texture & operator=(Texture &&other) noexcept
Definition: GLUtil.hh:56
BufferObject & operator=(BufferObject &&other) noexcept
Definition: GLUtil.hh:465
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition: GLUtil.hh:400
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:268
Wrapper around a pixel buffer.
Definition: GLUtil.hh:149
void resize(GLsizei width, GLsizei height)
Definition: GLUtil.cc:79
void setInterpolation(bool interpolation)
Enable/disable bilinear interpolation for this texture.
Definition: GLUtil.cc:55
GLsizei getHeight() const
Definition: GLUtil.hh:107
static bool enabled
Global switch to disable pixel buffers using the "-nopbo" option.
Definition: GLUtil.hh:141
GLint getUniformLocation(const char *name) const
Gets a reference to a uniform variable declared in the shader source.
Definition: GLUtil.cc:316
void bindAttribLocation(unsigned index, const char *name)
Bind the given name for a vertex shader attribute to the given location.
Definition: GLUtil.cc:311
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition: GLUtil.hh:45
PixelBuffer & operator=(PixelBuffer &&other) noexcept
Definition: GLUtil.hh:246
void link()
Links all attached shaders together into one program.
Definition: GLUtil.cc:291
bool isOK() const
Returns true iff this program was linked without errors.
Definition: GLUtil.cc:271
GLuint textureId
Definition: GLUtil.hh:89
~Texture()
Release openGL texture name.
Definition: GLUtil.hh:48
VertexShader(const std::string &filename)
Instantiates a vertex shader.
Definition: GLUtil.cc:231
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:393
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:302
void setWrapMode(bool wrap)
Definition: GLUtil.cc:63
void reset()
Release the shader program handle.
Definition: GLUtil.cc:265
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition: GLUtil.hh:338
Definition: gl_mat.hh:23
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:294
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition: GLUtil.hh:51
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:326