Commit 50c526d2 by gman@chromium.org

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
parent a1a86201
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
......@@ -207,6 +207,16 @@ typedef void* GLeglImageOES;
#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 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target
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
*------------------------------------------------------------------------*/
......
#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)
......
......@@ -773,7 +773,7 @@ void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
}
}
bool Display::getCompressedTextureSupport()
bool Display::getDXT1TextureSupport()
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
......@@ -781,6 +781,22 @@ bool Display::getCompressedTextureSupport()
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
}
bool Display::getDXT3TextureSupport()
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
}
bool Display::getDXT5TextureSupport()
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
}
bool Display::getFloatTextureSupport(bool *filtering, bool *renderable)
{
D3DDISPLAYMODE currentDisplayMode;
......
......@@ -63,7 +63,9 @@ class Display
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);
......
......@@ -156,8 +156,11 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) : m
mHasBeenCurrent = false;
mSupportsCompressedTextures = false;
mSupportsDXT1Textures = false;
mSupportsDXT3Textures = false;
mSupportsDXT5Textures = false;
mSupportsEventQueries = false;
mNumCompressedTextureFormats = 0;
mMaxSupportedSamples = 0;
mMaskedClearSavedState = NULL;
markAllStateDirty();
......@@ -280,7 +283,9 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
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 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
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 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
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 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
break;
case GL_COMPRESSED_TEXTURE_FORMATS:
{
if (supportsCompressedTextures())
if (supportsDXT1Textures())
{
*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[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
*params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
}
}
break;
......@@ -1422,7 +1438,12 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
// 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 @@ bool Context::supportsEventQueries() const
return mSupportsEventQueries;
}
bool Context::supportsCompressedTextures() const
bool Context::supportsDXT1Textures() const
{
return mSupportsDXT1Textures;
}
bool Context::supportsDXT3Textures() const
{
return mSupportsCompressedTextures;
return mSupportsDXT3Textures;
}
bool Context::supportsDXT5Textures() const
{
return mSupportsDXT5Textures;
}
bool Context::supportsFloatTextures() const
......@@ -3330,11 +3361,21 @@ void Context::initExtensionString()
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 ";
......
......@@ -437,7 +437,9 @@ class Context
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 @@ class Context
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 @@ class Context
bool mSupportsLuminanceTextures;
bool mSupportsLuminanceAlphaTextures;
bool mSupports32bitIndices;
int mNumCompressedTextureFormats;
// state caching flags
bool mClearStateDirty;
......
......@@ -49,6 +49,8 @@ bool Texture::Image::isRenderable() const
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 @@ D3DFORMAT Texture::Image::getD3DFormat() const
{
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::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLs
}
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 @@ void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei widt
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 @@ void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei widt
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)
{
FlipCopyDXT1BlockFull(source + x, dest + x);
}
}
break;
}
}
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)
{
// 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. 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);
FlipCopyDXT5BlockFull(source + x, dest + x);
}
}
break;
......
......@@ -185,6 +185,12 @@ class Texture : public RefCountObject
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();
......
......@@ -772,6 +772,8 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
{
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 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
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 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
{
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 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
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 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
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 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
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 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
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 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
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 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
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 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
{
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)
......
......@@ -200,18 +200,23 @@ GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
{
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;
}
......
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