blob: 623c6b81c01aeadffaa509fd22b1f0efb33aec34 [file] [log] [blame]
//
// Copyright 2015 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.
//
// Texture upload format tests:
// Test all texture unpack/upload formats for sampling correctness.
//
#include "common/mathutil.h"
#include "image_util/copyimage.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
namespace
{
class TextureUploadFormatTest : public ANGLETest
{};
struct TexFormat final
{
GLenum internalFormat;
GLenum unpackFormat;
GLenum unpackType;
TexFormat() = delete;
uint8_t bytesPerPixel() const
{
uint8_t bytesPerChannel;
switch (unpackType)
{
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
return 2;
case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_24_8:
case GL_UNSIGNED_INT_10F_11F_11F_REV:
case GL_UNSIGNED_INT_5_9_9_9_REV:
return 4;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
return 8;
case GL_UNSIGNED_BYTE:
case GL_BYTE:
bytesPerChannel = 1;
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
bytesPerChannel = 2;
break;
case GL_UNSIGNED_INT:
case GL_INT:
case GL_FLOAT:
bytesPerChannel = 4;
break;
default:
assert(false);
return 0;
}
switch (unpackFormat)
{
case GL_RGBA:
case GL_RGBA_INTEGER:
return bytesPerChannel * 4;
case GL_RGB:
case GL_RGB_INTEGER:
return bytesPerChannel * 3;
case GL_RG:
case GL_RG_INTEGER:
case GL_LUMINANCE_ALPHA:
return bytesPerChannel * 2;
case GL_RED:
case GL_RED_INTEGER:
case GL_LUMINANCE:
case GL_ALPHA:
case GL_DEPTH_COMPONENT:
return bytesPerChannel * 1;
default:
assert(false);
return 0;
}
}
};
template <const uint8_t bits>
constexpr uint32_t EncodeNormUint(const float val)
{
return static_cast<uint32_t>(val * (UINT32_MAX >> (32 - bits)) + 0.5); // round-half-up
}
} // anonymous namespace
namespace
{
template <typename DestT, typename SrcT, size_t SrcN>
void ZeroAndCopy(DestT &dest, const SrcT (&src)[SrcN])
{
dest.fill(0);
memcpy(dest.data(), src, sizeof(SrcT) * SrcN);
}
std::string EnumStr(const GLenum v)
{
std::stringstream ret;
ret << "0x" << std::hex << v;
return ret.str();
}
template <typename ColorT, typename DestT>
void EncodeThenZeroAndCopy(DestT &dest, const float srcVals[4])
{
ColorF srcValsF(srcVals[0], srcVals[1], srcVals[2], srcVals[3]);
ColorT encoded;
ColorT::writeColor(&encoded, &srcValsF);
dest.fill(0);
memcpy(dest.data(), &encoded, sizeof(ColorT));
}
} // anonymous namespace
// Upload (1,2,5,3) to integer formats, and (1,2,5,3)/8.0 to float formats.
// Draw a point into a 1x1 renderbuffer and readback the result for comparison with expectations.
// Test all internalFormat/unpackFormat/unpackType combinations from ES3.0.
TEST_P(TextureUploadFormatTest, All)
{
ANGLE_SKIP_TEST_IF(IsD3D9() || IsD3D11_FL93());
constexpr char kVertShaderES2[] = R"(
void main()
{
gl_PointSize = 1.0;
gl_Position = vec4(0, 0, 0, 1);
})";
constexpr char kFragShader_Floats[] = R"(
precision mediump float;
uniform sampler2D uTex;
void main()
{
gl_FragColor = texture2D(uTex, vec2(0,0));
})";
ANGLE_GL_PROGRAM(floatsProg, kVertShaderES2, kFragShader_Floats);
glDisable(GL_DITHER);
ASSERT_GL_NO_ERROR();
// Create the 1x1 framebuffer
GLRenderbuffer backbufferRB;
glBindRenderbuffer(GL_RENDERBUFFER, backbufferRB);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
GLFramebuffer backbufferFB;
glBindFramebuffer(GL_FRAMEBUFFER, backbufferFB);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, backbufferRB);
ASSERT_GL_NO_ERROR();
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glViewport(0, 0, 1, 1);
// Create and bind our test texture
GLTexture testTex;
glBindTexture(GL_TEXTURE_2D, testTex);
// Must be nearest because some texture formats aren't filterable!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Initialize our test variables
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
const bool hasSubrectUploads = !glGetError();
constexpr uint8_t srcIntVals[4] = {1u, 2u, 5u, 3u};
constexpr float srcVals[4] = {srcIntVals[0] / 8.0f, srcIntVals[1] / 8.0f, srcIntVals[2] / 8.0f,
srcIntVals[3] / 8.0f};
constexpr uint8_t refVals[4] = {static_cast<uint8_t>(EncodeNormUint<8>(srcVals[0])),
static_cast<uint8_t>(EncodeNormUint<8>(srcVals[1])),
static_cast<uint8_t>(EncodeNormUint<8>(srcVals[2])),
static_cast<uint8_t>(EncodeNormUint<8>(srcVals[3]))};
// Test a format with the specified data
const auto fnTestData = [&](const TexFormat &format, const void *const data, const GLColor &err,
const char *const info) {
ASSERT_GL_NO_ERROR();
glTexImage2D(GL_TEXTURE_2D, 0, format.internalFormat, 1, 1, 0, format.unpackFormat,
format.unpackType, data);
const auto uploadErr = glGetError();
if (uploadErr) // Format might not be supported. (e.g. on ES2)
return;
glClearColor(1, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 1);
const auto actual = ReadColor(0, 0);
GLColor expected;
switch (format.unpackFormat)
{
case GL_RGBA:
case GL_RGBA_INTEGER:
expected = {refVals[0], refVals[1], refVals[2], refVals[3]};
break;
case GL_RGB:
expected = {refVals[0], refVals[1], refVals[2], 255};
break;
case GL_RG:
expected = {refVals[0], refVals[1], 0, 255};
break;
case GL_RED:
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL:
expected = {refVals[0], 0, 0, 255};
break;
case GL_RGB_INTEGER:
expected = {refVals[0], refVals[1], refVals[2], refVals[0]};
break;
case GL_RG_INTEGER:
expected = {refVals[0], refVals[1], 0, refVals[0]};
break;
case GL_RED_INTEGER:
expected = {refVals[0], 0, 0, refVals[0]};
break;
case GL_LUMINANCE_ALPHA:
expected = {refVals[0], refVals[0], refVals[0], refVals[1]};
break;
case GL_LUMINANCE:
expected = {refVals[0], refVals[0], refVals[0], 255};
break;
case GL_ALPHA:
expected = {0, 0, 0, refVals[0]};
break;
default:
assert(false);
}
ASSERT_GL_NO_ERROR();
auto result = actual.ExpectNear(expected, err);
if (!result)
{
result << " [" << EnumStr(format.internalFormat) << "/" << EnumStr(format.unpackFormat)
<< "/" << EnumStr(format.unpackType) << " " << info << "]";
}
EXPECT_TRUE(result);
};
// Provide buffers for test data, and a func to run the test on both the data directly, and on
// a basic subrect selection to ensure pixel byte size is calculated correctly.
// Possible todo here is to add tests to ensure stride calculation.
std::array<uint8_t, sizeof(float) * 4> srcBuffer;
std::array<uint8_t, srcBuffer.size() * 2> subrectBuffer;
const auto fnTest = [&](const TexFormat &format, const GLColor &err) {
fnTestData(format, srcBuffer.data(), err, "simple");
if (!hasSubrectUploads)
return;
const auto bytesPerPixel = format.bytesPerPixel();
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
subrectBuffer.fill(0);
memcpy(subrectBuffer.data() + bytesPerPixel, srcBuffer.data(), bytesPerPixel);
fnTestData(format, subrectBuffer.data(), err, "subrect");
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
};
// Test All The Formats, organized by unpack format and type.
// (Combos from GLES 3.0.5 p111-112: Table 3.2: "Valid combinations of format, type, and sized
// internalformat.")
// Start with normalized ints
glUseProgram(floatsProg);
// RGBA+UNSIGNED_BYTE
{
constexpr uint8_t src[] = {static_cast<uint8_t>(EncodeNormUint<8>(srcVals[0])),
static_cast<uint8_t>(EncodeNormUint<8>(srcVals[1])),
static_cast<uint8_t>(EncodeNormUint<8>(srcVals[2])),
static_cast<uint8_t>(EncodeNormUint<8>(srcVals[3]))};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
fnTest({GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE}, {8, 8, 8, 255});
fnTest({GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE}, {16, 16, 16, 16});
fnTest({GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE}, {1, 1, 1, 0});
fnTest({GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE}, {8, 4, 8, 0});
fnTest({GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, {1, 1, 0, 0});
fnTest({GL_R8, GL_RED, GL_UNSIGNED_BYTE}, {1, 0, 0, 0});
fnTest({GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
fnTest({GL_RGB, GL_RGB, GL_UNSIGNED_BYTE}, {1, 1, 1, 0});
fnTest({GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
fnTest({GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE}, {1, 1, 1, 0});
fnTest({GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE}, {0, 0, 0, 1});
}
// RGBA+BYTE
{
constexpr uint8_t src[] = {static_cast<uint8_t>(EncodeNormUint<7>(srcVals[0])),
static_cast<uint8_t>(EncodeNormUint<7>(srcVals[1])),
static_cast<uint8_t>(EncodeNormUint<7>(srcVals[2])),
static_cast<uint8_t>(EncodeNormUint<7>(srcVals[3]))};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, {2, 2, 2, 2});
fnTest({GL_RGB8_SNORM, GL_RGB, GL_BYTE}, {2, 2, 2, 0});
fnTest({GL_RG8_SNORM, GL_RG, GL_BYTE}, {2, 2, 0, 0});
fnTest({GL_R8_SNORM, GL_RED, GL_BYTE}, {2, 0, 0, 0});
}
// RGB+UNSIGNED_SHORT_5_6_5
{
constexpr uint16_t src[] = {static_cast<uint16_t>((EncodeNormUint<5>(srcVals[0]) << 11) |
(EncodeNormUint<6>(srcVals[1]) << 5) |
(EncodeNormUint<5>(srcVals[2]) << 0))};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, {8, 4, 8, 0});
fnTest({GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, {8, 4, 8, 0});
}
// RGBA+UNSIGNED_SHORT_4_4_4_4
{
constexpr uint16_t src[] = {static_cast<uint16_t>(
(EncodeNormUint<4>(srcVals[0]) << 12) | (EncodeNormUint<4>(srcVals[1]) << 8) |
(EncodeNormUint<4>(srcVals[2]) << 4) | (EncodeNormUint<4>(srcVals[3]) << 0))};
ZeroAndCopy(srcBuffer, src);
// fnTest({GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, {16,16,16,16});
fnTest({GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, {16, 16, 16, 16});
}
// RGBA+UNSIGNED_SHORT_5_5_5_1
{
constexpr uint16_t src[] = {static_cast<uint16_t>(
(EncodeNormUint<5>(srcVals[0]) << 11) | (EncodeNormUint<5>(srcVals[1]) << 6) |
(EncodeNormUint<5>(srcVals[2]) << 1) | (EncodeNormUint<1>(srcVals[3]) << 0))};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, {8, 8, 8, 255});
fnTest({GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, {8, 8, 8, 255});
}
// RGBA+UNSIGNED_INT_2_10_10_10_REV
{
constexpr uint32_t src[] = {
(EncodeNormUint<10>(srcVals[0]) << 0) | (EncodeNormUint<10>(srcVals[1]) << 10) |
(EncodeNormUint<10>(srcVals[2]) << 20) | (EncodeNormUint<2>(srcVals[3]) << 30)};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, {1, 1, 1, 128});
fnTest({GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, {8, 8, 8, 255});
fnTest({GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, {1, 1, 1, 128});
}
// RGB+UNSIGNED_INT_2_10_10_10_REV
{
constexpr uint32_t src[] = {
(EncodeNormUint<10>(srcVals[0]) << 0) | (EncodeNormUint<10>(srcVals[1]) << 10) |
(EncodeNormUint<10>(srcVals[2]) << 20) | (EncodeNormUint<2>(srcVals[3]) << 30)};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGB, GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV}, {1, 1, 1, 0});
}
// DEPTH_COMPONENT+UNSIGNED_SHORT
{
const uint16_t src[] = {static_cast<uint16_t>(EncodeNormUint<16>(srcVals[0]))};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, {1, 0, 0, 0});
}
// DEPTH_COMPONENT+UNSIGNED_INT
{
constexpr uint32_t src[] = {EncodeNormUint<32>(srcVals[0])};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, {1, 0, 0, 0});
fnTest({GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, {1, 0, 0, 0});
}
// DEPTH_STENCIL+UNSIGNED_INT_24_8
{
// Drop stencil.
constexpr uint32_t src[] = {EncodeNormUint<24>(srcVals[0]) << 8};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, {1, 0, 0, 0});
}
if (getClientMajorVersion() < 3)
return;
constexpr char kVertShaderES3[] = R"(#version 300 es
void main()
{
gl_PointSize = 1.0;
gl_Position = vec4(0, 0, 0, 1);
})";
constexpr char kFragShader_Ints[] = R"(#version 300 es
precision mediump float;
uniform highp isampler2D uTex;
out vec4 oFragColor;
void main()
{
oFragColor = vec4(texture(uTex, vec2(0,0))) / 8.0;
})";
constexpr char kFragShader_Uints[] = R"(#version 300 es
precision mediump float;
uniform highp usampler2D uTex;
out vec4 oFragColor;
void main()
{
oFragColor = vec4(texture(uTex, vec2(0,0))) / 8.0;
})";
ANGLE_GL_PROGRAM(intsProg, kVertShaderES3, kFragShader_Ints);
ANGLE_GL_PROGRAM(uintsProg, kVertShaderES3, kFragShader_Uints);
// Non-normalized ints
glUseProgram(intsProg);
// RGBA_INTEGER+UNSIGNED_BYTE
{
constexpr uint8_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, {1, 1, 1, 1});
fnTest({GL_RGB8I, GL_RGB_INTEGER, GL_BYTE}, {1, 1, 1, 1});
fnTest({GL_RG8I, GL_RG_INTEGER, GL_BYTE}, {1, 1, 1, 1});
fnTest({GL_R8I, GL_RED_INTEGER, GL_BYTE}, {1, 1, 1, 1});
}
// RGBA_INTEGER+UNSIGNED_SHORT
{
constexpr uint16_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, {1, 1, 1, 1});
fnTest({GL_RGB16I, GL_RGB_INTEGER, GL_SHORT}, {1, 1, 1, 1});
fnTest({GL_RG16I, GL_RG_INTEGER, GL_SHORT}, {1, 1, 1, 1});
fnTest({GL_R16I, GL_RED_INTEGER, GL_SHORT}, {1, 1, 1, 1});
}
// RGBA_INTEGER+UNSIGNED_INT
{
constexpr uint32_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, {1, 1, 1, 1});
fnTest({GL_RGB32I, GL_RGB_INTEGER, GL_INT}, {1, 1, 1, 1});
fnTest({GL_RG32I, GL_RG_INTEGER, GL_INT}, {1, 1, 1, 1});
fnTest({GL_R32I, GL_RED_INTEGER, GL_INT}, {1, 1, 1, 1});
}
// Non-normalized uints
glUseProgram(uintsProg);
// RGBA_INTEGER+UNSIGNED_BYTE
{
constexpr uint8_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
fnTest({GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
fnTest({GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
fnTest({GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
}
// RGBA_INTEGER+UNSIGNED_SHORT
{
constexpr uint16_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
fnTest({GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
fnTest({GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
fnTest({GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
}
// RGBA_INTEGER+UNSIGNED_INT
{
constexpr uint32_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
fnTest({GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
fnTest({GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
fnTest({GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
}
// RGBA_INTEGER+UNSIGNED_INT_2_10_10_10_REV
{
constexpr uint32_t src[] = {static_cast<uint32_t>(srcIntVals[0] << 0) |
static_cast<uint32_t>(srcIntVals[1] << 10) |
static_cast<uint32_t>(srcIntVals[2] << 20) |
static_cast<uint32_t>(srcIntVals[3] << 30)};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV}, {1, 1, 1, 1});
}
// True floats
glUseProgram(floatsProg);
// RGBA+HALF_FLOAT
{
EncodeThenZeroAndCopy<R16G16B16A16F>(srcBuffer, srcVals);
fnTest({GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, {1, 1, 1, 1});
fnTest({GL_RGB16F, GL_RGB, GL_HALF_FLOAT}, {1, 1, 1, 0});
fnTest({GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT}, {1, 1, 1, 0});
fnTest({GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT}, {1, 1, 1, 0});
fnTest({GL_RG16F, GL_RG, GL_HALF_FLOAT}, {1, 1, 0, 0});
fnTest({GL_R16F, GL_RED, GL_HALF_FLOAT}, {1, 0, 0, 0});
fnTest({GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES}, {1, 1, 1, 1});
fnTest({GL_RGB, GL_RGB, GL_HALF_FLOAT_OES}, {1, 1, 1, 0});
fnTest({GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES}, {1, 1, 1, 1});
fnTest({GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES}, {1, 1, 1, 0});
fnTest({GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES}, {0, 0, 0, 1});
}
// RGBA+FLOAT
{
ZeroAndCopy(srcBuffer, srcVals);
fnTest({GL_RGBA32F, GL_RGBA, GL_FLOAT}, {1, 1, 1, 1});
fnTest({GL_RGBA16F, GL_RGBA, GL_FLOAT}, {1, 1, 1, 1});
fnTest({GL_RGB32F, GL_RGB, GL_FLOAT}, {1, 1, 1, 0});
fnTest({GL_RGB16F, GL_RGB, GL_FLOAT}, {1, 1, 1, 0});
fnTest({GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT}, {1, 1, 1, 0});
fnTest({GL_RGB9_E5, GL_RGB, GL_FLOAT}, {1, 1, 1, 0});
fnTest({GL_RG32F, GL_RG, GL_FLOAT}, {1, 1, 0, 0});
fnTest({GL_RG16F, GL_RG, GL_FLOAT}, {1, 1, 0, 0});
fnTest({GL_R32F, GL_RED, GL_FLOAT}, {1, 0, 0, 0});
fnTest({GL_R16F, GL_RED, GL_FLOAT}, {1, 0, 0, 0});
}
// UNSIGNED_INT_10F_11F_11F_REV
{
EncodeThenZeroAndCopy<R11G11B10F>(srcBuffer, srcVals);
fnTest({GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, {1, 1, 1, 0});
}
// UNSIGNED_INT_5_9_9_9_REV
{
EncodeThenZeroAndCopy<R9G9B9E5>(srcBuffer, srcVals);
fnTest({GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, {1, 1, 1, 0});
}
// DEPTH_COMPONENT+FLOAT
{
// Skip stencil.
constexpr float src[] = {srcVals[0], 0};
ZeroAndCopy(srcBuffer, src);
fnTest({GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, {1, 0, 0, 0});
fnTest({GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV},
{1, 0, 0, 0});
}
EXPECT_GL_NO_ERROR();
}
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(TextureUploadFormatTest);