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 openmsx {
24 
25 namespace GLUtil {
26 
27 // TODO this needs glu, but atm we don't link against glu (in windows)
28 //void checkGLError(const std::string& prefix);
29 
30 } // namespace GLUtil
31 
32 
36 class Texture
37 {
38 public:
40  Texture();
41 
43  Texture(Texture&& other)
44  : textureId(other.textureId)
45  {
46  other.textureId = 0; // 0 is not a valid openGL texture name
47  }
49  std::swap(textureId, other.textureId);
50  return *this;
51  }
52 
54  ~Texture();
55 
61  void bind() {
62  glBindTexture(GL_TEXTURE_2D, textureId);
63  }
64 
67  void enableInterpolation();
68 
72  void disableInterpolation();
73 
74  void setWrapMode(bool wrap);
75 
78  void drawRect(GLfloat tx, GLfloat ty, GLfloat twidth, GLfloat theight,
79  GLint x, GLint y, GLint width, GLint height);
80 
81 protected:
82  GLuint textureId;
83 
84 private:
85  // Disable copy, assign.
86  Texture(const Texture&);
87  Texture& operator=(const Texture&);
88 
89  friend class FrameBufferObject;
90 };
91 
92 class ColorTexture : public Texture
93 {
94 public:
96  ColorTexture() : width(0), height(0) {}
97 
100  : Texture(std::move(other))
101  {
102  width = other.width;
103  height = other.height;
104  }
106  *this = std::move(other);
107  width = other.width;
108  height = other.height;
109  return *this;
110  }
111 
115  ColorTexture(GLsizei width, GLsizei height);
116  void resize(GLsizei width, GLsizei height);
117 
118  GLsizei getWidth () const { return width; }
119  GLsizei getHeight() const { return height; }
120 
121 private:
122  // Disable copy, assign.
123  ColorTexture(const ColorTexture&);
125 
126  GLsizei width;
127  GLsizei height;
128 };
129 
130 class LuminanceTexture : public Texture
131 {
132 public:
135  : Texture(std::move(other))
136  {
137  }
139  *this = std::move(other);
140  return *this;
141  }
142 
146  LuminanceTexture(GLsizei width, GLsizei height);
147 
150  void updateImage(GLint x, GLint y,
151  GLsizei width, GLsizei height,
152  GLbyte* data);
153 
154 private:
155  // Disable copy, assign.
158 };
159 
160 class FrameBufferObject //: public noncopyable
161 {
162 public:
164  explicit FrameBufferObject(Texture& texture);
166  : bufferId(other.bufferId)
167  {
168  other.bufferId = 0;
169  }
171  std::swap(bufferId, other.bufferId);
172  return *this;
173  }
175 
176  void push();
177  void pop();
178 
179 private:
180  GLuint bufferId;
181 };
182 
184 {
187  static bool enabled;
188 };
189 
195 template <typename T> class PixelBuffer //: public noncopyable
196 {
197 public:
198  PixelBuffer();
199  PixelBuffer(PixelBuffer&& other);
201  ~PixelBuffer();
202 
208  bool openGLSupported() const;
209 
214  void setImage(GLuint width, GLuint height);
215 
220  void bind() const;
221 
224  void unbind() const;
225 
232  T* getOffset(GLuint x, GLuint y);
233 
242  T* mapWrite();
243 
248  void unmap() const;
249 
250 private:
253  MemBuffer<T> allocated;
254 
257  GLuint bufferId;
258 
261  GLuint width;
262 
265  GLuint height;
266 };
267 
268 // class PixelBuffer
269 
270 template <typename T>
272 {
273  if (PixelBuffers::enabled && GLEW_ARB_pixel_buffer_object) {
274  glGenBuffers(1, &bufferId);
275  } else {
276  //std::cerr << "OpenGL pixel buffers are not available" << std::endl;
277  bufferId = 0;
278  }
279 }
280 
281 template <typename T>
283  : allocated(std::move(other.allocated))
284  , bufferId(other.bufferId)
285  , width(other.width)
286  , height(other.height)
287 {
288  other.bufferId = 0;
289 }
290 
291 template <typename T>
293 {
294  std::swap(allocated, other.allocated);
295  std::swap(bufferId, other.bufferId);
296  std::swap(width, other.width);
297  std::swap(height, other.height);
298  return *this;
299 }
300 
301 template <typename T>
303 {
304  glDeleteBuffers(1, &bufferId); // ok to delete '0'
305 }
306 
307 template <typename T>
309 {
310  return bufferId != 0;
311 }
312 
313 template <typename T>
314 void PixelBuffer<T>::setImage(GLuint width, GLuint height)
315 {
316  this->width = width;
317  this->height = height;
318  if (bufferId != 0) {
319  bind();
320  // TODO make performance hint configurable?
321  glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
322  width * height * 4,
323  nullptr, // leave data undefined
324  GL_STREAM_DRAW); // performance hint
325  unbind();
326  } else {
327  allocated.resize(width * height);
328  }
329 }
330 
331 template <typename T>
333 {
334  if (bufferId != 0) {
335  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferId);
336  }
337 }
338 
339 template <typename T>
341 {
342  if (bufferId != 0) {
343  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
344  }
345 }
346 
347 template <typename T>
348 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
349 {
350  assert(x < width);
351  assert(y < height);
352  unsigned offset = x + width * y;
353  if (bufferId != 0) {
354  return static_cast<T*>(nullptr) + offset;
355  } else {
356  return &allocated[offset];
357  }
358 }
359 
360 template <typename T>
362 {
363  if (bufferId != 0) {
364  return reinterpret_cast<T*>(glMapBuffer(
365  GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY));
366  } else {
367  return allocated.data();
368  }
369 }
370 
371 template <typename T>
373 {
374  if (bufferId != 0) {
375  glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
376  }
377 }
378 
379 
380 
384 class Shader
385 {
386 public:
389  bool isOK() const;
390 
391 protected:
396  Shader(GLenum type, const std::string& filename);
397  Shader(GLenum type, const std::string& header,
398  const std::string& filename);
399  ~Shader();
400 
401 private:
402  void init(GLenum type, const std::string& header,
403  const std::string& filename);
404 
405  friend class ShaderProgram;
406 
407  GLuint handle;
408 };
409 
413 class VertexShader : public Shader
414 {
415 public:
419  explicit VertexShader(const std::string& filename);
420  VertexShader(const std::string& header, const std::string& filename);
421 };
422 
426 class FragmentShader : public Shader
427 {
428 public:
432  explicit FragmentShader(const std::string& filename);
433  FragmentShader(const std::string& header, const std::string& filename);
434 };
435 
440 {
441 public:
442  ShaderProgram();
443  ~ShaderProgram();
444 
448  bool isOK() const;
449 
452  void attach(const Shader& shader);
453 
457  void link();
458 
463  GLint getUniformLocation(const char* name) const;
464 
468  void activate() const;
469 
472  static void deactivate();
473 
474  void validate();
475 
476 private:
477  GLuint handle;
478 };
479 
480 } // namespace openmsx
481 
482 #endif // COMPONENT_GL
483 #endif // GLUTIL_HH
signed char offset
Definition: CPUCore.cc:252
Wrapper around an OpenGL shader: a program executed on the GPU.
Definition: GLUtil.hh:384
VertexShader(const std::string &filename)
Instantiates a vertex shader.
Definition: GLUtil.cc:285
Wrapper around an OpenGL program: a collection of vertex and fragment shaders.
Definition: GLUtil.hh:439
Wrapper around an OpenGL fragment shader: a program executed on the GPU that computes the colors of p...
Definition: GLUtil.hh:426
void unbind() const
Unbind this buffer.
Definition: GLUtil.hh:340
Wrapper around an OpenGL vertex shader: a program executed on the GPU that computes per-vertex stuff...
Definition: GLUtil.hh:413
Texture()
Default constructor, allocate a openGL texture name.
Definition: GLUtil.cc:38
void drawRect(GLfloat tx, GLfloat ty, GLfloat twidth, GLfloat theight, GLint x, GLint y, GLint width, GLint height)
Draws this texture as a rectangle on the frame buffer.
Definition: GLUtil.cc:72
T * getOffset(GLuint x, GLuint y)
Gets a pointer relative to the start of this buffer.
Definition: GLUtil.hh:348
void activate() const
Makes this program the active shader program.
Definition: GLUtil.cc:383
bool openGLSupported() const
Are PBOs supported by this openGL implementation? This class implements a SW fallback in case PBOs ar...
Definition: GLUtil.hh:308
void link()
Links all attached shaders together into one program.
Definition: GLUtil.cc:346
LuminanceTexture(LuminanceTexture &&other)
Move constructor and assignment.
Definition: GLUtil.hh:134
bool isOK() const
Returns true iff this program was linked without errors.
Definition: GLUtil.cc:326
ColorTexture & operator=(ColorTexture &&other)
Definition: GLUtil.hh:105
GLint getUniformLocation(const char *name) const
Gets a reference to a uniform variable declared in the shader source.
Definition: GLUtil.cc:366
void disableInterpolation()
Disables bilinear interpolation for this texture and uses nearest neighbour instead.
Definition: GLUtil.cc:56
GLsizei getWidth() const
Definition: GLUtil.hh:118
void bind()
Makes this texture the active GL texture.
Definition: GLUtil.hh:61
void setImage(GLuint width, GLuint height)
Sets the image for this buffer.
Definition: GLUtil.hh:314
static void deactivate()
Deactivates all shader programs.
Definition: GLUtil.cc:388
Texture & operator=(Texture &&other)
Definition: GLUtil.hh:48
GLsizei getHeight() const
Definition: GLUtil.hh:119
FragmentShader(const std::string &filename)
Instantiates a fragment shader.
Definition: GLUtil.cc:298
void bind() const
Bind this PixelBuffer.
Definition: GLUtil.hh:332
void unmap() const
Unmaps the contents of this buffer.
Definition: GLUtil.hh:372
void updateImage(GLint x, GLint y, GLsizei width, GLsizei height, GLbyte *data)
Redefines (part of) the image for this texture.
Definition: GLUtil.cc:134
FrameBufferObject(FrameBufferObject &&other)
Definition: GLUtil.hh:165
T * mapWrite()
Maps the contents of this buffer into memory.
Definition: GLUtil.hh:361
void attach(const Shader &shader)
Adds a given shader to this program.
Definition: GLUtil.cc:334
ColorTexture()
Default constructor, zero-sized texture.
Definition: GLUtil.hh:96
PixelBuffer & operator=(PixelBuffer &&other)
Definition: GLUtil.hh:292
static bool enabled
Global switch to disable pixel buffers using the "-nopbo" option.
Definition: GLUtil.hh:187
Most basic/generic texture: only contains a texture ID.
Definition: GLUtil.hh:36
Shader(GLenum type, const std::string &filename)
Instantiates a shader.
Definition: GLUtil.cc:221
void resize(GLsizei width, GLsizei height)
Definition: GLUtil.cc:98
ColorTexture(ColorTexture &&other)
Move constructor and assignment.
Definition: GLUtil.hh:99
FrameBufferObject & operator=(FrameBufferObject &&other)
Definition: GLUtil.hh:170
Wrapper around a pixel buffer.
Definition: GLUtil.hh:195
bool isOK() const
Returns true iff this shader is loaded and compiled without errors.
Definition: GLUtil.cc:274
Texture(Texture &&other)
Move constructor and assignment.
Definition: GLUtil.hh:43
uint8_t * data()
void setWrapMode(bool wrap)
Definition: GLUtil.cc:63
void enableInterpolation()
Enables bilinear interpolation for this texture.
Definition: GLUtil.cc:49
Based on boost::noncopyable, see boost documentation: http://www.boost.org/libs/utility.
Definition: noncopyable.hh:12
GLuint textureId
Definition: GLUtil.hh:82
~Texture()
Release openGL texture name.
Definition: GLUtil.cc:44
LuminanceTexture & operator=(LuminanceTexture &&other)
Definition: GLUtil.hh:138