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;
}
{ 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) },
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
{
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;
}
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;
/*
- * 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 )
GLint i = 1;
GLint log2 = 0;
- if (n < 0) {
+ if (n <= 0) {
return -1;
}
log2++;
}
if (i != n) {
- return -1;
+ return log2 - 1;
}
else {
return log2;
/*
* 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,
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)
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 */
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;
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;
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;
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;
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;
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;
dest->GenerateMipmap = src->GenerateMipmap;
dest->Palette = src->Palette;
dest->Complete = src->Complete;
+ dest->_IsPowerOfTwo = src->_IsPowerOfTwo;
}
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]) {
}
}
+ /* 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
#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:
{ \
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) \
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) \
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 */ \
/* 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] */ \
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); \
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); \
}
+/* Power of two image sizes only */
#define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
{ \
U = S * SIZE - 0.5F; \
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);
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);
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;
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;
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],
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,
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
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,
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;
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);
&& 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)