From 887e2cf01a99f7fe1b7c94320b7bdbbf0d6ad2f8 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 3 Jul 2003 03:05:48 +0000 Subject: [PATCH] Implemented GL_ARB_texture_non_power_of_two (except for auto mipmap generation). --- src/mesa/drivers/x11/xm_dd.c | 12 +++++-- src/mesa/main/extensions.c | 3 ++ src/mesa/main/mtypes.h | 1 + src/mesa/main/teximage.c | 63 ++++++++++++++++++++++++------------ src/mesa/main/texobj.c | 8 +++++ src/mesa/swrast/s_texture.c | 56 +++++++++++++++++++++++++------- src/mesa/swrast/s_triangle.c | 1 + 7 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index 30a8b51723f..3a3375f34c4 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -937,9 +937,15 @@ test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, if (target == GL_PROXY_TEXTURE_3D) { /* special case for 3D textures */ if (width * height * depth > 512 * 512 * 64 || - width < 2 * border || _mesa_bitcount(width - 2 * border) != 1 || - height < 2 * border || _mesa_bitcount(height - 2 * border) != 1 || - depth < 2 * border || _mesa_bitcount(depth - 2 * border) != 1) { + width < 2 * border || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || + height < 2 * border || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || + depth < 2 * border || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(depth - 2 * border) != 1)) { /* Bad size, or too many texels */ return GL_FALSE; } diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 4c0faf3a18d..75972c75593 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -57,6 +57,7 @@ static const struct { { OFF, "GL_ARB_texture_env_crossbar", F(ARB_texture_env_crossbar) }, { OFF, "GL_ARB_texture_env_dot3", F(ARB_texture_env_dot3) }, { OFF, "GL_ARB_texture_mirrored_repeat", F(ARB_texture_mirrored_repeat)}, + { OFF, "GL_ARB_texture_non_power_of_two", F(ARB_texture_non_power_of_two)}, { ON, "GL_ARB_transpose_matrix", 0 }, { OFF, "GL_ARB_vertex_buffer_object", F(ARB_vertex_buffer_object) }, { OFF, "GL_ARB_vertex_program", F(ARB_vertex_program) }, @@ -163,6 +164,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx) ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE; + ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; #if FEATURE_ARB_vertex_program /*ctx->Extensions.ARB_vertex_program = GL_TRUE;*/ #endif @@ -291,6 +293,7 @@ _mesa_enable_1_5_extensions(GLcontext *ctx) { ctx->Extensions.ARB_occlusion_query = GL_TRUE; ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE; + ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 2c73d989627..c116228bf85 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1469,6 +1469,7 @@ struct gl_extensions { GLboolean ARB_texture_env_crossbar; GLboolean ARB_texture_env_dot3; GLboolean ARB_texture_mirrored_repeat; + GLboolean ARB_texture_non_power_of_two; GLboolean ARB_vertex_buffer_object; GLboolean ARB_vertex_program; GLboolean ARB_window_pos; diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 1c10aaea016..d731e12ad3b 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -103,9 +103,8 @@ static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) /* - * Compute log base 2 of n. - * If n isn't an exact power of two return -1. - * If n < 0 return -1. + * Compute floor(log_base_2(n)). + * If n <= 0 return -1. */ static int logbase2( int n ) @@ -113,7 +112,7 @@ logbase2( int n ) GLint i = 1; GLint log2 = 0; - if (n < 0) { + if (n <= 0) { return -1; } @@ -122,7 +121,7 @@ logbase2( int n ) log2++; } if (i != n) { - return -1; + return log2 - 1; } else { return log2; @@ -820,6 +819,7 @@ clear_teximage_fields(struct gl_texture_image *img) /* * Initialize basic fields of the gl_texture_image struct. + * Note: width, height and depth include the border. */ void _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, @@ -845,9 +845,9 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, img->DepthLog2 = 0; else img->DepthLog2 = logbase2(depth - 2 * border); - img->Width2 = 1 << img->WidthLog2; - img->Height2 = 1 << img->HeightLog2; - img->Depth2 = 1 << img->DepthLog2; + img->Width2 = width - 2 * border; /*1 << img->WidthLog2;*/ + img->Height2 = height - 2 * border; /*1 << img->HeightLog2;*/ + img->Depth2 = depth - 2 * border; /*1 << img->DepthLog2;*/ img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); img->IsCompressed = is_compressed_format(internalFormat); if (img->IsCompressed) @@ -856,6 +856,13 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, else img->CompressedSize = 0; + if ((width == 1 || _mesa_bitcount(width - 2 * border) == 1) && + (height == 1 || _mesa_bitcount(height - 2 * border) == 1) && + (depth == 1 || _mesa_bitcount(depth - 2 * border) == 1)) + img->_IsPowerOfTwo = GL_TRUE; + else + img->_IsPowerOfTwo = GL_FALSE; + /* Compute Width/Height/DepthScale for mipmap lod computation */ if (target == GL_TEXTURE_RECTANGLE_NV) { /* scale = 1.0 since texture coords directly map to texels */ @@ -906,7 +913,8 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, case GL_PROXY_TEXTURE_1D: maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); if (width < 2 * border || width > 2 + maxSize || - _mesa_bitcount(width - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || level >= ctx->Const.MaxTextureLevels) { /* bad width or level */ return GL_FALSE; @@ -915,9 +923,11 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, case GL_PROXY_TEXTURE_2D: maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); if (width < 2 * border || width > 2 + maxSize || - _mesa_bitcount(width - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || height < 2 * border || height > 2 + maxSize || - _mesa_bitcount(height - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || level >= ctx->Const.MaxTextureLevels) { /* bad width or height or level */ return GL_FALSE; @@ -926,11 +936,14 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, case GL_PROXY_TEXTURE_3D: maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); if (width < 2 * border || width > 2 + maxSize || - _mesa_bitcount(width - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || height < 2 * border || height > 2 + maxSize || - _mesa_bitcount(height - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || depth < 2 * border || depth > 2 + maxSize || - _mesa_bitcount(depth - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(depth - 2 * border) != 1) || level >= ctx->Const.Max3DTextureLevels) { /* bad width or height or depth or level */ return GL_FALSE; @@ -947,9 +960,11 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, case GL_PROXY_TEXTURE_CUBE_MAP_ARB: maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); if (width < 2 * border || width > 2 + maxSize || - _mesa_bitcount(width - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || height < 2 * border || height > 2 + maxSize || - _mesa_bitcount(height - 2 * border) != 1 || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || level >= ctx->Const.MaxCubeTextureLevels) { /* bad width or height */ return GL_FALSE; @@ -2458,14 +2473,20 @@ compressed_texture_error_check(GLcontext *ctx, GLint dimensions, if (border != 0) return GL_INVALID_VALUE; - if (width < 1 || width > maxTextureSize || logbase2(width) < 0) + /* + * XXX We should probably use the proxy texture error check function here. + */ + if (width < 1 || width > maxTextureSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && logbase2(width) < 0)) return GL_INVALID_VALUE; - if ((height < 1 || height > maxTextureSize || logbase2(height) < 0) + if ((height < 1 || height > maxTextureSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && logbase2(height) < 0)) && dimensions > 1) return GL_INVALID_VALUE; - if ((depth < 1 || depth > maxTextureSize || logbase2(depth) < 0) + if ((depth < 1 || depth > maxTextureSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && logbase2(depth) < 0)) && dimensions > 2) return GL_INVALID_VALUE; @@ -2538,10 +2559,10 @@ compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, if (!is_compressed_format(format)) return GL_INVALID_ENUM; - if (width < 1 || width > maxTextureSize || logbase2(width) < 0) + if (width < 1 || width > maxTextureSize) return GL_INVALID_VALUE; - if ((height < 1 || height > maxTextureSize || logbase2(height) < 0) + if ((height < 1 || height > maxTextureSize) && dimensions > 1) return GL_INVALID_VALUE; diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 3d5d256240d..19b2b3f8e4a 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -228,6 +228,7 @@ _mesa_copy_texture_object( struct gl_texture_object *dest, dest->GenerateMipmap = src->GenerateMipmap; dest->Palette = src->Palette; dest->Complete = src->Complete; + dest->_IsPowerOfTwo = src->_IsPowerOfTwo; } @@ -257,6 +258,7 @@ _mesa_test_texobj_completeness( const GLcontext *ctx, GLint maxLog2 = 0, maxLevels = 0; t->Complete = GL_TRUE; /* be optimistic */ + t->_IsPowerOfTwo = GL_TRUE; /* may be set FALSE below */ /* Always need the base level image */ if (!t->Image[baseLevel]) { @@ -329,6 +331,12 @@ _mesa_test_texobj_completeness( const GLcontext *ctx, } } + /* check for non power of two */ + if (!t->Image[baseLevel]->_IsPowerOfTwo) { + t->_IsPowerOfTwo = GL_FALSE; + } + + /* extra checking for mipmaps */ if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) { /* * Mipmapping: determine if we have a complete set of mipmaps diff --git a/src/mesa/swrast/s_texture.c b/src/mesa/swrast/s_texture.c index a47e6a72ae8..1343b289fbd 100644 --- a/src/mesa/swrast/s_texture.c +++ b/src/mesa/swrast/s_texture.c @@ -43,6 +43,20 @@ #define WEIGHT_SHIFT 16 +/* + * Compute the remainder of a divided by b, but be careful with + * negative values so that GL_REPEAT mode works right. + */ +static INLINE GLint +repeat_remainder(GLint a, GLint b) +{ + if (a >= 0) + return a % b; + else + return (a + 1) % b + b - 1; +} + + /* * Used to compute texel locations for linear sampling. * Input: @@ -57,8 +71,14 @@ { \ if (wrapMode == GL_REPEAT) { \ U = S * SIZE - 0.5F; \ - I0 = IFLOOR(U) & (SIZE - 1); \ - I1 = (I0 + 1) & (SIZE - 1); \ + if (tObj->_IsPowerOfTwo) { \ + I0 = IFLOOR(U) & (SIZE - 1); \ + I1 = (I0 + 1) & (SIZE - 1); \ + } \ + else { \ + I0 = repeat_remainder(IFLOOR(U), SIZE); \ + I1 = repeat_remainder(I0 + 1, SIZE); \ + } \ } \ else if (wrapMode == GL_CLAMP_TO_EDGE) { \ if (S <= 0.0F) \ @@ -75,7 +95,7 @@ if (I1 >= (GLint) SIZE) \ I1 = SIZE - 1; \ } \ - else if (wrapMode == GL_CLAMP_TO_BORDER) { \ + else if (wrapMode == GL_CLAMP_TO_BORDER) { \ const GLfloat min = -1.0F / (2.0F * SIZE); \ const GLfloat max = 1.0F - min; \ if (S <= min) \ @@ -88,7 +108,7 @@ I0 = IFLOOR(U); \ I1 = I0 + 1; \ } \ - else if (wrapMode == GL_MIRRORED_REPEAT) { \ + else if (wrapMode == GL_MIRRORED_REPEAT) { \ const GLint flr = IFLOOR(S); \ if (flr & 1) \ U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \ @@ -150,7 +170,10 @@ /* s limited to [0,1) */ \ /* i limited to [0,size-1] */ \ I = IFLOOR(S * SIZE); \ - I &= (SIZE - 1); \ + if (tObj->_IsPowerOfTwo) \ + I &= (SIZE - 1); \ + else \ + I = repeat_remainder(I, SIZE); \ } \ else if (wrapMode == GL_CLAMP_TO_EDGE) { \ /* s limited to [min,max] */ \ @@ -164,7 +187,7 @@ else \ I = IFLOOR(S * SIZE); \ } \ - else if (wrapMode == GL_CLAMP_TO_BORDER) { \ + else if (wrapMode == GL_CLAMP_TO_BORDER) { \ /* s limited to [min,max] */ \ /* i limited to [-1, size] */ \ const GLfloat min = -1.0F / (2.0F * SIZE); \ @@ -176,7 +199,7 @@ else \ I = IFLOOR(S * SIZE); \ } \ - else if (wrapMode == GL_MIRRORED_REPEAT) { \ + else if (wrapMode == GL_MIRRORED_REPEAT) { \ const GLfloat min = 1.0F / (2.0F * SIZE); \ const GLfloat max = 1.0F - min; \ const GLint flr = IFLOOR(S); \ @@ -230,6 +253,7 @@ } +/* Power of two image sizes only */ #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \ { \ U = S * SIZE - 0.5F; \ @@ -1215,6 +1239,7 @@ sample_2d_linear_repeat(GLcontext *ctx, ASSERT(tObj->WrapT == GL_REPEAT); ASSERT(img->Border == 0); ASSERT(img->Format != GL_COLOR_INDEX); + ASSERT(img->_IsPowerOfTwo); COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width, i0, i1); COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1); @@ -1379,6 +1404,7 @@ sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx, ASSERT(lambda != NULL); ASSERT(tObj->WrapS == GL_REPEAT); ASSERT(tObj->WrapT == GL_REPEAT); + ASSERT(tObj->_IsPowerOfTwo); for (i = 0; i < n; i++) { GLint level; COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); @@ -1457,6 +1483,7 @@ opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit, ASSERT(tObj->WrapT==GL_REPEAT); ASSERT(img->Border==0); ASSERT(img->Format==GL_RGB); + ASSERT(img->_IsPowerOfTwo); for (k=0; kWrapT==GL_REPEAT); ASSERT(img->Border==0); ASSERT(img->Format==GL_RGBA); + ASSERT(img->_IsPowerOfTwo); for (i = 0; i < n; i++) { const GLint col = IFLOOR(texcoords[i][0] * width) & colMask; @@ -1521,10 +1549,11 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit, GLuint minStart, minEnd; /* texels with minification */ GLuint magStart, magEnd; /* texels with magnification */ - const GLboolean repeatNoBorder = (tObj->WrapS == GL_REPEAT) + const GLboolean repeatNoBorderPOT = (tObj->WrapS == GL_REPEAT) && (tObj->WrapT == GL_REPEAT) && (tImg->Border == 0 && (tImg->Width == tImg->RowStride)) - && (tImg->Format != GL_COLOR_INDEX); + && (tImg->Format != GL_COLOR_INDEX) + && tImg->_IsPowerOfTwo; ASSERT(lambda != NULL); compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], @@ -1535,7 +1564,7 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit, const GLuint m = minEnd - minStart; switch (tObj->MinFilter) { case GL_NEAREST: - if (repeatNoBorder) { + if (repeatNoBorderPOT) { switch (tImg->Format) { case GL_RGB: opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart, @@ -1573,7 +1602,7 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit, lambda + minStart, rgba + minStart); break; case GL_LINEAR_MIPMAP_LINEAR: - if (repeatNoBorder) + if (repeatNoBorderPOT) sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m, texcoords + minStart, lambda + minStart, rgba + minStart); else @@ -1592,7 +1621,7 @@ sample_lambda_2d( GLcontext *ctx, GLuint texUnit, switch (tObj->MagFilter) { case GL_NEAREST: - if (repeatNoBorder) { + if (repeatNoBorderPOT) { switch (tImg->Format) { case GL_RGB: opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart, @@ -2977,12 +3006,14 @@ _swrast_choose_texture_sample_func( GLcontext *ctx, ASSERT(t->MinFilter == GL_NEAREST); if (t->WrapS == GL_REPEAT && t->WrapT == GL_REPEAT && + t->_IsPowerOfTwo && t->Image[baseLevel]->Border == 0 && t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) { return &opt_sample_rgb_2d; } else if (t->WrapS == GL_REPEAT && t->WrapT == GL_REPEAT && + t->_IsPowerOfTwo && t->Image[baseLevel]->Border == 0 && t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) { return &opt_sample_rgba_2d; @@ -4188,6 +4219,7 @@ _swrast_texture_span( GLcontext *ctx, struct sw_span *span ) swrast->TextureSample[unit]( ctx, unit, texUnit->_Current, span->end, (const GLfloat (*)[4]) span->array->texcoords[unit], lambda, texels ); + /* GL_SGI_texture_color_table */ if (texUnit->ColorTableEnabled) { _swrast_texture_table_lookup(&texUnit->ColorTable, span->end, texels); diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index 0ce3459d544..86fe4dc1fdc 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -1074,6 +1074,7 @@ _swrast_choose_triangle( GLcontext *ctx ) && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT && texObj2D->WrapS==GL_REPEAT && texObj2D->WrapT==GL_REPEAT + && texObj2D->_IsPowerOfTwo && texImg->Border==0 && texImg->Width == texImg->RowStride && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) -- 2.30.2