From c9279ad2901cadff3086c3b83959e92430a5e46d Mon Sep 17 00:00:00 2001 From: havoc Date: Tue, 19 Dec 2006 06:47:27 +0000 Subject: [PATCH] support for GL_ARB_texture_non_power_of_two extension (makes quake textures look a bit sharper on cards that support it and saves video memory) known to be supported on NVIDIA Geforce 6 and above git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6661 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_textures.c | 45 +++++++++++++++++++++++++++++++++++---------- glquake.h | 3 +++ image.c | 34 +++++++++++++++++----------------- vid_shared.c | 4 ++++ 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/gl_textures.c b/gl_textures.c index e473f6fd..c3e200fb 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -86,7 +86,8 @@ typedef struct gltexture_s 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; @@ -351,20 +352,35 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int inwidth, in 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); } } @@ -649,9 +665,18 @@ static void R_Upload(gltexture_t *glt, unsigned char *data, int fragx, int fragy 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); diff --git a/glquake.h b/glquake.h index 47cb698b..b27cd252 100644 --- a/glquake.h +++ b/glquake.h @@ -399,6 +399,9 @@ extern int gl_support_clamptoedge; 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); diff --git a/image.c b/image.c index 3fad1afb..fa2252d6 100644 --- a/image.c +++ b/image.c @@ -765,7 +765,7 @@ unsigned char *LoadWAL (const unsigned char *f, int filesize, int matchwidth, in static void Image_StripImageExtension (const char *in, char *out, size_t size_out) { const char *end, *temp; - + if (size_out == 0) return; @@ -1358,6 +1358,7 @@ void Image_Resample (const void *indata, int inwidth, int inheight, int indepth, // 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) { @@ -1370,6 +1371,9 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in *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) { @@ -1380,9 +1384,9 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in *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); @@ -1391,14 +1395,13 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in 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); @@ -1406,7 +1409,6 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in out += 3; in += 6; } - in += nextrow; // skip a line } } else @@ -1417,9 +1419,9 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in // 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); @@ -1432,9 +1434,9 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in } 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); @@ -1456,9 +1458,9 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in *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); @@ -1467,14 +1469,13 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in 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); @@ -1482,7 +1483,6 @@ void Image_MipReduce(const unsigned char *in, unsigned char *out, int *width, in out += 3; in += 3; } - in += nextrow; // skip a line } } else diff --git a/vid_shared.c b/vid_shared.c index 6a2d0d2c..200f4458 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -33,6 +33,8 @@ int gl_stencil = false; 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 @@ -627,6 +629,7 @@ void VID_CheckExtensions(void) 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; @@ -679,6 +682,7 @@ void VID_CheckExtensions(void) // 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) -- 2.39.2