/* * Last edit by previous maintainer: * 2000/01/06 16:37:43, kusano * * Copyright (C) 1999 - 2005 Yoshi * Copyright (C) 2006 John M. Gabriele * Copyright (C) 2007 James Adam * * 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. */ #ifndef _RBOGL_H_ #define _RBOGL_H_ #include #ifdef __APPLE__ #include #include #include #include #elif defined WIN32 #include #include #else #include #include #endif #include "gl-enums.h" #ifdef __APPLE__ #ifndef APIENTRY #define APIENTRY /* to nothing */ #endif #endif typedef struct RArray RArray; extern VALUE cProc; #define LOAD_GL_FUNC(_NAME_) \ if (fptr_##_NAME_==NULL) \ fptr_##_NAME_ = load_gl_function(#_NAME_, 1); #define FORCE_PIXEL_STORE_MODE \ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); \ glPixelStorei(GL_PACK_ALIGNMENT, 1); \ glPixelStorei(GL_PACK_SKIP_PIXELS, 0); \ glPixelStorei(GL_PACK_SKIP_ROWS, 0); \ glPixelStorei(GL_PACK_ROW_LENGTH, 0); \ glPixelStorei(GL_PACK_SKIP_IMAGES, 0); \ glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0); /* glPixelStorei(GL_PACK_SKIP_VOLUMES_SGIS, 0); glPixelStorei(GL_PACK_IMAGE_DEPTH_SGIS, 0); */ #define RESTORE_PIXEL_STORE_MODE \ glPopClientAttrib(); /* -------------------------------------------------------------------- */ #ifndef NUM2DBL #define NUM2DBL(_val) num2double(_val) static inline double num2double( VALUE val ) { struct RFloat* flt; if (NIL_P(val)) return 0; flt = RFLOAT(f_float(0, val)); return flt->value; } #endif /* -------------------------------------------------------------------- */ #define ARY2INTEGRAL(_type_,_convert_) \ static inline int ary2c##_type_( arg, cary, maxlen ) \ VALUE arg; \ GL##_type_ cary[]; \ int maxlen; \ { \ int i; \ struct RArray* ary; \ VALUE entry; \ ary = RARRAY(rb_Array(arg)); \ if (maxlen < 1) \ maxlen = ary->len; \ else \ maxlen = maxlen < ary->len ? maxlen : ary->len; \ for (i=0; i < maxlen; i++) \ { \ entry = rb_ary_entry((VALUE)ary,i); \ cary[i] = (GL##_type_)_convert_(entry); \ } \ return i; \ } ARY2INTEGRAL(int,NUM2INT) ARY2INTEGRAL(uint,NUM2UINT) ARY2INTEGRAL(byte,NUM2INT) ARY2INTEGRAL(ubyte,NUM2INT) ARY2INTEGRAL(short,NUM2INT) ARY2INTEGRAL(ushort,NUM2INT) ARY2INTEGRAL(boolean,NUM2INT) #undef ARY2INTEGRAL /* -------------------------------------------------------------------- */ static inline int ary2cflt(arg, cary, maxlen) VALUE arg; float cary[]; int maxlen; { int i; struct RArray* ary; ary = RARRAY(rb_Array(arg)); if (maxlen < 1) maxlen = ary->len; else maxlen = maxlen < ary->len ? maxlen : ary->len; for (i=0; i < maxlen; i++) cary[i] = (float)NUM2DBL(rb_ary_entry((VALUE)ary,i)); return i; } /* -------------------------------------------------------------------- */ static inline int ary2cdbl(arg, cary, maxlen) VALUE arg; double cary[]; int maxlen; { int i; struct RArray* ary; ary = RARRAY(rb_Array(arg)); if (maxlen < 1) maxlen = ary->len; else maxlen = maxlen < ary->len ? maxlen : ary->len; for (i=0; i < maxlen; i++) cary[i] = NUM2DBL(rb_ary_entry((VALUE)ary,i)); return i; } /* -------------------------------------------------------------------- */ static inline void mary2ary(src, ary) VALUE src; VALUE ary; { struct RArray* tmp_ary; int i; tmp_ary = RARRAY(rb_Array(src)); for (i = 0; i < tmp_ary->len; i++) { if (TYPE(tmp_ary->ptr[i]) == T_ARRAY) mary2ary((VALUE)tmp_ary->ptr[i], ary); else rb_ary_push(ary, tmp_ary->ptr[i]); } } /* -------------------------------------------------------------------- */ static inline void ary2cmat4x4dbl(ary, cary) VALUE ary; double cary[]; { int i,j; RArray *ary_r,*ary_c; memset(cary, 0x0, sizeof(double[4*4])); ary_c = RARRAY(rb_Array(ary)); if (TYPE(ary_c->ptr[0]) != T_ARRAY) ary2cdbl((VALUE)ary_c, cary, 16); else { for (i = 0; i < ary_c->len && i < 4; i++) { ary_r = RARRAY(rb_Array(ary_c->ptr[i])); for(j = 0; j < ary_r->len && j < 4; j++) cary[i*4+j] = (GLdouble)NUM2DBL(ary_r->ptr[j]); } } } static inline void ary2cmat4x4flt(ary, cary) VALUE ary; float cary[]; { int i,j; RArray *ary_r,*ary_c; memset(cary, 0x0, sizeof(float[4*4])); ary_c = RARRAY(rb_Array(ary)); if (TYPE(ary_c->ptr[0]) != T_ARRAY) ary2cflt((VALUE)ary_c, cary, 16); else { for (i = 0; i < ary_c->len && i < 4; i++) { ary_r = RARRAY(rb_Array(ary_c->ptr[i])); for(j = 0; j < ary_r->len && j < 4; j++) cary[i*4+j] = (GLfloat)NUM2DBL(ary_r->ptr[j]); } } } /* -------------------------------------------------------------------- */ /*Need to find proper size for glReadPixels array*/ static inline int glformat_size(GLenum format) { switch(format) { case GL_COLOR_INDEX: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_STENCIL_INDEX: case GL_DEPTH_COMPONENT: case GL_LUMINANCE: return 1; case GL_LUMINANCE_ALPHA: return 2; case GL_RGB: case GL_BGR_EXT: return 3; case GL_RGBA: case GL_BGRA_EXT: case GL_ABGR_EXT: return 4; case 1: case 2: case 3: case 4: return format; default: return -1; } } /* -------------------------------------------------------------------- */ static inline int gltype_size(GLenum type) { switch(type) { case GL_BYTE: case GL_UNSIGNED_BYTE: case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: return 1; case GL_SHORT: case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_5_5_5_1: case GL_UNSIGNED_SHORT_1_5_5_5_REV: return 2; case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: case GL_UNSIGNED_INT_8_8_8_8: case GL_UNSIGNED_INT_8_8_8_8_REV: case GL_UNSIGNED_INT_10_10_10_2: case GL_UNSIGNED_INT_2_10_10_10_REV: return 4; case GL_BITMAP: return 0; default: return -1; } } /* -------------------------------------------------------------------- */ static inline VALUE allocate_buffer_with_string( int size ) { return rb_str_new(NULL, size); } /* -------------------------------------------------------------------- */ static inline void *load_gl_function(const char *name,int raise) { void *func_ptr = NULL; #if defined(__APPLE__) static const struct mach_header* library = NULL; char* symbolName; NSSymbol symbol; if (library == NULL) library = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL",NSADDIMAGE_OPTION_RETURN_ON_ERROR); if (library == NULL) rb_raise(rb_eRuntimeError,"Can't load OpenGL library for dynamic loading"); /* prepend a '_' for the Unix C symbol mangling convention */ symbolName = ALLOC_N(char,strlen(name) + 2); symbolName[0] = '_'; strcpy(symbolName+1, name); symbol = NSLookupSymbolInImage(library,symbolName,NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); xfree(symbolName); if (symbol == NULL) func_ptr = NULL; else func_ptr = NSAddressOfSymbol(symbol); #elif defined(WIN32) || defined(_WIN32) func_ptr = wglGetProcAddress((LPCSTR)name); #elif defined(GLX_VERSION_1_4) func_ptr = glXGetProcAddress((const GLubyte *)name); #else func_ptr = glXGetProcAddressARB((const GLubyte *)name); #endif if (func_ptr == NULL && raise == 1) rb_raise(rb_eNotImpError,"Function %s is not available at this machine",name); return func_ptr; } #endif /* _RBOGL_H_ */