Commit 68715287 by jbauman@chromium.org

Scale up non-multiple-of-4 dxt textures

D3D doesn't support DXT textures that aren't a multiple of 4 in size, so multiply the sizes by 2 or 4 so they work. Then ensure sampler parameters are set up correctly so they don't sample the unuploaded miplevels. BUG=https://code.google.com/p/angleproject/issues/detail?id=237 TEST= Review URL: https://codereview.appspot.com/6287045 git-svn-id: https://angleproject.googlecode.com/svn/trunk@1222 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 07ab841a
...@@ -2410,6 +2410,7 @@ void Context::applyTextures(SamplerType type) ...@@ -2410,6 +2410,7 @@ void Context::applyTextures(SamplerType type)
es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy); es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, texture->getLodOffset());
if (supportsTextureFilterAnisotropy()) if (supportsTextureFilterAnisotropy())
{ {
......
...@@ -118,6 +118,26 @@ static inline DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool force ...@@ -118,6 +118,26 @@ static inline DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool force
return d3dusage; return d3dusage;
} }
static void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) {
int upsampleCount = 0;
if (isCompressed)
{
// Don't expand the size of full textures that are at least 4x4
// already.
if (isImage || *requestWidth < 4 || *requestHeight < 4)
{
while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
{
*requestWidth <<= 1;
*requestHeight <<= 1;
upsampleCount++;
}
}
}
*levelOffset = upsampleCount;
}
Image::Image() Image::Image()
{ {
mWidth = 0; mWidth = 0;
...@@ -186,22 +206,7 @@ void Image::createSurface() ...@@ -186,22 +206,7 @@ void Image::createSurface()
int levelToFetch = 0; int levelToFetch = 0;
GLsizei requestWidth = mWidth; GLsizei requestWidth = mWidth;
GLsizei requestHeight = mHeight; GLsizei requestHeight = mHeight;
if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0)) MakeValidSize(true, IsCompressed(mFormat), &requestWidth, &requestHeight, &levelToFetch);
{
bool isMult4 = false;
int upsampleCount = 0;
while (!isMult4)
{
requestWidth <<= 1;
requestHeight <<= 1;
upsampleCount++;
if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
{
isMult4 = true;
}
}
levelToFetch = upsampleCount;
}
HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat, HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat,
poolToUse, &newTexture, NULL); poolToUse, &newTexture, NULL);
...@@ -1111,7 +1116,8 @@ void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, ...@@ -1111,7 +1116,8 @@ void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
TextureStorage::TextureStorage(DWORD usage) TextureStorage::TextureStorage(DWORD usage)
: mD3DUsage(usage), : mD3DUsage(usage),
mD3DPool(getDisplay()->getTexturePool(usage)), mD3DPool(getDisplay()->getTexturePool(usage)),
mTextureSerial(issueTextureSerial()) mTextureSerial(issueTextureSerial()),
mLodOffset(0)
{ {
} }
...@@ -1149,6 +1155,11 @@ unsigned int TextureStorage::issueTextureSerial() ...@@ -1149,6 +1155,11 @@ unsigned int TextureStorage::issueTextureSerial()
return mCurrentTextureSerial++; return mCurrentTextureSerial++;
} }
int TextureStorage::getLodOffset() const
{
return mLodOffset;
}
Texture::Texture(GLuint id) : RefCountObject(id) Texture::Texture(GLuint id) : RefCountObject(id)
{ {
mMinFilter = GL_NEAREST_MIPMAP_LINEAR; mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
...@@ -1405,6 +1416,12 @@ bool Texture::isImmutable() const ...@@ -1405,6 +1416,12 @@ bool Texture::isImmutable() const
return mImmutable; return mImmutable;
} }
int Texture::getLodOffset()
{
TextureStorage *texture = getStorage(false);
return texture ? texture->getLodOffset() : 0;
}
GLint Texture::creationLevels(GLsizei width, GLsizei height) const GLint Texture::creationLevels(GLsizei width, GLsizei height) const
{ {
if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture()) if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
...@@ -1477,7 +1494,8 @@ TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, in ...@@ -1477,7 +1494,8 @@ TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, in
if (width > 0 && height > 0) if (width > 0 && height > 0)
{ {
IDirect3DDevice9 *device = getDevice(); IDirect3DDevice9 *device = getDevice();
HRESULT result = device->CreateTexture(width, height, levels, getUsage(), format, getPool(), &mTexture, NULL); MakeValidSize(false, dx2es::IsCompressedD3DFormat(format), &width, &height, &mLodOffset);
HRESULT result = device->CreateTexture(width, height, levels + mLodOffset, getUsage(), format, getPool(), &mTexture, NULL);
if (FAILED(result)) if (FAILED(result))
{ {
...@@ -1503,7 +1521,7 @@ IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level) ...@@ -1503,7 +1521,7 @@ IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level)
if (mTexture) if (mTexture)
{ {
HRESULT result = mTexture->GetSurfaceLevel(level, &surface); HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
} }
...@@ -2197,7 +2215,9 @@ TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD ...@@ -2197,7 +2215,9 @@ TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD
if (size > 0) if (size > 0)
{ {
IDirect3DDevice9 *device = getDevice(); IDirect3DDevice9 *device = getDevice();
HRESULT result = device->CreateCubeTexture(size, levels, getUsage(), format, getPool(), &mTexture, NULL); int height = size;
MakeValidSize(false, dx2es::IsCompressedD3DFormat(format), &size, &height, &mLodOffset);
HRESULT result = device->CreateCubeTexture(size, levels + mLodOffset, getUsage(), format, getPool(), &mTexture, NULL);
if (FAILED(result)) if (FAILED(result))
{ {
...@@ -2223,7 +2243,7 @@ IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, i ...@@ -2223,7 +2243,7 @@ IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, i
if (mTexture) if (mTexture)
{ {
HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level, &surface); HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level + mLodOffset, &surface);
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
} }
......
...@@ -150,6 +150,10 @@ class TextureStorage ...@@ -150,6 +150,10 @@ class TextureStorage
DWORD getUsage() const; DWORD getUsage() const;
unsigned int getTextureSerial() const; unsigned int getTextureSerial() const;
virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
int getLodOffset() const;
protected:
int mLodOffset;
private: private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage); DISALLOW_COPY_AND_ASSIGN(TextureStorage);
...@@ -204,6 +208,7 @@ class Texture : public RefCountObject ...@@ -204,6 +208,7 @@ class Texture : public RefCountObject
unsigned int getRenderTargetSerial(GLenum target); unsigned int getRenderTargetSerial(GLenum target);
bool isImmutable() const; bool isImmutable() const;
int getLodOffset();
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
...@@ -427,4 +432,4 @@ class TextureCubeMap : public Texture ...@@ -427,4 +432,4 @@ class TextureCubeMap : public Texture
}; };
} }
#endif // LIBGLESV2_TEXTURE_H_ #endif // LIBGLESV2_TEXTURE_H_
\ No newline at end of file
...@@ -965,6 +965,21 @@ bool IsStencilTextureFormat(D3DFORMAT surfaceFormat) ...@@ -965,6 +965,21 @@ bool IsStencilTextureFormat(D3DFORMAT surfaceFormat)
return (surfaceFormat == D3DFMT_INTZ); return (surfaceFormat == D3DFMT_INTZ);
} }
bool IsCompressedD3DFormat(D3DFORMAT surfaceFormat)
{
switch(surfaceFormat)
{
case D3DFMT_DXT1:
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
return true;
default:
return false;
}
}
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
{ {
if (type == D3DMULTISAMPLE_NONMASKABLE) if (type == D3DMULTISAMPLE_NONMASKABLE)
......
...@@ -84,6 +84,7 @@ bool IsFloat32Format(D3DFORMAT surfaceFormat); ...@@ -84,6 +84,7 @@ bool IsFloat32Format(D3DFORMAT surfaceFormat);
bool IsFloat16Format(D3DFORMAT surfaceFormat); bool IsFloat16Format(D3DFORMAT surfaceFormat);
bool IsDepthTextureFormat(D3DFORMAT surfaceFormat); bool IsDepthTextureFormat(D3DFORMAT surfaceFormat);
bool IsStencilTextureFormat(D3DFORMAT surfaceFormat); bool IsStencilTextureFormat(D3DFORMAT surfaceFormat);
bool IsCompressedD3DFormat(D3DFORMAT format);
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
......
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