Implement CHROMIUM_copy_compressed_texture for D3D11.

BUG=angleproject:1356

Change-Id: Id563997d2921cf558c52a781ae66d8bde58d1f2f
Reviewed-on: https://chromium-review.googlesource.com/339847
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Geoff Lang 2016-04-20 11:13:22 -07:00 коммит произвёл Commit Bot
Родитель 55e98210ba
Коммит 47110bf4b3
35 изменённых файлов: 680 добавлений и 31 удалений

Просмотреть файл

@ -0,0 +1,88 @@
Name
CHROMIUM_copy_compressed_texture
Name Strings
GL_CHROMIUM_copy_compressed_texture
Version
Last Modifed Date: August 5, 2015
Dependencies
OpenGL ES 2.0 is required.
GL_AMD_compressed_ATC_texture, GL_ATI_texture_compression_atitc,
GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt5,
GL_EXT_texture_compression_s3tc and GL_OES_compressed_ETC1_RGB8_texture
affects the definition of this extension.
Overview
This extension provides functionality for copying compressed textures. It
adds a new function glCompressedCopyTextureCHROMIUM that works similarily
to glCopyTextureCHROMIUM, but for compressed textures.
Which compressed texture formats that this extension supports depends on
the supported texture compression formats of the host GPU.
Issues
glCompressedCopyTextureCHROMIUM will first try to copy into a compressed
texture of the same format as the source texture. If unsucessful, the
destination texture format will be changed to GL_RGBA and the texture will
be stored uncompressed.
New Procedures and Functions
The command
void glCompressedCopyTextureCHROMIUM (GLuint source_id, GLuint dest_id)
Copies the contents of a compressed texture referred to by <source_id> to
<dest_id> texture.
Texture level 0 is copied from the source image to level 0 of the
destination texture.
The internal format of the source texture must be one of the following
symbolic constants: GL_ATC_RGB_AMD, GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD,
GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
GL_ETC1_RGB8_OES
The destination texture will be created or replaced with the same internal
format as the source texture.
INVALID_OPERATION is generated if internal format of source texture is not
one of the valid formats described above.
INVALID_OPERATION is generated if destination texture is immutable.
INVALID_VALUE is generated if <source_id> or <dest_id> are not valid texture
objects.
INVALID_VALUE is generated if textures corresponding to <dest_id> have not
been bound as GL_TEXTURE_2D object.
INVALID_VALUE is generated if level 0 of the source texture is not defined.
Errors
None.
New Tokens
None.
New State
None.
Revision History
15/6/2015 Documented the extension.
5/8/2015 Added glCompressedCopySubTextureCHROMIUM.
1/6/2016 Remove glCompressedCopySubTextureCHROMIUM.
1/8/2016 Remove <target> argument.

Просмотреть файл

@ -1316,6 +1316,14 @@ GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM(GLuint sourceId,
#endif
#endif /* GL_CHROMIUM_copy_texture */
#ifndef GL_CHROMIUM_compressed_copy_texture
#define GL_CHROMIUM_compressed_copy_texture 1
typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC)(GLuint sourceId, GLuint destId);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
#endif
#endif /* GL_CHROMIUM_compressed_copy_texture */
#ifndef GL_CHROMIUM_sync_query
#define GL_CHROMIUM_sync_query 1
#define GL_COMMANDS_COMPLETED_CHROMIUM 0x84F7

Просмотреть файл

@ -166,6 +166,7 @@ Extensions::Extensions()
bindUniformLocation(false),
syncQuery(false),
copyTexture(false),
copyCompressedTexture(false),
webglCompatibility(false),
bindGeneratesResource(false),
robustClientMemory(false),
@ -580,6 +581,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocation);
map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture);
map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);

Просмотреть файл

@ -293,6 +293,9 @@ struct Extensions
// GL_CHROMIUM_copy_texture
bool copyTexture;
// GL_CHROMIUM_copy_compressed_texture
bool copyCompressedTexture;
// GL_ANGLE_webgl_compatibility
bool webglCompatibility;

Просмотреть файл

@ -3071,6 +3071,15 @@ void Context::copySubTextureCHROMIUM(GLuint sourceId,
unpackUnmultiplyAlpha == GL_TRUE, sourceTexture));
}
void Context::compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
{
syncStateForTexImage();
gl::Texture *sourceTexture = getTexture(sourceId);
gl::Texture *destTexture = getTexture(destId);
handleError(destTexture->copyCompressedTexture(sourceTexture));
}
void Context::getBufferPointerv(GLenum target, GLenum /*pname*/, void **params)
{
Buffer *buffer = mGLState.getTargetBuffer(target);

Просмотреть файл

@ -482,6 +482,7 @@ class Context final : public ValidationContext
GLboolean unpackFlipY,
GLboolean unpackPremultiplyAlpha,
GLboolean unpackUnmultiplyAlpha);
void compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
void generateMipmap(GLenum target);

Просмотреть файл

@ -49,9 +49,7 @@ class Path final : angle::NonCopyable
bool hasPathData() const { return mHasData; }
const rx::PathImpl *getImplementation() const { return mPath; }
rx::PathImpl *getImplementation() { return mPath; }
rx::PathImpl *getImplementation() const { return mPath; }
private:
rx::PathImpl *mPath;

Просмотреть файл

@ -241,8 +241,7 @@ class Program final : angle::NonCopyable, public LabeledObject
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
rx::ProgramImpl *getImplementation() { return mProgram; }
const rx::ProgramImpl *getImplementation() const { return mProgram; }
rx::ProgramImpl *getImplementation() const { return mProgram; }
bool attachShader(Shader *shader);
bool detachShader(Shader *shader);

Просмотреть файл

@ -95,17 +95,12 @@ Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
return NoError();
}
rx::RenderbufferImpl *Renderbuffer::getImplementation()
rx::RenderbufferImpl *Renderbuffer::getImplementation() const
{
ASSERT(mRenderbuffer);
return mRenderbuffer;
}
const rx::RenderbufferImpl *Renderbuffer::getImplementation() const
{
return mRenderbuffer;
}
GLsizei Renderbuffer::getWidth() const
{
return mWidth;

Просмотреть файл

@ -42,8 +42,7 @@ class Renderbuffer final : public egl::ImageSibling,
Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height);
Error setStorageEGLImageTarget(egl::Image *imageTarget);
rx::RenderbufferImpl *getImplementation();
const rx::RenderbufferImpl *getImplementation() const;
rx::RenderbufferImpl *getImplementation() const;
GLsizei getWidth() const;
GLsizei getHeight() const;

Просмотреть файл

@ -140,13 +140,9 @@ const SamplerState &Sampler::getSamplerState() const
return mSamplerState;
}
const rx::SamplerImpl *Sampler::getImplementation() const
rx::SamplerImpl *Sampler::getImplementation() const
{
return mImpl;
}
rx::SamplerImpl *Sampler::getImplementation()
{
return mImpl;
}
}

Просмотреть файл

@ -64,8 +64,7 @@ class Sampler final : public RefCountObject, public LabeledObject
const SamplerState &getSamplerState() const;
const rx::SamplerImpl *getImplementation() const;
rx::SamplerImpl *getImplementation();
rx::SamplerImpl *getImplementation() const;
private:
rx::SamplerImpl *mImpl;

Просмотреть файл

@ -96,7 +96,7 @@ class Shader final : angle::NonCopyable, public LabeledObject
GLenum getType() const { return mType; }
GLuint getHandle() const;
const rx::ShaderImpl *getImplementation() const { return mImplementation; }
rx::ShaderImpl *getImplementation() const { return mImplementation; }
void deleteSource();
void setSource(GLsizei count, const char *const *string, const GLint *length);

Просмотреть файл

@ -903,6 +903,21 @@ Error Texture::copySubTexture(const Offset &destOffset,
unpackUnmultiplyAlpha, source);
}
Error Texture::copyCompressedTexture(const Texture *source)
{
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
orphanImages();
ANGLE_TRY(mTexture->copyCompressedTexture(source));
ASSERT(source->getTarget() != GL_TEXTURE_CUBE_MAP && getTarget() != GL_TEXTURE_CUBE_MAP);
const auto &sourceDesc = source->mState.getImageDesc(source->getTarget(), 0);
mState.setImageDesc(getTarget(), 0, sourceDesc);
return NoError();
}
Error Texture::setStorage(GLenum target, GLsizei levels, GLenum internalFormat, const Extents &size)
{
ASSERT(target == mState.mTarget);

Просмотреть файл

@ -295,6 +295,7 @@ class Texture final : public egl::ImageSibling,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha,
const Texture *source);
Error copyCompressedTexture(const Texture *source);
Error setStorage(GLenum target, GLsizei levels, GLenum internalFormat, const Extents &size);
@ -305,8 +306,7 @@ class Texture final : public egl::ImageSibling,
egl::Surface *getBoundSurface() const;
egl::Stream *getBoundStream() const;
rx::TextureImpl *getImplementation() { return mTexture; }
const rx::TextureImpl *getImplementation() const { return mTexture; }
rx::TextureImpl *getImplementation() const { return mTexture; }
// FramebufferAttachmentObject implementation
Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;

Просмотреть файл

@ -87,8 +87,7 @@ class VertexArray final : public LabeledObject
return mState.getVertexAttributes();
}
rx::VertexArrayImpl *getImplementation() { return mVertexArray; }
const rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
size_t getMaxEnabledAttribute() const { return mState.getMaxEnabledAttribute(); }

Просмотреть файл

@ -297,12 +297,6 @@ inline DestT *GetImplAs(SrcT *src)
return GetAs<DestT>(src->getImplementation());
}
template <typename DestT, typename SrcT>
inline const DestT *GetImplAs(const SrcT *src)
{
return GetAs<const DestT>(src->getImplementation());
}
}
#include "angletypes.inl"

Просмотреть файл

@ -40,4 +40,11 @@ gl::Error TextureImpl::copySubTexture(const gl::Offset &destOffset,
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION, "CHROMIUM_copy_texture exposed but not implemented.");
}
gl::Error TextureImpl::copyCompressedTexture(const gl::Texture *source)
{
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION,
"CHROMIUM_copy_compressed_texture exposed but not implemented.");
}
}

Просмотреть файл

@ -72,6 +72,8 @@ class TextureImpl : public FramebufferAttachmentObjectImpl
bool unpackUnmultiplyAlpha,
const gl::Texture *source);
virtual gl::Error copyCompressedTexture(const gl::Texture *source);
virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0;
virtual gl::Error setEGLImageTarget(GLenum target, egl::Image *image) = 0;

Просмотреть файл

@ -35,6 +35,7 @@ class MockTextureImpl : public TextureImpl
bool,
bool,
const gl::Texture *));
MOCK_METHOD1(copyCompressedTexture, gl::Error(const gl::Texture *source));
MOCK_METHOD4(setStorage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &));
MOCK_METHOD3(setImageExternal,
gl::Error(GLenum, egl::Stream *, const egl::Stream::GLTextureDescription &));

Просмотреть файл

@ -169,6 +169,10 @@ class RendererD3D : public BufferFactoryD3D
bool unpackFlipY,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha) = 0;
virtual gl::Error copyCompressedTexture(const gl::Texture *source,
GLint sourceLevel,
TextureStorage *storage,
GLint destLevel) = 0;
// RenderTarget creation
virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0;

Просмотреть файл

@ -968,6 +968,26 @@ gl::Error TextureD3D_2D::copySubTexture(const gl::Offset &destOffset,
return gl::NoError();
}
gl::Error TextureD3D_2D::copyCompressedTexture(const gl::Texture *source)
{
GLenum sourceTarget = source->getTarget();
GLint sourceLevel = 0;
GLint destLevel = 0;
GLenum sizedInternalFormat = source->getFormat(sourceTarget, sourceLevel).asSized();
gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
redefineImage(destLevel, sizedInternalFormat, size, false);
ANGLE_TRY(initializeStorage(false));
ASSERT(mTexStorage);
ANGLE_TRY(mRenderer->copyCompressedTexture(source, sourceLevel, mTexStorage, destLevel));
return gl::NoError();
}
gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
ASSERT(GL_TEXTURE_2D && size.depth == 1);

Просмотреть файл

@ -170,6 +170,7 @@ class TextureD3D_2D : public TextureD3D
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha,
const gl::Texture *source) override;
gl::Error copyCompressedTexture(const gl::Texture *source) override;
gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;

Просмотреть файл

@ -3109,6 +3109,41 @@ gl::Error Renderer11::copyTexture(const gl::Texture *source,
return gl::NoError();
}
gl::Error Renderer11::copyCompressedTexture(const gl::Texture *source,
GLint sourceLevel,
TextureStorage *storage,
GLint destLevel)
{
TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
ASSERT(destStorage11);
ID3D11Resource *destResource = nullptr;
ANGLE_TRY(destStorage11->getResource(&destResource));
gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
ASSERT(sourceD3D);
TextureStorage *sourceStorage = nullptr;
ANGLE_TRY(sourceD3D->getNativeTexture(&sourceStorage));
TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
ASSERT(sourceStorage11);
ID3D11Resource *sourceResource = nullptr;
ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
mDeviceContext->CopySubresourceRegion(destResource, destSubresource, 0, 0, 0, sourceResource,
sourceSubresource, nullptr);
return gl::NoError();
}
gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
{
const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);

Просмотреть файл

@ -215,6 +215,10 @@ class Renderer11 : public RendererD3D
bool unpackFlipY,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha) override;
gl::Error copyCompressedTexture(const gl::Texture *source,
GLint sourceLevel,
TextureStorage *storage,
GLint destLevel) override;
// RenderTarget creation
gl::Error createRenderTarget(int width,

Просмотреть файл

@ -1239,6 +1239,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->lossyETCDecode = true;
extensions->syncQuery = GetEventQuerySupport(featureLevel);
extensions->copyTexture = true;
extensions->copyCompressedTexture = true;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.

Просмотреть файл

@ -2340,6 +2340,15 @@ gl::Error Renderer9::copyTexture(const gl::Texture *source,
return gl::Error(GL_INVALID_OPERATION);
}
gl::Error Renderer9::copyCompressedTexture(const gl::Texture *source,
GLint sourceLevel,
TextureStorage *storage,
GLint destLevel)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION);
}
gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
{
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);

Просмотреть файл

@ -211,6 +211,10 @@ class Renderer9 : public RendererD3D
bool unpackFlipY,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha) override;
gl::Error copyCompressedTexture(const gl::Texture *source,
GLint sourceLevel,
TextureStorage *storage,
GLint destLevel) override;
// RenderTarget creation
gl::Error createRenderTarget(int width,

Просмотреть файл

@ -3320,6 +3320,68 @@ bool ValidateCopySubTextureCHROMIUM(Context *context,
return true;
}
bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
{
if (!context->getExtensions().copyCompressedTexture)
{
context->handleError(Error(GL_INVALID_OPERATION,
"GL_CHROMIUM_copy_compressed_texture extension not available."));
return false;
}
const gl::Texture *source = context->getTexture(sourceId);
if (source == nullptr)
{
context->handleError(
Error(GL_INVALID_VALUE, "Source texture is not a valid texture object."));
return false;
}
if (source->getTarget() != GL_TEXTURE_2D)
{
context->handleError(
Error(GL_INVALID_VALUE, "Source texture must be of type GL_TEXTURE_2D."));
return false;
}
if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
{
context->handleError(Error(GL_INVALID_VALUE, "Source texture must level 0 defined."));
return false;
}
const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
if (!sourceFormat.info->compressed)
{
context->handleError(
Error(GL_INVALID_OPERATION, "Source texture must have a compressed internal format."));
return false;
}
const gl::Texture *dest = context->getTexture(destId);
if (dest == nullptr)
{
context->handleError(
Error(GL_INVALID_VALUE, "Destination texture is not a valid texture object."));
return false;
}
if (dest->getTarget() != GL_TEXTURE_2D)
{
context->handleError(
Error(GL_INVALID_VALUE, "Destination texture must be of type GL_TEXTURE_2D."));
return false;
}
if (dest->getImmutableFormat())
{
context->handleError(Error(GL_INVALID_OPERATION, "Destination cannot be immutable."));
return false;
}
return true;
}
bool ValidateCreateShader(Context *context, GLenum type)
{
switch (type)

Просмотреть файл

@ -325,6 +325,7 @@ bool ValidateCopySubTextureCHROMIUM(Context *context,
GLboolean unpackFlipY,
GLboolean unpackPremultiplyAlpha,
GLboolean unpackUnmultiplyAlpha);
bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId);
bool ValidateCreateShader(Context *context, GLenum type);
bool ValidateBufferData(ValidationContext *context,

Просмотреть файл

@ -1472,6 +1472,9 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
INSERT_PROC_ADDRESS(gl, CopyTextureCHROMIUM);
INSERT_PROC_ADDRESS(gl, CopySubTextureCHROMIUM);
// GL_CHROMIUM_copy_compressed_texture
INSERT_PROC_ADDRESS(gl, CompressedCopyTextureCHROMIUM);
// GL_ANGLE_webgl_compatibility
INSERT_PROC_ADDRESS(gl, EnableExtensionANGLE);

Просмотреть файл

@ -1950,6 +1950,23 @@ ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
}
}
ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
{
EVENT("(GLuint sourceId = %u, GLuint destId = %u)", sourceId, destId);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation() &&
!ValidateCompressedCopyTextureCHROMIUM(context, sourceId, destId))
{
return;
}
context->compressedCopyTextureCHROMIUM(sourceId, destId);
}
}
GL_APICALL GLboolean GL_APIENTRY EnableExtensionANGLE(const GLchar *name)
{
EVENT("(const GLchar *name = %p)", name);

Просмотреть файл

@ -259,6 +259,9 @@ ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
GLboolean unpackPremultiplyAlpha,
GLboolean unpackUnmultiplyAlpha);
// GL_CHROMIUM_copy_compressed_texture
ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
// GL_ANGLE_webgl_compatibility
GL_APICALL GLboolean GL_APIENTRY EnableExtensionANGLE(const GLchar *name);

Просмотреть файл

@ -24,6 +24,7 @@
'<(angle_path)/src/tests/gl_tests/ClearTest.cpp',
'<(angle_path)/src/tests/gl_tests/ColorMaskTest.cpp',
'<(angle_path)/src/tests/gl_tests/ComputeShaderTest.cpp',
'<(angle_path)/src/tests/gl_tests/CopyCompressedTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/CopyTexImageTest.cpp',
'<(angle_path)/src/tests/gl_tests/CopyTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/CubeMapTextureTest.cpp',

Просмотреть файл

@ -0,0 +1,369 @@
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CopyCompressedTextureTest.cpp: Tests of the GL_CHROMIUM_copy_compressed_texture extension
#include "test_utils/ANGLETest.h"
namespace angle
{
class CopyCompressedTextureTest : public ANGLETest
{
protected:
CopyCompressedTextureTest()
{
setWindowWidth(256);
setWindowHeight(256);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void SetUp() override
{
ANGLETest::SetUp();
glGenTextures(2, mTextures);
mProgram = CompileProgram(
"attribute vec2 a_position;\n"
"varying vec2 v_texcoord;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(a_position, 0.0, 1.0);\n"
" v_texcoord = (a_position + 1.0) * 0.5;\n"
"}\n",
"precision mediump float;\n"
"uniform sampler2D u_texture;\n"
"varying vec2 v_texcoord;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(u_texture, v_texcoord);\n"
"}\n");
ASSERT_NE(0u, mProgram);
if (extensionEnabled("GL_CHROMIUM_copy_compressed_texture"))
{
glCompressedCopyTextureCHROMIUM =
reinterpret_cast<PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC>(
eglGetProcAddress("glCompressedCopyTextureCHROMIUM"));
}
}
void TearDown() override
{
glDeleteTextures(2, mTextures);
glDeleteProgram(mProgram);
ANGLETest::TearDown();
}
bool checkExtensions() const
{
if (!extensionEnabled("GL_CHROMIUM_copy_compressed_texture"))
{
std::cout
<< "Test skipped because GL_CHROMIUM_copy_compressed_texture is not available."
<< std::endl;
return false;
}
EXPECT_NE(nullptr, glCompressedCopyTextureCHROMIUM);
if (glCompressedCopyTextureCHROMIUM == nullptr)
{
return false;
}
return true;
}
GLuint mProgram = 0;
GLuint mTextures[2] = {0, 0};
PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC glCompressedCopyTextureCHROMIUM = nullptr;
};
namespace
{
const GLColor &CompressedImageColor = GLColor::red;
// Single compressed ATC block of source pixels all set to:
// CompressedImageColor.
const uint8_t CompressedImageATC[8] = {0x0, 0x7c, 0x0, 0xf8, 0x55, 0x55, 0x55, 0x55};
// Single compressed ATCIA block of source pixels all set to:
// CompressedImageColor.
const uint8_t CompressedImageATCIA[16] = {0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x7c, 0x0, 0xf8, 0x55, 0x55, 0x55, 0x55};
// Single compressed DXT1 block of source pixels all set to:
// CompressedImageColor.
const uint8_t CompressedImageDXT1[8] = {0x00, 0xf8, 0x00, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
// Single compressed DXT5 block of source pixels all set to:
// CompressedImageColor.
const uint8_t CompressedImageDXT5[16] = {0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0xf8, 0x0, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa};
// Single compressed DXT1 block of source pixels all set to:
// CompressedImageColor.
const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
} // anonymous namespace
// Test to ensure that the basic functionality of the extension works.
TEST_P(CopyCompressedTextureTest, Basic)
{
if (!checkExtensions())
{
return;
}
if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
{
std::cout << "Test skipped because GL_EXT_texture_compression_dxt1 is not available."
<< std::endl;
return;
}
glBindTexture(GL_TEXTURE_2D, mTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
sizeof(CompressedImageDXT1), CompressedImageDXT1);
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, mTextures[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
ASSERT_GL_NO_ERROR();
// Load texture.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTextures[1]);
GLint textureLoc = glGetUniformLocation(mProgram, "u_texture");
glUseProgram(mProgram);
glUniform1i(textureLoc, 0);
// Draw.
drawQuad(mProgram, "a_position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, CompressedImageColor);
ASSERT_GL_NO_ERROR();
}
// Test validation of compressed formats
TEST_P(CopyCompressedTextureTest, InternalFormat)
{
if (!checkExtensions())
{
return;
}
struct Data
{
GLint format;
const uint8_t *data;
GLsizei dataSize;
Data() : Data(GL_NONE, nullptr, 0) {}
Data(GLint format, const uint8_t *data, GLsizei dataSize)
: format(format), data(data), dataSize(dataSize)
{
}
};
std::vector<Data> supportedFormats;
if (extensionEnabled("GL_AMD_compressed_ATC_texture"))
{
supportedFormats.push_back(
Data(GL_ATC_RGB_AMD, CompressedImageATC, sizeof(CompressedImageATC)));
supportedFormats.push_back(Data(GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, CompressedImageATCIA,
sizeof(CompressedImageATCIA)));
}
if (extensionEnabled("GL_EXT_texture_compression_dxt1"))
{
supportedFormats.push_back(Data(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedImageDXT1,
sizeof(CompressedImageDXT1)));
}
if (extensionEnabled("GL_ANGLE_texture_compression_dxt5"))
{
supportedFormats.push_back(Data(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, CompressedImageDXT5,
sizeof(CompressedImageDXT5)));
}
if (extensionEnabled("GL_OES_compressed_ETC1_RGB8_texture"))
{
supportedFormats.push_back(
Data(GL_ETC1_RGB8_OES, CompressedImageETC1, sizeof(CompressedImageETC1)));
}
for (const auto &supportedFormat : supportedFormats)
{
glBindTexture(GL_TEXTURE_2D, mTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, supportedFormat.format, 4, 4, 0,
supportedFormat.dataSize, supportedFormat.data);
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, mTextures[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
ASSERT_GL_NO_ERROR();
}
}
// Test that uncompressed textures generate errors when copying
TEST_P(CopyCompressedTextureTest, InternalFormatNotSupported)
{
if (!checkExtensions())
{
return;
}
glBindTexture(GL_TEXTURE_2D, mTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, mTextures[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Check that the GL_RGBA format reports an error.
glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
// Test validation of texture IDs
TEST_P(CopyCompressedTextureTest, InvalidTextureIds)
{
if (!checkExtensions())
{
return;
}
glBindTexture(GL_TEXTURE_2D, mTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
sizeof(CompressedImageDXT1), CompressedImageDXT1);
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, mTextures[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glCompressedCopyTextureCHROMIUM(mTextures[0], 99993);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glCompressedCopyTextureCHROMIUM(99994, mTextures[1]);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glCompressedCopyTextureCHROMIUM(99995, 99996);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
EXPECT_GL_NO_ERROR();
}
// Test that only 2D textures are valid
TEST_P(CopyCompressedTextureTest, BindingPoints)
{
if (!checkExtensions())
{
return;
}
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[0]);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
face++)
{
glCompressedTexImage2D(face, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
sizeof(CompressedImageDXT1), CompressedImageDXT1);
}
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextures[1]);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
}
// Test the destination texture cannot be immutable
TEST_P(CopyCompressedTextureTest, Immutable)
{
if (!checkExtensions() || getClientMajorVersion() < 3)
{
return;
}
glBindTexture(GL_TEXTURE_2D, mTextures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0,
sizeof(CompressedImageDXT1), CompressedImageDXT1);
ASSERT_GL_NO_ERROR();
glBindTexture(GL_TEXTURE_2D, mTextures[1]);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glCompressedCopyTextureCHROMIUM(mTextures[0], mTextures[1]);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(CopyCompressedTextureTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_OPENGL(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace angle