Commit 390208b5 by Minmin Gong Committed by Commit Bot

Implements ETC lossy decode for ETC2 formats.

This is the 2nd payload of GL_ANGLE_lossy_etc_decode feature. In this change, RGB8, SRGB8, RGB8A1, and SRGB8A1 formats in ETC2 family can be converted to BC1. BUG=angleproject:1285 Change-Id: I96fe2f07c62716a31d37f20a202b6cabbb4ebbd2 Reviewed-on: https://chromium-review.googlesource.com/447846 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 461d9a30
......@@ -561,6 +561,16 @@ void LoadETC2RGB8ToRGBA8(size_t width,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2RGB8ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2SRGB8ToRGBA8(size_t width,
size_t height,
size_t depth,
......@@ -571,6 +581,16 @@ void LoadETC2SRGB8ToRGBA8(size_t width,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2SRGB8ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2RGB8A1ToRGBA8(size_t width,
size_t height,
size_t depth,
......@@ -581,6 +601,16 @@ void LoadETC2RGB8A1ToRGBA8(size_t width,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2RGB8A1ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2SRGB8A1ToRGBA8(size_t width,
size_t height,
size_t depth,
......@@ -591,6 +621,16 @@ void LoadETC2SRGB8A1ToRGBA8(size_t width,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2SRGB8A1ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch);
void LoadETC2RGBA8ToRGBA8(size_t width,
size_t height,
size_t depth,
......
......@@ -528,8 +528,9 @@ struct ETC2Block
int b2 = extend_4to8bits(block.HB2);
static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
const int d = distance[(block.Hda << 2) | (block.Hdb << 1) |
((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)];
const int orderingTrickBit =
((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
const R8G8B8A8 paintColors[4] = {
createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
......@@ -1129,8 +1130,48 @@ struct ETC2Block
const uint8_t alphaValues[4][4],
bool nonOpaquePunchThroughAlpha) const
{
// TODO (mgong): Will be implemented soon
UNIMPLEMENTED();
static const size_t kNumColors = 4;
// Table C.8, distance index for T and H modes
const auto &block = u.idht.mode.tm;
int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
int g1 = extend_4to8bits(block.TG1);
int b1 = extend_4to8bits(block.TB1);
int r2 = extend_4to8bits(block.TR2);
int g2 = extend_4to8bits(block.TG2);
int b2 = extend_4to8bits(block.TB2);
static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
const int d = distance[block.Tda << 1 | block.Tdb];
// In ETC opaque punch through formats, index == 2 means transparent pixel.
// Thus we don't need to compute its color, just assign it as black.
const R8G8B8A8 paintColors[kNumColors] = {
createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d),
nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0) : createRGBA(r2, g2, b2),
createRGBA(r2 - d, g2 - d, b2 - d),
};
int pixelIndices[kNumPixelsInBlock];
int pixelIndexCounts[kNumColors] = {0};
for (size_t j = 0; j < 4; j++)
{
int *row = &pixelIndices[j * 4];
for (size_t i = 0; i < 4; i++)
{
const size_t pixelIndex = getIndex(i, j);
row[i] = static_cast<int>(pixelIndex);
pixelIndexCounts[pixelIndex]++;
}
}
int minColorIndex, maxColorIndex;
selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
&maxColorIndex);
packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
maxColorIndex, nonOpaquePunchThroughAlpha);
}
void transcodeHBlockToBC1(uint8_t *dest,
......@@ -1141,8 +1182,51 @@ struct ETC2Block
const uint8_t alphaValues[4][4],
bool nonOpaquePunchThroughAlpha) const
{
// TODO (mgong): Will be implemented soon
UNIMPLEMENTED();
static const size_t kNumColors = 4;
// Table C.8, distance index for T and H modes
const auto &block = u.idht.mode.hm;
int r1 = extend_4to8bits(block.HR1);
int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
int r2 = extend_4to8bits(block.HR2);
int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
int b2 = extend_4to8bits(block.HB2);
static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
const int orderingTrickBit =
((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
// In ETC opaque punch through formats, index == 2 means transparent pixel.
// Thus we don't need to compute its color, just assign it as black.
const R8G8B8A8 paintColors[kNumColors] = {
createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0)
: createRGBA(r2 + d, g2 + d, b2 + d),
createRGBA(r2 - d, g2 - d, b2 - d),
};
int pixelIndices[kNumPixelsInBlock];
int pixelIndexCounts[kNumColors] = {0};
for (size_t j = 0; j < 4; j++)
{
int *row = &pixelIndices[j * 4];
for (size_t i = 0; i < 4; i++)
{
const size_t pixelIndex = getIndex(i, j);
row[i] = static_cast<int>(pixelIndex);
pixelIndexCounts[pixelIndex]++;
}
}
int minColorIndex, maxColorIndex;
selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
&maxColorIndex);
packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
maxColorIndex, nonOpaquePunchThroughAlpha);
}
void transcodePlanarBlockToBC1(uint8_t *dest,
......@@ -1152,8 +1236,22 @@ struct ETC2Block
size_t h,
const uint8_t alphaValues[4][4]) const
{
// TODO (mgong): Will be implemented soon
UNIMPLEMENTED();
static const size_t kNumColors = kNumPixelsInBlock;
R8G8B8A8 rgbaBlock[kNumColors];
decodePlanarBlock(reinterpret_cast<uint8_t *>(rgbaBlock), x, y, w, h, sizeof(R8G8B8A8) * 4,
alphaValues);
// Planar block doesn't have a color table, fill indices as full
int pixelIndices[kNumPixelsInBlock] = {0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15};
int pixelIndexCounts[kNumColors] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int minColorIndex, maxColorIndex;
selectEndPointPCA(pixelIndexCounts, rgbaBlock, kNumColors, &minColorIndex, &maxColorIndex);
packBC1(dest, pixelIndices, pixelIndexCounts, rgbaBlock, kNumColors, minColorIndex,
maxColorIndex, false);
}
// Single channel utility functions
......@@ -1499,6 +1597,20 @@ void LoadETC2RGB8ToRGBA8(size_t width,
outputRowPitch, outputDepthPitch, false);
}
void LoadETC2RGB8ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch)
{
LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
outputRowPitch, outputDepthPitch, false);
}
void LoadETC2SRGB8ToRGBA8(size_t width,
size_t height,
size_t depth,
......@@ -1513,6 +1625,20 @@ void LoadETC2SRGB8ToRGBA8(size_t width,
outputRowPitch, outputDepthPitch, false);
}
void LoadETC2SRGB8ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch)
{
LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
outputRowPitch, outputDepthPitch, false);
}
void LoadETC2RGB8A1ToRGBA8(size_t width,
size_t height,
size_t depth,
......@@ -1527,6 +1653,20 @@ void LoadETC2RGB8A1ToRGBA8(size_t width,
outputRowPitch, outputDepthPitch, true);
}
void LoadETC2RGB8A1ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch)
{
LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
outputRowPitch, outputDepthPitch, true);
}
void LoadETC2SRGB8A1ToRGBA8(size_t width,
size_t height,
size_t depth,
......@@ -1541,6 +1681,20 @@ void LoadETC2SRGB8A1ToRGBA8(size_t width,
outputRowPitch, outputDepthPitch, true);
}
void LoadETC2SRGB8A1ToBC1(size_t width,
size_t height,
size_t depth,
const uint8_t *input,
size_t inputRowPitch,
size_t inputDepthPitch,
uint8_t *output,
size_t outputRowPitch,
size_t outputDepthPitch)
{
LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
outputRowPitch, outputDepthPitch, true);
}
void LoadETC2RGBA8ToRGBA8(size_t width,
size_t height,
size_t depth,
......
......@@ -618,7 +618,12 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
AddDepthStencilFormat(&map, GL_STENCIL_INDEX8, 0, 8, 0, GL_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, NeverSupported);
// From GL_ANGLE_lossy_etc_decode
map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
// | Internal format | |W |H |BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
// From GL_EXT_texture_norm16
// | Internal format | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
......
......@@ -45,6 +45,10 @@
"GL_DEPTH_COMPONENT32_OES": "D24_UNORM_S8_UINT",
"GL_ETC1_RGB8_OES": "R8G8B8A8_UNORM",
"GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": "BC1_RGB_UNORM_BLOCK",
"GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_BLOCK",
"GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_SRGB_BLOCK",
"GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_BLOCK",
"GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_SRGB_BLOCK",
"GL_LUMINANCE16F_EXT": "R16G16B16A16_FLOAT",
"GL_LUMINANCE32F_EXT": "R32G32B32A32_FLOAT",
"GL_LUMINANCE8_ALPHA8_EXT": "R8G8B8A8_UNORM",
......
......@@ -195,6 +195,19 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev
Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
return info;
}
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
{
static constexpr Format info(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE,
angle::Format::ID::BC1_RGB_UNORM_BLOCK,
DXGI_FORMAT_BC1_UNORM,
DXGI_FORMAT_BC1_UNORM,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_BC1_UNORM,
GL_RGBA8,
nullptr);
return info;
}
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
{
static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
......@@ -208,6 +221,19 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev
Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
return info;
}
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
{
static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
DXGI_FORMAT_BC1_UNORM,
DXGI_FORMAT_BC1_UNORM,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_BC1_UNORM,
GL_RGBA8,
nullptr);
return info;
}
case GL_COMPRESSED_RGBA8_ETC2_EAC:
{
static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
......@@ -689,6 +715,19 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev
Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
return info;
}
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
{
static constexpr Format info(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE,
angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK,
DXGI_FORMAT_BC1_UNORM_SRGB,
DXGI_FORMAT_BC1_UNORM_SRGB,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_BC1_UNORM_SRGB,
GL_RGBA8,
nullptr);
return info;
}
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
{
static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
......@@ -702,6 +741,19 @@ const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &dev
nullptr);
return info;
}
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
{
static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK,
DXGI_FORMAT_BC1_UNORM_SRGB,
DXGI_FORMAT_BC1_UNORM_SRGB,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_BC1_UNORM_SRGB,
GL_RGBA8,
nullptr);
return info;
}
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
{
static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
......
......@@ -519,6 +519,26 @@
"GL_UNSIGNED_BYTE": "LoadETC1RGB8ToBC1"
}
},
"GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": {
"BC1_RGB_UNORM_BLOCK": {
"GL_UNSIGNED_BYTE": "LoadETC2RGB8ToBC1"
}
},
"GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": {
"BC1_RGB_UNORM_SRGB_BLOCK": {
"GL_UNSIGNED_BYTE": "LoadETC2SRGB8ToBC1"
}
},
"GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": {
"BC1_RGBA_UNORM_BLOCK": {
"GL_UNSIGNED_BYTE": "LoadETC2RGB8A1ToBC1"
}
},
"GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": {
"BC1_RGBA_UNORM_SRGB_BLOCK": {
"GL_UNSIGNED_BYTE": "LoadETC2SRGB8A1ToBC1"
}
},
"GL_R16_EXT": {
"R16_UNORM": {
"GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
......
......@@ -250,6 +250,18 @@ LoadImageFunctionInfo COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM(GLenum type)
}
}
LoadImageFunctionInfo COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
{
switch (type)
{
case GL_UNSIGNED_BYTE:
return LoadImageFunctionInfo(LoadETC2RGB8ToBC1, true);
default:
UNREACHABLE();
return LoadImageFunctionInfo(UnreachableLoadFunction, true);
}
}
LoadImageFunctionInfo COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM(GLenum type)
{
switch (type)
......@@ -262,6 +274,19 @@ LoadImageFunctionInfo COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM
}
}
LoadImageFunctionInfo
COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK(GLenum type)
{
switch (type)
{
case GL_UNSIGNED_BYTE:
return LoadImageFunctionInfo(LoadETC2RGB8A1ToBC1, true);
default:
UNREACHABLE();
return LoadImageFunctionInfo(UnreachableLoadFunction, true);
}
}
LoadImageFunctionInfo COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM(GLenum type)
{
switch (type)
......@@ -370,6 +395,19 @@ LoadImageFunctionInfo COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
}
}
LoadImageFunctionInfo COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK(
GLenum type)
{
switch (type)
{
case GL_UNSIGNED_BYTE:
return LoadImageFunctionInfo(LoadETC2SRGB8ToBC1, true);
default:
UNREACHABLE();
return LoadImageFunctionInfo(UnreachableLoadFunction, true);
}
}
LoadImageFunctionInfo COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
{
switch (type)
......@@ -382,6 +420,20 @@ LoadImageFunctionInfo COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNOR
}
}
LoadImageFunctionInfo
COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK(
GLenum type)
{
switch (type)
{
case GL_UNSIGNED_BYTE:
return LoadImageFunctionInfo(LoadETC2SRGB8A1ToBC1, true);
default:
UNREACHABLE();
return LoadImageFunctionInfo(UnreachableLoadFunction, true);
}
}
LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default(GLenum type)
{
switch (type)
......@@ -1577,6 +1629,16 @@ LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleForma
break;
}
}
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
{
switch (angleFormat)
{
case Format::ID::BC1_RGB_UNORM_BLOCK:
return COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK;
default:
break;
}
}
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
{
switch (angleFormat)
......@@ -1587,6 +1649,16 @@ LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleForma
break;
}
}
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
{
switch (angleFormat)
{
case Format::ID::BC1_RGBA_UNORM_BLOCK:
return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK;
default:
break;
}
}
case GL_COMPRESSED_RGBA8_ETC2_EAC:
{
switch (angleFormat)
......@@ -1645,6 +1717,16 @@ LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleForma
break;
}
}
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
{
switch (angleFormat)
{
case Format::ID::BC1_RGB_UNORM_SRGB_BLOCK:
return COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK;
default:
break;
}
}
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
{
switch (angleFormat)
......@@ -1655,6 +1737,16 @@ LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleForma
break;
}
}
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
{
switch (angleFormat)
{
case Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK:
return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK;
default:
break;
}
}
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
return COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
......
......@@ -1714,6 +1714,12 @@ bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
return true;
default:
......
......@@ -454,6 +454,10 @@ bool ValidateES2TexImageParameters(Context *context,
}
break;
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
if (!context->getExtensions().lossyETCDecode)
{
context->handleError(Error(
......@@ -668,11 +672,15 @@ bool ValidateES2TexImageParameters(Context *context,
}
break;
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
if (context->getExtensions().lossyETCDecode)
{
context->handleError(
Error(GL_INVALID_OPERATION,
"ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
"ETC lossy decode formats can't work with this type."));
return false;
}
else
......@@ -841,6 +849,10 @@ bool ValidateES2CopyTexImageParameters(ValidationContext *context,
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
case GL_ETC1_RGB8_OES:
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
context->handleError(Error(GL_INVALID_OPERATION));
return false;
case GL_DEPTH_COMPONENT:
......@@ -973,10 +985,14 @@ bool ValidateES2CopyTexImageParameters(ValidationContext *context,
}
break;
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
if (context->getExtensions().lossyETCDecode)
{
context->handleError(Error(GL_INVALID_OPERATION,
"ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
"ETC lossy decode formats can't be copied to."));
return false;
}
else
......@@ -1115,6 +1131,10 @@ bool ValidateES2TexStorageParameters(Context *context,
}
break;
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
if (!context->getExtensions().lossyETCDecode)
{
context->handleError(
......
......@@ -63,11 +63,196 @@ TEST_P(ETCTextureTest, ETC1Validation)
sizeof(pixel), pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 2, 2, 0,
sizeof(pixel), pixel);
sizeof(pixel), pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 1, 1, 0,
sizeof(pixel), pixel);
sizeof(pixel), pixel);
EXPECT_GL_NO_ERROR();
}
else
{
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
}
// Tests a texture with ETC2 RGB8 lossy decode format
TEST_P(ETCTextureTest, ETC2RGB8Validation)
{
bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
glBindTexture(GL_TEXTURE_2D, mTexture);
GLubyte pixel[] = {
0x00, 0x00, 0xf8, 0x02, 0x43, 0xff, 0x04, 0x12, // Individual/differential block
0x1c, 0x65, 0xc6, 0x62, 0xff, 0xf0, 0xff, 0x00, // T block
0x62, 0xf2, 0xe3, 0x32, 0xff, 0x0f, 0xff, 0x00, // H block
0x71, 0x88, 0xfb, 0xee, 0x87, 0x07, 0x11, 0x1f // Planar block
};
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
sizeof(pixel), pixel);
if (supported)
{
EXPECT_GL_NO_ERROR();
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, sizeof(pixel), pixel);
EXPECT_GL_NO_ERROR();
const GLsizei imageSize = 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
}
else
{
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
}
// Tests a texture with ETC2 SRGB8 lossy decode format
TEST_P(ETCTextureTest, ETC2SRGB8Validation)
{
bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
glBindTexture(GL_TEXTURE_2D, mTexture);
GLubyte pixel[] = {
0x00, 0x00, 0xf8, 0x02, 0x43, 0xff, 0x04, 0x12, // Individual/differential block
0x1c, 0x65, 0xc6, 0x62, 0xff, 0xf0, 0xff, 0x00, // T block
0x62, 0xf2, 0xe3, 0x32, 0xff, 0x0f, 0xff, 0x00, // H block
0x71, 0x88, 0xfb, 0xee, 0x87, 0x07, 0x11, 0x1f // Planar block
};
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
sizeof(pixel), pixel);
if (supported)
{
EXPECT_GL_NO_ERROR();
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, sizeof(pixel),
pixel);
EXPECT_GL_NO_ERROR();
const GLsizei imageSize = 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
}
else
{
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
}
// Tests a texture with ETC2 RGB8 punchthrough A1 lossy decode format
TEST_P(ETCTextureTest, ETC2RGB8A1Validation)
{
bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
glBindTexture(GL_TEXTURE_2D, mTexture);
GLubyte pixel[] = {
0x80, 0x98, 0x59, 0x02, 0x6e, 0xe7, 0x44, 0x47, // Individual/differential block
0xeb, 0x85, 0x68, 0x30, 0x77, 0x73, 0x44, 0x44, // T block
0xb4, 0x05, 0xab, 0x92, 0xf8, 0x8c, 0x07, 0x73, // H block
0xbb, 0x90, 0x15, 0xba, 0x8a, 0x8c, 0xd5, 0x5f // Planar block
};
glCompressedTexImage2D(GL_TEXTURE_2D, 0,
GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
sizeof(pixel), pixel);
if (supported)
{
EXPECT_GL_NO_ERROR();
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
sizeof(pixel), pixel);
EXPECT_GL_NO_ERROR();
const GLsizei imageSize = 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 1,
GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 2,
GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 3,
GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
}
else
{
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
}
// Tests a texture with ETC2 SRGB8 punchthrough A1 lossy decode format
TEST_P(ETCTextureTest, ETC2SRGB8A1Validation)
{
bool supported = extensionEnabled("GL_ANGLE_lossy_etc_decode");
glBindTexture(GL_TEXTURE_2D, mTexture);
GLubyte pixel[] = {
0x80, 0x98, 0x59, 0x02, 0x6e, 0xe7, 0x44, 0x47, // Individual/differential block
0xeb, 0x85, 0x68, 0x30, 0x77, 0x73, 0x44, 0x44, // T block
0xb4, 0x05, 0xab, 0x92, 0xf8, 0x8c, 0x07, 0x73, // H block
0xbb, 0x90, 0x15, 0xba, 0x8a, 0x8c, 0xd5, 0x5f // Planar block
};
glCompressedTexImage2D(GL_TEXTURE_2D, 0,
GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
sizeof(pixel), pixel);
if (supported)
{
EXPECT_GL_NO_ERROR();
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
sizeof(pixel), pixel);
EXPECT_GL_NO_ERROR();
const GLsizei imageSize = 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 1,
GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4,
4, 0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 2,
GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 2,
2, 0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
glCompressedTexImage2D(GL_TEXTURE_2D, 3,
GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 1,
1, 0, imageSize, pixel);
EXPECT_GL_NO_ERROR();
}
else
{
......
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