Implements compressed textures.

TRAC #12714 Signed-off-by: Daniel Koch Author: Shannon Woods git-svn-id: https://angleproject.googlecode.com/svn/trunk@397 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent f5cde483
......@@ -222,6 +222,12 @@ typedef void* GLeglImageOES;
#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
#endif
/* GL_EXT_texture_compression_dxt1 */
#ifndef GL_EXT_texture_compression_dxt1
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#endif
/*------------------------------------------------------------------------*
* IMG extension tokens
*------------------------------------------------------------------------*/
......@@ -642,6 +648,11 @@ typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GL
#define GL_EXT_texture_type_2_10_10_10_REV 1
#endif
/* GL_EXT_texture_compression_dxt1 */
#ifndef GL_EXT_texture_compression_dxt1
#define GL_EXT_texture_compression_dxt1 1
#endif
/*------------------------------------------------------------------------*
* IMG extension functions
*------------------------------------------------------------------------*/
......
......@@ -479,4 +479,12 @@ void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
}
}
bool Display::getCompressedTextureSupport()
{
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
}
}
......@@ -61,6 +61,7 @@ class Display
virtual IDirect3DDevice9 *getDevice();
virtual D3DCAPS9 getDeviceCaps();
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
virtual bool getCompressedTextureSupport();
private:
DISALLOW_COPY_AND_ASSIGN(Display);
......
......@@ -265,6 +265,8 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mMaxSupportedSamples = max;
mSupportsCompressedTextures = display->getCompressedTextureSupport();
initExtensionString();
mState.viewportX = 0;
......@@ -1146,8 +1148,6 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
......@@ -1185,6 +1185,20 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_SUBPIXEL_BITS: *params = 4; break;
case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; 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;
}
}
break;
case GL_MAX_SAMPLES_ANGLE:
{
GLsizei maxSamples = getMaxSupportedSamples();
......@@ -1237,6 +1251,15 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
params[1] = maxDimension;
}
break;
case GL_COMPRESSED_TEXTURE_FORMATS:
{
if (supportsCompressedTextures())
{
params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
}
}
break;
case GL_VIEWPORT:
params[0] = mState.viewportX;
params[1] = mState.viewportY;
......@@ -2762,6 +2785,11 @@ int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const
return -1;
}
bool Context::supportsCompressedTextures() const
{
return mSupportsCompressedTextures;
}
void Context::detachBuffer(GLuint buffer)
{
// [OpenGL ES 2.0.24] section 2.9 page 22:
......@@ -2958,6 +2986,10 @@ void Context::initExtensionString()
mExtensionString += "GL_ANGLE_framebuffer_blit ";
mExtensionString += "GL_OES_rgb8_rgba8 ";
if (supportsCompressedTextures())
{
mExtensionString += "GL_EXT_texture_compression_dxt1 ";
}
if (getMaxSupportedSamples() != 0)
{
......
......@@ -377,6 +377,7 @@ class Context
GLsizei getMaxSupportedSamples() const;
int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
const char *getExtensionString() const;
bool supportsCompressedTextures() const;
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
......@@ -442,6 +443,7 @@ class Context
bool mSupportsShaderModel3;
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsCompressedTextures;
// state caching flags
bool mClearStateDirty;
......
......@@ -305,6 +305,14 @@ GLenum Framebuffer::completeness()
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
if (IsTextureTarget(mColorbufferType))
{
if (IsCompressed(colorbuffer->getFormat()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
}
width = colorbuffer->getWidth();
height = colorbuffer->getHeight();
samples = colorbuffer->getSamples();
......@@ -349,6 +357,14 @@ GLenum Framebuffer::completeness()
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
if (IsTextureTarget(mDepthbufferType))
{
if (IsCompressed(depthbuffer->getFormat()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
}
}
if (mStencilbufferType != GL_NONE)
......@@ -383,6 +399,14 @@ GLenum Framebuffer::completeness()
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
if (IsTextureTarget(mStencilbufferType))
{
if (IsCompressed(stencilbuffer->getFormat()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
}
}
if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
......
......@@ -41,7 +41,7 @@ class RenderbufferStorage
virtual int getWidth() const;
virtual int getHeight() const;
GLenum getFormat() const;
virtual GLenum getFormat() const;
D3DFORMAT getD3DFormat() const;
GLsizei getSamples() const;
unsigned int getSerial() const;
......
......@@ -23,7 +23,7 @@ namespace gl
{
Texture::Image::Image()
: width(0), height(0), dirty(false), surface(NULL)
: width(0), height(0), dirty(false), surface(NULL), format(GL_NONE)
{
}
......@@ -177,7 +177,15 @@ GLuint Texture::getHeight() const
// Selects an internal Direct3D 9 format for storing an Image
D3DFORMAT Texture::selectFormat(GLenum format)
{
return D3DFMT_A8R8G8B8;
if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
{
return D3DFMT_DXT1;
}
else
{
return D3DFMT_A8R8G8B8;
}
}
int Texture::imagePitch(const Image &img) const
......@@ -305,14 +313,13 @@ void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei
}
}
void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, Image *img)
{
IDirect3DTexture9 *newTexture = NULL;
IDirect3DSurface9 *newSurface = NULL;
if (width != 0 && height != 0)
{
//HRESULT result = getDevice()->CreateOffscreenPlainSurface(width, height, selectFormat(format), D3DPOOL_SYSTEMMEM, &newSurface, NULL);
HRESULT result = getDevice()->CreateTexture(width, height, 1, NULL, selectFormat(format), D3DPOOL_SYSTEMMEM, &newTexture, NULL);
if (FAILED(result))
......@@ -331,18 +338,46 @@ void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type
img->width = width;
img->height = height;
img->format = format;
}
void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
{
createSurface(width, height, format, img);
if (pixels != NULL && newSurface != NULL)
if (pixels != NULL && img->surface != NULL)
{
D3DLOCKED_RECT locked;
HRESULT result = newSurface->LockRect(&locked, NULL, 0);
HRESULT result = img->surface->LockRect(&locked, NULL, 0);
ASSERT(SUCCEEDED(result));
if (SUCCEEDED(result))
{
loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
newSurface->UnlockRect();
img->surface->UnlockRect();
}
img->dirty = true;
}
mDirtyMetaData = true;
}
void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
{
createSurface(width, height, format, img);
if (pixels != NULL && img->surface != NULL)
{
D3DLOCKED_RECT locked;
HRESULT result = img->surface->LockRect(&locked, NULL, 0);
ASSERT(SUCCEEDED(result));
if (SUCCEEDED(result))
{
memcpy(locked.pBits, pixels, imageSize);
img->surface->UnlockRect();
}
img->dirty = true;
......@@ -374,6 +409,46 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
return true;
}
bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
{
if (width + xoffset > img->width || height + yoffset > img->height)
{
error(GL_INVALID_VALUE);
return false;
}
if (format != getFormat())
{
error(GL_INVALID_OPERATION);
return false;
}
RECT updateRegion;
updateRegion.left = xoffset;
updateRegion.right = xoffset + width;
updateRegion.bottom = yoffset + height;
updateRegion.top = yoffset;
D3DLOCKED_RECT locked;
HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0);
ASSERT(SUCCEEDED(result));
if (SUCCEEDED(result))
{
GLsizei inputPitch = ComputeCompressedPitch(width, format);
int rows = imageSize / inputPitch;
for (int i = 0; i < rows; ++i)
{
memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
}
img->surface->UnlockRect();
}
img->dirty = true;
return true;
}
IDirect3DBaseTexture9 *Texture::getTexture()
{
if (!isComplete())
......@@ -484,6 +559,11 @@ GLenum Texture2D::getTarget() const
return GL_TEXTURE_2D;
}
GLenum Texture2D::getFormat() const
{
return mImageArray[0].format;
}
// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
// Call this when a particular level of the texture must be defined with a specific format, width and height.
......@@ -542,6 +622,13 @@ void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsi
Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
}
void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
redefineTexture(level, internalFormat, width, height);
Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
}
void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
ASSERT(mImageArray[level].surface != NULL);
......@@ -585,6 +672,14 @@ void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei widt
}
}
void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
{
commitRect(level, xoffset, yoffset, width, height);
}
}
void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
{
if (redefineTexture(level, internalFormat, width, height))
......@@ -715,6 +810,11 @@ bool Texture2D::isComplete() const
return true;
}
bool Texture2D::isCompressed() const
{
return IsCompressed(getFormat());
}
// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
IDirect3DBaseTexture9 *Texture2D::createTexture()
{
......@@ -954,6 +1054,11 @@ GLenum TextureCubeMap::getTarget() const
return GL_TEXTURE_CUBE_MAP;
}
GLenum TextureCubeMap::getFormat() const
{
return mImageArray[0][0].format;
}
void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
......@@ -984,6 +1089,13 @@ void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei wi
setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
}
void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
redefineTexture(level, internalFormat, width);
Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
}
void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
int face = faceIndex(faceTarget);
......@@ -1027,6 +1139,14 @@ void TextureCubeMap::subImage(GLenum face, GLint level, GLint xoffset, GLint yof
}
}
void TextureCubeMap::subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(face)][level]))
{
commitRect(face, level, xoffset, yoffset, width, height);
}
}
// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool TextureCubeMap::isComplete() const
{
......@@ -1093,6 +1213,11 @@ bool TextureCubeMap::isComplete() const
return true;
}
bool TextureCubeMap::isCompressed() const
{
return IsCompressed(getFormat());
}
// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
{
......@@ -1538,4 +1663,9 @@ int Texture::TextureColorbufferProxy::getHeight() const
return mTexture->getHeight();
}
GLenum Texture::TextureColorbufferProxy::getFormat() const
{
return mTexture->getFormat();
}
}
......@@ -55,7 +55,9 @@ class Texture : public RefCountObject
GLuint getWidth() const;
GLuint getHeight() const;
virtual GLenum getFormat() const = 0;
virtual bool isComplete() const = 0;
virtual bool isCompressed() const = 0;
IDirect3DBaseTexture9 *getTexture();
virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
......@@ -82,6 +84,7 @@ class Texture : public RefCountObject
virtual int getWidth() const;
virtual int getHeight() const;
virtual GLenum getFormat() const;
private:
Texture *mTexture;
......@@ -108,6 +111,8 @@ class Texture : public RefCountObject
void setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
void setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
void needRenderTarget();
......@@ -147,6 +152,8 @@ class Texture : public RefCountObject
bool mDirty;
bool mDirtyMetaData;
bool mIsRenderable;
void createSurface(GLsizei width, GLsizei height, GLenum format, Image *img);
};
class Texture2D : public Texture
......@@ -157,13 +164,17 @@ class Texture2D : public Texture
~Texture2D();
GLenum getTarget() const;
GLenum getFormat() const;
void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void copySubImage(GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
bool isComplete() const;
bool isCompressed() const;
virtual void generateMipmaps();
......@@ -197,6 +208,7 @@ class TextureCubeMap : public Texture
~TextureCubeMap();
GLenum getTarget() const;
GLenum getFormat() const;
void setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
......@@ -205,11 +217,15 @@ class TextureCubeMap : public Texture
void setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum face, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
void copySubImage(GLenum face, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
bool isComplete() const;
bool isCompressed() const;
virtual void generateMipmaps();
......
......@@ -183,6 +183,49 @@ GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
return (rawPitch + alignment - 1) & ~(alignment - 1);
}
GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
{
switch (format)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
break;
default:
return 0;
}
ASSERT(width % 4 == 0);
return 8 * width / 4;
}
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
{
switch (format)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
break;
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)
{
return true;
}
else
{
return false;
}
}
// Returns the size, in bytes, of a single texel in an Image
int ComputePixelSize(GLenum format, GLenum type)
{
......
......@@ -29,6 +29,9 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig
int ComputePixelSize(GLenum format, GLenum type);
GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment);
GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
bool IsCompressed(GLenum format);
bool IsCubemapTextureTarget(GLenum target);
bool IsTextureTarget(GLenum target);
bool CheckTextureFormatType(GLenum format, GLenum 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