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
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 1c2179e..f542399 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2410,6 +2410,7 @@
es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, texture->getLodOffset());
if (supportsTextureFilterAnisotropy())
{
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index cd4d637..9cb9c98 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -118,6 +118,26 @@
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()
{
mWidth = 0;
@@ -186,22 +206,7 @@
int levelToFetch = 0;
GLsizei requestWidth = mWidth;
GLsizei requestHeight = mHeight;
- if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
- {
- bool isMult4 = false;
- int upsampleCount = 0;
- while (!isMult4)
- {
- requestWidth <<= 1;
- requestHeight <<= 1;
- upsampleCount++;
- if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
- {
- isMult4 = true;
- }
- }
- levelToFetch = upsampleCount;
- }
+ MakeValidSize(true, IsCompressed(mFormat), &requestWidth, &requestHeight, &levelToFetch);
HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat,
poolToUse, &newTexture, NULL);
@@ -1111,7 +1116,8 @@
TextureStorage::TextureStorage(DWORD usage)
: mD3DUsage(usage),
mD3DPool(getDisplay()->getTexturePool(usage)),
- mTextureSerial(issueTextureSerial())
+ mTextureSerial(issueTextureSerial()),
+ mLodOffset(0)
{
}
@@ -1149,6 +1155,11 @@
return mCurrentTextureSerial++;
}
+int TextureStorage::getLodOffset() const
+{
+ return mLodOffset;
+}
+
Texture::Texture(GLuint id) : RefCountObject(id)
{
mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
@@ -1405,6 +1416,12 @@
return mImmutable;
}
+int Texture::getLodOffset()
+{
+ TextureStorage *texture = getStorage(false);
+ return texture ? texture->getLodOffset() : 0;
+}
+
GLint Texture::creationLevels(GLsizei width, GLsizei height) const
{
if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
@@ -1477,7 +1494,8 @@
if (width > 0 && height > 0)
{
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))
{
@@ -1503,7 +1521,7 @@
if (mTexture)
{
- HRESULT result = mTexture->GetSurfaceLevel(level, &surface);
+ HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
ASSERT(SUCCEEDED(result));
}
@@ -2197,7 +2215,9 @@
if (size > 0)
{
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))
{
@@ -2223,7 +2243,7 @@
if (mTexture)
{
- HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level, &surface);
+ HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level + mLodOffset, &surface);
ASSERT(SUCCEEDED(result));
}
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index ccddf57..6d67df7 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -150,6 +150,10 @@
DWORD getUsage() const;
unsigned int getTextureSerial() const;
virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
+ int getLodOffset() const;
+
+ protected:
+ int mLodOffset;
private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage);
@@ -204,6 +208,7 @@
unsigned int getRenderTargetSerial(GLenum target);
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.
@@ -427,4 +432,4 @@
};
}
-#endif // LIBGLESV2_TEXTURE_H_
\ No newline at end of file
+#endif // LIBGLESV2_TEXTURE_H_
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index 5cf005d..e6f8993 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -965,6 +965,21 @@
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)
{
if (type == D3DMULTISAMPLE_NONMASKABLE)
diff --git a/src/libGLESv2/utilities.h b/src/libGLESv2/utilities.h
index 5174680..3357eb0 100644
--- a/src/libGLESv2/utilities.h
+++ b/src/libGLESv2/utilities.h
@@ -84,6 +84,7 @@
bool IsFloat16Format(D3DFORMAT surfaceFormat);
bool IsDepthTextureFormat(D3DFORMAT surfaceFormat);
bool IsStencilTextureFormat(D3DFORMAT surfaceFormat);
+bool IsCompressedD3DFormat(D3DFORMAT format);
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);