@@ -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; | |||
} |
@@ -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; | |||
} | |||
@@ -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; |
@@ -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; | |||
@@ -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 |
@@ -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; k<n; k++) { | |||
GLint i = IFLOOR(texcoords[k][0] * width) & colMask; | |||
@@ -1496,6 +1523,7 @@ opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, | |||
ASSERT(tObj->WrapT==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); |
@@ -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) |