opengl-core 1.0.1 → 1.2.0
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.
- checksums.yaml +4 -4
- data/ext/opengl-core/opengl_stub.c +10 -5
- data/lib/opengl-core.rb +21 -0
- data/lib/opengl-core/aux.rb +7 -0
- data/lib/opengl-core/aux/buffer.rb +44 -0
- data/lib/opengl-core/aux/gl.rb +238 -0
- data/lib/opengl-core/aux/marked.rb +66 -0
- data/lib/opengl-core/aux/program.rb +116 -0
- data/lib/opengl-core/aux/shader.rb +49 -0
- data/lib/opengl-core/aux/texture.rb +45 -0
- data/lib/opengl-core/aux/vertex_array.rb +43 -0
- data/lib/opengl-core/gl_commands.rb +6732 -4350
- data/lib/opengl-core/gl_enums.rb +1263 -19
- data/lib/opengl-core/gl_sym.rb +30 -5
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c407076d78ec2776bf4d930d623b95f2c761c70b
|
4
|
+
data.tar.gz: d4685fda0b7fa879b6de9a3bb3871b5fa4d077b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 998d1e941a7d72130eb9a45ee307694d247d28f2639e6dc30083b49edaf34ddb8d320a692197105e5c9668c04a3a21c77e00aa6cf3d8764574b0fdecadead5c9
|
7
|
+
data.tar.gz: 112b7d8abd9e5dc7620fdfb82b82f08a88b336e95fbbd80a2148c8136ebdfc428c0d21d2887031c11fc8bde533a5aa9743004d8351656598d030444b6f47123e
|
@@ -1,6 +1,7 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
|
3
3
|
|
4
|
+
/* @api private */
|
4
5
|
static VALUE plat_is_apple(VALUE self)
|
5
6
|
{
|
6
7
|
#if defined(__APPLE__)
|
@@ -11,6 +12,7 @@ static VALUE plat_is_apple(VALUE self)
|
|
11
12
|
}
|
12
13
|
|
13
14
|
|
15
|
+
/* @api private */
|
14
16
|
static VALUE plat_is_windows(VALUE self)
|
15
17
|
{
|
16
18
|
#if defined(_WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
|
@@ -21,6 +23,7 @@ static VALUE plat_is_windows(VALUE self)
|
|
21
23
|
}
|
22
24
|
|
23
25
|
|
26
|
+
/* @api private */
|
24
27
|
static VALUE plat_is_unix(VALUE self)
|
25
28
|
{
|
26
29
|
#if defined(__unix) || defined(__unix__) || defined(unix) || defined(__APPLE__)
|
@@ -31,6 +34,7 @@ static VALUE plat_is_unix(VALUE self)
|
|
31
34
|
}
|
32
35
|
|
33
36
|
|
37
|
+
/* @api private */
|
34
38
|
static VALUE plat_is_linux(VALUE self)
|
35
39
|
{
|
36
40
|
#if defined(__linux__) || defined(linux) || defined(__linux)
|
@@ -43,9 +47,10 @@ static VALUE plat_is_linux(VALUE self)
|
|
43
47
|
|
44
48
|
void Init_opengl_stub(void)
|
45
49
|
{
|
46
|
-
VALUE
|
47
|
-
|
48
|
-
rb_define_singleton_method(
|
49
|
-
rb_define_singleton_method(
|
50
|
-
rb_define_singleton_method(
|
50
|
+
VALUE gl_module = rb_define_module("Gl");
|
51
|
+
VALUE gl_sym_module = rb_define_module_under(gl_module, "GlSym");
|
52
|
+
rb_define_singleton_method(gl_sym_module, "apple?", plat_is_apple, 0);
|
53
|
+
rb_define_singleton_method(gl_sym_module, "windows?", plat_is_windows, 0);
|
54
|
+
rb_define_singleton_method(gl_sym_module, "unix?", plat_is_unix, 0);
|
55
|
+
rb_define_singleton_method(gl_sym_module, "linux?", plat_is_linux, 0);
|
51
56
|
}
|
data/lib/opengl-core.rb
CHANGED
@@ -4,4 +4,25 @@ require 'opengl-core/gl_enums'
|
|
4
4
|
require 'opengl-core/gl_commands'
|
5
5
|
|
6
6
|
module Gl
|
7
|
+
|
8
|
+
# Checks if a GL command is availalbe to use. This necessarily loads the
|
9
|
+
# command if it's not yet loaded just to check if it exists, so do not call
|
10
|
+
# this from multiple threads when other Gl commands are being loaded. If you
|
11
|
+
# want to ensure this only reads, you can call load_all_gl_commands! ahead of
|
12
|
+
# time and query it afterward.
|
13
|
+
def have_gl_command?(command)
|
14
|
+
!!GlSym.__load_gl_sym__(command.intern)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Does what it says on the tin. Should only be called once, preferably from
|
18
|
+
# the main thread, though I'm not aware of any thread requirements re: symbol
|
19
|
+
# loading. If you're using Gl commands from multiple threads with multiple
|
20
|
+
# contexts, you should call this before using any Gl commands.
|
21
|
+
def load_all_gl_commands!()
|
22
|
+
GlSym::GL_COMMAND_TYPES.each_key { |fnsym| GlSym.__load_gl_sym__(fnsym) }
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
extend self
|
27
|
+
|
7
28
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'opengl-core/aux/gl'
|
2
|
+
require 'opengl-core/aux/marked'
|
3
|
+
|
4
|
+
class Gl::Buffer < Gl::GlInternalMarked
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
attr_reader :target
|
8
|
+
|
9
|
+
def initialize(target, name = nil)
|
10
|
+
super()
|
11
|
+
@name = (name != 0 && name) || 0
|
12
|
+
@target = target
|
13
|
+
__mark__ if @name != 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete
|
17
|
+
if @name != 0
|
18
|
+
Gl.glDeleteBuffers(@name)
|
19
|
+
@name = 0
|
20
|
+
super
|
21
|
+
end
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def bind(target = nil)
|
26
|
+
if @name == 0
|
27
|
+
@name = Gl.glGenBuffers(1)[0]
|
28
|
+
__mark__
|
29
|
+
end
|
30
|
+
Gl.glBindBuffer(target || @target, @name)
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.unbind(target)
|
35
|
+
Gl.glBindBuffer(target, 0)
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def unbind(target = nil)
|
40
|
+
self.class.unbind(target || @target)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'opengl-core'
|
2
|
+
|
3
|
+
module Gl
|
4
|
+
|
5
|
+
# @api private
|
6
|
+
UINT_BASE = { :packed => [0].pack('I!').freeze, :unpack => 'I!*' }
|
7
|
+
UINT16_BASE = { :packed => [0].pack('S').freeze, :unpack => 'S*' }
|
8
|
+
UINT32_BASE = { :packed => [0].pack('L').freeze, :unpack => 'L*' }
|
9
|
+
UINT64_BASE = { :packed => [0].pack('Q').freeze, :unpack => 'Q*' }
|
10
|
+
INT_BASE = { :packed => [0].pack('i!').freeze, :unpack => 'i!*' }
|
11
|
+
INT16_BASE = { :packed => [0].pack('s').freeze, :unpack => 's*' }
|
12
|
+
INT32_BASE = { :packed => [0].pack('l').freeze, :unpack => 'l*' }
|
13
|
+
INT64_BASE = { :packed => [0].pack('q').freeze, :unpack => 'q*' }
|
14
|
+
USHORT_BASE = { :packed => [0].pack('S!').freeze, :unpack => 'S!*' }
|
15
|
+
SHORT_BASE = { :packed => [0].pack('s!').freeze, :unpack => 's!*' }
|
16
|
+
FLOAT_BASE = { :packed => [0.0].pack('F').freeze, :unpack => 'F*' }
|
17
|
+
DOUBLE_BASE = { :packed => [0.0].pack('D').freeze, :unpack => 'D*' }
|
18
|
+
POINTER_BASE = case Fiddle::SIZEOF_VOIDP
|
19
|
+
when 2 then { :packed => [0.0].pack('S').freeze, :unpack => 'S*' }
|
20
|
+
when 4 then { :packed => [0.0].pack('L').freeze, :unpack => 'L*' }
|
21
|
+
when 8 then { :packed => [0.0].pack('Q').freeze, :unpack => 'Q*' }
|
22
|
+
else raise "Pointer size is incompatible with opengl-core"
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
def self.__define_gl_gen_object_method__(name, type_base)
|
27
|
+
pack_string = type_base[:packed]
|
28
|
+
unpack_kind = type_base[:unpack]
|
29
|
+
|
30
|
+
self.module_exec(name, :"#{name}__", pack_string, unpack_kind) {
|
31
|
+
|func_name, raw_name, buffer_elem, pack_as|
|
32
|
+
define_method(func_name) {
|
33
|
+
|count|
|
34
|
+
output_buffer = buffer_elem * count
|
35
|
+
send(raw_name, count, output_buffer)
|
36
|
+
output_buffer.unpack(pack_as)
|
37
|
+
}
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
def self.__define_gl_delete_object_method__(name, type_base)
|
43
|
+
unpack_kind = type_base[:unpack]
|
44
|
+
|
45
|
+
self.module_exec(name, :"#{name}__", unpack_kind) {
|
46
|
+
|func_name, raw_name, pack_as|
|
47
|
+
define_method(func_name) {
|
48
|
+
|objects|
|
49
|
+
objects = [objects] unless objects.kind_of?(Array)
|
50
|
+
input_buffer = objects.pack(pack_as)
|
51
|
+
send(raw_name, objects.length, input_buffer)
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
def self.__define_gl_get_method__(name, type_base)
|
58
|
+
pack_string = type_base[:packed]
|
59
|
+
unpack_kind = type_base[:unpack]
|
60
|
+
|
61
|
+
self.module_exec(name, :"#{name}v__", pack_string, unpack_kind) {
|
62
|
+
|func_name, raw_name, buffer_elem, pack_as|
|
63
|
+
define_method(func_name) {
|
64
|
+
|pname|
|
65
|
+
output_buffer = String.new(buffer_elem)
|
66
|
+
send(raw_name, pname, output_buffer)
|
67
|
+
output_buffer.unpack(pack_as)[0]
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# @!method self.glGenTextures(count)
|
74
|
+
# Returns an array of generated texture names.
|
75
|
+
__define_gl_gen_object_method__ :glGenTextures, UINT_BASE
|
76
|
+
# @!method self.glDeleteTextures(count, objects)
|
77
|
+
__define_gl_delete_object_method__ :glDeleteTextures, UINT_BASE
|
78
|
+
|
79
|
+
# @!method self.glGenVertexArrays(count)
|
80
|
+
# Returns an array of generated vertex array object names.
|
81
|
+
__define_gl_gen_object_method__ :glGenVertexArrays, UINT_BASE
|
82
|
+
# @!method self.glDeleteVertexArrays(count, objects)
|
83
|
+
__define_gl_delete_object_method__ :glDeleteVertexArrays, UINT_BASE
|
84
|
+
|
85
|
+
# @!method self.glGenBuffers(count)
|
86
|
+
# Returns an array of generated buffer object names.
|
87
|
+
__define_gl_gen_object_method__ :glGenBuffers, UINT_BASE
|
88
|
+
# @!method self.glDeleteBuffers(count, objects)
|
89
|
+
__define_gl_delete_object_method__ :glDeleteBuffers, UINT_BASE
|
90
|
+
|
91
|
+
# @!method self.glGenQueries(count)
|
92
|
+
# Returns an array of generated query object names.
|
93
|
+
__define_gl_gen_object_method__ :glGenQueries, UINT_BASE
|
94
|
+
# @!method self.glDeleteQueries(count, objects)
|
95
|
+
__define_gl_delete_object_method__ :glDeleteQueries, UINT_BASE
|
96
|
+
|
97
|
+
# @!method self.glGenSamplers(count)
|
98
|
+
# Returns an array of generated sampler object names.
|
99
|
+
__define_gl_gen_object_method__ :glGenSamplers, UINT_BASE
|
100
|
+
# @!method self.glDeleteSamplers(count, objects)
|
101
|
+
__define_gl_delete_object_method__ :glDeleteSamplers, UINT_BASE
|
102
|
+
|
103
|
+
# @!method self.glGenFramebuffers(count)
|
104
|
+
# Returns an array of generated framebuffer object names.
|
105
|
+
__define_gl_gen_object_method__ :glGenFramebuffers, UINT_BASE
|
106
|
+
# @!method self.glDeleteFramebuffers(count, objects)
|
107
|
+
__define_gl_delete_object_method__ :glDeleteFramebuffers, UINT_BASE
|
108
|
+
|
109
|
+
# @!method self.glGenRenderbuffers(count)
|
110
|
+
# Returns an array of generated renderbuffer object names.
|
111
|
+
__define_gl_gen_object_method__ :glGenRenderbuffers, UINT_BASE
|
112
|
+
# @!method self.glDeleteRenderbuffers(count, objects)
|
113
|
+
__define_gl_delete_object_method__ :glDeleteRenderbuffers, UINT_BASE
|
114
|
+
|
115
|
+
# @!method self.glGenRenderbuffersProgramPipelines(count)
|
116
|
+
# Returns an array of generated program pipeline object names.
|
117
|
+
__define_gl_gen_object_method__ :glGenProgramPipelines, UINT_BASE
|
118
|
+
# @!method self.glDeleteRenderbuffersProgramPipelines(count, objects)
|
119
|
+
__define_gl_delete_object_method__ :glDeleteProgramPipelines, UINT_BASE
|
120
|
+
|
121
|
+
# @!method self.glGenRenderbuffersTrasnformFeedbacks(count)
|
122
|
+
# Returns an array of generated transform feedback objects
|
123
|
+
__define_gl_gen_object_method__ :glGenTransformFeedbacks, UINT_BASE
|
124
|
+
# @!method self.glDeleteRenderbuffersTrasnformFeedbacks(count, objects)
|
125
|
+
__define_gl_delete_object_method__ :glDeleteTransformFeedbacks, UINT_BASE
|
126
|
+
|
127
|
+
__define_gl_get_method__ :glGetInteger, UINT_BASE
|
128
|
+
__define_gl_get_method__ :glGetInteger64, INT64_BASE
|
129
|
+
__define_gl_get_method__ :glGetFloat, FLOAT_BASE
|
130
|
+
__define_gl_get_method__ :glGetDouble, DOUBLE_BASE
|
131
|
+
|
132
|
+
# @return [Boolean] Returns the boolean value of the given parameter name.
|
133
|
+
def glGetBoolean(pname)
|
134
|
+
buffer = '0'
|
135
|
+
glGetBooleanv(pname, buffer)
|
136
|
+
!!buffer.unpack('C')[0]
|
137
|
+
end
|
138
|
+
|
139
|
+
# @return [String] Returns the string value of the given parameter name.
|
140
|
+
def glGetString(name)
|
141
|
+
glGetString__(name).to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
# @return [String] Returns the string value of a parameter name at a given index.
|
145
|
+
def glGetStringi(name, index)
|
146
|
+
glGetStringi__(name, index).to_s
|
147
|
+
end
|
148
|
+
|
149
|
+
def glVertexAttribPointer(index, size, type, normalized, stride, offset)
|
150
|
+
offset = case offset
|
151
|
+
when Fiddle::Pointer then offset
|
152
|
+
when Numeric then Fiddle::Pointer.new(offset)
|
153
|
+
else offset
|
154
|
+
end
|
155
|
+
glVertexAttribPointer__ index, size, type, normalized, stride, offset
|
156
|
+
end
|
157
|
+
|
158
|
+
def glShaderSource(shader, sources)
|
159
|
+
sources = [sources] unless sources.kind_of?(Array)
|
160
|
+
source_lengths = sources.map { |s| s.bytesize }.pack('i*')
|
161
|
+
source_pointers = sources.pack('p')
|
162
|
+
glShaderSource__(shader, sources.length, source_pointers, source_lengths)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns the version or release number. Calls glGetString.
|
166
|
+
def gl_version()
|
167
|
+
glGetString(GL_VERSION)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the implementation vendor. Calls glGetString.
|
171
|
+
def gl_vendor()
|
172
|
+
glGetString(GL_VENDOR)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns the renderer. Calls glGetString.
|
176
|
+
def gl_renderer()
|
177
|
+
glGetString(GL_RENDERER)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Returns the shading language version. Calls glGetString.
|
181
|
+
def gl_shading_language_version()
|
182
|
+
glGetString(GL_SHADING_LANGUAGE_VERSION)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Gets an array of GL extensions. This calls glGetIntegerv and glGetStringi,
|
186
|
+
# so be aware that you should probably cache the results.
|
187
|
+
def gl_extensions()
|
188
|
+
(0 ... glGetInteger(GL_NUM_EXTENSIONS)).map { |index| glGetStringi(GL_EXTENSIONS, index) }
|
189
|
+
end
|
190
|
+
|
191
|
+
def glGetShader(shader, pname)
|
192
|
+
base = String.new(INT_BASE[:packed])
|
193
|
+
glGetShaderiv__(shader, pname, base)
|
194
|
+
base.unpack(INT_BASE[:unpack])[0]
|
195
|
+
end
|
196
|
+
|
197
|
+
def glGetShaderInfoLog(shader)
|
198
|
+
length = glGetShader(shader, GL_INFO_LOG_LENGTH)
|
199
|
+
return '' if length == 0
|
200
|
+
output = ' ' * length
|
201
|
+
glGetShaderInfoLog__(shader, output.bytesize, 0, output)
|
202
|
+
output
|
203
|
+
end
|
204
|
+
|
205
|
+
def glGetShaderSource(shader)
|
206
|
+
length = glGetShader(shader, GL_SHADER_SOURCE_LENGTH)
|
207
|
+
return '' if length == 0
|
208
|
+
output = ' ' * length
|
209
|
+
glGetShaderInfoLog__(shader, output.bytesize, 0, output)
|
210
|
+
output
|
211
|
+
end
|
212
|
+
|
213
|
+
def glGetProgram(program, pname)
|
214
|
+
base = String.new(INT_BASE[:packed])
|
215
|
+
glGetProgramiv__(program, pname, base)
|
216
|
+
base.unpack(INT_BASE[:unpack])[0]
|
217
|
+
end
|
218
|
+
|
219
|
+
def glGetProgramInfoLog(program)
|
220
|
+
length = glGetProgram(program, GL_INFO_LOG_LENGTH)
|
221
|
+
return '' if length == 0
|
222
|
+
output = ' ' * length
|
223
|
+
glGetProgramInfoLog__(program, output.bytesize, 0, output)
|
224
|
+
output
|
225
|
+
end
|
226
|
+
|
227
|
+
def glGetProgramBinary(program)
|
228
|
+
binary_length = glGetProgram(program, GL_PROGRAM_BINARY_LENGTH)
|
229
|
+
return [nil, nil] if binary_length == 0
|
230
|
+
format_buffer = String.new(UINT_BASE[:packed])
|
231
|
+
binary_buffer = ' ' * binary_length
|
232
|
+
glGetProgramBinary(program, binary_buffer.bytesize, 0, format_buffer, binary_buffer)
|
233
|
+
[format_buffer.unpack(UINT_BASE[:unpack])[0], binary_buffer]
|
234
|
+
end
|
235
|
+
|
236
|
+
extend self
|
237
|
+
|
238
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Gl ; end
|
2
|
+
|
3
|
+
class Gl::GlInternalMarked
|
4
|
+
|
5
|
+
@@allocated__ = {}
|
6
|
+
|
7
|
+
def ==(other)
|
8
|
+
(self.kind_of?(other.class) || other.kind_of?(self.class)) && (self.name == other.name)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Should be overridden by subclasses to handle freeing resources when marked.
|
12
|
+
# If unmarked, should be a no-op.
|
13
|
+
def delete
|
14
|
+
__unmark__
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
# Deletes all objects of the given type. Should be used carefully if at all.
|
19
|
+
def self.delete_all
|
20
|
+
__marked_allocated__.keys.each { |marked| marked.delete }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Clears all marked objects. If deletion is already guaranteed for all marked
|
24
|
+
# objects, you may use this to let all marked objects of this type get GC'd.
|
25
|
+
def self.clear_all
|
26
|
+
__marked_allocated__.clear
|
27
|
+
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
# Marks the class to prevent it from being garbage collected.
|
31
|
+
def __mark__
|
32
|
+
self.class.__marked_allocated__[self] = true
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
# Unmarks the class and allows it to be garbage collected.
|
37
|
+
def __unmark__
|
38
|
+
self.class.__marked_allocated__.delete(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
# Returns whether the object is currently marked to keep it from being GC'd.
|
43
|
+
def marked?
|
44
|
+
self.class.__marked_allocated__.include?(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @api private
|
48
|
+
# Allocates a hash for the subclass. This will be done regardless of whether
|
49
|
+
# this function is called.
|
50
|
+
def self.inherited(subclass)
|
51
|
+
@@allocated__[subclass] = @@allocated__[subclass] || {}
|
52
|
+
end
|
53
|
+
|
54
|
+
# @api private
|
55
|
+
# Returns a Hash of marked objects.
|
56
|
+
def self.__marked_allocated__
|
57
|
+
(@@allocated__[self.class] || (@@allocated__[self.class] = {}))
|
58
|
+
end
|
59
|
+
|
60
|
+
# @api private
|
61
|
+
# Returns all allocated marked objects for this class.
|
62
|
+
def self.allocated
|
63
|
+
__marked_allocated__.keys
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'opengl-core/aux/gl'
|
2
|
+
require 'opengl-core/aux/marked'
|
3
|
+
|
4
|
+
# Needed even if the class isn't actually used
|
5
|
+
class Gl::Shader ; end
|
6
|
+
|
7
|
+
class Gl::Program < Gl::GlInternalMarked
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :kind
|
11
|
+
|
12
|
+
def initialize(name = nil)
|
13
|
+
super()
|
14
|
+
@name = (name != 0 && name) || Gl.glCreateProgram()
|
15
|
+
@validate_status = nil
|
16
|
+
@link_status = nil
|
17
|
+
@uniform_locations = {}
|
18
|
+
__mark__
|
19
|
+
end
|
20
|
+
|
21
|
+
def load_binary(binary_format, binary_string)
|
22
|
+
Gl.glProgramBinary(@name, binary_format, binary_string, binary_string.bytesize)
|
23
|
+
@link_status = nil
|
24
|
+
__reload_uniforms__ if (link_successful = linked?)
|
25
|
+
link_successful
|
26
|
+
end
|
27
|
+
|
28
|
+
def binary
|
29
|
+
Gl.glGetProgramBinary(@name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete
|
33
|
+
if @name != 0
|
34
|
+
Gl.glDeleteProgram(@name)
|
35
|
+
@name = 0
|
36
|
+
super
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def __reload_uniforms__
|
42
|
+
@uniform_locations.keys.each {
|
43
|
+
|key|
|
44
|
+
@uniform_locations[key] = uniform_location(key)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def link
|
49
|
+
Gl.glLinkProgram(@name)
|
50
|
+
@link_status = nil
|
51
|
+
__reload_uniforms__ if (link_successful = linked?)
|
52
|
+
link_successful
|
53
|
+
end
|
54
|
+
|
55
|
+
def linked?
|
56
|
+
@link_status = (!@link_status.nil? && @link_status) ||
|
57
|
+
Gl.glGetProgram(@name, Gl::GL_LINK_STATUS) == GL_TRUE
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate
|
61
|
+
Gl.glValidateProgram(@name)
|
62
|
+
@validate_status = nil
|
63
|
+
valid?
|
64
|
+
end
|
65
|
+
|
66
|
+
def valid?
|
67
|
+
@validate_status = (!@validate_status.nil? && @validate_status) ||
|
68
|
+
Gl.glGetProgram(@name, Gl::GL_VALIDATE_STATUS) == GL_TRUE
|
69
|
+
end
|
70
|
+
|
71
|
+
def info_log
|
72
|
+
Gl.glGetProgramInfoLog(@name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def use
|
76
|
+
Gl.glUseProgram(@name)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def attach_shader(shader)
|
81
|
+
case shader
|
82
|
+
when ::Gl::Shader then Gl.glAttachShader(@name, shader.name)
|
83
|
+
else Gl.glAttachShader(@name, shader)
|
84
|
+
end
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def hint_uniform(uniform_name)
|
89
|
+
@uniform_locations[uniform_name.to_sym] =
|
90
|
+
(@uniform_locations[uniform_name.to_sym] || -1)
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
def uniform_location(uniform_name)
|
95
|
+
uniform_sym = uniform_name.to_sym
|
96
|
+
@uniform_locations[uniform_sym] ||
|
97
|
+
(@uniform_locations[uniform_sym] =
|
98
|
+
Gl.glGetUniformLocation(@name, uniform_name.to_s))
|
99
|
+
end
|
100
|
+
alias_method :[], :uniform_location
|
101
|
+
|
102
|
+
def subroutine_uniform_location(shader_kind, uniform_name)
|
103
|
+
Gl.glGetSubroutineUniformLocation(@name, shader_kind, uniform_name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def bind_attrib_location(attrib_index, attrib_name)
|
107
|
+
Gl.glBindAttribLocation(@name, attrib_index, attrib_name.to_s)
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def bind_frag_data_location(color_number, frag_data_name)
|
112
|
+
Gl.glBindFragDataLocation(@name, color_number, frag_data_name.to_s)
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|