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 "noncopyable.hh"
19 #include "build-info.hh"
20 #include <string>
21 #include <cassert>
22 
23 namespace gl {
24 
25 // TODO this needs glu, but atm we don't link against glu (in windows)
26 //void checkGLError(const std::string& prefix);
27 
28 
29 // Dummy object, to be able to construct empty handler objects.
30 struct Null {};
31 
32 
36 class Texture
37 {
38 public:
40  explicit Texture(bool interpolation = false, bool wrap = false);
41 
43  explicit Texture(Null) : textureId(0) {}
44 
46  ~Texture() { reset(); }
47 
49  Texture(Texture&& other)
50  : textureId(other.textureId)
51  {
52  other.textureId = 0; // 0 is not a valid openGL texture name
53  }
55  std::swap(textureId, other.textureId);
56  return *this;
57  }
58 
60  void allocate();
61 
63  void reset();
64 
68  GLuint get() const { return textureId; }
69 
75  void bind() {
76  glBindTexture(GL_TEXTURE_2D, textureId);
77  }
78 
82  void setInterpolation(bool interpolation);
83 
84  void setWrapMode(bool wrap);
85 
86 protected:
87  GLuint textureId;
88 
89 private:
90  // Disable copy, assign.
91  Texture(const Texture&);
92  Texture& operator=(const Texture&);
93 
94  friend class FrameBufferObject;
95 };
96 
97 class ColorTexture : public Texture
98 {
99 public:
101  ColorTexture() : width(0), height(0) {}
102 
105  : Texture(std::move(other))
106  {
107  width = other.width;
108  height = other.height;
109  }
111  *this = std::move(other);
112  width = other.width;
113  height = other.height;
114  return *this;
115  }
116 
120  ColorTexture(GLsizei width, GLsizei height);
121  void resize(GLsizei width, GLsizei height);
122 
123  GLsizei getWidth () const { return width; }
124  GLsizei getHeight() const { return height; }
125 
126 private:
127  // Disable copy, assign.
128  ColorTexture(const ColorTexture&);
130 
131  GLsizei width;
132  GLsizei height;
133 };
134 
135 class FrameBufferObject //: public noncopyable
136 {
137 public:
139  explicit FrameBufferObject(Texture& texture);
141  : bufferId(other.bufferId)
142  {
143  other.bufferId = 0;
144  }
146  std::swap(bufferId, other.bufferId);
147  return *this;
148  }
150 
151  void push();
152  void pop();
153 
154 private:
155  GLuint bufferId;
156 };
157 
159 {
162  static bool enabled;
163 };
164 
170 template <typename T> class PixelBuffer //: public noncopyable
171 {
172 public:
173  PixelBuffer();
174  PixelBuffer(PixelBuffer&& other);
176  ~PixelBuffer();
177 
183  bool openGLSupported() const;
184 
189  void setImage(GLuint width, GLuint height);
190 
195  void bind() const;
196 
199  void unbind() const;
200 
207  T* getOffset(GLuint x, GLuint y);
208 
217  T* mapWrite();
218 
223  void unmap() const;
224 
225 private:
228  openmsx::MemBuffer<T> allocated;
229 
232  GLuint bufferId;
233 
236  GLuint width;
237 
240  GLuint height;
241 };
242 
243 // class PixelBuffer
244 
245 template <typename T>
247 {
248  if (PixelBuffers::enabled && GLEW_ARB_pixel_buffer_object) {
249  glGenBuffers(1, &bufferId);
250  } else {
251  //std::cerr << "OpenGL pixel buffers are not available" << std::endl;
252  bufferId = 0;
253  }
254 }
255 
256 template <typename T>
258  : allocated(std::move(other.allocated))
259  , bufferId(other.bufferId)
260  , width(other.width)
261  , height(other.height)
262 {
263  other.bufferId = 0;
264 }
265 
266 template <typename T>
268 {
269  std::swap(allocated, other.allocated);
270  std::swap(bufferId, other.bufferId);
271  std::swap(width, other.width);
272  std::swap(height, other.height);
273  return *this;
274 }
275 
276 template <typename T>
278 {
279  glDeleteBuffers(1, &bufferId); // ok to delete '0'
280 }
281 
282 template <typename T>
284 {
285  return bufferId != 0;
286 }
287 
288 template <typename T>
289 void PixelBuffer<T>::setImage(GLuint width, GLuint height)
290 {
291  this->width = width;
292  this->height = height;
293  if (bufferId != 0) {
294  bind();
295  // TODO make performance hint configurable?
296  glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
297  width * height * 4,
298  nullptr, // leave data undefined
299  GL_STREAM_DRAW); // performance hint
300  unbind();
301  } else {
302  allocated.resize(width * height);
303  }
304 }
305 
306 template <typename T>
308 {
309  if (bufferId != 0) {
310  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferId);
311  }
312 }
313 
314 template <typename T>
316 {
317  if (bufferId != 0) {
318  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
319  }
320 }
321 
322 template <typename T>
323 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
324 {
325  assert(x < width);
326  assert(y < height);
327  unsigned offset = x + width * y;
328  if (bufferId != 0) {
329  return static_cast<T*>(nullptr) + offset;
330  } else {
331  return &allocated[offset];
332  }
333 }
334 
335 template <typename T>
337 {
338  if (bufferId != 0) {
339  return reinterpret_cast<T*>(glMapBuffer(
340  GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY));
341  } else {
342  return allocated.data();
343  }
344 }
345 
346 template <typename T>
348 {
349  if (bufferId != 0) {
350  glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
351  }
352 }
353 
354 
355 
359 class Shader
360 {
361 public:
364  bool isOK() const;
365 
366 protected:
371  Shader(GLenum type, const std::string& filename);
372  Shader(GLenum type, const std::string& header,
373  const std::string& filename);
374  ~Shader();
375 
376 private:
377  void init(GLenum type, const std::string& header,
378  const std::string& filename);
379 
380  friend class ShaderProgram;
381 
382  GLuint handle;
383 };
384 
388 class VertexShader : public Shader
389 {
390 public:
394  explicit VertexShader(const std::string& filename);
395  VertexShader(const std::string& header, const std::string& filename);
396 };
397 
401 class FragmentShader : public Shader
402 {
403 public:
407  explicit FragmentShader(const std::string& filename);
408  FragmentShader(const std::string& header, const std::string& filename);
409 };
410 
415 {
416 public:
419 
421  explicit ShaderProgram(Null) : handle(0) {}
422 
425 
427  void allocate();
428 
430  void reset();
431 
435  GLuint get() const { return handle; }
436 
440  bool isOK() const;
441 
444  void attach(const Shader& shader);
445 
449  void link();
450 
454  void bindAttribLocation(unsigned index, const char* name);
455 
460  GLint getUniformLocation(const char* name) const;
461 
465  void activate() const;
466 
467  void validate();
468 
469 private:
470  GLuint handle;
471 };
472 
473 class BufferObject //: public noncopyable
474 {
475 public:
476  BufferObject();
477  ~BufferObject();
479  : bufferId(other.bufferId)
480  {
481  other.bufferId = 0;
482  }
484  std::swap(bufferId, other.bufferId);
485  return *this;
486  }
487 
488  GLuint get() const { return bufferId; }
489 
490 private:
491  GLuint bufferId;
492 };
493 
494 } // namespace gl
495 
496 #endif // COMPONENT_GL
497 #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:336
signed char offset
Definition: CPUCore.cc:252
void allocate()
Allocate a shader program handle.
Definition: GLUtil.cc:257
~ShaderProgram()
Destroy handler object (release the underlying openGL object).
Definition: GLUtil.hh:424
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition: GLUtil.hh:401
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:36
GLsizei getWidth() const
Definition: GLUtil.hh:123
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff...
Definition: GLUtil.hh:388
ColorTexture()
Default constructor, zero-sized texture.
Definition: GLUtil.hh:101
FrameBufferObject(FrameBufferObject &&other)
Definition: GLUtil.hh:140
ShaderProgram(Null)
Create null handler (don't yet allocate a openGL object).
Definition: GLUtil.hh:421
bool openGLSupported() const
Are PBOs supported by this openGL implementation? This class implements a SW fallback in case PBOs ar...
Definition: GLUtil.hh:283
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:75
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:307
ColorTexture(ColorTexture &&other)
Move constructor and assignment.
Definition: GLUtil.hh:104
ShaderProgram()
Create handler and allocate underlying openGL object.
Definition: GLUtil.hh:418
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:289
Wrapper around a pixel buffer.
Definition: GLUtil.hh:170
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:124
static bool enabled
Global switch to disable pixel buffers using the "-nopbo" option.
Definition: GLUtil.hh:162
ColorTexture & operator=(ColorTexture &&other)
Definition: GLUtil.hh:110
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(bool interpolation=false, bool wrap=false)
Allocate a openGL texture name and enable/disable interpolation.
Definition: GLUtil.cc:37
Texture(Texture &&other)
Move constructor and assignment.
Definition: GLUtil.hh:49
Texture(Null)
Create null-handle (not yet allocate an openGL handle).
Definition: GLUtil.hh:43
Texture & operator=(Texture &&other)
Definition: GLUtil.hh:54
BufferObject & operator=(BufferObject &&other)
Definition: GLUtil.hh:483
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
FrameBufferObject & operator=(FrameBufferObject &&other)
Definition: GLUtil.hh:145
GLuint textureId
Definition: GLUtil.hh:87
~Texture()
Release openGL texture name.
Definition: GLUtil.hh:46
VertexShader(const std::string &filename)
Instantiates a vertex shader.
Definition: GLUtil.cc:231
BufferObject(BufferObject &&other)
Definition: GLUtil.hh:478
PixelBuffer & operator=(PixelBuffer &&other)
Definition: GLUtil.hh:267
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:414
Based on boost::noncopyable, see boost documentation: http://www.boost.org/libs/utility.
Definition: noncopyable.hh:12
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:323
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:359
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:315
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:347