Acme-MITHALDU-BleedingOpenGL
view release on metacpan or search on metacpan
pogl_rpn.xs view on Meta::CPAN
int fbo_width = 0;
int i,j,count,dim,cols;
SV * sv = ST(1);
int free_mat = 0;
/* Get transform matrix OGA */
if (sv != &PL_sv_undef && sv_derived_from(sv,"OpenGL::Array"))
{
IV ref = SvIV((SV*)SvRV(sv));
oga_struct *oga_mat = INT2PTR(OpenGL__Array,ref);
count = oga_mat->item_count;
for (i=0;i<oga_mat->type_count;i++)
{
if (oga_mat->types[i] != GL_FLOAT)
croak("Unsupported datatype in affine matrix");
}
mat = (GLfloat *)oga_mat->data;
}
else
{
count = items - 1;
free_mat = 1;
}
if (!count) croak("No matrix values");
/* Currently only support GLfloat */
for (i=0;i<oga->type_count;i++)
{
if (oga->types[i] != GL_FLOAT)
croak("Unsupported datatype");
}
/* Scalar Multiply */
if (count == 1)
{
GLfloat scalar = mat ? mat[0] : (GLfloat)SvNV(ST(1));
for (i=0;i<len;i++) data[i] *= scalar;
XSRETURN_EMPTY;
}
/* Calc matrix dimension from sqrt of array size */
dim = (int)sqrt(count);
if (count != dim*dim) croak("Not a square matrix");
/* Affine matrix dimension is one element larger than vector data */
cols = dim - 1;
if (len % cols)
croak("Matrix does not match array vector size");
/* Grab affine matrix */
if (!mat)
{
mat = malloc(sizeof(GLfloat) * count);
for (i=0; i<count; i++)
mat[i] = (GLfloat)SvNV(ST(i+1));
}
#if 0 /* Need to figure out why this is slower than CPU calcs */
/* Use GPU if FBOs and Fragment Programs are supported */
fbo_width = gpgpu_width(len);
if (dim == 4 && fbo_width)
{
GLuint target = GL_TEXTURE_RECTANGLE_ARB;
int w = fbo_width;
int h = len / (w*3);
/* Setup and enable FBO */
enable_fbo(oga,w,h,target,GL_RGB32F_ARB,GL_RGB,GL_FLOAT);
/* Pass affine matrix to shader */
enable_affine(oga);
for (i=0;i<4;i++)
{
glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
i,&mat[i<<2]);
}
/* Render to FBO via fragment shader */
glBegin(GL_QUADS);
{
glTexCoord2i(0,0); glVertex2i(0,0);
glTexCoord2i(w,0); glVertex2i(w,0);
glTexCoord2i(w,h); glVertex2i(w,h);
glTexCoord2i(0,h); glVertex2i(0,h);
}
glEnd();
/* Done rendering */
disable_affine(oga);
/* Save back to OGA */
//glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(0,0,w,h,GL_RGB,GL_FLOAT,oga->data);
disable_fbo(oga);
}
/* Use CPU to do transform */
else
#endif
{
int s = sizeof(GLfloat) * cols;
GLfloat *vec = malloc(s);
int k,r;
/* Iterate each data row */
for (i=0; i < len; i+=cols)
{
/* Iterate each result column */
for (j=0,r=0; j<cols; j++,r+=dim)
{
vec[j] = 0.0;
/* Iterate each matrix column */
for (k=0; k<cols; k++)
{
vec[j] += data[i+k] * mat[r+k];
}
/* Matrix translate column */
vec[j] += mat[r+cols];
}
( run in 0.807 second using v1.01-cache-2.11-cpan-df04353d9ac )