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 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
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.1
6
+ before_install: gem install bundler -v 2.1.4
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ --readme README.md
2
+ --title 'OpenGL Registry'
3
+ --charset utf-8
4
+ --markup markdown
5
+ --protected
6
+ lib/**/*.rb
7
+ --exclude lib/opengl/registry/words.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # Version History
2
+
3
+ ## 1.0
4
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
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
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
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,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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