int texturetype;
// palette if the texture is TEXTYPE_PALETTE
const unsigned int *palette;
- // power of 2 size, after gl_picmip and gl_max_size are applied
+ // actual stored texture size after gl_picmip and gl_max_size are applied
+ // (power of 2 if gl_support_arb_texture_non_power_of_two is not supported)
int tilewidth, tileheight, tiledepth;
// 1 or 6 depending on texturetype
int sides;
if (outwidth)
{
- for (width2 = 1;width2 < inwidth;width2 <<= 1);
- for (width2 >>= picmip;width2 > maxsize;width2 >>= 1);
+ if (gl_support_arb_texture_non_power_of_two)
+ width2 = min(inwidth >> picmip, maxsize);
+ else
+ {
+ for (width2 = 1;width2 < inwidth;width2 <<= 1);
+ for (width2 >>= picmip;width2 > maxsize;width2 >>= 1);
+ }
*outwidth = max(1, width2);
}
if (outheight)
{
- for (height2 = 1;height2 < inheight;height2 <<= 1);
- for (height2 >>= picmip;height2 > maxsize;height2 >>= 1);
+ if (gl_support_arb_texture_non_power_of_two)
+ height2 = min(inheight >> picmip, maxsize);
+ else
+ {
+ for (height2 = 1;height2 < inheight;height2 <<= 1);
+ for (height2 >>= picmip;height2 > maxsize;height2 >>= 1);
+ }
*outheight = max(1, height2);
}
if (outdepth)
{
- for (depth2 = 1;depth2 < indepth;depth2 <<= 1);
- for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1);
+ if (gl_support_arb_texture_non_power_of_two)
+ depth2 = min(indepth >> picmip, maxsize);
+ else
+ {
+ for (depth2 = 1;depth2 < indepth;depth2 <<= 1);
+ for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1);
+ }
*outdepth = max(1, depth2);
}
}
qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
// these are rounded up versions of the size to do better resampling
- for (width = 1;width < glt->inputwidth ;width <<= 1);
- for (height = 1;height < glt->inputheight;height <<= 1);
- for (depth = 1;depth < glt->inputdepth ;depth <<= 1);
+ if (gl_support_arb_texture_non_power_of_two)
+ {
+ width = glt->inputwidth;
+ height = glt->inputheight;
+ depth = glt->inputdepth;
+ }
+ else
+ {
+ for (width = 1;width < glt->inputwidth ;width <<= 1);
+ for (height = 1;height < glt->inputheight;height <<= 1);
+ for (depth = 1;depth < glt->inputdepth ;depth <<= 1);
+ }
R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
R_MakeResizeBufferBigger(fragwidth * fragheight * fragdepth * glt->sides * glt->bytesperpixel);
extern void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum);
extern int gl_support_stenciltwoside;
+//GL_ARB_texture_non_power_of_two
+extern int gl_support_arb_texture_non_power_of_two;
+
extern void (GLAPIENTRY *qglScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
extern void (GLAPIENTRY *qglClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
static void Image_StripImageExtension (const char *in, char *out, size_t size_out)
{
const char *end, *temp;
-
+
if (size_out == 0)
return;
// in can be the same as out
void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth, int bytesperpixel)
{
+ const unsigned char *inrow;
int x, y, nextrow;
if (*depth != 1 || destdepth != 1)
{
*depth >>= 1;
return;
}
+ // note: if given odd width/height this discards the last row/column of
+ // pixels, rather than doing a proper box-filter scale down
+ inrow = in;
nextrow = *width * bytesperpixel;
if (*width > destwidth)
{
*height >>= 1;
if (bytesperpixel == 4)
{
- for (y = 0;y < *height;y++)
+ for (y = 0;y < *height;y++, inrow += nextrow * 2)
{
- for (x = 0;x < *width;x++)
+ for (in = inrow, x = 0;x < *width;x++)
{
out[0] = (unsigned char) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
out[1] = (unsigned char) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
out += 4;
in += 8;
}
- in += nextrow; // skip a line
}
}
else if (bytesperpixel == 3)
{
- for (y = 0;y < *height;y++)
+ for (y = 0;y < *height;y++, inrow += nextrow * 2)
{
- for (x = 0;x < *width;x++)
+ for (in = inrow, x = 0;x < *width;x++)
{
out[0] = (unsigned char) ((in[0] + in[3] + in[nextrow ] + in[nextrow+3]) >> 2);
out[1] = (unsigned char) ((in[1] + in[4] + in[nextrow+1] + in[nextrow+4]) >> 2);
out += 3;
in += 6;
}
- in += nextrow; // skip a line
}
}
else
// reduce width
if (bytesperpixel == 4)
{
- for (y = 0;y < *height;y++)
+ for (y = 0;y < *height;y++, inrow += nextrow)
{
- for (x = 0;x < *width;x++)
+ for (in = inrow, x = 0;x < *width;x++)
{
out[0] = (unsigned char) ((in[0] + in[4]) >> 1);
out[1] = (unsigned char) ((in[1] + in[5]) >> 1);
}
else if (bytesperpixel == 3)
{
- for (y = 0;y < *height;y++)
+ for (y = 0;y < *height;y++, inrow += nextrow)
{
- for (x = 0;x < *width;x++)
+ for (in = inrow, x = 0;x < *width;x++)
{
out[0] = (unsigned char) ((in[0] + in[3]) >> 1);
out[1] = (unsigned char) ((in[1] + in[4]) >> 1);
*height >>= 1;
if (bytesperpixel == 4)
{
- for (y = 0;y < *height;y++)
+ for (y = 0;y < *height;y++, inrow += nextrow * 2)
{
- for (x = 0;x < *width;x++)
+ for (in = inrow, x = 0;x < *width;x++)
{
out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
out += 4;
in += 4;
}
- in += nextrow; // skip a line
}
}
else if (bytesperpixel == 3)
{
- for (y = 0;y < *height;y++)
+ for (y = 0;y < *height;y++, inrow += nextrow * 2)
{
- for (x = 0;x < *width;x++)
+ for (in = inrow, x = 0;x < *width;x++)
{
out[0] = (unsigned char) ((in[0] + in[nextrow ]) >> 1);
out[1] = (unsigned char) ((in[1] + in[nextrow+1]) >> 1);
out += 3;
in += 3;
}
- in += nextrow; // skip a line
}
}
else
int gl_texture3d = false;
// GL_ARB_texture_cubemap
int gl_texturecubemap = false;
+// GL_ARB_texture_non_power_of_two
+int gl_support_arb_texture_non_power_of_two = false;
// GL_ARB_texture_env_dot3
int gl_dot3arb = false;
// GL_SGIS_texture_edge_clamp
gl_supportslockarrays = false;
gl_texture3d = false;
gl_texturecubemap = false;
+ gl_support_arb_texture_non_power_of_two = false;
gl_dot3arb = false;
gl_support_clamptoedge = false;
gl_support_anisotropy = false;
// COMMANDLINEOPTION: GL: -nocubemap disables GL_ARB_texture_cube_map (required for bumpmapping)
if ((gl_texturecubemap = GL_CheckExtension("GL_ARB_texture_cube_map", NULL, "-nocubemap", false)))
qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &gl_max_cube_map_texture_size);
+ gl_support_arb_texture_non_power_of_two = GL_CheckExtension("GL_ARB_texture_non_power_of_two", NULL, "-notexturenonpoweroftwo", false);
// COMMANDLINEOPTION: GL: -nocva disables GL_EXT_compiled_vertex_array (renders faster)
gl_supportslockarrays = GL_CheckExtension("GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "-nocva", false);
// COMMANDLINEOPTION: GL: -noedgeclamp disables GL_EXT_texture_edge_clamp or GL_SGIS_texture_edge_clamp (recommended, some cards do not support the other texture clamp method)