Implement Anisotropic Texture filtering support
Bug=297
Authored-by: Conor Dickinson, Cloud Party, Inc.
Signed-off-by: Daniel Koch
git-svn-id: https://angleproject.googlecode.com/svn/trunk@1219 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 7946011..1c2179e 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -274,8 +274,9 @@
mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
mMaxRenderbufferDimension = mMaxTextureDimension;
mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
- TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d",
- mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel);
+ mMaxTextureAnisotropy = mDisplay->getTextureFilterAnisotropySupport();
+ TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f",
+ mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy);
const D3DFORMAT renderBufferFormats[] =
{
@@ -313,6 +314,7 @@
mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
mSupportsDepthTextures = mDisplay->getDepthTextureSupport();
+ mSupportsTextureFilterAnisotropy = mMaxTextureAnisotropy >= 2.0f;
mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
@@ -1425,6 +1427,13 @@
params[2] = mState.blendColor.blue;
params[3] = mState.blendColor.alpha;
break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!supportsTextureFilterAnisotropy())
+ {
+ return false;
+ }
+ *params = mMaxTextureAnisotropy;
+ break;
default:
return false;
}
@@ -1833,6 +1842,14 @@
*numParams = 4;
}
break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!supportsTextureFilterAnisotropy())
+ {
+ return false;
+ }
+ *type = GL_FLOAT;
+ *numParams = 1;
+ break;
default:
return false;
}
@@ -2383,15 +2400,21 @@
GLenum wrapT = texture->getWrapT();
GLenum minFilter = texture->getMinFilter();
GLenum magFilter = texture->getMagFilter();
+ float maxAnisotropy = texture->getMaxAnisotropy();
mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
- mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter, maxAnisotropy));
D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
- es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
+ es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+
+ if (supportsTextureFilterAnisotropy())
+ {
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)maxAnisotropy);
+ }
}
if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyImages())
@@ -3522,6 +3545,16 @@
return mSupportsInstancing;
}
+bool Context::supportsTextureFilterAnisotropy() const
+{
+ return mSupportsTextureFilterAnisotropy;
+}
+
+float Context::getTextureMaxAnisotropy() const
+{
+ return mMaxTextureAnisotropy;
+}
+
void Context::detachBuffer(GLuint buffer)
{
// [OpenGL ES 2.0.24] section 2.9 page 22:
@@ -3772,6 +3805,11 @@
mExtensionString += "GL_EXT_texture_compression_dxt1 ";
}
+ if (supportsTextureFilterAnisotropy())
+ {
+ mExtensionString += "GL_EXT_texture_filter_anisotropic ";
+ }
+
mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
mExtensionString += "GL_EXT_texture_storage ";
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 2f21a2d..2097fe4 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -500,6 +500,9 @@
bool supports32bitIndices() const;
bool supportsNonPower2Texture() const;
bool supportsInstancing() const;
+ bool supportsTextureFilterAnisotropy() const;
+
+ float getTextureMaxAnisotropy() const;
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
@@ -605,6 +608,7 @@
int mMaxTextureDimension;
int mMaxCubeTextureDimension;
int mMaxTextureLevel;
+ float mMaxTextureAnisotropy;
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsEventQueries;
@@ -622,6 +626,7 @@
bool mSupportsLuminanceAlphaTextures;
bool mSupportsDepthTextures;
bool mSupports32bitIndices;
+ bool mSupportsTextureFilterAnisotropy;
int mNumCompressedTextureFormats;
// state caching flags
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 6ff2453..cd4d637 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -1157,6 +1157,7 @@
mWrapT = GL_REPEAT;
mDirtyParameters = true;
mUsage = GL_NONE;
+ mMaxAnisotropy = 1.0f;
mDirtyImages = true;
@@ -1253,6 +1254,22 @@
}
}
+// Returns true on successful max anisotropy update (valid anisotropy value)
+bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy)
+{
+ textureMaxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy);
+ if (textureMaxAnisotropy < 1.0f)
+ {
+ return false;
+ }
+ if (mMaxAnisotropy != textureMaxAnisotropy)
+ {
+ mMaxAnisotropy = textureMaxAnisotropy;
+ mDirtyParameters = true;
+ }
+ return true;
+}
+
// Returns true on successful usage state update (valid enum parameter)
bool Texture::setUsage(GLenum usage)
{
@@ -1287,6 +1304,11 @@
return mWrapT;
}
+float Texture::getMaxAnisotropy() const
+{
+ return mMaxAnisotropy;
+}
+
GLenum Texture::getUsage() const
{
return mUsage;
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 313a162..ccddf57 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -179,12 +179,14 @@
bool setMagFilter(GLenum filter);
bool setWrapS(GLenum wrap);
bool setWrapT(GLenum wrap);
+ bool setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy);
bool setUsage(GLenum usage);
GLenum getMinFilter() const;
GLenum getMagFilter() const;
GLenum getWrapS() const;
GLenum getWrapT() const;
+ float getMaxAnisotropy() const;
GLenum getUsage() const;
virtual bool isSamplerComplete() const = 0;
@@ -229,6 +231,7 @@
GLenum mMagFilter;
GLenum mWrapS;
GLenum mWrapT;
+ float mMaxAnisotropy;
bool mDirtyParameters;
GLenum mUsage;
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index ca4ddff..9f3e591 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -3860,6 +3860,13 @@
case GL_TEXTURE_USAGE_ANGLE:
*params = (GLfloat)texture->getUsage();
break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->supportsTextureFilterAnisotropy())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ *params = (GLfloat)texture->getMaxAnisotropy();
+ break;
default:
return error(GL_INVALID_ENUM);
}
@@ -3915,6 +3922,13 @@
case GL_TEXTURE_USAGE_ANGLE:
*params = texture->getUsage();
break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->supportsTextureFilterAnisotropy())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ *params = (GLint)texture->getMaxAnisotropy();
+ break;
default:
return error(GL_INVALID_ENUM);
}
@@ -5482,12 +5496,84 @@
void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
{
- glTexParameteri(target, pname, (GLint)param);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
+
+ try
+ {
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ gl::Texture *texture;
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ texture = context->getTexture2D();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture = context->getTextureCubeMap();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ if (!texture->setWrapS((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_WRAP_T:
+ if (!texture->setWrapT((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ if (!texture->setMinFilter((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ if (!texture->setMagFilter((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ if (!texture->setUsage((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->supportsTextureFilterAnisotropy())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
}
void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
{
- glTexParameteri(target, pname, (GLint)*params);
+ glTexParameterf(target, pname, (GLfloat)*params);
}
void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
@@ -5546,6 +5632,16 @@
return error(GL_INVALID_ENUM);
}
break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->supportsTextureFilterAnisotropy())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()))
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
default:
return error(GL_INVALID_ENUM);
}
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index a7c62d9..5cf005d 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -646,8 +646,13 @@
(alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
}
-D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
{
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3DTEXF_ANISOTROPIC;
+ }
+
D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
switch (magFilter)
{
@@ -659,7 +664,7 @@
return d3dMagFilter;
}
-void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
{
switch (minFilter)
{
@@ -692,6 +697,11 @@
*d3dMipFilter = D3DTEXF_NONE;
UNREACHABLE();
}
+
+ if (maxAnisotropy > 1.0f)
+ {
+ *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+ }
}
bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
diff --git a/src/libGLESv2/utilities.h b/src/libGLESv2/utilities.h
index cf22418..5174680 100644
--- a/src/libGLESv2/utilities.h
+++ b/src/libGLESv2/utilities.h
@@ -63,8 +63,8 @@
D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
-D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter);
-void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy);
bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
D3DFORMAT ConvertRenderbufferFormat(GLenum format);