opengl-registry 1.0.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 +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +6 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/Rakefile +3 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/opengl/registry.rb +318 -0
- data/lib/opengl/registry/argument.rb +60 -0
- data/lib/opengl/registry/enum.rb +64 -0
- data/lib/opengl/registry/extension.rb +23 -0
- data/lib/opengl/registry/feature.rb +48 -0
- data/lib/opengl/registry/feature_group.rb +38 -0
- data/lib/opengl/registry/feature_provider.rb +45 -0
- data/lib/opengl/registry/function.rb +86 -0
- data/lib/opengl/registry/group.rb +62 -0
- data/lib/opengl/registry/native_type.rb +59 -0
- data/lib/opengl/registry/token.rb +29 -0
- data/lib/opengl/registry/version.rb +10 -0
- data/lib/opengl/registry/words.rb +39 -0
- data/lib/opengl/spec.rb +176 -0
- data/opengl-registry.gemspec +37 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 140b56969d6bf604555783463786f8c26cf5df295867117030082ea8ea554569
|
4
|
+
data.tar.gz: 0e4416074336ef92dca0946b188fb2afbfa19b40046aa054a73f47bfda269a11
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 50fa00baa919c7556ce6b4628be3d5c3ec0a0938770c083519939276d247925ddc5e0b0f6c1802b6b72e373b84bab0bd3c20c0ed2e9b44ae6da5d87b61949efc
|
7
|
+
data.tar.gz: 7415697ad77a33c8148d9a1fb97fe97a59e79f154e3704b84593a7fa4fe9faac0894d2237c8ee236b915e8ff99ad2639796b2a29d9ca40a567c1c0c68ffdb206
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 ForeverZer0
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# OpenGL Registry
|
2
|
+
|
3
|
+
Parses the Khronos OpenGL registry into a standardized and user-friendly data structure that can be walked through, providing an essential need for tools that generate code to create an OpenGL wrapper/bindings, for any language. Given an API name, version, and profile, is capable of filtering and grouping data structures that cover that specific subset of definitions, using a typical Ruby object-oriented approach.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'opengl-registry'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install opengl-registry
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
#### Get the OpenGL Registry from Khronos
|
24
|
+
|
25
|
+
You can either download the latest copy of [gl.xml](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/gl.xml) directly from the [Khronos repo](https://github.com/KhronosGroup/OpenGL-Registry/tree/master/), or fetch it through the API.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'opengl-registry'
|
29
|
+
|
30
|
+
GL::Registry.download('/path/to/save/gl.xml')
|
31
|
+
```
|
32
|
+
|
33
|
+
For successive runs, you can simply check that the version you have is up to date.
|
34
|
+
```ruby
|
35
|
+
if GL::Registry.outdated?('/path/to/gl.xml')
|
36
|
+
# Download updated copy
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
#### Create a Registry instance
|
41
|
+
|
42
|
+
First step is to create the registry, which is essentially a container that stores every definition defined for OpenGL, OpenGLES (Embedded Systems), and OpenGLSC (Security Critical).
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
registry = GL::Registry.load('/path/to/gl.xml')
|
46
|
+
```
|
47
|
+
|
48
|
+
Alternatively, if you have the XML as a string...
|
49
|
+
```ruby
|
50
|
+
registry = GL::Registry.parse(xml_string)
|
51
|
+
```
|
52
|
+
|
53
|
+
#### Create the OpenGL specification you wish to target
|
54
|
+
|
55
|
+
In order to filter results and definitions by a subset of the API, version, profile, etc, create a new spec.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
extensions = ['GL_ARB_get_program_binary', 'GL_ARB_texture_storage']
|
59
|
+
spec = GL::Spec.new(registry, :gl, 3.3, :core, extensions)
|
60
|
+
```
|
61
|
+
|
62
|
+
The created `spec` object can be then used to enumerate through every definition that this subset defines. The data will automatically be filtered and sorted, allowing for easy inspection of each entity.
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
spec.functions.each do |function|
|
66
|
+
# Print out the function name and return type
|
67
|
+
puts "#{function.name} (#{function.type})"
|
68
|
+
|
69
|
+
# Loop through argument definitions
|
70
|
+
function.arguments.each do |argument|
|
71
|
+
puts " #{argument.name} (#{argument.type})"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
spec.enums.each do |enum|
|
76
|
+
# Enums also define "groups" for creating C-style enumeration types, etc
|
77
|
+
puts "#{enum.name} = #{enum.value}"
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
There are many helper functions throughout for detailed filtering, and retrieving any relevant information that might be required, such as generating bindings for a particular language, etc. See the [documentation](https://www.rubydoc.info/gems/opengl-registry/1.0.0) for more details.
|
82
|
+
|
83
|
+
## License
|
84
|
+
|
85
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "opengl/registry"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ox'
|
4
|
+
require 'net/http'
|
5
|
+
require 'json'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
require_relative 'registry/version'
|
10
|
+
require_relative 'registry/words'
|
11
|
+
require_relative 'registry/token'
|
12
|
+
require_relative 'registry/native_type'
|
13
|
+
require_relative 'registry/group'
|
14
|
+
require_relative 'registry/enum'
|
15
|
+
require_relative 'registry/argument'
|
16
|
+
require_relative 'registry/function'
|
17
|
+
require_relative 'registry/feature_provider'
|
18
|
+
require_relative 'registry/feature'
|
19
|
+
require_relative 'registry/feature_group'
|
20
|
+
require_relative 'registry/extension'
|
21
|
+
require_relative 'spec'
|
22
|
+
|
23
|
+
##
|
24
|
+
# Top-level namespace.
|
25
|
+
#
|
26
|
+
# @author Eric "ForeverZer0" Freed
|
27
|
+
module GL
|
28
|
+
|
29
|
+
##
|
30
|
+
# Container for all definitions of the OpenGL registry.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
#
|
34
|
+
# # Check if registry XML file is up to data
|
35
|
+
# if GL::Registry.outdated?('gl.xml')
|
36
|
+
# GL::Registry.download('gl.xml')
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# registry = GL::Registry.load('gl.xml')
|
40
|
+
# spec = GL::Spec.new(registry, :gl, 3.3, :core)
|
41
|
+
#
|
42
|
+
# # Use "spec" object to enumerate over detailed objects defining each token
|
43
|
+
#
|
44
|
+
class Registry
|
45
|
+
|
46
|
+
##
|
47
|
+
# An array of OpenGL type names, as symbols.
|
48
|
+
GL_TYPES = %i[
|
49
|
+
GLenum GLboolean GLbitfield GLvoid GLbyte GLubyte GLshort GLushort GLint
|
50
|
+
GLuint GLclampx GLsizei GLfloat GLclampf GLdouble GLclampd
|
51
|
+
GLeglClientBufferEXT GLeglImageOES GLchar GLhandleARB GLhalf GLhalfARB
|
52
|
+
GLfixed GLintptr GLintptrARB GLsizeiptr GLsizeiptrARB GLint64 GLint64EXT
|
53
|
+
GLuint64 GLuint64EXT GLsync struct\ _cl_context struct\ _cl_event
|
54
|
+
GLDEBUGPROC GLDEBUGPROCARB GLDEBUGPROCKHR GLDEBUGPROCAMD GLhalfNV
|
55
|
+
GLvdpauSurfaceNV GLVULKANPROCNV
|
56
|
+
].freeze
|
57
|
+
|
58
|
+
##
|
59
|
+
# @return [Array<Group>] a collection of all enumeration groups defined by OpenGL.
|
60
|
+
# @note This is for reference only, and should not be used for building definitions or determining a comprehensive
|
61
|
+
# list of which enum values belong in each group, use the {Enum#groups} property instead.
|
62
|
+
attr_reader :groups
|
63
|
+
|
64
|
+
##
|
65
|
+
# @return [Array<Function>] a complete collection of all OpenGL functions.
|
66
|
+
attr_reader :functions
|
67
|
+
|
68
|
+
##
|
69
|
+
# @!attribute [r] enums
|
70
|
+
# @return [Array<Enum>] a complete collection of all OpenGL enum values.
|
71
|
+
|
72
|
+
##
|
73
|
+
# @return [Array<FeatureGroup>] a complete collection of all OpenGL feature groups.
|
74
|
+
attr_reader :features
|
75
|
+
|
76
|
+
##
|
77
|
+
# @return [Array<Extension>] a complete collection of all OpenGL extensions.
|
78
|
+
attr_reader :extensions
|
79
|
+
|
80
|
+
##
|
81
|
+
# Creates a new {Registry} from the specified XML file.
|
82
|
+
#
|
83
|
+
# @param path [String] The path to the registry file.
|
84
|
+
#
|
85
|
+
# @return [Registry] a newly created and parsed {Registry}.
|
86
|
+
def self.load(path)
|
87
|
+
doc = Ox.load_file(path, mode: :generic)
|
88
|
+
new(doc.root)
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Creates a new {Registry} from the specified XML string.
|
93
|
+
#
|
94
|
+
# @param xml [String] The OpenGL registry as an XML string.
|
95
|
+
#
|
96
|
+
# @return [Registry] a newly created and parsed {Registry}.
|
97
|
+
def self.parse(xml)
|
98
|
+
doc = Ox.load(xml, mode: :generic)
|
99
|
+
new(doc.root)
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# @return [Array<Symbol>] an array of Symbol objects that represent each defined API in the registry.
|
104
|
+
def api_names
|
105
|
+
# RubyMine warns that the return value is wrong. It lies.
|
106
|
+
#noinspection RubyYardReturnMatch
|
107
|
+
@features.map(&:api).uniq
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Retrieves an array of profiles defined in the registry.
|
112
|
+
#
|
113
|
+
# @overload profiles
|
114
|
+
#
|
115
|
+
# @overload profiles(api)
|
116
|
+
# @param api [Symbol] An API to limit results to a specific API.
|
117
|
+
#
|
118
|
+
# @overload profiles(api, version)
|
119
|
+
# @param api [Symbol] An API to limit results to a specific API.
|
120
|
+
# @param version [String|Float] A version to limit results to.
|
121
|
+
#
|
122
|
+
# @return [Array<Symbol>] an array of defined profiles.
|
123
|
+
def profiles(api = nil, version = '1.0')
|
124
|
+
# RubyMine warns that the return value is wrong. It lies.
|
125
|
+
if api
|
126
|
+
values = @features.find_all { |group| group.api == api && group.version <= version.to_s }
|
127
|
+
#noinspection RubyYardReturnMatch
|
128
|
+
return values.flat_map(&:additions).map(&:profile).uniq
|
129
|
+
end
|
130
|
+
#noinspection RubyYardReturnMatch
|
131
|
+
@features.flat_map(&:additions).map(&:profile).uniq
|
132
|
+
end
|
133
|
+
|
134
|
+
def enums
|
135
|
+
#noinspection RubyResolve
|
136
|
+
@enums ||= each_enum.to_a
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
# Enumerates through each enum defined in the registry.
|
141
|
+
#
|
142
|
+
# @overload each_enum
|
143
|
+
# When called without a block, returns an Enumerator.
|
144
|
+
# @return [Enumerator] An enum enumerator.
|
145
|
+
#
|
146
|
+
# @overload each_enum(&block)
|
147
|
+
# When called with a block, yields each item to the block and returns `nil`.
|
148
|
+
# @yieldparam enum [Enum] Yields an enum to the block.
|
149
|
+
# @return [void]
|
150
|
+
def each_enum
|
151
|
+
#noinspection RubyYardReturnMatch
|
152
|
+
return enum_for(__method__) unless block_given?
|
153
|
+
@groups.each do |group|
|
154
|
+
group.members.each { |item| yield item }
|
155
|
+
end
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
|
159
|
+
##
|
160
|
+
# Enumerates through each group defined in the registry.
|
161
|
+
#
|
162
|
+
# @overload each_group
|
163
|
+
# When called without a block, returns an Enumerator.
|
164
|
+
# @return [Enumerator] A group enumerator.
|
165
|
+
#
|
166
|
+
# @overload each_group(&block)
|
167
|
+
# When called with a block, yields each item to the block and returns `nil`.
|
168
|
+
# @yieldparam group [Group] Yields a group to the block.
|
169
|
+
# @return [void]
|
170
|
+
def each_group
|
171
|
+
#noinspection RubyYardReturnMatch
|
172
|
+
return enum_for(__method__) unless block_given?
|
173
|
+
@groups.each { |item| yield item }
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# Enumerates through each function defined in the registry.
|
179
|
+
#
|
180
|
+
# @overload each_function
|
181
|
+
# When called without a block, returns an Enumerator.
|
182
|
+
# @return [Enumerator] A function enumerator.
|
183
|
+
#
|
184
|
+
# @overload each_function(&block)
|
185
|
+
# When called with a block, yields each item to the block and returns `nil`.
|
186
|
+
# @yieldparam enum [Function] Yields a function to the block.
|
187
|
+
# @return [void]
|
188
|
+
def each_function
|
189
|
+
#noinspection RubyYardReturnMatch
|
190
|
+
return enum_for(__method__) unless block_given?
|
191
|
+
@functions.each { |item| yield item }
|
192
|
+
nil
|
193
|
+
end
|
194
|
+
|
195
|
+
##
|
196
|
+
# Enumerates through each feature group defined in the registry.
|
197
|
+
#
|
198
|
+
# @overload each_feature
|
199
|
+
# When called without a block, returns an Enumerator.
|
200
|
+
# @return [Enumerator] A feature group enumerator.
|
201
|
+
#
|
202
|
+
# @overload each_feature(&block)
|
203
|
+
# When called with a block, yields each item to the block and returns `nil`.
|
204
|
+
# @yieldparam enum [FeatureGroup] Yields a group to the block.
|
205
|
+
# @return [void]
|
206
|
+
def each_feature
|
207
|
+
#noinspection RubyYardReturnMatch
|
208
|
+
return enum_for(__method__) unless block_given?
|
209
|
+
@features.each { |item| yield item }
|
210
|
+
nil
|
211
|
+
end
|
212
|
+
|
213
|
+
##
|
214
|
+
# Enumerates through each extension defined in the registry.
|
215
|
+
#
|
216
|
+
# @overload each_enum
|
217
|
+
# When called without a block, returns an Enumerator.
|
218
|
+
# @return [Enumerator] An extension enumerator.
|
219
|
+
#
|
220
|
+
# @overload each_enum(&block)
|
221
|
+
# When called with a block, yields each item to the block and returns `nil`.
|
222
|
+
# @yieldparam enum [Extension] Yields an extension to the block.
|
223
|
+
# @return [void]
|
224
|
+
def each_extension
|
225
|
+
#noinspection RubyYardReturnMatch
|
226
|
+
return enum_for(__method__) unless block_given?
|
227
|
+
@extensions.each { |item| yield item }
|
228
|
+
nil
|
229
|
+
end
|
230
|
+
|
231
|
+
##
|
232
|
+
# Download the latest version of the OpenGL registry to the specified file.
|
233
|
+
#
|
234
|
+
# @param path [String] The path where the file will be saved.
|
235
|
+
#
|
236
|
+
# @return [Boolean] `true` on success, otherwise `false` if an error occurred.
|
237
|
+
def self.download(path)
|
238
|
+
begin
|
239
|
+
URI.open('https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/master/xml/gl.xml') do |io|
|
240
|
+
FileUtils.mv(io.path, path)
|
241
|
+
end
|
242
|
+
return true
|
243
|
+
rescue
|
244
|
+
return false
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
##
|
249
|
+
# Compares the registry at the specified path to the current registry version and returns value indicating if there
|
250
|
+
# is a newer version available.
|
251
|
+
#
|
252
|
+
# @param path [String] The path to a registry file to test.
|
253
|
+
#
|
254
|
+
# @return [Boolean] `true` if a newer version is available, otherwise `false` if file is current and/or an error
|
255
|
+
# occurred.
|
256
|
+
#
|
257
|
+
# @note This method is not guaranteed to be accurate, it only uses the timestamps in the file's metadata, which
|
258
|
+
# could be inaccurate due to file copying, system time changes, creating from different source, etc.
|
259
|
+
def self.outdated?(path)
|
260
|
+
|
261
|
+
return false unless path && File.exist?(path)
|
262
|
+
|
263
|
+
begin
|
264
|
+
uri = URI('https://api.github.com/repos/KhronosGroup/OpenGL-Registry/commits?path=xml/gl.xml')
|
265
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 3, read_timeout: 5) do |http|
|
266
|
+
|
267
|
+
req = Net::HTTP::Get.new(uri)
|
268
|
+
response = http.request(req)
|
269
|
+
|
270
|
+
if response.code == '200'
|
271
|
+
json = JSON.parse(response.body, symbolize_names: true)
|
272
|
+
commit = DateTime.parse(json.first[:commit][:author][:date]).to_time
|
273
|
+
return File.mtime(path) < commit
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
277
|
+
rescue
|
278
|
+
warn('failed to query current registry version')
|
279
|
+
return false
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
private
|
284
|
+
|
285
|
+
def initialize(root)
|
286
|
+
raise ArgumentError, 'root cannot be nil' unless root
|
287
|
+
|
288
|
+
@groups = []
|
289
|
+
root.locate('enums').each do |enum|
|
290
|
+
next unless enum.is_a?(Ox::Element)
|
291
|
+
@groups << Group.new(enum)
|
292
|
+
end
|
293
|
+
|
294
|
+
@functions = []
|
295
|
+
root.locate('commands/command').each do |function|
|
296
|
+
next unless function.is_a?(Ox::Element)
|
297
|
+
@functions << Function.new(function)
|
298
|
+
end
|
299
|
+
|
300
|
+
@features = []
|
301
|
+
root.locate('feature').each do |feature|
|
302
|
+
next unless feature.is_a?(Ox::Element)
|
303
|
+
@features << FeatureGroup.new(feature)
|
304
|
+
end
|
305
|
+
|
306
|
+
@extensions = []
|
307
|
+
root.locate('extensions/extension').each do |extension|
|
308
|
+
next unless extension.is_a?(Ox::Element)
|
309
|
+
@extensions << Extension.new(extension)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
registry = GL::Registry.load('/code/ruby/khronos-temp/gl.xml')
|
316
|
+
spec = GL::Spec.new(registry, :gl, 4.3, :compatibility)
|
317
|
+
|
318
|
+
p spec.enums.size
|