rays 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.doc/ext/rays/bitmap.cpp +70 -233
  3. data/.doc/ext/rays/bounds.cpp +339 -57
  4. data/.doc/ext/rays/color.cpp +58 -48
  5. data/.doc/ext/rays/color_space.cpp +174 -0
  6. data/.doc/ext/rays/font.cpp +31 -53
  7. data/.doc/ext/rays/image.cpp +64 -67
  8. data/.doc/ext/rays/matrix.cpp +22 -50
  9. data/.doc/ext/rays/native.cpp +9 -2
  10. data/.doc/ext/rays/painter.cpp +276 -259
  11. data/.doc/ext/rays/point.cpp +186 -52
  12. data/.doc/ext/rays/rays.cpp +25 -20
  13. data/.doc/ext/rays/shader.cpp +61 -0
  14. data/.doc/ext/rays/texture.cpp +47 -59
  15. data/{README → README.md} +0 -0
  16. data/Rakefile +6 -5
  17. data/VERSION +1 -1
  18. data/ext/rays/bitmap.cpp +88 -248
  19. data/ext/rays/bounds.cpp +437 -141
  20. data/ext/rays/color.cpp +79 -69
  21. data/ext/rays/color_space.cpp +185 -0
  22. data/ext/rays/extconf.rb +14 -63
  23. data/ext/rays/font.cpp +44 -65
  24. data/ext/rays/image.cpp +82 -81
  25. data/ext/rays/matrix.cpp +32 -60
  26. data/ext/rays/native.cpp +9 -2
  27. data/ext/rays/painter.cpp +345 -321
  28. data/ext/rays/point.cpp +212 -69
  29. data/ext/rays/rays.cpp +29 -23
  30. data/ext/rays/shader.cpp +63 -0
  31. data/ext/rays/texture.cpp +64 -74
  32. data/include/rays/bitmap.h +21 -12
  33. data/include/rays/bounds.h +67 -9
  34. data/include/rays/color.h +23 -7
  35. data/include/rays/{colorspace.h → color_space.h} +6 -3
  36. data/include/rays/exception.h +17 -11
  37. data/include/rays/font.h +4 -3
  38. data/include/rays/image.h +11 -6
  39. data/include/rays/matrix.h +15 -12
  40. data/include/rays/opengl.h +54 -1
  41. data/include/rays/painter.h +98 -108
  42. data/include/rays/point.h +45 -5
  43. data/include/rays/rays.h +2 -2
  44. data/include/rays/ruby/bitmap.h +2 -16
  45. data/include/rays/ruby/bounds.h +4 -16
  46. data/include/rays/ruby/color.h +3 -16
  47. data/include/rays/ruby/color_space.h +27 -0
  48. data/include/rays/ruby/font.h +2 -16
  49. data/include/rays/ruby/image.h +2 -16
  50. data/include/rays/ruby/matrix.h +2 -16
  51. data/include/rays/ruby/painter.h +2 -16
  52. data/include/rays/ruby/point.h +3 -16
  53. data/include/rays/ruby/shader.h +27 -0
  54. data/include/rays/ruby/texture.h +2 -16
  55. data/include/rays/ruby.h +1 -0
  56. data/include/rays/shader.h +48 -0
  57. data/include/rays/texture.h +13 -2
  58. data/include/rays.h +2 -1
  59. data/lib/rays/bitmap.rb +20 -11
  60. data/lib/rays/bounds.rb +29 -68
  61. data/lib/rays/color.rb +39 -0
  62. data/lib/rays/color_space.rb +33 -0
  63. data/lib/rays/font.rb +29 -0
  64. data/lib/rays/image.rb +22 -0
  65. data/lib/rays/module.rb +11 -7
  66. data/lib/rays/painter.rb +103 -40
  67. data/lib/rays/point.rb +19 -36
  68. data/lib/rays/shader.rb +13 -0
  69. data/lib/rays/texture.rb +9 -0
  70. data/lib/rays.rb +4 -0
  71. data/rays.gemspec +3 -4
  72. data/src/bounds.cpp +272 -63
  73. data/src/color.cpp +168 -21
  74. data/src/{colorspace.cpp → color_space.cpp} +38 -1
  75. data/src/exception.cpp +24 -15
  76. data/src/frame_buffer.cpp +275 -0
  77. data/src/frame_buffer.h +79 -0
  78. data/src/image.cpp +80 -36
  79. data/src/ios/bitmap.mm +340 -0
  80. data/src/ios/font.mm +206 -0
  81. data/src/{cocoa → ios}/helper.h +2 -2
  82. data/src/{cocoa → ios}/helper.mm +0 -0
  83. data/src/ios/opengl.mm +21 -0
  84. data/src/ios/program.cpp +122 -0
  85. data/src/{cocoa → ios}/rays.mm +8 -7
  86. data/src/matrix.cpp +10 -22
  87. data/src/opengl.cpp +64 -0
  88. data/src/{cocoa → osx}/bitmap.mm +121 -70
  89. data/src/{cocoa → osx}/font.mm +32 -24
  90. data/src/osx/helper.h +26 -0
  91. data/src/osx/helper.mm +25 -0
  92. data/src/osx/opengl.mm +103 -0
  93. data/src/osx/rays.mm +43 -0
  94. data/src/painter.cpp +596 -422
  95. data/src/point.cpp +154 -11
  96. data/src/program.cpp +513 -0
  97. data/src/program.h +73 -0
  98. data/src/render_buffer.cpp +120 -0
  99. data/src/render_buffer.h +47 -0
  100. data/src/shader.cpp +117 -0
  101. data/src/texture.cpp +104 -134
  102. data/test/helper.rb +10 -3
  103. data/test/test_bitmap.rb +18 -0
  104. data/test/test_bounds.rb +81 -35
  105. data/test/test_color.rb +29 -2
  106. data/test/test_image.rb +63 -0
  107. data/test/test_painter.rb +120 -0
  108. data/test/test_point.rb +30 -9
  109. data/test/test_shader.rb +37 -0
  110. data/test/test_texture.rb +18 -0
  111. metadata +75 -58
  112. data/.gitignore +0 -14
  113. data/ChangeLog +0 -8
data/src/point.cpp CHANGED
@@ -1,18 +1,22 @@
1
1
  #include "rays/point.h"
2
2
 
3
3
 
4
+ #include <xot/string.h>
5
+ #include "rays/exception.h"
6
+
7
+
4
8
  namespace Rays
5
9
  {
6
10
 
7
11
 
8
12
  Point::Point (coord value)
9
13
  {
10
- set(value);
14
+ reset(value);
11
15
  }
12
16
 
13
17
  Point::Point (coord x, coord y, coord z)
14
18
  {
15
- set(x, y, z);
19
+ reset(x, y, z);
16
20
  }
17
21
 
18
22
  Point
@@ -22,13 +26,13 @@ namespace Rays
22
26
  }
23
27
 
24
28
  Point&
25
- Point::set (coord value)
29
+ Point::reset (coord value)
26
30
  {
27
- return set(value, value, 0);
31
+ return reset(value, value, 0);
28
32
  }
29
33
 
30
34
  Point&
31
- Point::set (coord x, coord y, coord z)
35
+ Point::reset (coord x, coord y, coord z)
32
36
  {
33
37
  this->x = x;
34
38
  this->y = y;
@@ -36,16 +40,155 @@ namespace Rays
36
40
  return *this;
37
41
  }
38
42
 
39
- coord*
40
- Point::array ()
43
+ Point&
44
+ Point::move_to (coord x, coord y, coord z)
45
+ {
46
+ return reset(x, y, z);
47
+ }
48
+
49
+ Point&
50
+ Point::move_to (const Point& point)
51
+ {
52
+ return reset(point.x, point.y, point.z);
53
+ }
54
+
55
+ Point&
56
+ Point::move_by (coord x, coord y, coord z)
57
+ {
58
+ return reset(this->x + x, this->y + y, this->z + z);
59
+ }
60
+
61
+ Point&
62
+ Point::move_by (const Point& point)
41
63
  {
42
- return (coord*) this;
64
+ return reset(this->x + point.x, this->y + point.y, this->z + point.z);
65
+ }
66
+
67
+ String
68
+ Point::inspect () const
69
+ {
70
+ return Xot::stringf("x=%f y=%f z=%f", x, y, z);
71
+ }
72
+
73
+ coord&
74
+ Point::operator [] (size_t index)
75
+ {
76
+ if (index >= 3)
77
+ argument_error(__FILE__, __LINE__);
78
+
79
+ return array[index];
80
+ }
81
+
82
+ const coord&
83
+ Point::operator [] (size_t index) const
84
+ {
85
+ return const_cast<Point*>(this)->operator[](index);
86
+ }
87
+
88
+ Point
89
+ Point::operator - () const
90
+ {
91
+ return Point(-x, -y, -z);
92
+ }
93
+
94
+ Point&
95
+ Point::operator += (const Point& rhs)
96
+ {
97
+ x += rhs.x;
98
+ y += rhs.y;
99
+ z += rhs.z;
100
+ return *this;
101
+ }
102
+
103
+ Point&
104
+ Point::operator -= (const Point& rhs)
105
+ {
106
+ x -= rhs.x;
107
+ y -= rhs.y;
108
+ z -= rhs.z;
109
+ return *this;
43
110
  }
44
111
 
45
- const coord*
46
- Point::array () const
112
+ Point&
113
+ Point::operator *= (const Point& rhs)
114
+ {
115
+ x *= rhs.x;
116
+ y *= rhs.y;
117
+ z *= rhs.z;
118
+ return *this;
119
+ }
120
+
121
+ Point&
122
+ Point::operator /= (const Point& rhs)
123
+ {
124
+ x /= rhs.x;
125
+ y /= rhs.y;
126
+ z /= rhs.z;
127
+ return *this;
128
+ }
129
+
130
+ Point&
131
+ Point::operator /= (coord rhs)
132
+ {
133
+ x /= rhs;
134
+ y /= rhs;
135
+ z /= rhs;
136
+ return *this;
137
+ }
138
+
139
+ bool
140
+ operator == (const Point& lhs, const Point& rhs)
141
+ {
142
+ return
143
+ lhs.x == rhs.x &&
144
+ lhs.y == rhs.y &&
145
+ lhs.z == rhs.z;
146
+ }
147
+
148
+ bool
149
+ operator != (const Point& lhs, const Point& rhs)
150
+ {
151
+ return !operator==(lhs, rhs);
152
+ }
153
+
154
+ Point
155
+ operator + (const Point& lhs, const Point& rhs)
156
+ {
157
+ Point t = lhs;
158
+ t += rhs;
159
+ return t;
160
+ }
161
+
162
+ Point
163
+ operator - (const Point& lhs, const Point& rhs)
164
+ {
165
+ Point t = lhs;
166
+ t -= rhs;
167
+ return t;
168
+ }
169
+
170
+ Point
171
+ operator * (const Point& lhs, const Point& rhs)
172
+ {
173
+ Point t = lhs;
174
+ t *= rhs;
175
+ return t;
176
+ }
177
+
178
+ Point
179
+ operator / (const Point& lhs, const Point& rhs)
180
+ {
181
+ Point t = lhs;
182
+ t /= rhs;
183
+ return t;
184
+ }
185
+
186
+ Point
187
+ operator / (const Point& lhs, coord rhs)
47
188
  {
48
- return const_cast<Point*>(this)->array();
189
+ Point t = lhs;
190
+ t /= rhs;
191
+ return t;
49
192
  }
50
193
 
51
194
 
data/src/program.cpp ADDED
@@ -0,0 +1,513 @@
1
+ #include "program.h"
2
+
3
+
4
+ #include <vector>
5
+ #include <algorithm>
6
+ #include <boost/scoped_ptr.hpp>
7
+ #include <boost/scoped_array.hpp>
8
+ #include "rays/exception.h"
9
+ #include "rays/shader.h"
10
+
11
+
12
+ namespace Rays
13
+ {
14
+
15
+
16
+ class UniformValue
17
+ {
18
+
19
+ public:
20
+
21
+ virtual ~UniformValue () {}
22
+
23
+ virtual void apply (GLint location) const =0;
24
+
25
+ };// UniformValue
26
+
27
+
28
+ template <typename T, int DIMENSION>
29
+ class UniformValueT : public UniformValue
30
+ {
31
+
32
+ public:
33
+
34
+ UniformValueT (T arg1)
35
+ {
36
+ assert(DIMENSION == 1);
37
+ array[0] = arg1;
38
+ }
39
+
40
+ UniformValueT (T arg1, T arg2)
41
+ {
42
+ assert(DIMENSION == 2);
43
+ array[0] = arg1;
44
+ array[1] = arg2;
45
+ }
46
+
47
+ UniformValueT (T arg1, T arg2, T arg3)
48
+ {
49
+ assert(DIMENSION == 3);
50
+ array[0] = arg1;
51
+ array[1] = arg2;
52
+ array[2] = arg3;
53
+ }
54
+
55
+ UniformValueT (T arg1, T arg2, T arg3, T arg4)
56
+ {
57
+ assert(DIMENSION == 4);
58
+ array[0] = arg1;
59
+ array[1] = arg2;
60
+ array[2] = arg3;
61
+ array[3] = arg4;
62
+ }
63
+
64
+ UniformValueT (const T* args, size_t size)
65
+ {
66
+ assert(size == DIMENSION);
67
+ for (size_t i = 0; i < size; ++i)
68
+ array[i] = args[i];
69
+ }
70
+
71
+ void apply (GLint location) const;
72
+
73
+ private:
74
+
75
+ T array[DIMENSION];
76
+
77
+ };// UniformValueT
78
+
79
+
80
+ template <> void UniformValueT<int, 1>::apply (GLint location) const {glUniform1iv(location, 1, array);}
81
+
82
+ template <> void UniformValueT<int, 2>::apply (GLint location) const {glUniform2iv(location, 1, array);}
83
+
84
+ template <> void UniformValueT<int, 3>::apply (GLint location) const {glUniform3iv(location, 1, array);}
85
+
86
+ template <> void UniformValueT<int, 4>::apply (GLint location) const {glUniform4iv(location, 1, array);}
87
+
88
+ template <> void UniformValueT<float, 1>::apply (GLint location) const {glUniform1fv(location, 1, array);}
89
+
90
+ template <> void UniformValueT<float, 2>::apply (GLint location) const {glUniform2fv(location, 1, array);}
91
+
92
+ template <> void UniformValueT<float, 3>::apply (GLint location) const {glUniform3fv(location, 1, array);}
93
+
94
+ template <> void UniformValueT<float, 4>::apply (GLint location) const {glUniform4fv(location, 1, array);}
95
+
96
+
97
+ struct Uniform
98
+ {
99
+
100
+ struct Data
101
+ {
102
+
103
+ String name;
104
+
105
+ boost::scoped_ptr<const UniformValue> value;
106
+
107
+ };// Data
108
+
109
+ Xot::PImpl<Data, true> self;
110
+
111
+ Uniform (const char* name, const UniformValue* value)
112
+ {
113
+ if (!name || !value || name[0] == '\0')
114
+ argument_error(__FILE__, __LINE__);
115
+
116
+ self->name = name;
117
+ self->value.reset(value);
118
+ }
119
+
120
+ void apply (GLuint program) const
121
+ {
122
+ GLint location = glGetUniformLocation(program, self->name);
123
+ if (location < 0) return;
124
+
125
+ self->value->apply(location);
126
+ check_error(__FILE__, __LINE__);
127
+ }
128
+
129
+ bool operator == (const Uniform& rhs) const
130
+ {
131
+ return self.get() == rhs.self.get();
132
+ }
133
+
134
+ bool operator != (const Uniform& rhs) const
135
+ {
136
+ return !operator==(rhs);
137
+ }
138
+
139
+ };// Uniform
140
+
141
+
142
+ typedef std::vector<Shader> ShaderList;
143
+
144
+ typedef std::vector<ShaderList> ShaderStack;
145
+
146
+ typedef std::vector<Uniform> UniformList;
147
+
148
+ typedef std::vector<UniformList> UniformStack;
149
+
150
+
151
+ struct Program::Data
152
+ {
153
+
154
+ int id;
155
+
156
+ ShaderStack shader_stack;
157
+
158
+ UniformStack uniform_stack;
159
+
160
+ bool need_link, using_;
161
+
162
+ Data ()
163
+ : id(-1), need_link(false), using_(false)
164
+ {
165
+ shader_stack.push_back(ShaderList());
166
+ uniform_stack.push_back(UniformList());
167
+ }
168
+
169
+ ~Data ()
170
+ {
171
+ clear();
172
+ }
173
+
174
+ void create ()
175
+ {
176
+ if (is_valid())
177
+ invalid_state_error(__FILE__, __LINE__, "program is already created.");
178
+
179
+ id = glCreateProgram();
180
+ }
181
+
182
+ void clear ()
183
+ {
184
+ if (shader_stack.size() != 1 || uniform_stack.size() != 1)
185
+ invalid_state_error(__FILE__, __LINE__, "stack state is invalid.");
186
+
187
+ ShaderList& list = shader_stack.back();
188
+ for (ShaderList::iterator it = list.begin(); it != list.end(); ++it)
189
+ detach(*it);
190
+
191
+ if (id >= 0) glDeleteProgram((GLuint) id);
192
+
193
+ id = -1;
194
+ }
195
+
196
+ void attach (const Shader& shader)
197
+ {
198
+ if (!is_valid()) create();
199
+
200
+ ShaderList& list = shader_stack.back();
201
+ ShaderList::iterator it = std::find(list.begin(), list.end(), shader);
202
+ if (it != list.end()) return;
203
+
204
+ glAttachShader(id, shader.id());
205
+ check_error(__FILE__, __LINE__);
206
+
207
+ list.push_back(shader);
208
+ need_link = true;
209
+ }
210
+
211
+ void detach (const Shader& shader)
212
+ {
213
+ ShaderList& list = shader_stack.back();
214
+ ShaderList::iterator it = std::find(list.begin(), list.end(), shader);
215
+ if (it == list.end())
216
+ rays_error(__FILE__, __LINE__, "shader is not attached.");
217
+
218
+ glDetachShader(id, shader.id());
219
+ check_error(__FILE__, __LINE__);
220
+
221
+ list.erase(it);
222
+ need_link = true;
223
+ }
224
+
225
+ void set_uniform (const char* name, const UniformValue* value)
226
+ {
227
+ if (uniform_stack.empty())
228
+ invalid_state_error(__FILE__, __LINE__);
229
+
230
+ UniformList& list = uniform_stack.back();
231
+ std::remove_if(list.begin(), list.end(), UniformNameEqualFun(name));
232
+ list.push_back(Uniform(name, value));
233
+
234
+ if (using_) list.back().apply(id);
235
+ }
236
+
237
+ void update (bool uniforms = true)
238
+ {
239
+ link();
240
+
241
+ use(!shader_stack.back().empty());
242
+ if (using_ && uniforms) apply_all_uniforms();
243
+ }
244
+
245
+ bool is_valid () const
246
+ {
247
+ return id >= 0;
248
+ }
249
+
250
+ private:
251
+
252
+ void link ()
253
+ {
254
+ if (!need_link) return;
255
+
256
+ glLinkProgram(id);
257
+
258
+ GLint status = GL_FALSE;
259
+ glGetProgramiv(id, GL_LINK_STATUS, &status);
260
+ if (status == GL_FALSE)
261
+ {
262
+ int len = 0;
263
+ glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len);
264
+
265
+ boost::scoped_array<char> buffer(new char[len]);
266
+ int written = 0;
267
+ glGetProgramInfoLog(id, len, &written, &buffer[0]);
268
+
269
+ opengl_error(__FILE__, __LINE__, &buffer[0]);
270
+ }
271
+
272
+ check_error(__FILE__, __LINE__);
273
+
274
+ need_link = false;
275
+ }
276
+
277
+ void use (bool state)
278
+ {
279
+ if (state == using_) return;
280
+
281
+ glUseProgram(state ? id : 0);
282
+ using_ = state;
283
+ }
284
+
285
+ void apply_all_uniforms ()
286
+ {
287
+ if (uniform_stack.empty())
288
+ invalid_state_error(__FILE__, __LINE__);
289
+
290
+ UniformList& list = uniform_stack.back();
291
+ for (UniformList::iterator it = list.begin(); it != list.end(); ++it)
292
+ it->apply(id);
293
+ }
294
+
295
+ struct UniformNameEqualFun
296
+ {
297
+
298
+ String name;
299
+
300
+ UniformNameEqualFun (const char* name)
301
+ : name(name)
302
+ {
303
+ }
304
+
305
+ bool operator () (const Uniform& uniform) const
306
+ {
307
+ return uniform.self->name == name;
308
+ }
309
+
310
+ };// UniformNameEqualFun
311
+
312
+ };// Program::Data
313
+
314
+
315
+ Program::Program ()
316
+ {
317
+ }
318
+
319
+ Program::~Program ()
320
+ {
321
+ }
322
+
323
+ void
324
+ Program::attach (const Shader& shader)
325
+ {
326
+ self->attach(shader);
327
+ self->update();
328
+ }
329
+
330
+ void
331
+ Program::detach (const Shader& shader)
332
+ {
333
+ if (!*this)
334
+ invalid_state_error(__FILE__, __LINE__);
335
+
336
+ self->detach(shader);
337
+ self->update(false);
338
+ }
339
+
340
+ void
341
+ Program::set_uniform (const char* name, int arg1)
342
+ {
343
+ self->set_uniform(name, new UniformValueT<int, 1>(arg1));
344
+ }
345
+
346
+ void
347
+ Program::set_uniform (const char* name, int arg1, int arg2)
348
+ {
349
+ self->set_uniform(name, new UniformValueT<int, 2>(arg1, arg2));
350
+ }
351
+
352
+ void
353
+ Program::set_uniform (const char* name, int arg1, int arg2, int arg3)
354
+ {
355
+ self->set_uniform(name, new UniformValueT<int, 3>(arg1, arg2, arg3));
356
+ }
357
+
358
+ void
359
+ Program::set_uniform (const char* name, int arg1, int arg2, int arg3, int arg4)
360
+ {
361
+ self->set_uniform(name, new UniformValueT<int, 4>(arg1, arg2, arg3, arg4));
362
+ }
363
+
364
+ void
365
+ Program::set_uniform (const char* name, const int* args, size_t size)
366
+ {
367
+ UniformValue* value = NULL;
368
+ switch (size)
369
+ {
370
+ case 1: value = new UniformValueT<int, 1>(args, 1); break;
371
+ case 2: value = new UniformValueT<int, 2>(args, 2); break;
372
+ case 3: value = new UniformValueT<int, 3>(args, 3); break;
373
+ case 4: value = new UniformValueT<int, 4>(args, 4); break;
374
+ }
375
+
376
+ if (value == NULL)
377
+ argument_error(__FILE__, __LINE__, "invalid 'size' value.");
378
+
379
+ self->set_uniform(name, value);
380
+ }
381
+
382
+ void
383
+ Program::set_uniform (const char* name, float arg1)
384
+ {
385
+ self->set_uniform(name, new UniformValueT<float, 1>(arg1));
386
+ }
387
+
388
+ void
389
+ Program::set_uniform (const char* name, float arg1, float arg2)
390
+ {
391
+ self->set_uniform(name, new UniformValueT<float, 2>(arg1, arg2));
392
+ }
393
+
394
+ void
395
+ Program::set_uniform (const char* name, float arg1, float arg2, float arg3)
396
+ {
397
+ self->set_uniform(name, new UniformValueT<float, 3>(arg1, arg2, arg3));
398
+ }
399
+
400
+ void
401
+ Program::set_uniform (const char* name, float arg1, float arg2, float arg3, float arg4)
402
+ {
403
+ self->set_uniform(name, new UniformValueT<float, 4>(arg1, arg2, arg3, arg4));
404
+ }
405
+
406
+ void
407
+ Program::set_uniform (const char* name, const float* args, size_t size)
408
+ {
409
+ UniformValue* value = NULL;
410
+ switch (size)
411
+ {
412
+ case 1: value = new UniformValueT<float, 1>(args, 1); break;
413
+ case 2: value = new UniformValueT<float, 2>(args, 2); break;
414
+ case 3: value = new UniformValueT<float, 3>(args, 3); break;
415
+ case 4: value = new UniformValueT<float, 4>(args, 4); break;
416
+ }
417
+
418
+ if (value == NULL)
419
+ argument_error(__FILE__, __LINE__, "invalid 'size' value.");
420
+
421
+ self->set_uniform(name, value);
422
+ }
423
+
424
+ void
425
+ Program::push ()
426
+ {
427
+ self->shader_stack.push_back(self->shader_stack.back());
428
+ self->uniform_stack.push_back(self->uniform_stack.back());
429
+ }
430
+
431
+ static void
432
+ pop_shader_stack (Program::Data* self)
433
+ {
434
+ if (!self)
435
+ argument_error(__FILE__, __LINE__);
436
+
437
+ if (self->shader_stack.size() < 2)
438
+ invalid_state_error(__FILE__, __LINE__, "shader stack underflow.");
439
+
440
+ size_t size = self->shader_stack.size();
441
+ ShaderList& prev = self->shader_stack[size - 1];
442
+ ShaderList& next = self->shader_stack[size - 2];
443
+
444
+ ShaderList::iterator prev_end = prev.end();
445
+ ShaderList::iterator next_end = next.end();
446
+
447
+ for (ShaderList::iterator it = prev.begin(); it != prev_end; ++it)
448
+ {
449
+ ShaderList::iterator found = std::find(next.begin(), next_end, *it);
450
+ if (found == next_end) self->detach(*it);
451
+ }
452
+
453
+ for (ShaderList::iterator it = next.begin(); it != next_end; ++it)
454
+ {
455
+ ShaderList::iterator found = std::find(prev.begin(), prev_end, *it);
456
+ if (found == prev_end) self->attach(*it);
457
+ }
458
+
459
+ self->shader_stack.pop_back();
460
+ }
461
+
462
+ static void
463
+ pop_uniform_stack (Program::Data* self)
464
+ {
465
+ if (!self)
466
+ argument_error(__FILE__, __LINE__);
467
+
468
+ if (self->uniform_stack.size() < 2)
469
+ invalid_state_error(__FILE__, __LINE__, "uniform stack underflow.");
470
+
471
+ size_t size = self->uniform_stack.size();
472
+ UniformList& prev = self->uniform_stack[size - 1];
473
+ UniformList& next = self->uniform_stack[size - 2];
474
+
475
+ UniformList::iterator prev_end = prev.end();
476
+ UniformList::iterator next_end = next.end();
477
+
478
+ for (UniformList::iterator it = next.begin(); it != next_end; ++it)
479
+ {
480
+ UniformList::iterator found = std::find(prev.begin(), prev_end, *it);
481
+ if (found == prev_end) it->apply(self->id);
482
+ }
483
+
484
+ self->uniform_stack.pop_back();
485
+ }
486
+
487
+ void
488
+ Program::pop ()
489
+ {
490
+ pop_shader_stack(self.get());
491
+ pop_uniform_stack(self.get());
492
+ self->update();
493
+ }
494
+
495
+ GLuint
496
+ Program::id () const
497
+ {
498
+ return self->id;
499
+ }
500
+
501
+ Program::operator bool () const
502
+ {
503
+ return self->is_valid();
504
+ }
505
+
506
+ bool
507
+ Program::operator ! () const
508
+ {
509
+ return !operator bool();
510
+ }
511
+
512
+
513
+ }// Rays