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 //: public noncopyable
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  friend class FrameBufferObject;
85 };
86 
87 class ColorTexture : public Texture
88 {
89 public:
90  ColorTexture() : width(0), height(0) {}
91 
95  ColorTexture(GLsizei width, GLsizei height);
96  void resize(GLsizei width, GLsizei height);
97 
98  GLsizei getWidth () const { return width; }
99  GLsizei getHeight() const { return height; }
100 
101 private:
102  GLsizei width;
103  GLsizei height;
104 };
105 
106 class LuminanceTexture : public Texture
107 {
108 public:
112  LuminanceTexture(GLsizei width, GLsizei height);
113 
116  void updateImage(GLint x, GLint y,
117  GLsizei width, GLsizei height,
118  GLbyte* data);
119 };
120 
121 class FrameBufferObject //: public noncopyable
122 {
123 public:
125  explicit FrameBufferObject(Texture& texture);
127  : bufferId(other.bufferId)
128  {
129  other.bufferId = 0;
130  }
132  std::swap(bufferId, other.bufferId);
133  return *this;
134  }
136 
137  void push();
138  void pop();
139 
140 private:
141  GLuint bufferId;
142 };
143 
145 {
148  static bool enabled;
149 };
150 
156 template <typename T> class PixelBuffer //: public noncopyable
157 {
158 public:
159  PixelBuffer();
160  PixelBuffer(PixelBuffer&& other);
162  ~PixelBuffer();
163 
169  bool openGLSupported() const;
170 
175  void setImage(GLuint width, GLuint height);
176 
181  void bind() const;
182 
185  void unbind() const;
186 
193  T* getOffset(GLuint x, GLuint y);
194 
203  T* mapWrite();
204 
209  void unmap() const;
210 
211 private:
214  MemBuffer<T> allocated;
215 
218  GLuint bufferId;
219 
222  GLuint width;
223 
226  GLuint height;
227 };
228 
229 // class PixelBuffer
230 
231 template <typename T>
233 {
234 #ifdef GL_VERSION_1_5
235  if (PixelBuffers::enabled &&
236  GLEW_ARB_pixel_buffer_object) {
237  glGenBuffers(1, &bufferId);
238  } else
239 #endif
240  {
241  //std::cerr << "OpenGL pixel buffers are not available" << std::endl;
242  bufferId = 0;
243  }
244 }
245 
246 template <typename T>
248  : allocated(std::move(other.allocated))
249  , bufferId(other.bufferId)
250  , width(other.width)
251  , height(other.height)
252 {
253  other.bufferId = 0;
254 }
255 
256 template <typename T>
258 {
259  std::swap(allocated, other.allocated);
260  std::swap(bufferId, other.bufferId);
261  std::swap(width, other.width);
262  std::swap(height, other.height);
263  return *this;
264 }
265 
266 template <typename T>
268 {
269 #ifdef GL_VERSION_1_5
270  if (bufferId != 0) {
271  glDeleteBuffers(1, &bufferId);
272  }
273 #endif
274 }
275 
276 template <typename T>
278 {
279  return bufferId != 0;
280 }
281 
282 template <typename T>
283 void PixelBuffer<T>::setImage(GLuint width, GLuint height)
284 {
285  this->width = width;
286  this->height = height;
287 #ifdef GL_VERSION_1_5
288  if (bufferId != 0) {
289  bind();
290  // TODO make performance hint configurable?
291  glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
292  width * height * 4,
293  nullptr, // leave data undefined
294  GL_STREAM_DRAW); // performance hint
295  unbind();
296  } else
297 #endif
298  {
299  allocated.resize(width * height);
300  }
301 }
302 
303 template <typename T>
305 {
306 #ifdef GL_VERSION_1_5
307  if (bufferId != 0) {
308  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferId);
309  }
310 #endif
311 }
312 
313 template <typename T>
315 {
316 #ifdef GL_VERSION_1_5
317  if (bufferId != 0) {
318  glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
319  }
320 #endif
321 }
322 
323 template <typename T>
324 T* PixelBuffer<T>::getOffset(GLuint x, GLuint y)
325 {
326  assert(x < width);
327  assert(y < height);
328  unsigned offset = x + width * y;
329 #ifdef GL_VERSION_1_5
330  if (bufferId != 0) {
331  return static_cast<T*>(nullptr) + offset;
332  }
333 #endif
334  return &allocated[offset];
335 }
336 
337 template <typename T>
339 {
340 #ifdef GL_VERSION_1_5
341  if (bufferId != 0) {
342  return reinterpret_cast<T*>(glMapBuffer(
343  GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY));
344  }
345 #endif
346  return allocated.data();
347 }
348 
349 template <typename T>
351 {
352 #ifdef GL_VERSION_1_5
353  if (bufferId != 0) {
354  glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
355  }
356 #endif
357 }
358 
359 
360 
364 class Shader
365 {
366 public:
369  bool isOK() const;
370 
371 protected:
376  Shader(GLenum type, const std::string& filename);
377  Shader(GLenum type, const std::string& header,
378  const std::string& filename);
379  ~Shader();
380 
381 private:
382  void init(GLenum type, const std::string& header,
383  const std::string& filename);
384 
385  friend class ShaderProgram;
386 
387  GLuint handle;
388 };
389 
393 class VertexShader : public Shader
394 {
395 public:
399  explicit VertexShader(const std::string& filename);
400  VertexShader(const std::string& header, const std::string& filename);
401 };
402 
406 class FragmentShader : public Shader
407 {
408 public:
412  explicit FragmentShader(const std::string& filename);
413  FragmentShader(const std::string& header, const std::string& filename);
414 };
415 
420 {
421 public:
422  ShaderProgram();
423  ~ShaderProgram();
424 
428  bool isOK() const;
429 
432  void attach(const Shader& shader);
433 
437  void link();
438 
443  GLint getUniformLocation(const char* name) const;
444 
448  void activate() const;
449 
452  static void deactivate();
453 
454  void validate();
455 
456 private:
457  GLuint handle;
458 };
459 
460 } // namespace openmsx
461 
462 #endif // COMPONENT_GL
463 #endif // GLUTIL_HH