#include "gl_util.h" int gl_texparameter_count(GLenum pname) { #ifdef GL_EXT_texture_object switch (pname) { case GL_TEXTURE_PRIORITY_EXT: case GL_TEXTURE_RESIDENT_EXT: return 1; } #endif /* FIXME: Missing stuff? */ #ifdef GL_VERSION_1_2 switch (pname) { case GL_TEXTURE_WRAP_R: case GL_TEXTURE_DEPTH: return 1; case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: return 1; } #endif switch (pname) { case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: case GL_TEXTURE_PRIORITY: case GL_TEXTURE_RESIDENT: return 1; case GL_TEXTURE_BORDER_COLOR: return 4; default: croak("Unknown texparameter parameter"); } return 0; // Just to make the compiler happy } int gl_texenv_count(GLenum pname) { switch (pname) { case GL_TEXTURE_ENV_MODE: return 1; case GL_TEXTURE_ENV_COLOR: return 4; default: croak("Unknown texenv parameter"); } return 0; // Just to make the compiler happy } int gl_texgen_count(GLenum pname) { switch (pname) { case GL_TEXTURE_GEN_MODE: return 1; case GL_OBJECT_PLANE: case GL_EYE_PLANE: return 4; default: croak("Unknown texgen parameter"); } return 0; // Just to make the compiler happy } int gl_material_count(GLenum pname) { switch (pname) { case GL_AMBIENT: case GL_DIFFUSE: case GL_AMBIENT_AND_DIFFUSE: case GL_SPECULAR: case GL_EMISSION: return 4; case GL_COLOR_INDEXES: return 3; case GL_SHININESS: return 1; default: croak("Unknown material parameter"); } return 0; // Just to make the compiler happy } int gl_map_count(GLenum target, GLenum query) { switch (query) { case GL_COEFF: switch (target) { case GL_MAP1_VERTEX_3: case GL_MAP1_NORMAL: case GL_MAP1_TEXTURE_COORD_3: return 3; case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: case GL_MAP1_TEXTURE_COORD_4: return 4; case GL_MAP1_TEXTURE_COORD_2: return 2; case GL_MAP1_INDEX: case GL_MAP1_TEXTURE_COORD_1: return 1; case GL_MAP2_VERTEX_3: case GL_MAP2_NORMAL: case GL_MAP2_TEXTURE_COORD_3: return 3; case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: case GL_MAP2_TEXTURE_COORD_4: return 4; case GL_MAP2_TEXTURE_COORD_2: return 2; case GL_MAP2_INDEX: case GL_MAP2_TEXTURE_COORD_1: return 1; default: croak("Unknown map target"); } case GL_ORDER: switch (target) { case GL_MAP1_VERTEX_3: case GL_MAP1_NORMAL: case GL_MAP1_TEXTURE_COORD_3: case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: case GL_MAP1_TEXTURE_COORD_4: case GL_MAP1_TEXTURE_COORD_2: case GL_MAP1_INDEX: case GL_MAP1_TEXTURE_COORD_1: return 1; case GL_MAP2_VERTEX_3: case GL_MAP2_NORMAL: case GL_MAP2_TEXTURE_COORD_3: case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: case GL_MAP2_TEXTURE_COORD_4: case GL_MAP2_TEXTURE_COORD_2: case GL_MAP2_INDEX: case GL_MAP2_TEXTURE_COORD_1: return 2; default: croak("Unknown map target"); } case GL_DOMAIN: switch (target) { case GL_MAP1_VERTEX_3: case GL_MAP1_NORMAL: case GL_MAP1_TEXTURE_COORD_3: case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: case GL_MAP1_TEXTURE_COORD_4: case GL_MAP1_TEXTURE_COORD_2: case GL_MAP1_INDEX: case GL_MAP1_TEXTURE_COORD_1: return 2; case GL_MAP2_VERTEX_3: case GL_MAP2_NORMAL: case GL_MAP2_TEXTURE_COORD_3: case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: case GL_MAP2_TEXTURE_COORD_4: case GL_MAP2_TEXTURE_COORD_2: case GL_MAP2_INDEX: case GL_MAP2_TEXTURE_COORD_1: return 4; default: croak("Unknown map target"); } default: croak("Unknown map query"); } return 0; // Just to make the compiler happy } int gl_light_count(GLenum pname) { switch (pname) { case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: case GL_POSITION: return 4; case GL_SPOT_DIRECTION: return 3; case GL_SPOT_EXPONENT: case GL_SPOT_CUTOFF: case GL_CONSTANT_ATTENUATION: case GL_LINEAR_ATTENUATION: case GL_QUADRATIC_ATTENUATION: return 1; default: croak("Unknown light parameter"); } return 0; // Just to make the compiler happy } int gl_lightmodel_count(GLenum pname) { switch (pname) { case GL_LIGHT_MODEL_AMBIENT: return 4; case GL_LIGHT_MODEL_LOCAL_VIEWER: case GL_LIGHT_MODEL_TWO_SIDE: return 1; default: croak("Unknown light model"); } return 0; // Just to make the compiler happy } int gl_fog_count(GLenum pname) { switch (pname) { case GL_FOG_COLOR: return 4; case GL_FOG_MODE: case GL_FOG_DENSITY: case GL_FOG_START: case GL_FOG_END: case GL_FOG_INDEX: return 1; default: croak("Unknown fog parameter"); } return 0; // Just to make the compiler happy } int gl_get_count(GLenum param) { /* 3 */ #ifdef GL_EXT_polygon_offset switch (param) { case GL_POLYGON_OFFSET_EXT: case GL_POLYGON_OFFSET_FACTOR_EXT: case GL_POLYGON_OFFSET_BIAS_EXT: return 1; } #endif #ifdef GL_VERSION_1_2 switch (param) { case GL_TEXTURE_3D: case GL_UNPACK_SKIP_IMAGES: case GL_UNPACK_IMAGE_HEIGHT: case GL_PACK_SKIP_IMAGES: case GL_PACK_IMAGE_HEIGHT: case GL_MAX_3D_TEXTURE_SIZE: return 1; case GL_RESCALE_NORMAL: return 1; case GL_LIGHT_MODEL_COLOR_CONTROL: return 1; case GL_MAX_ELEMENTS_VERTICES: case GL_MAX_ELEMENTS_INDICES: return 1; } #endif #ifdef GL_VERSION_1_1 switch (param) { case GL_TEXTURE_COORD_ARRAY: case GL_TEXTURE_COORD_ARRAY_SIZE: case GL_TEXTURE_COORD_ARRAY_STRIDE: case GL_TEXTURE_COORD_ARRAY_TYPE: case GL_VERTEX_ARRAY: case GL_VERTEX_ARRAY_SIZE: case GL_VERTEX_ARRAY_STRIDE: case GL_VERTEX_ARRAY_TYPE: case GL_POLYGON_OFFSET_FACTOR: case GL_POLYGON_OFFSET_UNITS: case GL_POLYGON_OFFSET_FILL: case GL_POLYGON_OFFSET_LINE: case GL_POLYGON_OFFSET_POINT: case GL_NORMAL_ARRAY: case GL_NORMAL_ARRAY_STRIDE: case GL_NORMAL_ARRAY_TYPE: case GL_INDEX_LOGIC_OP: case GL_INDEX_ARRAY: case GL_INDEX_ARRAY_STRIDE: case GL_INDEX_ARRAY_TYPE: case GL_EDGE_FLAG_ARRAY: case GL_EDGE_FLAG_ARRAY_STRIDE: case GL_COLOR_ARRAY: case GL_COLOR_ARRAY_SIZE: case GL_COLOR_ARRAY_STRIDE: case GL_COLOR_ARRAY_TYPE: case GL_COLOR_LOGIC_OP: return 1; } #endif /* 18 */ #ifdef GL_EXT_cmyka switch (param) { case GL_PACK_CMYK_HINT_EXT: case GL_UNPACK_CMYK_HINT_EXT: return 1; } #endif /* 30 */ #ifdef GL_EXT_vertex_array switch (param) { case GL_VERTEX_ARRAY_EXT: case GL_VERTEX_ARRAY_SIZE_EXT: case GL_VERTEX_ARRAY_STRIDE_EXT: case GL_VERTEX_ARRAY_TYPE_EXT: case GL_VERTEX_ARRAY_COUNT_EXT: case GL_NORMAL_ARRAY_EXT: case GL_NORMAL_ARRAY_STRIDE_EXT: case GL_NORMAL_ARRAY_TYPE_EXT: case GL_NORMAL_ARRAY_COUNT_EXT: case GL_COLOR_ARRAY_EXT: case GL_COLOR_ARRAY_SIZE_EXT: case GL_COLOR_ARRAY_STRIDE_EXT: case GL_COLOR_ARRAY_TYPE_EXT: case GL_COLOR_ARRAY_COUNT_EXT: case GL_INDEX_ARRAY_EXT: case GL_INDEX_ARRAY_STRIDE_EXT: case GL_INDEX_ARRAY_TYPE_EXT: case GL_INDEX_ARRAY_COUNT_EXT: case GL_TEXTURE_COORD_ARRAY_EXT: case GL_TEXTURE_COORD_ARRAY_SIZE_EXT: case GL_TEXTURE_COORD_ARRAY_STRIDE_EXT: case GL_TEXTURE_COORD_ARRAY_TYPE_EXT: case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: case GL_EDGE_FLAG_ARRAY_EXT: case GL_EDGE_FLAG_ARRAY_STRIDE_EXT: case GL_EDGE_FLAG_ARRAY_COUNT_EXT: return 1; } #endif #ifdef GL_EXT_framebuffer_object switch (param) { case GL_FRAMEBUFFER_BINDING_EXT: case GL_RENDERBUFFER_BINDING_EXT: case GL_MAX_COLOR_ATTACHMENTS_EXT: case GL_MAX_RENDERBUFFER_SIZE_EXT: return 1; } #endif #ifdef GL_ARB_point_parameters switch (param) { case GL_POINT_SIZE_MIN_ARB: case GL_POINT_SIZE_MAX_ARB: case GL_POINT_FADE_THRESHOLD_SIZE_ARB: return 1; case GL_POINT_DISTANCE_ATTENUATION_ARB: return 3; } #endif /* 79 */ #if defined(GL_EXT_clip_volume_hint) && defined(GL_VOLUME_CLIPPING_HINT_EXT) switch (param) { case GL_VOLUME_CLIPPING_HINT_EXT: return 1; } #endif switch (param) { case GL_ACCUM_ALPHA_BITS: case GL_ACCUM_RED_BITS: case GL_ACCUM_BLUE_BITS: case GL_ACCUM_GREEN_BITS: case GL_ALPHA_BIAS: case GL_ALPHA_BITS: case GL_ALPHA_SCALE: case GL_ALPHA_TEST: case GL_ALPHA_TEST_FUNC: case GL_ALPHA_TEST_REF: case GL_ATTRIB_STACK_DEPTH: case GL_AUTO_NORMAL: case GL_AUX_BUFFERS: case GL_BLEND: case GL_BLEND_DST: case GL_BLEND_EQUATION_EXT: case GL_BLEND_SRC: case GL_BLUE_BIAS: case GL_BLUE_BITS: case GL_BLUE_SCALE: case GL_CLIENT_ATTRIB_STACK_DEPTH: case GL_COLOR_MATERIAL: case GL_COLOR_MATERIAL_FACE: case GL_COLOR_MATERIAL_PARAMETER: case GL_CULL_FACE: case GL_CULL_FACE_MODE: case GL_CURRENT_INDEX: case GL_CURRENT_RASTER_DISTANCE: case GL_CURRENT_RASTER_INDEX: case GL_CURRENT_RASTER_POSITION_VALID: case GL_DEPTH_BIAS: case GL_DEPTH_BITS: case GL_DEPTH_CLEAR_VALUE: case GL_DEPTH_FUNC: case GL_DEPTH_SCALE: case GL_DEPTH_TEST: case GL_DEPTH_WRITEMASK: case GL_DITHER: case GL_DOUBLEBUFFER: case GL_DRAW_BUFFER: case GL_EDGE_FLAG: case GL_FOG_DENSITY: case GL_FOG_END: case GL_FOG_HINT: case GL_FOG_INDEX: case GL_FOG_MODE: case GL_FOG_START: case GL_FRONT_FACE: case GL_GREEN_BIAS: case GL_GREEN_BITS: case GL_GREEN_SCALE: case GL_INDEX_BITS: case GL_INDEX_CLEAR_VALUE: case GL_INDEX_MODE: case GL_INDEX_OFFSET: case GL_INDEX_SHIFT: case GL_INDEX_WRITEMASK: case GL_LIGHTING: case GL_LIGHT_MODEL_LOCAL_VIEWER: case GL_LIGHT_MODEL_TWO_SIDE: case GL_LINE_SMOOTH: case GL_LINE_SMOOTH_HINT: case GL_LINE_STIPPLE: case GL_LINE_STIPPLE_PATTERN: case GL_LINE_STIPPLE_REPEAT: case GL_LINE_WIDTH: case GL_LINE_WIDTH_GRANULARITY: case GL_LIST_BASE: case GL_LIST_INDEX: case GL_LIST_MODE: case GL_LOGIC_OP_MODE: case GL_MAP1_COLOR_4: case GL_MAP1_GRID_SEGMENTS: case GL_MAP1_INDEX: case GL_MAP1_NORMAL: case GL_MAP1_TEXTURE_COORD_1: case GL_MAP1_TEXTURE_COORD_2: case GL_MAP1_TEXTURE_COORD_3: case GL_MAP1_TEXTURE_COORD_4: case GL_MAP1_VERTEX_3: case GL_MAP1_VERTEX_4: case GL_MAP2_INDEX: case GL_MAP2_NORMAL: case GL_MAP2_TEXTURE_COORD_1: case GL_MAP2_TEXTURE_COORD_2: case GL_MAP2_TEXTURE_COORD_3: case GL_MAP2_TEXTURE_COORD_4: case GL_MAP2_VERTEX_3: case GL_MAP2_VERTEX_4: case GL_MAP_COLOR: case GL_MAP_STENCIL: case GL_MATRIX_MODE: case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: case GL_MAX_ATTRIB_STACK_DEPTH: case GL_MAX_CLIP_PLANES: case GL_MAX_EVAL_ORDER: case GL_MAX_LIGHTS: case GL_MAX_LIST_NESTING: case GL_MAX_MODELVIEW_STACK_DEPTH: case GL_MAX_NAME_STACK_DEPTH: case GL_MAX_PIXEL_MAP_TABLE: case GL_MAX_PROJECTION_STACK_DEPTH: case GL_MAX_TEXTURE_SIZE: case GL_MAX_TEXTURE_STACK_DEPTH: case GL_MODELVIEW_STACK_DEPTH: case GL_NAME_STACK_DEPTH: case GL_NORMALIZE: case GL_PACK_ALIGNMENT: case GL_PACK_LSB_FIRST: case GL_PACK_ROW_LENGTH: case GL_PACK_SKIP_PIXELS: case GL_PACK_SKIP_ROWS: case GL_PACK_SWAP_BYTES: case GL_PERSPECTIVE_CORRECTION_HINT: case GL_PIXEL_MAP_A_TO_A_SIZE: case GL_PIXEL_MAP_B_TO_B_SIZE: case GL_PIXEL_MAP_G_TO_G_SIZE: case GL_PIXEL_MAP_I_TO_A_SIZE: case GL_PIXEL_MAP_I_TO_B_SIZE: case GL_PIXEL_MAP_I_TO_G_SIZE: case GL_PIXEL_MAP_I_TO_I_SIZE: case GL_PIXEL_MAP_I_TO_R_SIZE: case GL_PIXEL_MAP_R_TO_R_SIZE: case GL_PIXEL_MAP_S_TO_S_SIZE: case GL_POINT_SIZE: case GL_POINT_SIZE_GRANULARITY: case GL_POINT_SIZE_RANGE: case GL_POINT_SMOOTH: case GL_POINT_SMOOTH_HINT: case GL_POLYGON_SMOOTH: case GL_POLYGON_SMOOTH_HINT: case GL_POLYGON_STIPPLE: case GL_PROJECTION_STACK_DEPTH: case GL_READ_BUFFER: case GL_RED_BIAS: case GL_RED_BITS: case GL_RED_SCALE: case GL_RENDER_MODE: case GL_RGBA_MODE: case GL_SCISSOR_TEST: case GL_SHADE_MODEL: case GL_STENCIL_BITS: case GL_STENCIL_CLEAR_VALUE: case GL_STENCIL_FAIL: case GL_STENCIL_FUNC: case GL_STENCIL_PASS_DEPTH_FAIL: case GL_STENCIL_PASS_DEPTH_PASS: case GL_STENCIL_REF: case GL_STENCIL_TEST: case GL_STENCIL_VALUE_MASK: case GL_STENCIL_WRITEMASK: case GL_STEREO: case GL_SUBPIXEL_BITS: case GL_TEXTURE_1D: case GL_TEXTURE_BINDING_1D: case GL_TEXTURE_2D: case GL_TEXTURE_BINDING_2D: case GL_TEXTURE_GEN_Q: case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_T: case GL_TEXTURE_STACK_DEPTH: case GL_UNPACK_ALIGNMENT: case GL_UNPACK_LSB_FIRST: case GL_UNPACK_ROW_LENGTH: case GL_UNPACK_SKIP_PIXELS: case GL_UNPACK_SKIP_ROWS: case GL_UNPACK_SWAP_BYTES: case GL_ZOOM_X: case GL_ZOOM_Y: return 1; case GL_DEPTH_RANGE: case GL_LINE_WIDTH_RANGE: case GL_MAP1_GRID_DOMAIN: case GL_MAP2_GRID_SEGMENTS: case GL_MAX_VIEWPORT_DIMS: case GL_POLYGON_MODE: return 2; case GL_CURRENT_NORMAL: return 3; case GL_ACCUM_CLEAR_VALUE: case GL_BLEND_COLOR_EXT: case GL_COLOR_CLEAR_VALUE: case GL_COLOR_WRITEMASK: case GL_CURRENT_COLOR: case GL_CURRENT_RASTER_COLOR: case GL_CURRENT_RASTER_POSITION: case GL_CURRENT_RASTER_TEXTURE_COORDS: case GL_CURRENT_TEXTURE_COORDS: case GL_FOG_COLOR: case GL_LIGHT_MODEL_AMBIENT: case GL_MAP2_GRID_DOMAIN: case GL_SCISSOR_BOX: case GL_VIEWPORT: return 4; case GL_MODELVIEW_MATRIX: case GL_PROJECTION_MATRIX: case GL_TEXTURE_MATRIX: return 16; default: { /* GL_LIGHTi = 1 */ static GLint max_lights = 0; if (!max_lights) glGetIntegerv(GL_MAX_LIGHTS, &max_lights); if ((param > GL_LIGHT0) && (param <= (GLenum)(GL_LIGHT0 + max_lights))) return 1; } { /* GL_CLIP_PLANEi = 1 */ static GLint max_clip_planes = 0; if (!max_clip_planes) glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes); if ((param > GL_CLIP_PLANE0) && (param <= (GLenum)(GL_CLIP_PLANE0 + max_clip_planes))) return 1; } croak("Unknown param"); } return 0; // Just to make the compiler happy } int gl_pixelmap_size(GLenum map) { GLint s; switch (map) { case GL_PIXEL_MAP_I_TO_I: glGetIntegerv(GL_PIXEL_MAP_I_TO_I_SIZE, &s); return s; case GL_PIXEL_MAP_S_TO_S: glGetIntegerv(GL_PIXEL_MAP_S_TO_S_SIZE, &s); return s; case GL_PIXEL_MAP_I_TO_R: glGetIntegerv(GL_PIXEL_MAP_I_TO_R_SIZE, &s); return s; case GL_PIXEL_MAP_I_TO_G: glGetIntegerv(GL_PIXEL_MAP_I_TO_G_SIZE, &s); return s; case GL_PIXEL_MAP_I_TO_B: glGetIntegerv(GL_PIXEL_MAP_I_TO_B_SIZE, &s); return s; case GL_PIXEL_MAP_I_TO_A: glGetIntegerv(GL_PIXEL_MAP_I_TO_A_SIZE, &s); return s; case GL_PIXEL_MAP_R_TO_R: glGetIntegerv(GL_PIXEL_MAP_R_TO_R_SIZE, &s); return s; case GL_PIXEL_MAP_G_TO_G: glGetIntegerv(GL_PIXEL_MAP_G_TO_G_SIZE, &s); return s; case GL_PIXEL_MAP_B_TO_B: glGetIntegerv(GL_PIXEL_MAP_B_TO_B_SIZE, &s); return s; case GL_PIXEL_MAP_A_TO_A: glGetIntegerv(GL_PIXEL_MAP_A_TO_A_SIZE, &s); return s; default: croak("unknown pixelmap"); } return 0; // Just to make the compiler happy } int gl_state_count(GLenum state) { switch (state) { case GL_CURRENT_COLOR: return 4; case GL_CURRENT_INDEX: return 1; } return 0; } unsigned long gl_pixelbuffer_size( GLenum format, GLsizei width, GLsizei height, GLenum type, int mode); GLvoid * EL(SV * sv, int needlen) { STRLEN skip = 0; SV * svref; if (SvREADONLY(sv)) croak("Readonly value for buffer"); if(SvROK(sv)) { svref = SvRV(sv); sv = svref; } else { #ifdef USE_STRICT_UNGLOB if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV) sv_unglob(sv); #endif SvUPGRADE(sv, SVt_PV); SvGROW(sv, (unsigned int)(needlen + 1)); SvPOK_on(sv); SvCUR_set(sv, needlen); *SvEND(sv) = '\0'; /* Why is this here? -chm */ } return SvPV_force(sv, skip); } GLvoid * ELI(SV * sv, GLsizei width, GLsizei height, GLenum format, GLenum type, int mode) { int needlen = 0; if (!SvROK(sv)) /* don't calc length if arg is a perl ref */ needlen = gl_pixelbuffer_size(format, width, height, type, mode); return EL(sv, needlen); } int gl_type_size(GLenum type) { switch (type) { #ifdef GL_VERSION_1_2 case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: return sizeof(GLubyte); 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 sizeof(GLushort); 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 sizeof(GLuint); #endif case GL_UNSIGNED_BYTE: return sizeof(GLubyte); break; case GL_BITMAP: return sizeof(GLubyte); break; case GL_BYTE: return sizeof(GLbyte); break; case GL_UNSIGNED_SHORT: return sizeof(GLushort); break; case GL_SHORT: return sizeof(GLshort); break; case GL_UNSIGNED_INT: return sizeof(GLuint); break; case GL_INT: return sizeof(GLint); break; case GL_FLOAT: return sizeof(GLfloat); break; case GL_DOUBLE: return sizeof(GLdouble); break; case GL_2_BYTES: return 2; case GL_3_BYTES: return 3; case GL_4_BYTES: return 4; default: croak("unknown type"); } return 0; // Just to make the compiler happy } int gl_component_count(GLenum format, GLenum type) { int n; switch (format) { #ifdef GL_VERSION_1_2 case GL_BGR: n = 3; break; case GL_BGRA: n = 4; break; #endif /* 18 */ #ifdef GL_EXT_cmyka case GL_CMYK: n = 4; break; case GL_CMYKA: n = 5; break; #endif #ifdef GL_EXT_agbr case GL_AGBR: n = 4; break; #endif case GL_COLOR_INDEX: case GL_STENCIL_INDEX: case GL_DEPTH_COMPONENT: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: n = 1; break; case GL_LUMINANCE_ALPHA: n = 2; break; case GL_RGB: n = 3; break; case GL_RGBA: n = 4; break; default: croak("unknown format"); } #ifdef GL_VERSION_1_2 switch (type) { case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: 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: 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: n = 1; } #endif return n; } /* From Mesa */ /* Compute ceiling of integer quotient of A divided by B: */ #define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) unsigned long gl_pixelbuffer_size( GLenum format, GLsizei width, GLsizei height, GLenum type, int mode) { GLint n; /* elements in a group */ GLint l; /* number of groups in a row */ GLint r; /* pack/unpack row length (overrides l if nonzero) */ GLint s; /* size (in bytes) of an element */ GLint a; /* alignment */ unsigned long k; /* size in bytes of row */ r = 0; a = 4; if (mode == gl_pixelbuffer_pack) { glGetIntegerv(GL_PACK_ROW_LENGTH, &r); glGetIntegerv(GL_PACK_ALIGNMENT, &a); } else if (mode == gl_pixelbuffer_unpack) { glGetIntegerv(GL_UNPACK_ROW_LENGTH, &r); glGetIntegerv(GL_UNPACK_ALIGNMENT, &a); } l = r > 0 ? r : width; s = gl_type_size(type); n = gl_component_count(format, type); /* From Mesa, more or less */ if (type == GL_BITMAP) { k = a * CEILING( n * l, 8 * a); } else { k = l * s * n; if ( s < a ) { k = (a / s * CEILING(k, a)) * s; } } return k * height; } /* Compute ceiling of integer quotient of A divided by B: */ #define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) void gl_pixelbuffer_size2( GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int mode, GLsizei * length, GLsizei * items) { GLint n; /* elements in a group */ GLint l; /* number of groups in a row */ GLint s; /* size (in bytes) of an element */ GLint a; /* alignment */ unsigned long k; /* size in bytes of row */ a = 4; l = width; if (mode == gl_pixelbuffer_pack) { glGetIntegerv(GL_PACK_ROW_LENGTH, &l); glGetIntegerv(GL_PACK_ALIGNMENT, &a); } else if (mode == gl_pixelbuffer_unpack) { glGetIntegerv(GL_UNPACK_ROW_LENGTH, &l); glGetIntegerv(GL_UNPACK_ALIGNMENT, &a); } s = gl_type_size(type); n = gl_component_count(format, type); /* From Mesa, more or less */ if (type == GL_BITMAP) { k = a * CEILING( n * l, 8 * a); } else { k = l * s * n; if ( s < a ) { k = (a / s * CEILING(k, a)) * s; } } *items = l * n * height * depth; *length = (k * height * depth); } void pgl_set_type(SV * sv, GLenum type, void ** ptr) { #define RIV(t) \ (*(t*)*ptr) = (t)SvIV(sv); \ *(unsigned char**)ptr += sizeof(t);\ break; #define RNV(t) \ (*(t*)*ptr) = (t)SvNV(sv); \ *(unsigned char**)ptr += sizeof(t);\ break; switch (type) { #ifdef GL_VERSION_1_2 case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: RIV(GLubyte) 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: RIV(GLushort) 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: RIV(GLuint) #endif case GL_UNSIGNED_BYTE: case GL_BITMAP: case GL_BYTE: RIV(GLubyte) case GL_UNSIGNED_SHORT: case GL_SHORT: RIV(GLushort) case GL_UNSIGNED_INT: case GL_INT: RIV(GLuint) case GL_FLOAT: RNV(GLfloat) case GL_DOUBLE: RNV(GLdouble) case GL_2_BYTES: { unsigned long v = SvIV(sv); (*(GLubyte*)*ptr) = (GLubyte)(v >> 8); *(unsigned char**)ptr++; (*(GLubyte*)*ptr) = (GLubyte)(v & 0xff); *(unsigned char**)ptr++; break; } case GL_3_BYTES: { unsigned long v = SvIV(sv); (*(GLubyte*)*ptr) = (GLubyte)((v >> 16) & 0xff); *(unsigned char**)ptr++; (*(GLubyte*)*ptr) = (GLubyte)((v >> 8) & 0xff); *(unsigned char**)ptr++; (*(GLubyte*)*ptr) = (GLubyte)((v >> 0) & 0xff); *(unsigned char**)ptr++; break; } case GL_4_BYTES: { unsigned long v = SvIV(sv); (*(GLubyte*)*ptr) = (GLubyte)((v >> 24) & 0xff); *(unsigned char**)ptr++; (*(GLubyte*)*ptr) = (GLubyte)((v >> 16) & 0xff); *(unsigned char**)ptr++; (*(GLubyte*)*ptr) = (GLubyte)((v >> 8) & 0xff); *(unsigned char**)ptr++; (*(GLubyte*)*ptr) = (GLubyte)((v >> 0) & 0xff); *ptr++; break; } default: croak("Unable to set data with unknown type"); } #undef RIV #undef RNV } SV * pgl_get_type(GLenum type, void ** ptr) { SV * result = 0; #define RIV(t) \ result = newSViv((*(t*)*ptr)); \ *(unsigned char**)ptr += sizeof(t); \ break; #define RNV(t) \ result = newSVnv((*(t*)*ptr)); \ *(unsigned char**)ptr += sizeof(t); \ break; switch (type) { #ifdef GL_VERSION_1_2 case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: RIV(GLubyte) 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: RIV(GLushort) 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: RIV(GLuint) #endif case GL_UNSIGNED_BYTE: case GL_BITMAP: case GL_BYTE: RIV(GLubyte) case GL_UNSIGNED_SHORT: case GL_SHORT: RIV(GLushort) case GL_UNSIGNED_INT: case GL_INT: RIV(GLuint) case GL_FLOAT: RNV(GLfloat) case GL_DOUBLE: RNV(GLdouble) case GL_2_BYTES: { unsigned long v; v = (*(GLubyte*)*ptr) << 8; *(unsigned char**)ptr++; v |= (*(GLubyte*)*ptr) << 0; *(unsigned char**)ptr++; result = newSViv(v); break; } case GL_3_BYTES: { unsigned long v; v = (*(GLubyte*)*ptr) << 16; *(unsigned char**)ptr++; v |= (*(GLubyte*)*ptr) << 8; *(unsigned char**)ptr++; v |= (*(GLubyte*)*ptr) << 0; *(unsigned char**)ptr++; result = newSViv(v); break; } case GL_4_BYTES: { unsigned long v; v = (*(GLubyte*)*ptr) << 24; *(unsigned char**)ptr++; v |= (*(GLubyte*)*ptr) << 16; *(unsigned char**)ptr++; v |= (*(GLubyte*)*ptr) << 8; *(unsigned char**)ptr++; v |= (*(GLubyte*)*ptr) << 0; *(unsigned char**)ptr++; result = newSViv(v); break; } default: croak("Unable to get data with unknown type"); } return result; #undef RIV #undef RNV } GLvoid * pack_image_ST(SV ** stack, int count, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int mode) { int i; void * ptr, * optr; GLsizei size, max; gl_pixelbuffer_size2(width, height, depth, format, type, mode, &size, &max); optr = ptr = malloc(size); for (i=0;i= 0) { SV ** sv; sv = av_fetch(ast[level], apos[level]++, 0); if (!sv) { level--; continue; } if (SvROK(*sv)) { if (SvTYPE(SvRV(*sv)) != SVt_PVAV) { croak("Weird nest 2"); } level++; if (level >= 8) goto too_many_levels; ast[level] = (AV*)SvRV(*sv); apos[level] = 0; } else { if (!max--) goto too_much_data; pgl_set_type(*sv, type, &ptr); } } } else { if (!max--) goto too_much_data; pgl_set_type(stack[i], type, &ptr); } } if (max>0) goto too_little_data; return optr; too_little_data: croak("too little data"); too_much_data: croak("too much data"); too_many_levels: croak("too many levels"); return 0; // Just to make the compiler happy } GLvoid * allocate_image_ST(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int mode) { //int i; void * ptr; GLsizei size, max; gl_pixelbuffer_size2(width, height, depth, format, type, mode, &size, &max); ptr = malloc(size); return ptr; } SV ** unpack_image_ST(SV ** SP, void * data, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int mode) { #define sp SP int i; GLsizei size, max; gl_pixelbuffer_size2(width, height, depth, format, type, mode, &size, &max); EXTEND(sp, max); for (i=0;ikeycode < 256) *ks = (KeySym)xkey->keycode; else if (xkey->keycode == 256 + VK_ESC) *ks = (KeySym)27; else if (xkey->keycode == 256 + VK_ENTER) *ks = (KeySym)'\n'; else if (xkey->keycode == 256 + VK_SPACE) *ks = (KeySym)' '; else if (xkey->keycode == 256 + VK_TAB) *ks = (KeySym)'\t'; else *ks = (KeySym)'\0'; } static MRESULT EXPENTRY WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { static float t = 0.0; static SWP clientsize; static USHORT mycode; static ULONG key; switch(msg) { case WM_SIZE: WinQueryWindowPos(hwnd,&clientsize); if (LastEventMask & StructureNotifyMask) { XEvent x; SV *ev; x.type = ConfigureNotify; x.xconfigure.width = clientsize.cx; x.xconfigure.height = clientsize.cy; av_push(EventAv, newSVpv((char*)&x,sizeof(XEvent))); } else { /* Upon a resize, query new window size and set OpenGL viewport */ glViewport(0, 0, clientsize.cx, clientsize.cy); } return WinDefWindowProc(hwnd, msg, mp1, mp2); case WM_TIMER: /* Upon getting a timer message, the invalidate rectangle call */ /* will cause a WM_PAINT message to be sent, enabling animation */ WinInvalidateRect(hwnd, NULLHANDLE, 0); return WinDefWindowProc(hwnd, msg, mp1, mp2); case WM_PAINT: if (LastEventMask & ExposureMask) { XEvent x; SV *ev; x.type = Expose; av_push(EventAv, newSVpv((char*)&x,sizeof(XEvent))); } return WinDefWindowProc(hwnd, msg, mp1, mp2); case WM_CHAR: mycode = (USHORT)SHORT1FROMMP(mp1); if ((mycode & KC_CHAR) && !(mycode & KC_KEYUP)) key = CHAR1FROMMP(mp2); else if ((mycode & KC_VIRTUALKEY) && !(mycode & KC_KEYUP)) key = CHAR3FROMMP(mp2) + 256; else key = 0; if (key && (LastEventMask & KeyPressMask)) { XEvent x; SV *ev; x.type = KeyPress; x.xkey.keycode = key; av_push(EventAv, newSVpv((char*)&x,sizeof(XEvent))); } return WinDefWindowProc(hwnd, msg, mp1, mp2); default: return WinDefWindowProc(hwnd, msg, mp1, mp2); } } struct Tk_Window_t {long type; HWND w;}; Window nativeWindowId(Display *d, Window id) { if (!WinIsWindow(*d,id)) /* Tk handle? */ return ((struct Tk_Window_t*)id)->w; return id; } Window MyCreateWindow(Display *d, Window par, int x, int y, int w, int h) { HWND hwnd = 0, hwndTop; int err; /* fprintf(stderr, "Creating with parent=%#lx.\n", (long)par); */ if (par != HWND_DESKTOP) { ULONG createflags = 0; par = nativeWindowId(d, par); /* fprintf(stderr, "Creating with parent=%#lx.\n", (long)par); */ if (!WinRegisterClass( Perl_hab, (PSZ)"PerlGLkid", WindowProc, CS_MOVENOTIFY, /* Need at least this! */ /* As documented CS_SIZEREDRAW is needed too... */ /* But this would not improve the visual appearence... */ 0)) croak("Cannot register class"); err = CheckWinError( hwnd = WinCreateWindow( par, /* Parent */ (PSZ)"PerlGLkid", /* class name */ NULL, /* window title */ WS_VISIBLE, /* Window style */ x,y,w,h, par, /* Owner */ HWND_TOP, /* Position */ FID_CLIENT, /* Standard id */ 0, /* No class data */ 0)); /* No presentation parameters */ } else { ULONG createflags = FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX | FCF_TASKLIST | FCF_SIZEBORDER; if (!WinRegisterClass( Perl_hab, (PSZ)"PerlGLtop", WindowProc, CS_SIZEREDRAW | CS_MOVENOTIFY, /* Need at least this! */ 0)) croak("Cannot register class"); err = CheckWinError( hwndTop = WinCreateStdWindow( par, /* Parent */ WS_VISIBLE, /* Frame style */ &createflags, /* min FCF_MENU|FCF_MINMAX */ (PSZ)"PerlGLtop", /* class name */ "OpenGL Sample",/* window title */ WS_VISIBLE, /* client style */ 0, /* resource handle */ 1, /* Resource ID */ &hwnd)); } if (err) croak("Cannot create window, $^E=%#x", WinGetLastError(*d)); if (!hwnd) croak("Error creating window"); /* you must set window size before you call pglMakeCurrent */ if ((par == HWND_DESKTOP) && !WinSetWindowPos( hwndTop, HWND_TOP, x, y, w, /* XXXX Add border! */ h, SWP_ACTIVATE | SWP_SIZE | SWP_MOVE | SWP_SHOW)) croak("Couldn't position window!\n"); return hwnd; } void glpMoveResizeWindow(int x, int y, unsigned int width, unsigned int height, Window w, Display* display) { SWP parPos; w = nativeWindowId(display, w); WinQueryWindowPos(WinQueryWindow(w, QW_PARENT), &parPos); /* Translate Y coordinates to PM: relative to parent */ WinSetWindowPos(w, HWND_TOP, x, parPos.cy - height - y, width, height, SWP_MOVE | SWP_SIZE); } void glpMoveWindow(int x, int y, Window w, Display* display) { SWP parPos; SWP myPos; w = nativeWindowId(display, w); WinQueryWindowPos(WinQueryWindow(w, QW_PARENT), &parPos); WinQueryWindowPos(w, &myPos); /* Translate Y coordinates to PM: relative to parent */ WinSetWindowPos(w, HWND_TOP, x, parPos.cy - myPos.cy - y, 0, 0, SWP_MOVE); } void glpResizeWindow(unsigned int width, unsigned int height, Window w, Display* display) { SWP parPos; SWP myPos; w = nativeWindowId(display, w); WinQueryWindowPos(WinQueryWindow(w, QW_PARENT), &parPos); WinQueryWindowPos(w, &myPos); /* Translate Y coordinates to PM: relative to parent... */ /* Need to move too to leave the upper left corner at the same place... */ WinSetWindowPos(w, HWND_TOP, myPos.x, parPos.cy - myPos.cy - myPos.y, width, height, SWP_MOVE | SWP_SIZE); } void morphPM() { PPIB pib; PTIB tib; DosGetInfoBlocks(&tib, &pib); if (pib->pib_ultype != 3) /* 2 is VIO */ pib->pib_ultype = 3; /* 3 is PM */ } #undef glutCreateWindow int my_glutCreateWindow(name) { morphPM(); return glutCreateWindow(name); } #endif