File: conv.h

package info (click to toggle)
ruby-opengl 0.60.1%2Bdfsg2-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 2,044 kB
  • ctags: 4,889
  • sloc: ansic: 24,676; ruby: 9,400; sh: 12; makefile: 10
file content (244 lines) | stat: -rw-r--r-- 7,399 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*
 * Copyright (C) 2007 Jan Dvorak <jan.dvorak@kraxnet.cz>
 *
 * This program is distributed under the terms of the MIT license.
 * See the included MIT-LICENSE file for the terms of this license.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/* Functions and macros for datatype conversion between Ruby and C */

/*
   Fast inline conversion functions as a replacement for the ones in libruby.
   FIXNUM_P is simple logical AND check so it comes first, TYPE() is simple function,
   and specified in header file so it can be inlined. For conversion, FIX2LONG is
   simple right shift, and RFLOAT()-> just pointer dereference. For converting
   Fixnum and Float types (which accounts for 99.9% of things you would want to pass
   to OpenGL), there is large performance boost as result.

	 Also ruby 'true' and 'false' are converted to GL_TRUE/GL_FALSE for compatibility, and
	 finally, we fallback to library functions for any other data types (and error handling).
*/

#if RUBY_VERSION <190
#define	FLOAT_VAL_ACCESS(val) RFLOAT(val)->value
#else
#define	FLOAT_VAL_ACCESS(val) RFLOAT(val)->float_value
#endif

#define FASTCONV(_name_,_type_,_convfix_,_convfallback_) \
static inline _type_ _name_(val) \
VALUE val; \
{ \
	if (FIXNUM_P(val)) \
		return (_type_) _convfix_(val); \
\
	if (TYPE(val) == T_FLOAT) \
		return (_type_)FLOAT_VAL_ACCESS(val); \
\
	if ((val) == Qtrue) \
		return (_type_)(GL_TRUE); \
\
	if ((val) == Qfalse || (val) == Qnil) \
		return (_type_)(GL_FALSE); \
\
	return (_convfallback_(val)); \
}

FASTCONV(num2double,double,FIX2LONG,rb_num2dbl)
#if SIZEOF_INT < SIZEOF_LONG
/* For 64bit platforms with LP64 mode */
FASTCONV(num2int,long,FIX2LONG,rb_num2int)
FASTCONV(num2uint,unsigned long,FIX2ULONG,rb_num2uint)
#else
/* All other platforms */
FASTCONV(num2int,long,FIX2LONG,(int)NUM2LONG)
FASTCONV(num2uint,unsigned long,FIX2ULONG,(unsigned int)NUM2ULONG)
#endif

#undef NUM2DBL
#define NUM2DBL num2double

#undef NUM2INT
#define NUM2INT num2int

#undef NUM2UINT
#define NUM2UINT num2uint

#undef FASTCONV

/* For conversion between ruby and GL boolean values */
#define GLBOOL2RUBY(x) (x)==GL_TRUE? Qtrue :( (x)==GL_FALSE? Qfalse : INT2NUM((x)))
#define RUBYBOOL2GL(x) (x)==Qtrue? GL_TRUE : GL_FALSE

#define cond_GLBOOL2RUBY_FUNC(_name_,_type_,_conv_) \
static inline VALUE _name_(GLenum pname,_type_ value) \
{ \
	switch (pname) { \
	case GL_DELETE_STATUS: \
	case GL_LINK_STATUS: \
	case GL_VALIDATE_STATUS: \
	case GL_COMPILE_STATUS: \
	case GL_MINMAX_SINK: \
	case GL_HISTOGRAM_SINK: \
	case GL_COORD_REPLACE: \
	case GL_TEXTURE_COMPRESSED: \
	case GL_GENERATE_MIPMAP: \
	case GL_TEXTURE_RESIDENT: \
	case GL_BUFFER_MAPPED: \
	case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: \
	case GL_VERTEX_ATTRIB_ARRAY_ENABLED: \
	case GL_QUERY_RESULT_AVAILABLE: \
	case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: \
	case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT: \
	case GL_FENCE_STATUS_NV: \
	case GL_TEXTURE_FLOAT_COMPONENTS_NV: \
	case GL_SHADER_CONSISTENT_NV: \
	case GL_TEXTURE_COMPARE_SGIX: \
	case GLU_TESS_BOUNDARY_ONLY: \
	case GLU_CULLING: \
	case GLU_AUTO_LOAD_MATRIX: \
		return GLBOOL2RUBY(value); \
	default: \
		return _conv_(value); \
	} \
}

cond_GLBOOL2RUBY_FUNC(cond_GLBOOL2RUBY,GLint,INT2NUM)
cond_GLBOOL2RUBY_FUNC(cond_GLBOOL2RUBY_U,GLuint,UINT2NUM)
cond_GLBOOL2RUBY_FUNC(cond_GLBOOL2RUBY_LL,GLint64EXT,LL2NUM)
cond_GLBOOL2RUBY_FUNC(cond_GLBOOL2RUBY_ULL,GLuint64EXT,ULL2NUM)
cond_GLBOOL2RUBY_FUNC(cond_GLBOOL2RUBY_F,GLfloat,rb_float_new)
cond_GLBOOL2RUBY_FUNC(cond_GLBOOL2RUBY_D,GLdouble,rb_float_new)


/* For conversion between ruby array (or object that can be converted to array) and C array.
   The C array has to be preallocated by calling function. */
#define ARY2CTYPE(_type_,_convert_) \
static inline int ary2c##_type_( arg, cary, maxlen ) \
VALUE arg; \
GL##_type_ cary[]; \
int maxlen; \
{ \
    int i; \
    struct RArray* ary; \
    ary = RARRAY(rb_Array(arg)); \
    if (maxlen < 1) \
        maxlen = RARRAY_LEN(ary); \
    else \
        maxlen = maxlen < RARRAY_LEN(ary) ? maxlen : RARRAY_LEN(ary); \
    for (i=0; i < maxlen; i++) \
        cary[i] = (GL##_type_)_convert_(rb_ary_entry((VALUE)ary,i)); \
    return i; \
}

ARY2CTYPE(int,NUM2INT)
ARY2CTYPE(uint,NUM2UINT)
ARY2CTYPE(byte,NUM2INT)
ARY2CTYPE(ubyte,NUM2INT)
ARY2CTYPE(short,NUM2INT)
ARY2CTYPE(ushort,NUM2INT)
ARY2CTYPE(boolean,NUM2INT)
ARY2CTYPE(float,NUM2DBL)
ARY2CTYPE(double,NUM2DBL)

#define ary2cflt ary2cfloat
#define ary2cdbl ary2cdouble

#undef ARY2CTYPE

/* Converts either array or object responding to #to_a to C-style array */
#define ARY2CMAT(_type_) \
static inline void ary2cmat##_type_(rary, cary, cols, rows, count) \
VALUE rary; \
_type_ cary[]; \
int cols,rows; \
{ \
	int i; \
\
	rary = rb_Array(rary); \
	rary = rb_funcall(rary,rb_intern("flatten"),0); \
\
	if (RARRAY_LEN(rary) != cols*rows) \
		rb_raise(rb_eArgError, "passed array/matrix must have %i*%i elements",cols,rows); \
\
	for (i=0; i < cols*rows; i++) \
		cary[i] = (_type_) NUM2DBL(rb_ary_entry(rary,i)); \
}

ARY2CMAT(double)
ARY2CMAT(float)
#undef ARY2CMAT

#define ARY2CMATCNT(_type_) \
static inline void ary2cmat##_type_##count(rary, cary, cols, rows) \
VALUE rary; \
_type_ cary[]; \
int cols,rows; \
{ \
	int i; \
\
	rary = rb_Array(rary); \
	rary = rb_funcall(rary,rb_intern("flatten"),0); \
\
	if (RARRAY_LEN(rary)<1 || (RARRAY_LEN(rary) % (cols*rows) != 0)) {\
		xfree(cary); \
		rb_raise(rb_eArgError, "passed array/matrix must conatain n x (%i*%i) elements",cols,rows); \
	} \
\
	for (i=0; i < RARRAY_LEN(rary); i++) \
		cary[i] = (_type_) NUM2DBL(rb_ary_entry(rary,i)); \
}

ARY2CMATCNT(double)
ARY2CMATCNT(float)
#undef ARY2CMATCNT


#define EMPTY
#define FREE(_x_) xfree(_x_);

#define RET_ARRAY_OR_SINGLE(_size_,_conv_,_params_) RET_ARRAY_OR_SINGLE_FUNC(_size_,_conv_,_params_,EMPTY)
#define RET_ARRAY_OR_SINGLE_FREE(_size_,_conv_,_params_) RET_ARRAY_OR_SINGLE_FUNC(_size_,_conv_,_params_,FREE(_params_))

#define RET_ARRAY_OR_SINGLE_FUNC(_size_,_conv_,_params_,_extra_) \
{ \
	int iter; \
	VALUE return_array; \
	if (_size_ == 1) { \
		return_array = _conv_(_params_[0]); \
	} else { \
		return_array = rb_ary_new2(_size_); \
		for(iter=0;iter<_size_;iter++) \
			rb_ary_push(return_array, _conv_(_params_[iter])); \
	} \
	_extra_ \
	CHECK_GLERROR \
	return return_array; \
}

#define RET_ARRAY_OR_SINGLE_BOOL(_size_,_conv_,_enum_,_params_) RET_ARRAY_OR_SINGLE_BOOL_FUNC(_size_,_conv_,_enum_,_params_,EMPTY)
#define RET_ARRAY_OR_SINGLE_BOOL_FREE(_size_,_conv_,_enum_,_params_) RET_ARRAY_OR_SINGLE_BOOL_FUNC(_size_,_conv_,_enum_,_params_,FREE(_params_))

#define RET_ARRAY_OR_SINGLE_BOOL_FUNC(_size_,_conv_,_enum_,_params_,_extra_) \
{ \
	int iter; \
	VALUE return_array; \
	if (_size_ == 1) { \
		return_array = _conv_(_enum_,_params_[0]); \
	} else { \
		return_array = rb_ary_new2(_size_); \
		for(iter=0;iter<_size_;iter++) \
			rb_ary_push(return_array, _conv_(_enum_,_params_[iter])); \
	} \
	_extra_ \
	CHECK_GLERROR \
	return return_array; \
}