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  : width(0), height(0)
227 {
228  if (PixelBuffers::enabled && GLEW_ARB_pixel_buffer_object) {
229  glGenBuffers(1, &bufferId);
230  } else {
231  //std::cerr << "OpenGL pixel buffers are not available" << std::endl;
232  bufferId = 0;
233  }
234 }
235 
236 template <typename T>
238  : allocated(std::move(other.allocated))
239  , bufferId(other.bufferId)
240  , width(other.width)
241  , height(other.height)
242 {
243  other.bufferId = 0;
244 }
245 
246 template <typename T>
248 {
249  std::swap(allocated, other.allocated);
250  std::swap(bufferId, other.bufferId);
251  std::swap(width, other.width);
252  std::swap(height, other.height);
253  return *this;
254 }
255 
256 template <typename T>
258 {
259  glDeleteBuffers(1, &bufferId); // ok to delete '0'
260 }
261 
262 template <typename T>
264 {
265  return bufferId != 0;
266 }
267 
268 template <typename T>
269 void PixelBuffer<T>::setImage(GLuint width_, GLuint height_)
270 {
271  width = width_;
272  height = height_;
273  if (bufferId != 0) {
274  bind();
275  // TODO make performance hint configurable?
276  glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
277  width * height * 4,
278  nullptr, // leave data undefined
279  GL_STREAM_DRAW); // performance hint
280  unbind();
281  } else {
282  allocated.resize(width * height);
283  }
284 }
285 
286 template <typename T>
288 {
289  if (bufferId != 0) {
290  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferId);
291  }
292 }
293 
294 template <typename T>
296 {
297  if (bufferId != 0) {
298  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
299  }
300 }
301 
302 template <typename T>
303 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
304 {
305  assert(x < width);
306  assert(y < height);
307  unsigned offset = x + width * y;
308  if (bufferId != 0) {
309  return static_cast<T*>(nullptr) + offset;
310  } else {
311  return &allocated[offset];
312  }
313 }
314 
315 template <typename T>
317 {
318  if (bufferId != 0) {
319  return reinterpret_cast<T*>(glMapBuffer(
320  GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY));
321  } else {
322  return allocated.data();
323  }
324 }
325 
326 template <typename T>
328 {
329  if (bufferId != 0) {
330  glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
331  }
332 }
333 
334 
335 
339 class Shader
340 {
341 public:
344  bool isOK() const;
345 
346 protected:
351  Shader(GLenum type, const std::string& filename);
352  Shader(GLenum type, const std::string& header,
353  const std::string& filename);
354  ~Shader();
355 
356 private:
357  void init(GLenum type, const std::string& header,
358  const std::string& filename);
359 
360  friend class ShaderProgram;
361 
362  GLuint handle;
363 };
364 
368 class VertexShader : public Shader
369 {
370 public:
374  explicit VertexShader(const std::string& filename);
375  VertexShader(const std::string& header, const std::string& filename);
376 };
377 
381 class FragmentShader : public Shader
382 {
383 public:
387  explicit FragmentShader(const std::string& filename);
388  FragmentShader(const std::string& header, const std::string& filename);
389 };
390 
395 {
396 public:
397  ShaderProgram(const ShaderProgram&) = delete;
398  ShaderProgram& operator=(const ShaderProgram&) = delete;
399 
401  ShaderProgram() { allocate(); }
402 
404  explicit ShaderProgram(Null) : handle(0) {}
405 
407  ~ShaderProgram() { reset(); }
408 
410  void allocate();
411 
413  void reset();
414 
418  GLuint get() const { return handle; }
419 
423  bool isOK() const;
424 
427  void attach(const Shader& shader);
428 
432  void link();
433 
437  void bindAttribLocation(unsigned index, const char* name);
438 
443  GLint getUniformLocation(const char* name) const;
444 
448  void activate() const;
449 
450  void validate();
451 
452 private:
453  GLuint handle;
454 };
455 
457 {
458 public:
459  BufferObject();
460  ~BufferObject();
461  BufferObject(BufferObject&& other) noexcept
462  : bufferId(other.bufferId)
463  {
464  other.bufferId = 0;
465  }
466  BufferObject& operator=(BufferObject&& other) noexcept {
467  std::swap(bufferId, other.bufferId);
468  return *this;
469  }
470 
471  GLuint get() const { return bufferId; }
472 
473 private:
474  GLuint bufferId;
475 };
476 
477 } // namespace gl
478 
479 #endif // COMPONENT_GL
480 #endif // GLUTIL_HH
GLsizei getHeight() const
Definition: GLUtil.hh:107
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition: GLUtil.hh:407
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition: GLUtil.hh:381
FrameBufferObject(FrameBufferObject &&other) noexcept
Definition: GLUtil.hh:119
Most basic/generic texture: only contains a texture ID.
Definition: GLUtil.hh:35
BufferObject(BufferObject &&other) noexcept
Definition: GLUtil.hh:461
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff...
Definition: GLUtil.hh:368
ColorTexture()
Default constructor, zero-sized texture.
Definition: GLUtil.hh:98
ShaderProgram(Null)
Create null handler (don&#39;t yet allocate a openGL object).
Definition: GLUtil.hh:404
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:77
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:466
GLsizei getWidth() const
Definition: GLUtil.hh:106
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition: GLUtil.hh:401
Wrapper around a pixel buffer.
Definition: GLUtil.hh:149
static bool enabled
Global switch to disable pixel buffers using the "-nopbo" option.
Definition: GLUtil.hh:141
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition: GLUtil.hh:45
GLuint textureId
Definition: GLUtil.hh:89
~Texture()
Release openGL texture name.
Definition: GLUtil.hh:48
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:394
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition: GLUtil.hh:339
Definition: gl_mat.hh:24
Texture(Texture &&other) noexcept
Move constructor and assignment.
Definition: GLUtil.hh:51