From 24e2ebd8099c23191b021150e2422a00d9913aac Mon Sep 17 00:00:00 2001 From: Chris Marshall Date: Mon, 7 Aug 2017 17:13:00 -0400 Subject: [PATCH] Add some xs for gpgpu and _o GL routines Still need to figure out how to merged this into OpenGL::Modern in a clean way. This appears to include the main functions of concern. --- gpgpu_gl.xs | 246 +++++++++++++ pogl_gl_oga_p_funs.xs | 817 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1063 insertions(+) create mode 100644 gpgpu_gl.xs create mode 100644 pogl_gl_oga_p_funs.xs diff --git a/gpgpu_gl.xs b/gpgpu_gl.xs new file mode 100644 index 0000000..cf7ff93 --- /dev/null +++ b/gpgpu_gl.xs @@ -0,0 +1,246 @@ +/* Last saved: Mon 07 Aug 2017 04:53:34 PM */ + +/* Copyright (c) 1998 Kenneth Albanowski. All rights reserved. + * Copyright (c) 2007 Bob Free. All rights reserved. + * Copyright (c) 2009 Chris Marshall. All rights reserved. + * This program is free software; you can redistribute it and/or + * modify it under the same terms as Perl itself. + */ + +#include + +#include "pgopogl.h" + +#ifdef HAVE_GL +#include "gl_util.h" + +/* Note: this is caching procs once for all contexts */ +/* !!! This should instead cache per context */ +#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_W32API)) +#define loadProc(proc,name) \ +{ \ + if (!proc) \ + { \ + proc = (void *)wglGetProcAddress(name); \ + if (!proc) croak(name " is not supported by this renderer"); \ + } \ +} +#define testProc(proc,name) ((proc) ? 1 : !!(proc = (void *)wglGetProcAddress(name))) +#else /* not using WGL */ +#define loadProc(proc,name) +#define testProc(proc,name) 1 +#endif /* not defined _WIN32, __CYGWIN__, and HAVE_W32API */ +#endif /* defined HAVE_GL */ + + +/********************/ +/* GPGPU Utils */ +/********************/ + +GLint FBO_MAX = -1; + +/* Get max GPGPU data size */ +int gpgpu_size(void) +{ +#if defined(GL_ARB_texture_rectangle) && defined(GL_ARB_texture_float) && \ + defined(GL_ARB_fragment_program) && defined(GL_EXT_framebuffer_object) + if (FBO_MAX == -1) + { + if (testProc(glProgramStringARB,"glProgramStringARB") && + testProc(glGenProgramsARB,"glGenProgramsARB") && + testProc(glBindProgramARB,"glBindProgramARB") && + testProc(glIsProgramARB,"glIsProgramARB") && + testProc(glProgramLocalParameter4fvARB,"glProgramLocalParameter4fvARB") && + testProc(glDeleteProgramsARB,"glDeleteProgramsARB") && + testProc(glGenFramebuffersEXT,"glGenFramebuffersEXT") && + testProc(glGenRenderbuffersEXT,"glGenRenderbuffersEXT") && + testProc(glBindFramebufferEXT,"glBindFramebufferEXT") && + testProc(glFramebufferTexture2DEXT,"glFramebufferTexture2DEXT") && + testProc(glBindRenderbufferEXT,"glBindRenderbufferEXT") && + testProc(glRenderbufferStorageEXT,"glRenderbufferStorageEXT") && + testProc(glFramebufferRenderbufferEXT,"glFramebufferRenderbufferEXT") && + testProc(glCheckFramebufferStatusEXT,"glCheckFramebufferStatusEXT") && + testProc(glDeleteRenderbuffersEXT,"glDeleteRenderbuffersEXT") && + testProc(glDeleteFramebuffersEXT,"glDeleteFramebuffersEXT")) + { + glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT,&FBO_MAX); + } + else + { + FBO_MAX = 0; + } + } + return(FBO_MAX); +#else + return(0); +#endif +} + +/* Get max square array width for a given GPGPU data size */ +int gpgpu_width(int len) +{ + int max = gpgpu_size(); + if (max && len && !(len%3)) + { + int count = len / 3; + int w = (int)sqrt(count); + + while ((w <= count) && (w <= max)) + { + if (!(count%w)) return(w); + w++; + } + } + return(0); +} + +#ifdef GL_ARB_fragment_program +static char affine_prog[] = + "!!ARBfp1.0\n" + "PARAM affine[4] = {program.local[0..3]};\n" + "TEMP decal;\n" + "TEX decal, fragment.texcoord[0], texture[0], RECT;\n" + "MOV decal.w, 1.0;\n" + "DP4 result.color.x, decal, affine[0];\n" + "DP4 result.color.y, decal, affine[1];\n" + "DP4 result.color.z, decal, affine[2];\n" + "END\n"; + +/* Enable affine shader program */ +void enable_affine(oga_struct * oga) +{ + if (!oga) return; + if (!oga->affine_handle) + { + /* Load shader program */ + glGenProgramsARB(1,&oga->affine_handle); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,oga->affine_handle); + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, + GL_PROGRAM_FORMAT_ASCII_ARB, strlen(affine_prog),affine_prog); + + /* Validate shader program */ + if (!glIsProgramARB(oga->affine_handle)) + { + GLint errorPos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&errorPos); + if (errorPos < 0) errorPos = strlen(affine_prog); + croak("Affine fragment program error\n%s",&affine_prog[errorPos]); + } + } + glEnable(GL_FRAGMENT_PROGRAM_ARB); +} + +/* Disable affine shader program */ +void disable_affine(oga_struct * oga) +{ + if (!oga) return; + if (oga->affine_handle) glDisable(GL_FRAGMENT_PROGRAM_ARB); +} +#endif + +#ifdef GL_EXT_framebuffer_object +/* Unbind an FBO to an OGA */ +void release_fbo(oga_struct * oga) +{ + if (oga->fbo_handle) + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1,&oga->fbo_handle); + } + + if (oga->tex_handle[0] || oga->tex_handle[1]) + { + glBindTexture(oga->target,0); + if (oga->tex_handle[0]) glDeleteTextures(1,&oga->tex_handle[0]); + if (oga->tex_handle[1]) glDeleteTextures(1,&oga->tex_handle[1]); + } +} + +/* Enable an FBO bound to an OGA */ +void enable_fbo(oga_struct * oga, int w, int h, GLuint target, + GLuint pixel_type, GLuint pixel_format, GLuint element_size) +{ + if (!oga) return; + + if ((oga->fbo_w != w) || (oga->fbo_h != h) || + (oga->target != target) || + (oga->pixel_type != pixel_type) || + (oga->pixel_format != pixel_format) || + (oga->element_size != element_size)) release_fbo(oga); + + if (!oga->fbo_handle) + { + GLenum status; + + /* Save params */ + oga->fbo_w = w; + oga->fbo_h = h; + oga->target = target; + oga->pixel_type = pixel_type; + oga->pixel_format = pixel_format; + oga->element_size = element_size; + + /* Set up FBO */ + glGenTextures(2,oga->tex_handle); + glGenFramebuffersEXT(1,&oga->fbo_handle); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,oga->fbo_handle); + + glViewport(0,0,w,h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0,w,0,h); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glBindTexture(target,oga->tex_handle[1]); + glTexParameteri(target,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(target,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(target,GL_TEXTURE_WRAP_S,GL_CLAMP); + glTexParameteri(target,GL_TEXTURE_WRAP_T,GL_CLAMP); + + glTexImage2D(target,0,pixel_type,w,h,0, + pixel_format,element_size,0); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT,target,oga->tex_handle[1],0); + + status = glCheckFramebufferStatusEXT(GL_RENDERBUFFER_EXT); + if (status) croak("enable_fbo status: %04X\n",status); + } + else + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,oga->fbo_handle); + } + + /* Load data */ + glBindTexture(target,oga->tex_handle[0]); + glTexImage2D(target,0,pixel_type,w,h,0, + pixel_format,element_size,oga->data); + + glEnable(target); + //glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBindTexture(target,oga->tex_handle[0]); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); +} + +/* Disable an FBO bound to an OGA */ +void disable_fbo(oga_struct * oga) +{ + if (!oga) return; + if (oga->fbo_handle) + { + glDisable(oga->target); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); + } +} +#endif + +MODULE = OpenGL::Array PACKAGE = OpenGL::Array + +#//# glpHasGPGPU(); +int +glpHasGPGPU() + CODE: + RETVAL = gpgpu_size(); + OUTPUT: + RETVAL diff --git a/pogl_gl_oga_p_funs.xs b/pogl_gl_oga_p_funs.xs new file mode 100644 index 0000000..ff99659 --- /dev/null +++ b/pogl_gl_oga_p_funs.xs @@ -0,0 +1,817 @@ +/* Last saved: Mon 07 Aug 2017 05:11:17 PM */ + +/* Copyright (c) 1998 Kenneth Albanowski. All rights reserved. + * Copyright (c) 2007 Bob Free. All rights reserved. + * Copyright (c) 2009 Chris Marshall. All rights reserved. + * This program is free software; you can redistribute it and/or + * modify it under the same terms as Perl itself. + */ + +#include + +#include "pgopogl.h" + +#include "gl_util.h" + +/* Note: this is caching procs once for all contexts */ +/* !!! This should instead cache per context */ +#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_W32API)) +#define loadProc(proc,name) \ +{ \ + if (!proc) \ + { \ + proc = (void *)wglGetProcAddress(name); \ + if (!proc) croak(name " is not supported by this renderer"); \ + } \ +} +#define testProc(proc,name) ((proc) ? 1 : !!(proc = (void *)wglGetProcAddress(name))) +#else /* not using WGL */ +#define loadProc(proc,name) +#define testProc(proc,name) 1 +#endif /* not defined _WIN32, __CYGWIN__, and HAVE_W32API */ + + +MODULE = OpenGL::GL::OGA PACKAGE = OpenGL::Array + + + +#if defined(GL_VERSION_1_1) || defined(GL_EXT_vertex_array) + +#//# glVertexPointerEXT_p($size, (OGA)pointer); +void +glVertexPointerEXT_p(size, oga) + GLint size + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glVertexPointerEXT,"glVertexPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glVertexPointer(size, oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glVertexPointerEXT(size, oga->types[0], 0, oga->item_count/size, data); +#endif + } + +#//# glVertexPointer_p($size, (OGA)pointer); +void +glVertexPointer_p(size, oga) + GLint size + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glVertexPointerEXT,"glVertexPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glVertexPointer(size, oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glVertexPointerEXT(size, oga->types[0], 0, oga->item_count/size, data); +#endif + } + + +#//# glNormalPointerEXT_p((OGA)pointer); +void +glNormalPointerEXT_p(oga) + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glNormalPointerEXT,"glNormalPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glNormalPointer(oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glNormalPointerEXT(oga->types[0], 0, oga->item_count/3, data); +#endif + } + +#//# glNormalPointer_p((OGA)pointer); +void +glNormalPointer_p(oga) + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glNormalPointerEXT,"glNormalPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glNormalPointer(oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glNormalPointerEXT(oga->types[0], 0, oga->item_count/3, data); +#endif + } + + +#//# glColorPointerEXT_p($size, (OGA)pointer); +void +glColorPointerEXT_p(size, oga) + GLint size + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glColorPointerEXT,"glColorPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glColorPointer(size, oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glColorPointerEXT(size, oga->types[0], 0, oga->item_count/size, data); +#endif + } + +#//# glColorPointer_p($size, (OGA)pointer); +void +glColorPointer_p(size, oga) + GLint size + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glColorPointerEXT,"glColorPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glColorPointer(size, oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glColorPointerEXT(size, oga->types[0], 0, oga->item_count/size, data); +#endif + } + + +#//# glIndexPointerEXT_p((OGA)pointer); +void +glIndexPointerEXT_p(oga) + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glIndexPointerEXT,"glIndexPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glIndexPointer(oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glIndexPointerEXT(oga->types[0], 0, oga->item_count, data); +#endif + } + +#//# glIndexPointer_p((OGA)pointer); +void +glIndexPointer_p(oga) + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glIndexPointerEXT,"glIndexPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glIndexPointer(oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glIndexPointerEXT(oga->types[0], 0, oga->item_count, data); +#endif + } + + +#//# glTexCoordPointerEXT_p($size, (OGA)pointer); +void +glTexCoordPointerEXT_p(size, oga) + GLint size + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glTexCoordPointerEXT,"glTexCoordPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glTexCoordPointer(size, oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glTexCoordPointerEXT(size, oga->types[0], 0, oga->item_count/size, data); +#endif + } + +#//# glTexCoordPointer_p($size, (OGA)pointer); +void +glTexCoordPointer_p(size, oga) + GLint size + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glTexCoordPointerEXT,"glTexCoordPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glTexCoordPointer(size, oga->types[0], 0, data); +#else // GL_EXT_vertex_array + glTexCoordPointerEXT(size, oga->types[0], 0, oga->item_count/size, data); +#endif + } + + +#//# glEdgeFlagPointerEXT_p((OGA)pointer); +void +glEdgeFlagPointerEXT_p(oga) + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glTexCoordPointerEXT,"glEdgeFlagPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glEdgeFlagPointer(0, data); +#else // GL_EXT_vertex_array + glEdgeFlagPointerEXT(0, oga->item_count, data); +#endif + } + +#//# glEdgeFlagPointer_p((OGA)pointer); +void +glEdgeFlagPointer_p(oga) + OpenGL::Array oga + INIT: +#ifndef GL_VERSION_1_1 // GL_EXT_vertex_array + loadProc(glTexCoordPointerEXT,"glEdgeFlagPointerEXT"); +#endif + CODE: + { + GLvoid * data = oga->data; +#ifdef GL_VERSION_2_0 + glBindBuffer(GL_ARRAY_BUFFER, oga->bind); + data = NULL; +#elif defined(GL_ARB_vertex_buffer_object) + if (testProc(glBindBufferARB,"glBindBufferARB")) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, oga->bind); + data = NULL; + } +#endif +#ifdef GL_VERSION_1_1 + glEdgeFlagPointer(0, data); +#else // GL_EXT_vertex_array + glEdgeFlagPointerEXT(0, oga->item_count, data); +#endif + } + +#endif // GL_EXT_vertex_array || GL_VERSION_1_1 + + +#ifdef GL_VERSION_1_4 + +#//# glBufferData_p($target,(OGA)data,$usage); +void +glBufferData_p(target,oga,usage) + GLenum target + OpenGL::Array oga + GLenum usage + CODE: + { + glBufferData(target,oga->data_length,oga->data,usage); + } + + +#//# glBufferSubData_p($target,$offset,(OGA)data); +void +glBufferSubData_p(target,offset,oga) + GLenum target + GLint offset + OpenGL::Array oga + CODE: + { + glBufferSubData(target,offset*oga->total_types_width,oga->data_length,oga->data); + } + + +#//# $oga = glGetBufferSubData_p($target,$offset,$count,@types); +#//- If no types are provided, GLubyte is assumed +OpenGL::Array +glGetBufferSubData_p(target,offset,count,...) + GLenum target + GLint offset + GLsizei count + CODE: + { + oga_struct * oga = malloc(sizeof(oga_struct)); + GLint size; + + oga->item_count = count; + oga->type_count = (items - 3); + + if (oga->type_count) + { + int i,j; + + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + for(i=0,j=0;itype_count;i++) { + oga->types[i] = SvIV(ST(i+3)); + oga->type_offset[i] = j; + j += gl_type_size(oga->types[i]); + } + oga->total_types_width = j; + } + else + { + oga->type_count = 1; + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + + oga->types[0] = GL_UNSIGNED_BYTE; + oga->type_offset[0] = 0; + oga->total_types_width = gl_type_size(oga->types[0]); + } + if (!oga->total_types_width) croak("Unable to determine type sizes\n"); + + glGetBufferParameteriv(target,GL_BUFFER_SIZE,&size); + size /= oga->total_types_width; + if (offset > size) croak("Offset is greater than elements in buffer: %d\n",size); + + if ((offset+count) > size) count = size - offset; + + oga->data_length = oga->total_types_width * count; + oga->data = malloc(oga->data_length); + + glGetBufferSubData(target,offset*oga->total_types_width, + oga->data_length,oga->data); + + oga->free_data = 1; + + RETVAL = oga; + } + OUTPUT: + RETVAL + + +#define FIXME /* !!! Need to refactor with glGetBufferPointerv_p */ + +#//# $oga = glMapBuffer_p($target,$access,@types); +#//- If no types are provided, GLubyte is assumed +OpenGL::Array +glMapBuffer_p(target,access,...) + GLenum target + GLenum access + CODE: + { + GLsizeiptr size; + oga_struct * oga; + int i,j; + + void * buffer = glMapBuffer(target,access); + if (!buffer) croak("Unable to map buffer\n"); + + glGetBufferParameteriv(target,GL_BUFFER_SIZE,(GLint*)&size); + if (!size) croak("Buffer has no size\n"); + + oga = malloc(sizeof(oga_struct)); + + oga->type_count = (items - 2); + + if (oga->type_count) + { + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + for(i=0,j=0;itype_count;i++) { + oga->types[i] = SvIV(ST(i+2)); + oga->type_offset[i] = j; + j += gl_type_size(oga->types[i]); + } + oga->total_types_width = j; + } + else + { + oga->type_count = 1; + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + + oga->types[0] = GL_UNSIGNED_BYTE; + oga->type_offset[0] = 0; + oga->total_types_width = gl_type_size(oga->types[0]); + } + + if (!oga->total_types_width) croak("Unable to determine type sizes\n"); + oga->item_count = size / oga->total_types_width; + + oga->data_length = oga->total_types_width * oga->item_count; + + oga->data = buffer; + + oga->free_data = 0; + + RETVAL = oga; + } + OUTPUT: + RETVAL + + +#//# $oga = glGetBufferPointerv_p($target,$pname,@types); +#//- If no types are provided, GLubyte is assumed +OpenGL::Array +glGetBufferPointerv_p(target,pname,...) + GLenum target + GLenum pname + CODE: + { + GLsizeiptr size; + oga_struct * oga; + void * buffer; + int i,j; + + glGetBufferPointerv(target,pname,&buffer); + if (!buffer) croak("Buffer is not mapped\n"); + + glGetBufferParameteriv(target,GL_BUFFER_SIZE,(GLint*)&size); + if (!size) croak("Buffer has no size\n"); + + oga = malloc(sizeof(oga_struct)); + + oga->type_count = (items - 2); + + if (oga->type_count) + { + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + for(i=0,j=0;itype_count;i++) { + oga->types[i] = SvIV(ST(i+2)); + oga->type_offset[i] = j; + j += gl_type_size(oga->types[i]); + } + oga->total_types_width = j; + } + else + { + oga->type_count = 1; + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + + oga->types[0] = GL_UNSIGNED_BYTE; + oga->type_offset[0] = 0; + oga->total_types_width = gl_type_size(oga->types[0]); + } + + if (!oga->total_types_width) croak("Unable to determine type sizes\n"); + oga->item_count = size / oga->total_types_width; + + oga->data_length = oga->total_types_width * oga->item_count; + + oga->data = buffer; + + oga->free_data = 0; + + RETVAL = oga; + } + OUTPUT: + RETVAL + +#endif // GL_VERSION_1_4 + + +#ifdef GL_ARB_vertex_buffer_object + +#//# glBufferDataARB_p($target,(OGA)data,$usage); +void +glBufferDataARB_p(target,oga,usage) + GLenum target + OpenGL::Array oga + GLenum usage + INIT: + loadProc(glBufferDataARB,"glBufferDataARB"); + CODE: + { + glBufferDataARB(target,oga->data_length,oga->data,usage); + } + +#//# glBufferSubDataARB_p($target,$offset,(OGA)data); +void +glBufferSubDataARB_p(target,offset,oga) + GLenum target + GLint offset + OpenGL::Array oga + INIT: + loadProc(glBufferSubDataARB,"glBufferSubDataARB"); + CODE: + { + glBufferSubDataARB(target,offset*oga->total_types_width,oga->data_length,oga->data); + } + + +#//# $oga = glGetBufferSubDataARB_p($target,$offset,$count,@types); +#//- If no types are provided, GLubyte is assumed +OpenGL::Array +glGetBufferSubDataARB_p(target,offset,count,...) + GLenum target + GLint offset + GLsizei count + INIT: + loadProc(glGetBufferSubDataARB,"glGetBufferSubDataARB"); + loadProc(glGetBufferParameterivARB,"glGetBufferParameterivARB"); + CODE: + { + oga_struct * oga = malloc(sizeof(oga_struct)); + GLint size; + + oga->item_count = count; + oga->type_count = (items - 3); + + if (oga->type_count) + { + int i,j; + + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + for(i=0,j=0;itype_count;i++) { + oga->types[i] = SvIV(ST(i+3)); + oga->type_offset[i] = j; + j += gl_type_size(oga->types[i]); + } + oga->total_types_width = j; + } + else + { + oga->type_count = 1; + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + + oga->types[0] = GL_UNSIGNED_BYTE; + oga->type_offset[0] = 0; + oga->total_types_width = gl_type_size(oga->types[0]); + } + if (!oga->total_types_width) croak("Unable to determine type sizes\n"); + + glGetBufferParameterivARB(target,GL_BUFFER_SIZE_ARB,&size); + size /= oga->total_types_width; + if (offset > size) croak("Offset is greater than elements in buffer: %d\n",size); + + if ((offset+count) > size) count = size - offset; + + oga->data_length = oga->total_types_width * count; + oga->data = malloc(oga->data_length); + + glGetBufferSubDataARB(target,offset*oga->total_types_width, + oga->data_length,oga->data); + + oga->free_data = 1; + + RETVAL = oga; + } + OUTPUT: + RETVAL + + +#define FIXME /* !!! Need to refactor with glGetBufferPointervARB_p */ + +#//# $oga = glMapBufferARB_p($target,$access,@types); +#//- If no types are provided, GLubyte is assumed +OpenGL::Array +glMapBufferARB_p(target,access,...) + GLenum target + GLenum access + INIT: + loadProc(glMapBufferARB,"glMapBufferARB"); + loadProc(glGetBufferParameterivARB,"glGetBufferParameterivARB"); + CODE: + { + GLsizeiptrARB size; + oga_struct * oga; + int i,j; + + void * buffer = glMapBufferARB(target,access); + if (!buffer) croak("Unable to map buffer\n"); + + glGetBufferParameterivARB(target,GL_BUFFER_SIZE_ARB,(GLint*)&size); + if (!size) croak("Buffer has no size\n"); + + oga = malloc(sizeof(oga_struct)); + + oga->type_count = (items - 2); + + if (oga->type_count) + { + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + for(i=0,j=0;itype_count;i++) { + oga->types[i] = SvIV(ST(i+2)); + oga->type_offset[i] = j; + j += gl_type_size(oga->types[i]); + } + oga->total_types_width = j; + } + else + { + oga->type_count = 1; + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + + oga->types[0] = GL_UNSIGNED_BYTE; + oga->type_offset[0] = 0; + oga->total_types_width = gl_type_size(oga->types[0]); + } + + if (!oga->total_types_width) croak("Unable to determine type sizes\n"); + oga->item_count = size / oga->total_types_width; + + oga->data_length = oga->total_types_width * oga->item_count; + + oga->data = buffer; + + oga->free_data = 0; + + RETVAL = oga; + } + OUTPUT: + RETVAL + + +#//# $oga = glGetBufferPointervARB_p($target,$pname,@types); +#//- If no types are provided, GLubyte is assumed +OpenGL::Array +glGetBufferPointervARB_p(target,pname,...) + GLenum target + GLenum pname + INIT: + loadProc(glGetBufferPointervARB,"glGetBufferPointervARB"); + loadProc(glGetBufferParameterivARB,"glGetBufferParameterivARB"); + CODE: + { + GLsizeiptrARB size; + oga_struct * oga; + void * buffer; + int i,j; + + glGetBufferPointervARB(target,pname,&buffer); + if (!buffer) croak("Buffer is not mapped\n"); + + glGetBufferParameterivARB(target,GL_BUFFER_SIZE_ARB,(GLint*)&size); + if (!size) croak("Buffer has no size\n"); + + oga = malloc(sizeof(oga_struct)); + + oga->type_count = (items - 2); + + if (oga->type_count) + { + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + for(i=0,j=0;itype_count;i++) { + oga->types[i] = SvIV(ST(i+2)); + oga->type_offset[i] = j; + j += gl_type_size(oga->types[i]); + } + oga->total_types_width = j; + } + else + { + oga->type_count = 1; + oga->types = malloc(sizeof(GLenum) * oga->type_count); + oga->type_offset = malloc(sizeof(GLint) * oga->type_count); + + oga->types[0] = GL_UNSIGNED_BYTE; + oga->type_offset[0] = 0; + oga->total_types_width = gl_type_size(oga->types[0]); + } + + if (!oga->total_types_width) croak("Unable to determine type sizes\n"); + oga->item_count = size / oga->total_types_width; + + oga->data_length = oga->total_types_width * oga->item_count; + + oga->data = buffer; + + oga->free_data = 0; + + RETVAL = oga; + } + OUTPUT: + RETVAL + +#endif // GL_ARB_vertex_buffer_object