OpenGL-Sandbox
view release on metacpan or search on metacpan
lib/OpenGL/Sandbox.c view on Meta::CPAN
need= width * height * pixel_size;
if (need > data_len)
carp_croak("Require at least %d bytes of pixel data (got %d)", need, data_len);
}
else if (!SvOK(data_sv) || SvIV(data_sv) == 0) {
if (xoffset || yoffset) carp_croak("Can't use NULL pixel data when specifying a sub-image");
data= NULL;
data_len= 0;
}
else
carp_croak("Expected scalar-ref %sfor data argument", (xoffset || yoffset)? "":"or undef ");
}
/* TODO: support OpenGL 4.5 which doesn't need to bind to anything */
if (!tx_id_p || !(tx_id= SvUV(tx_id_p)))
croak("tx_id must be initialized first");
glBindTexture(target, tx_id);
if (pitch) {
/* OpenGL doesn't do row length in bytes, it does it in pixels. This is not helpful. */
if (!pixel_size)
croak("Don't know how to apply 'pitch' to pixels of format=%d type=%d", format, type);
switch (pitch > 0 ? pitch % pixel_size : -1) {
case 0: pix_align= 1; row_len= pitch / pixel_size; break;
case 1: if ((pitch & 1) == 0) { pix_align= 2; row_len= pitch / pixel_size; break; }
case 2:
case 3: if ((pitch & 3) == 0) { pix_align= 4; row_len= pitch / pixel_size; break; }
case 4:
case 5:
case 6:
case 7: if ((pitch & 7) == 0) { pix_align= 8; row_len= pitch / pixel_size; break; }
default:
croak("Unsupported buffer pitch %d for pixel size %d", pitch, pixel_size);
}
glGetIntegerv(GL_UNPACK_ALIGNMENT, &orig_pix_align);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &orig_row_len);
}
/* If xoffset or yoffset are nonzero, then this requires the texture to be loaded already,
* and the internal format and mipmap and etc is irrelevant. */
if (xoffset || yoffset) {
if (pitch) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_len);
glPixelStorei(GL_UNPACK_ALIGNMENT, pix_align);
}
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data);
if (pitch) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, orig_row_len);
glPixelStorei(GL_UNPACK_ALIGNMENT, orig_pix_align);
}
return;
}
/* Else we are defining the storage for the texture and more things need considered.
* Also the texture object should be updated with the result of the calculations below. */
if (internal_p) internal_fmt= SvIV(internal_p);
else if (known_format) internal_fmt= default_internal_fmt;
else carp_croak("No default internal_format for given format %d; must be specified", format);
/* use mipmaps if the user set it to true, or if the min_filter uses a mipmap,
and default in absence of any user prefs is true. But not if the user has specified 'level' */
with_mipmaps= level? 0
: mipmap_p? SvTRUE(mipmap_p)
: !min_filter_p? 1
: (SvIV(min_filter_p) == GL_NEAREST || SvIV(min_filter_p) == GL_LINEAR) ? 0
: 1;
if (with_mipmaps) {
if (major < 3) {
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
if (mag_filter_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, SvIV(mag_filter_p));
if (min_filter_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, SvIV(min_filter_p));
}
} else if (!level) {
if (mag_filter_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, SvIV(mag_filter_p));
/* this one needs overridden even if user didn't request it, because default uses mipmaps */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_p? SvIV(min_filter_p) : GL_LINEAR);
/* and inform opengl that this is the only mipmap level */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
if (pitch) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_len);
glPixelStorei(GL_UNPACK_ALIGNMENT, pix_align);
}
glTexImage2D(target, level, internal_fmt, width, height, 0, format, type, data);
if (pitch) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, orig_row_len);
glPixelStorei(GL_UNPACK_ALIGNMENT, orig_pix_align);
}
if (with_mipmaps && major >= 3) {
/* glEnable(GL_TEXTURE_2D); correct bug in ATI, accoridng to Khronos FAQ */
glGenerateMipmap(GL_TEXTURE_2D);
/* examples show setting these after mipmap generation. Does it matter? */
if (mag_filter_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, SvIV(mag_filter_p));
if (min_filter_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, SvIV(min_filter_p));
}
if (!level) {
if (wrap_s_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, SvIV(wrap_s_p));
if (wrap_t_p)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, SvIV(wrap_t_p));
}
/* update attributes */
if (!hv_store(self, "width", 5, sv=newSViv(width), 0)
|| !hv_store(self, "height", 6, sv=newSViv(height), 0)
|| (known_format &&
!hv_store(self, "has_alpha", 9, sv=newSViv(has_alpha? 1 : 0), 0))
|| !hv_store(self, "internal_format", 15, sv=newSViv(internal_fmt), 0)
|| !hv_store(self, "loaded", 6, sv=newSViv(1), 0)
) {
if (sv) sv_2mortal(sv);
croak("Can't store results in supplied hash");
}
return;
( run in 1.809 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )