Add support for DXT3 and DXT5
TEST=none
BUG=none
Review URL: http://codereview.appspot.com/4809068
git-svn-id: https://angleproject.googlecode.com/svn/trunk@721 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/extensions/ANGLE_texture_compression_dxt.txt b/extensions/ANGLE_texture_compression_dxt.txt
new file mode 100644
index 0000000..d155730
--- /dev/null
+++ b/extensions/ANGLE_texture_compression_dxt.txt
@@ -0,0 +1,73 @@
+Name
+
+ ANGLE_texture_compression_dxt
+
+Name Strings
+
+ GL_ANGLE_texture_compression_dxt3
+ GL_ANGLE_texture_compression_dxt5
+
+Contributors
+
+ Gregg Tavares, Google Inc.
+ Daniel Koch, TransGaming Inc.
+ Al Patrick, Google Inc.
+
+Contacts
+
+ Gregg Tavares, Google Inc. (gman 'at' google 'dot' com)
+
+Status
+
+ Implemented in ANGLE ES2
+
+Version
+
+ Last Modified Date: Aug 2, 2011
+
+Number
+
+ OpenGL ES Extension #..
+
+Dependencies
+
+ Requires OpenGL ES 2.0.
+
+ The extension is written against the OpenGL ES 2.0 specification.
+
+Overview
+
+ These extensions are exactly the same as EXT_texture_compression_dxt1
+ except they expose the formats COMPRESSED_RGBA_S3TC_DXT3_ANGLE and
+ COMPRESSED_RGBA_S3TC_DXT5_ANGLE respectively.
+
+ See EXT_texture_compression_dxt1 for the full list of changes. Also
+ see EXT_texture_compression_s3tc for a description of the formats.
+
+New Procedures and Functions
+
+ None.
+
+New Types
+
+ None.
+
+New Tokens
+
+ Accepted by the <internalformat> parameter of CompressedTexImage2D
+ and the <format> parameter of CompressedTexSubImage2D:
+
+ COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+ COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+
+Errors
+
+ None.
+
+New State
+
+ None.
+
+Revision History
+
+
diff --git a/include/GLES2/gl2ext.h b/include/GLES2/gl2ext.h
index 4eae246..9371ad7 100644
--- a/include/GLES2/gl2ext.h
+++ b/include/GLES2/gl2ext.h
@@ -207,6 +207,16 @@
#define GL_MAX_SAMPLES_ANGLE 0x8D57
#endif
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#endif
+
/*------------------------------------------------------------------------*
* APPLE extension tokens
*------------------------------------------------------------------------*/
@@ -790,6 +800,16 @@
typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
#endif
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
/*------------------------------------------------------------------------*
* APPLE extension functions
*------------------------------------------------------------------------*/
diff --git a/src/common/version.h b/src/common/version.h
index 739791f..e4607fb 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -1,7 +1,7 @@
#define MAJOR_VERSION 0
#define MINOR_VERSION 0
#define BUILD_VERSION 0
-#define BUILD_REVISION 720
+#define BUILD_REVISION 721
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index ea5fcc3..791eca4 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -773,7 +773,7 @@
}
}
-bool Display::getCompressedTextureSupport()
+bool Display::getDXT1TextureSupport()
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
@@ -781,6 +781,22 @@
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
}
+bool Display::getDXT3TextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
+}
+
+bool Display::getDXT5TextureSupport()
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
+
+ return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
+}
+
bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
{
D3DDISPLAYMODE currentDisplayMode;
diff --git a/src/libEGL/Display.h b/src/libEGL/Display.h
index 3c6ac88..f241670 100644
--- a/src/libEGL/Display.h
+++ b/src/libEGL/Display.h
@@ -63,7 +63,9 @@
virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
bool isDeviceLost();
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
- virtual bool getCompressedTextureSupport();
+ virtual bool getDXT1TextureSupport();
+ virtual bool getDXT3TextureSupport();
+ virtual bool getDXT5TextureSupport();
virtual bool getEventQuerySupport();
virtual bool getFloatTextureSupport(bool *filtering, bool *renderable);
virtual bool getHalfFloatTextureSupport(bool *filtering, bool *renderable);
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index f6dd3f5..77fff26 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -156,8 +156,11 @@
mHasBeenCurrent = false;
- mSupportsCompressedTextures = false;
+ mSupportsDXT1Textures = false;
+ mSupportsDXT3Textures = false;
+ mSupportsDXT5Textures = false;
mSupportsEventQueries = false;
+ mNumCompressedTextureFormats = 0;
mMaxSupportedSamples = 0;
mMaskedClearSavedState = NULL;
markAllStateDirty();
@@ -280,7 +283,9 @@
mMaxSupportedSamples = max;
mSupportsEventQueries = display->getEventQuerySupport();
- mSupportsCompressedTextures = display->getCompressedTextureSupport();
+ mSupportsDXT1Textures = display->getDXT1TextureSupport();
+ mSupportsDXT3Textures = display->getDXT3TextureSupport();
+ mSupportsDXT5Textures = display->getDXT5TextureSupport();
mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
mSupportsLuminanceTextures = display->getLuminanceTextureSupport();
@@ -288,6 +293,20 @@
mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
+ mNumCompressedTextureFormats = 0;
+ if (supportsDXT1Textures())
+ {
+ mNumCompressedTextureFormats += 2;
+ }
+ if (supportsDXT3Textures())
+ {
+ mNumCompressedTextureFormats += 1;
+ }
+ if (supportsDXT5Textures())
+ {
+ mNumCompressedTextureFormats += 1;
+ }
+
initExtensionString();
mState.viewportX = 0;
@@ -1240,18 +1259,7 @@
case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
- {
- if (supportsCompressedTextures())
- {
- // at current, only GL_COMPRESSED_RGB_S3TC_DXT1_EXT and
- // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT are supported
- *params = 2;
- }
- else
- {
- *params = 0;
- }
- }
+ params[0] = mNumCompressedTextureFormats;
break;
case GL_MAX_SAMPLES_ANGLE:
{
@@ -1307,10 +1315,18 @@
break;
case GL_COMPRESSED_TEXTURE_FORMATS:
{
- if (supportsCompressedTextures())
+ if (supportsDXT1Textures())
{
- params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ }
+ if (supportsDXT3Textures())
+ {
+ *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ }
+ if (supportsDXT5Textures())
+ {
+ *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
}
}
break;
@@ -1422,7 +1438,12 @@
// application.
switch (pname)
{
- case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = mNumCompressedTextureFormats;
+ }
+ break;
case GL_SHADER_BINARY_FORMATS:
{
*type = GL_INT;
@@ -3053,9 +3074,19 @@
return mSupportsEventQueries;
}
-bool Context::supportsCompressedTextures() const
+bool Context::supportsDXT1Textures() const
{
- return mSupportsCompressedTextures;
+ return mSupportsDXT1Textures;
+}
+
+bool Context::supportsDXT3Textures() const
+{
+ return mSupportsDXT3Textures;
+}
+
+bool Context::supportsDXT5Textures() const
+{
+ return mSupportsDXT5Textures;
}
bool Context::supportsFloatTextures() const
@@ -3330,11 +3361,21 @@
mExtensionString += "GL_NV_fence ";
}
- if (supportsCompressedTextures())
+ if (supportsDXT1Textures())
{
mExtensionString += "GL_EXT_texture_compression_dxt1 ";
}
+ if (supportsDXT3Textures())
+ {
+ mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
+ }
+
+ if (supportsDXT5Textures())
+ {
+ mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
+ }
+
if (supportsFloatTextures())
{
mExtensionString += "GL_OES_texture_float ";
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 3002654..77d9406 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -437,7 +437,9 @@
int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
const char *getExtensionString() const;
bool supportsEventQueries() const;
- bool supportsCompressedTextures() const;
+ bool supportsDXT1Textures() const;
+ bool supportsDXT3Textures() const;
+ bool supportsDXT5Textures() const;
bool supportsFloatTextures() const;
bool supportsFloatLinearFilter() const;
bool supportsFloatRenderableTextures() const;
@@ -532,7 +534,9 @@
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsEventQueries;
- bool mSupportsCompressedTextures;
+ bool mSupportsDXT1Textures;
+ bool mSupportsDXT3Textures;
+ bool mSupportsDXT5Textures;
bool mSupportsFloatTextures;
bool mSupportsFloatLinearFilter;
bool mSupportsFloatRenderableTextures;
@@ -542,6 +546,7 @@
bool mSupportsLuminanceTextures;
bool mSupportsLuminanceAlphaTextures;
bool mSupports32bitIndices;
+ int mNumCompressedTextureFormats;
// state caching flags
bool mClearStateDirty;
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 0187bcf..e143535 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -49,6 +49,8 @@
case D3DFMT_L8:
case D3DFMT_A8L8:
case D3DFMT_DXT1:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT5:
return false;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
@@ -69,6 +71,14 @@
{
return D3DFMT_DXT1;
}
+ else if (type == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
+ {
+ return D3DFMT_DXT3;
+ }
+ else if (type == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
+ {
+ return D3DFMT_DXT5;
+ }
else if (type == GL_FLOAT)
{
return D3DFMT_A32B32G32R32F;
@@ -767,6 +777,132 @@
}
void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const {
+ switch (getD3DFormat())
+ {
+ case D3DFMT_DXT1:
+ loadDXT1ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+ case D3DFMT_DXT3:
+ loadDXT3ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+ case D3DFMT_DXT5:
+ loadDXT5ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+ }
+}
+
+static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
+ // A DXT1 block layout is:
+ // [0-1] color0.
+ // [2-3] color1.
+ // [4-7] color bitmap, 2 bits per pixel.
+ // So each of the 4-7 bytes represents one line, flipping a block is just
+ // flipping those bytes.
+
+ // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
+ dest[0] = source[0];
+
+ // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
+ dest[1] = (source[1] >> 24) |
+ ((source[1] << 8) & 0x00FF0000) |
+ ((source[1] >> 8) & 0x0000FF00) |
+ (source[1] << 24);
+}
+
+// Flips the first 2 lines of a DXT1 block in the y direction.
+static void FlipCopyDXT1BlockHalf(const unsigned int* source, unsigned int* dest) {
+ // See layout above.
+ dest[0] = source[0];
+ dest[1] = ((source[1] << 8) & 0x0000FF00) |
+ ((source[1] >> 8) & 0x000000FF);
+}
+
+// Flips a full DXT3 block in the y direction.
+static void FlipCopyDXT3BlockFull(const unsigned int* source, unsigned int* dest) {
+ // A DXT3 block layout is:
+ // [0-7] alpha bitmap, 4 bits per pixel.
+ // [8-15] a DXT1 block.
+
+ // First and Second 32 bits are 4bit per pixel alpha and need to be flipped.
+ dest[0] = (source[1] >> 16) | (source[1] << 16);
+ dest[1] = (source[0] >> 16) | (source[0] << 16);
+
+ // And flip the DXT1 block using the above function.
+ FlipCopyDXT1BlockFull(source + 2, dest + 2);
+}
+
+// Flips the first 2 lines of a DXT3 block in the y direction.
+static void FlipCopyDXT3BlockHalf(const unsigned int* source, unsigned int* dest) {
+ // See layout above.
+ dest[0] = (source[1] >> 16) | (source[1] << 16);
+ FlipCopyDXT1BlockHalf(source + 2, dest + 2);
+}
+
+// Flips a full DXT5 block in the y direction.
+static void FlipCopyDXT5BlockFull(const unsigned int* source, unsigned int* dest) {
+ // A DXT5 block layout is:
+ // [0] alpha0.
+ // [1] alpha1.
+ // [2-7] alpha bitmap, 3 bits per pixel.
+ // [8-15] a DXT1 block.
+
+ // The alpha bitmap doesn't easily map lines to bytes, so we have to
+ // interpret it correctly. Extracted from
+ // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
+ //
+ // The 6 "bits" bytes of the block are decoded into one 48-bit integer:
+ //
+ // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
+ // 256 * (bits_4 + 256 * bits_5))))
+ //
+ // bits is a 48-bit unsigned integer, from which a three-bit control code
+ // is extracted for a texel at location (x,y) in the block using:
+ //
+ // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
+ //
+ // where bit 47 is the most significant and bit 0 is the least
+ // significant bit.
+ const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
+ unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
+ unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
+ unsigned int line_2_3 = sourceBytes[5] + 256 * (sourceBytes[6] + 256 * sourceBytes[7]);
+ // swap lines 0 and 1 in line_0_1.
+ unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
+ ((line_0_1 & 0xfff000) >> 12);
+ // swap lines 2 and 3 in line_2_3.
+ unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
+ ((line_2_3 & 0xfff000) >> 12);
+ destBytes[0] = sourceBytes[0];
+ destBytes[1] = sourceBytes[1];
+ destBytes[2] = line_3_2 & 0xff;
+ destBytes[3] = (line_3_2 & 0xff00) >> 8;
+ destBytes[4] = (line_3_2 & 0xff0000) >> 8;
+ destBytes[5] = line_1_0 & 0xff;
+ destBytes[6] = (line_1_0 & 0xff00) >> 8;
+ destBytes[7] = (line_1_0 & 0xff0000) >> 8;
+
+ // And flip the DXT1 block using the above function.
+ FlipCopyDXT1BlockFull(source + 2, dest + 2);
+}
+
+// Flips the first 2 lines of a DXT5 block in the y direction.
+static void FlipCopyDXT5BlockHalf(const unsigned int* source, unsigned int* dest) {
+ // See layout above.
+ const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
+ unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
+ unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
+ unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
+ ((line_0_1 & 0xfff000) >> 12);
+ destBytes[0] = sourceBytes[0];
+ destBytes[1] = sourceBytes[1];
+ destBytes[2] = line_1_0 & 0xff;
+ destBytes[3] = (line_1_0 & 0xff00) >> 8;
+ destBytes[4] = (line_1_0 & 0xff0000) >> 8;
+ FlipCopyDXT1BlockHalf(source + 2, dest + 2);
+}
+
+void Texture::loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const
{
ASSERT(xoffset % 4 == 0);
@@ -778,29 +914,24 @@
const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+ // Round width up in case it is less than 4.
+ int blocksAcross = (width + 3) / 4;
+ int intsAcross = blocksAcross * 2;
+
switch (height)
{
case 1:
- // Round width up in case it is 1.
- for (int x = 0; x < (width + 1) / 2; x += 2)
+ for (int x = 0; x < intsAcross; x += 2)
{
- // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
+ // just copy the block
dest[x] = source[x];
-
- // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 3 rows being unused. No flipping should occur.
dest[x + 1] = source[x + 1];
}
break;
case 2:
- // Round width up in case it is 1.
- for (int x = 0; x < (width + 1) / 2; x += 2)
+ for (int x = 0; x < intsAcross; x += 2)
{
- // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
- dest[x] = source[x];
-
- // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors, the last 2 rows being unused. Only the top 2 rows should be flipped.
- dest[x + 1] = ((source[x + 1] << 8) & 0x0000FF00) |
- ((source[x + 1] >> 8) & 0x000000FF);
+ FlipCopyDXT1BlockHalf(source + x, dest + x);
}
break;
default:
@@ -810,17 +941,109 @@
const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
- // Round width up in case it is 1.
- for (int x = 0; x < (width + 1) / 2; x += 2)
+ for (int x = 0; x < intsAcross; x += 2)
{
- // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
- dest[x] = source[x];
+ FlipCopyDXT1BlockFull(source + x, dest + x);
+ }
+ }
+ break;
+ }
+}
- // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
- dest[x + 1] = (source[x + 1] >> 24) |
- ((source[x + 1] << 8) & 0x00FF0000) |
- ((source[x + 1] >> 8) & 0x0000FF00) |
- (source[x + 1] << 24);
+void Texture::loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+ ASSERT(width % 4 == 0 || width == 2 || width == 1);
+ ASSERT(inputPitch % 16 == 0);
+ ASSERT(outputPitch % 16 == 0);
+
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+
+ // Round width up in case it is less than 4.
+ int blocksAcross = (width + 3) / 4;
+ int intsAcross = blocksAcross * 4;
+
+ switch (height)
+ {
+ case 1:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ // just copy the block
+ dest[x] = source[x];
+ dest[x + 1] = source[x + 1];
+ dest[x + 2] = source[x + 2];
+ dest[x + 3] = source[x + 3];
+ }
+ break;
+ case 2:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT3BlockHalf(source + x, dest + x);
+ }
+ break;
+ default:
+ ASSERT(height % 4 == 0);
+ for (int y = 0; y < height / 4; ++y)
+ {
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
+
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT3BlockFull(source + x, dest + x);
+ }
+ }
+ break;
+ }
+}
+
+void Texture::loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+ ASSERT(width % 4 == 0 || width == 2 || width == 1);
+ ASSERT(inputPitch % 16 == 0);
+ ASSERT(outputPitch % 16 == 0);
+
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+
+ // Round width up in case it is less than 4.
+ int blocksAcross = (width + 3) / 4;
+ int intsAcross = blocksAcross * 4;
+
+ switch (height)
+ {
+ case 1:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ // just copy the block
+ dest[x] = source[x];
+ dest[x + 1] = source[x + 1];
+ dest[x + 2] = source[x + 2];
+ dest[x + 3] = source[x + 3];
+ }
+ break;
+ case 2:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT5BlockHalf(source + x, dest + x);
+ }
+ break;
+ default:
+ ASSERT(height % 4 == 0);
+ for (int y = 0; y < height; ++y)
+ {
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
+
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT5BlockFull(source + x, dest + x);
}
}
break;
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 5bdb2fb..95045b8 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -185,6 +185,12 @@
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
static unsigned int issueSerial();
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 23957fe..26f2f23 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -772,6 +772,8 @@
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
break;
default:
return error(GL_INVALID_ENUM);
@@ -821,9 +823,27 @@
return error(GL_INVALID_ENUM);
}
- if (!context->supportsCompressedTextures())
- {
- return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ switch (internalformat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->supportsDXT5Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ default: UNREACHABLE();
}
if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
@@ -897,6 +917,8 @@
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
break;
default:
return error(GL_INVALID_ENUM);
@@ -916,9 +938,27 @@
return error(GL_INVALID_VALUE);
}
- if (!context->supportsCompressedTextures())
- {
- return error(GL_INVALID_ENUM); // in this case, it's as though the format switch has failed.
+ switch (format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->supportsDXT5Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ default: UNREACHABLE();
}
if (imageSize != gl::ComputeCompressedSize(width, height, format))
@@ -929,7 +969,7 @@
if (xoffset % 4 != 0 || yoffset % 4 != 0)
{
return error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction
- // does not exist unless DXT1 textures are supported.
+ // does not exist unless DXT textures are supported.
}
if (target == GL_TEXTURE_2D)
@@ -1093,7 +1133,27 @@
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->supportsCompressedTextures())
+ if (context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->supportsDXT5Textures())
{
return error(GL_INVALID_OPERATION);
}
@@ -1245,6 +1305,8 @@
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
return error(GL_INVALID_OPERATION);
default:
return error(GL_INVALID_OPERATION);
@@ -4467,6 +4529,8 @@
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
break;
default:
return error(GL_INVALID_VALUE);
@@ -4511,10 +4575,10 @@
return error(GL_INVALID_ENUM);
}
- if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
- {
- if (context->supportsCompressedTextures())
+ switch (format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (context->supportsDXT1Textures())
{
return error(GL_INVALID_OPERATION);
}
@@ -4522,6 +4586,29 @@
{
return error(GL_INVALID_ENUM);
}
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->supportsDXT5Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ break;
}
if (type == GL_FLOAT)
diff --git a/src/libGLESv2/utilities.cpp b/src/libGLESv2/utilities.cpp
index ba23fd3..01cca3c 100644
--- a/src/libGLESv2/utilities.cpp
+++ b/src/libGLESv2/utilities.cpp
@@ -200,18 +200,23 @@
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
default:
return 0;
}
- return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
}
bool IsCompressed(GLenum format)
{
if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
{
return true;
}