blob: 8583e340907e152380aadc6284fa94c4229f8963 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "graphics_translation/gles/texture_codecs.h"
#include "graphics_translation/gles/debug.h"
#include "gtest/gtest.h"
namespace {
template <typename T, size_t N>
size_t ArraySize(const T(&)[N]) { return N; }
using std::hex;
using std::dec;
void FillPixels3x4(size_t bpp, size_t alignment, const uint8_t* src,
uint8_t* dst) {
ASSERT_TRUE(alignment == 1 || alignment == 2 ||
alignment == 4 || alignment == 8);
size_t stride = (3 * bpp + alignment - 1) & ~(alignment - 1);
for (size_t y = 0; y < 4; y++) {
uint8_t* next = dst + stride;
for (size_t x = 0; x < 3 * bpp; x++) {
*dst++ = *src++;
}
dst = next;
}
}
void ConvertToRgba(const TextureConverter& conv,
GLenum format, GLenum type, GLsizei align,
const uint8_t* encoded, const uint32_t(&expected)[12]) {
uint32_t decoded[16];
memset(decoded, 0xe0, sizeof(decoded));
void * p = conv.Convert(3, 4, align, encoded, decoded);
EXPECT_EQ(decoded, p);
for (size_t i = 0; i < ArraySize(expected); i++)
EXPECT_EQ(expected[i], decoded[i])
<< "Difference at index " << i << " expected 0x" << hex
<< expected[i] << " actual 0x" << decoded[i] << dec << " for "
<< GetEnumString(format) << " " << GetEnumString(type);
for (size_t i = ArraySize(expected); i < ArraySize(decoded); i++)
EXPECT_EQ(0xe0e0e0e0, decoded[i])
<< "Unexpected value at index " << i << " of 0x" << hex << decoded[i]
<< dec << " for " << GetEnumString(format) << " "
<< GetEnumString(type);
}
template <size_t N>
void ConvertFromRgba(const TextureConverter& conv,
GLenum format, GLenum type,
const uint32_t(&rgba)[12], const uint8_t(&expected)[N]) {
uint8_t encoded[3 * 8 * 4];
memset(encoded, 0xe0, sizeof(encoded));
void * p = conv.Convert(3, 4, 4, rgba, encoded);
EXPECT_EQ(encoded, p);
for (size_t i = 0; i < ArraySize(expected) && i < ArraySize(encoded); i++)
EXPECT_EQ(expected[i], encoded[i])
<< "Difference at index " << i << " expected 0x" << hex
<< expected[i] << " actual 0x" << encoded[i] << dec << " for "
<< GetEnumString(format) << " " << GetEnumString(type);
for (size_t i = ArraySize(expected); i < ArraySize(encoded); i++)
EXPECT_EQ(0xe0, encoded[i])
<< "Unexpected value at index " << i << " of 0x" << hex << encoded[i]
<< dec << " for " << GetEnumString(format) << " "
<< GetEnumString(type);
}
// Encode and decode 12 pixels.
template <size_t N>
void PackAndUnpack12(GLenum format, GLenum type, size_t bpp,
const uint8_t(&original)[N],
const uint32_t(&expected)[12]) {
uint8_t encoded[N + 42] __attribute__((aligned(8)));
TextureConverter c(format, type, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_TRUE(c.IsValid())
<< " for " << GetEnumString(format) << " " << GetEnumString(type);
TextureConverter d(GL_RGBA, GL_UNSIGNED_BYTE, format, type);
ASSERT_TRUE(d.IsValid())
<< " for " << GetEnumString(format) << " " << GetEnumString(type);
// Test and verify decode alignment is 1, encoded is aligned to 8.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 1, original, encoded);
ConvertToRgba(c, format, type, 1, encoded, expected);
// Test and verify decode alignment is 1, encoded is aligned to 1.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 1, original, encoded + 1);
ConvertToRgba(c, format, type, 1, encoded + 1, expected);
// Test and verify decode alignment is 2, encoded is aligned to 8.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 2, original, encoded);
ConvertToRgba(c, format, type, 2, encoded, expected);
// Test and verify decode alignment is 2, encoded is aligned to 2.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 2, original, encoded + 2);
ConvertToRgba(c, format, type, 2, encoded + 2, expected);
// Test and verify decode alignment is 4, encoded is aligned to 8.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 4, original, encoded);
ConvertToRgba(c, format, type, 4, encoded, expected);
// Test and verify decode alignment is 4, encoded is aligned to 4.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 2, original, encoded + 4);
ConvertToRgba(c, format, type, 2, encoded + 4, expected);
// Test and verify decode alignment is 8, encoded is aligned to 8.
memset(encoded, 0xe0, sizeof(encoded));
FillPixels3x4(bpp, 8, original, encoded);
ConvertToRgba(c, format, type, 8, encoded, expected);
uint8_t encoded_expected[N + 42];
memset(encoded_expected, 0xe0, sizeof(encoded_expected));
FillPixels3x4(bpp, 4, original, encoded_expected);
ConvertFromRgba(d, format, type, expected, encoded_expected);
}
} // end anonymous namespace
TEST(TextureCodec, Invalid) {
TextureConverter c(GL_RGBA, GL_UNSIGNED_SHORT, GL_RGBA, GL_UNSIGNED_BYTE);
ASSERT_TRUE(!c.IsValid());
}
TEST(TextureCodec, Rgba) {
const uint8_t original[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
const uint32_t expected[] = {
htonl(0x00010203), htonl(0x04050607),
htonl(0x08090a0b), htonl(0x0c0d0e0f),
htonl(0xffffffff), htonl(0x00000000),
htonl(0x55555555), htonl(0xaaaaaaaa),
htonl(0x00010203), htonl(0x04050607),
htonl(0x08090a0b), htonl(0x0c0d0e0f)};
PackAndUnpack12(GL_RGBA, GL_UNSIGNED_BYTE, 4, original, expected);
}
TEST(TextureCodec, Rgb) {
const uint8_t original[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b};
const uint32_t expected[] = {
htonl(0x000102ff), htonl(0x030405ff),
htonl(0x060708ff), htonl(0x090a0bff),
htonl(0xffffffff), htonl(0x000000ff),
htonl(0x555555ff), htonl(0xaaaaaaff),
htonl(0x000102ff), htonl(0x030405ff),
htonl(0x060708ff), htonl(0x090a0bff)};
PackAndUnpack12(GL_RGB, GL_UNSIGNED_BYTE, 3, original, expected);
}
TEST(TextureCodec, LumninanceAlpha) {
const uint8_t original[] = {
0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0xff, 0xff, 0x00, 0x00,
0x55, 0x55, 0xaa, 0xaa};
const uint32_t expected[] = {
htonl(0x00000001), htonl(0x02020203),
htonl(0x04040405), htonl(0x06060607),
htonl(0x00000001), htonl(0x02020203),
htonl(0x04040405), htonl(0x06060607),
htonl(0xffffffff), htonl(0x00000000),
htonl(0x55555555), htonl(0xaaaaaaaa)};
PackAndUnpack12(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 2, original, expected);
}
TEST(TextureCodec, Luminance) {
const uint8_t original[] = {
0x00, 0x01,
0x02, 0x03,
0x00, 0x01,
0x02, 0x03,
0xff, 0x00,
0x55, 0xaa};
const uint32_t expected[] = {
htonl(0x000000ff), htonl(0x010101ff),
htonl(0x020202ff), htonl(0x030303ff),
htonl(0x000000ff), htonl(0x010101ff),
htonl(0x020202ff), htonl(0x030303ff),
htonl(0xffffffff), htonl(0x000000ff),
htonl(0x555555ff), htonl(0xaaaaaaff)};
PackAndUnpack12(GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, original, expected);
}
TEST(TextureCodec, Alpha) {
const uint8_t original[] = {
0x00, 0x01,
0x02, 0x03,
0xff, 0x00,
0x02, 0x03,
0xff, 0x00,
0x55, 0xaa};
const uint32_t expected[] = {
htonl(0x00000000), htonl(0x00000001),
htonl(0x00000002), htonl(0x00000003),
htonl(0x000000ff), htonl(0x00000000),
htonl(0x00000002), htonl(0x00000003),
htonl(0x000000ff), htonl(0x00000000),
htonl(0x00000055), htonl(0x000000aa)};
PackAndUnpack12(GL_ALPHA, GL_UNSIGNED_BYTE, 1, original, expected);
}
TEST(TextureCodec, Rgba4444) {
const uint8_t original[] = {
0x00, 0xf0, 0x00, 0x0f,
0xf0, 0x00, 0x0f, 0x00,
0xff, 0xff, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00,
0x55, 0x55, 0xaa, 0xaa};
const uint32_t expected[] = {
htonl(0xff000000), htonl(0x00ff0000),
htonl(0x0000ff00), htonl(0x000000ff),
htonl(0xffffffff), htonl(0x00000000),
htonl(0xffffffff), htonl(0x00000000),
htonl(0xffffffff), htonl(0x00000000),
htonl(0x55555555), htonl(0xaaaaaaaa)};
PackAndUnpack12(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 2, original, expected);
}
TEST(TextureCodec, Rgba5551) {
const uint8_t original[] = {
0x00, 0xf8, 0xc0, 0x07,
0x3e, 0x00, 0x01, 0x00,
0x3e, 0x00, 0x01, 0x00,
0xff, 0xff, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00,
0x55, 0x55, 0xaa, 0xaa};
const uint32_t expected[] = {
htonl(0xff000000), htonl(0x00ff0000),
htonl(0x0000ff00), htonl(0x000000ff),
htonl(0x0000ff00), htonl(0x000000ff),
htonl(0xffffffff), htonl(0x00000000),
htonl(0xffffffff), htonl(0x00000000),
htonl(0x52ad52ff), htonl(0xad52ad00)};
PackAndUnpack12(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 2, original, expected);
}
TEST(TextureCodec, Rgb565) {
const uint8_t original[] = {
0x1f, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00,
0x00, 0xf8, 0xe0, 0x07,
0x1f, 0x00, 0x00, 0x00,
0xff, 0xff, 0x00, 0x00,
0x55, 0x55, 0xaa, 0xaa};
const uint32_t expected[] = {
htonl(0x0000ffff), htonl(0x000000ff),
htonl(0xffffffff), htonl(0x000000ff),
htonl(0xff0000ff), htonl(0x00ff00ff),
htonl(0x0000ffff), htonl(0x000000ff),
htonl(0xffffffff), htonl(0x000000ff),
htonl(0x52aaadff), htonl(0xad5552ff)};
PackAndUnpack12(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2, original, expected);
}