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
parent 95a758f3
......@@ -13,3 +13,5 @@ Google Inc.
3DLabs Inc. Ltd.
Cloud Party, Inc.
......@@ -44,6 +44,9 @@ Adobe Systems Inc.
Alexandru Chiculita
Max Vujovic
Cloud Party, Inc.
Conor Dickinson
Aitor Moreno <aitormoreno at gmail.com>
Jim Hauxwell <james at dattrax.co.uk>
ddefrostt
......
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 1217
#define BUILD_REVISION 1219
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -1089,6 +1089,16 @@ bool Display::getLuminanceAlphaTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
}
float Display::getTextureFilterAnisotropySupport() const
{
// Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2))
{
return mDeviceCaps.MaxAnisotropy;
}
return 1.0f;
}
D3DPOOL Display::getBufferPool(DWORD usage) const
{
if (mD3d9Ex != NULL)
......
......@@ -81,6 +81,7 @@ class Display
virtual bool getDepthTextureSupport() const;
virtual bool getOcclusionQuerySupport() const;
virtual bool getInstancingSupport() const;
virtual float getTextureFilterAnisotropySupport() const;
virtual D3DPOOL getBufferPool(DWORD usage) const;
virtual D3DPOOL getTexturePool(DWORD usage) const;
......
......@@ -274,8 +274,9 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
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 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
mSupportsDepthTextures = mDisplay->getDepthTextureSupport();
mSupportsTextureFilterAnisotropy = mMaxTextureAnisotropy >= 2.0f;
mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
......@@ -1425,6 +1427,13 @@ bool Context::getFloatv(GLenum pname, GLfloat *params)
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 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
*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 @@ void Context::applyTextures(SamplerType type)
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 @@ bool Context::supportsInstancing() const
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 @@ void Context::initExtensionString()
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 ";
......
......@@ -500,6 +500,9 @@ class Context
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 @@ class Context
int mMaxTextureDimension;
int mMaxCubeTextureDimension;
int mMaxTextureLevel;
float mMaxTextureAnisotropy;
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsEventQueries;
......@@ -622,6 +626,7 @@ class Context
bool mSupportsLuminanceAlphaTextures;
bool mSupportsDepthTextures;
bool mSupports32bitIndices;
bool mSupportsTextureFilterAnisotropy;
int mNumCompressedTextureFormats;
// state caching flags
......
......@@ -1157,6 +1157,7 @@ Texture::Texture(GLuint id) : RefCountObject(id)
mWrapT = GL_REPEAT;
mDirtyParameters = true;
mUsage = GL_NONE;
mMaxAnisotropy = 1.0f;
mDirtyImages = true;
......@@ -1253,6 +1254,22 @@ bool Texture::setWrapT(GLenum wrap)
}
}
// 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 @@ GLenum Texture::getWrapT() const
return mWrapT;
}
float Texture::getMaxAnisotropy() const
{
return mMaxAnisotropy;
}
GLenum Texture::getUsage() const
{
return mUsage;
......
......@@ -179,12 +179,14 @@ class Texture : public RefCountObject
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 @@ class Texture : public RefCountObject
GLenum mMagFilter;
GLenum mWrapS;
GLenum mWrapT;
float mMaxAnisotropy;
bool mDirtyParameters;
GLenum mUsage;
......
......@@ -3860,6 +3860,13 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
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 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
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 glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
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 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint 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);
}
......
......@@ -646,8 +646,13 @@ DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
(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 @@ D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
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 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT
*d3dMipFilter = D3DTEXF_NONE;
UNREACHABLE();
}
if (maxAnisotropy > 1.0f)
{
*d3dMinFilter = D3DTEXF_ANISOTROPIC;
}
}
bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
......
......@@ -63,8 +63,8 @@ D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment