opengl-core 1.0.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|