1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # OpenGL graphics rendering library for embedded systems, version 2.0.
19 # Defines the annotations `glsl_vertex_shader` and `glsl_fragment_shader`
20 # applicable on string literals to check shader code using `glslangValidator`.
21 # The tool must be in PATH. It can be downloaded from
22 # https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
24 # Most services of this module are a direct wrapper of the underlying
25 # C library. If a method or class is not documented in Nit, refer to
26 # the official documentation by the Khronos Group at:
27 # http://www.khronos.org/opengles/sdk/docs/man/
30 new_annotation glsl_vertex_shader
31 new_annotation glsl_fragment_shader
35 #include <GLES2/gl2.h>
38 # Opengl ES program to which we attach shaders
39 extern class GLProgram `{GLuint`}
40 new `{ return glCreateProgram(); `}
42 fun is_ok
: Bool `{ return glIsProgram(recv); `}
44 fun attach_shader(shader: GLShader) `{ glAttachShader(recv, shader); `}
46 fun bind_attrib_location
(index
: Int, name
: String) import String.to_cstring
`{
47 GLchar *c_name = String_to_cstring(name);
48 glBindAttribLocation(recv, index, c_name);
51 fun attrib_location
(name
: String): Int import String.to_cstring
`{
52 GLchar *c_name = String_to_cstring(name);
53 return glGetAttribLocation(recv, c_name);
56 fun query
(pname
: Int): Int `{
58 glGetProgramiv(recv, pname, &val);
62 fun link
`{ glLinkProgram(recv); `}
63 fun is_linked: Bool do return query("8B82".to_hex) != 0
65 fun use `{ glUseProgram(recv); `}
67 fun delete
`{ glDeleteProgram(recv); `}
68 fun is_deleted: Bool do return query("8B80".to_hex) != 0
70 fun validate `{ glValidateProgram(recv); `}
71 fun is_validated
: Bool do return query
("8B83".to_hex
) != 0
73 fun info_log
: String import NativeString.to_s
`{
75 glGetProgramiv(recv, GL_INFO_LOG_LENGTH, &size);
76 GLchar *msg = malloc(size);
77 glGetProgramInfoLog(recv, size, NULL, msg);
78 return NativeString_to_s(msg);
82 # Abstract OpenGL ES shader object, implemented by `GLFragmentShader` and `GLVertexShader`
83 extern class GLShader `{GLuint`}
84 fun source=(code: String) import String.to_cstring, String.length `{
85 GLchar *c_code
= String_to_cstring(code
);
86 glShaderSource
(recv
, 1, (const
GLchar * const
*)&c_code
, NULL);
88 fun source: nullable String import NativeString.to_s `{
90 glGetShaderiv
(recv
, GL_SHADER_SOURCE_LENGTH, &size
);
91 if (size
== 0) return NULL;
92 GLchar *code
= malloc
(size
);
93 glGetShaderSource
(recv
, size
, NULL, code
);
94 return NativeString_to_s(code
);
97 protected fun query(pname: Int): Int `{
99 glGetShaderiv
(recv
, pname
, &val
);
103 fun compile `{ glCompileShader(recv); `}
104 fun is_compiled
: Bool do return query
("8B81".to_hex
) != 0
106 fun delete
`{ glDeleteShader(recv); `}
107 fun is_deleted: Bool do return query("8B80".to_hex) != 0
109 fun is_ok: Bool `{ return glIsShader(recv); `}
111 fun info_log
: String import NativeString.to_s
`{
113 glGetShaderiv(recv, GL_INFO_LOG_LENGTH, &size);
114 GLchar *msg = malloc(size);
115 glGetShaderInfoLog(recv, size, NULL, msg);
116 return NativeString_to_s(msg);
121 extern class GLFragmentShader
124 new `{ return glCreateShader(GL_FRAGMENT_SHADER); `}
127 extern class GLVertexShader
130 new `{ return glCreateShader(GL_VERTEX_SHADER); `}
133 # An array of `Float` associated to a program variable
137 protected var glfloat_array
: GLfloatArray
139 init(index
, count
: Int, array
: Array[Float])
143 self.glfloat_array
= new GLfloatArray(array
)
146 fun attrib_pointer
do attrib_pointer_intern
(index
, count
, glfloat_array
)
147 private fun attrib_pointer_intern
(index
, count
: Int, array
: GLfloatArray) `{
148 glVertexAttribPointer(index, count, GL_FLOAT, GL_FALSE, 0, array);
151 fun enable
do enable_intern
(index
)
152 private fun enable_intern
(index
: Int) `{ glEnableVertexAttribArray(index); `}
154 fun draw_arrays_triangles do draw_arrays_triangles_intern(index, count)
155 private fun draw_arrays_triangles_intern(index, count: Int) `{
156 glDrawArrays
(GL_TRIANGLES, index
, count
);
160 # Low level array of `Float`
161 extern class GLfloatArray `{GLfloat *`}
162 new (array
: Array[Float]) import Array[Float].length
, Array[Float].[] `{
164 int len = Array_of_Float_length(array);
165 GLfloat *vertex_array = malloc(sizeof(GLfloat)*len);
166 for (i = 0; i < len; i ++) vertex_array[i] = Array_of_Float__index(array, i);
171 extern class GLError `{ GLenum `}
172 fun is_ok: Bool do return is_no_error
173 fun is_no_error: Bool `{ return recv == GL_NO_ERROR; `}
174 fun is_invalid_enum
: Bool `{ return recv == GL_INVALID_ENUM; `}
175 fun is_invalid_value: Bool `{ return recv == GL_INVALID_VALUE; `}
176 fun is_invalid_operation
: Bool `{ return recv == GL_INVALID_OPERATION; `}
177 fun is_invalid_framebuffer_operation: Bool `{ return recv == GL_INVALID_FRAMEBUFFER_OPERATION; `}
178 fun is_out_of_memory
: Bool `{ return recv == GL_OUT_OF_MEMORY; `}
182 if is_no_error then return "No error"
183 if is_invalid_enum then return "Invalid enum"
184 if is_invalid_value then return "Invalid value"
185 if is_invalid_operation then return "Invalid operation"
186 if is_invalid_framebuffer_operation then return "invalid framebuffer operation"
187 if is_out_of_memory then return "Out of memory"
188 return "Truely unknown error"
192 protected fun gl_clear_color(r, g, b, a: Float) `{ glClearColor(r, g, b, a); `}
193 protected fun gl_viewport
(x
, y
, width
, height
: Int) `{ glViewport(x, y, width, height); `}
194 protected fun gl_vertex_attrib_pointer_int(index, length: Int, normalize: Bool, stride: Int, vertex: Array[Int]) import Array[Int].length, Array[Int].intern_items `{
195 int
* c_vertex
= Array_of_Int_intern_items(vertex
);
196 glVertexAttribPointer
(index
, length
, GL_INT, normalize
, stride
, c_vertex
);
198 protected fun gl_vertex_attrib_pointer_float(index, length: Int, normalize: Bool, stride: Int, vertex: Array[Float]) import Array[Float].length, Array[Float].intern_items `{
199 int
* c_vertex
= Array_of_Float_intern_items(vertex
);
200 glVertexAttribPointer
(index
, length
, GL_FLOAT, normalize
, stride
, c_vertex
);
203 # Direct call to `glClear
`, call with a combinaison of `gl_clear_color_buffer
`,
204 # `gl_stencil_buffer_bit
` and `gl_color_buffer_bit
`.
205 private fun gl_clear(flag: Int) `{ glClear(flag); `}
207 protected fun gl_depth_buffer_bit
: Int do return once
"0100".to_hex
208 protected fun gl_stencil_buffer_bit
: Int do return once
"0400".to_hex
209 protected fun gl_color_buffer_bit
: Int do return once
"4000".to_hex
211 protected fun gl_clear_color_buffer
do gl_clear
(gl_color_buffer_bit
)
212 protected fun gl_clear_depth_buffer
do gl_clear
(gl_depth_buffer_bit
)
213 protected fun gl_clear_stencil_buffer
do gl_clear
(gl_stencil_buffer_bit
)
215 protected fun gl_error
: GLError `{ return glGetError(); `}
216 protected fun assert_no_gl_error
219 if not error.is_ok then
220 print "GL error: {error}"
225 private fun gl_get_bool(key: Int): Bool `{
227 glGetBooleanv
(GL_SHADER_COMPILER, &val
);
228 return val
== GL_TRUE;
230 private fun gl_get_float(key: Int): Float `{
232 glGetFloatv
(key
, &val
);
235 private fun gl_get_int(key: Int): Int `{
237 glGetIntegerv
(key
, &val
);
241 fun gl_shader_compiler: Bool do return gl_get_bool("8DFA".to_hex)