blob: e2611b2bbd6ecfacabd4b5deb7b98b22baeda2a7 [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2018 The Khronos Group Inc.
*
* 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.
*
*/ /*!
* \file es3cCopyTexImageConversionsTests.cpp
* \brief Tests verifying glCopyTexImage2D..
*/ /*-------------------------------------------------------------------*/
#include "es3cCopyTexImageConversionsTests.hpp"
#include "deMath.h"
#include "deSharedPtr.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluStrUtil.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTestLog.hpp"
#include <cstring>
#include <limits>
#include <map>
using namespace glw;
namespace es3cts
{
// Amount of entries database should allocate for its entries upon creation.
#define N_START_CONVERSION_DATABASE_ENTRIES (32)
// Should 3D textures be used as source attachments, this field defines
// their depth. It MUST be at least 2, because the test implementation
// also uses second array (counted from one) to store the data-set information.
#define TEXTURE_DEPTH (2)
// Data set height
#define TEXTURE_HEIGHT (2)
// Data set width
#define TEXTURE_WIDTH (2)
// Defines for non color-renderable textures support
#define NUMBER_OF_ELEMENTS_IN_VEC4 (4)
#define NUMBER_OF_POINTS_TO_DRAW (TEXTURE_WIDTH * TEXTURE_HEIGHT)
#define TEXTURE_COORDINATES_ARRAY_SIZE (TEXTURE_WIDTH * TEXTURE_HEIGHT * NUMBER_OF_ELEMENTS_IN_VEC4 * sizeof(float))
#define TEXTURE_2D_SAMPLER_TYPE (0)
#define TEXTURE_3D_SAMPLER_TYPE (1)
#define TEXTURE_2D_ARRAY_SAMPLER_TYPE (2)
#define TEXTURE_CUBE_SAMPLER_TYPE (3)
#define SRC_TEXTURE_COORDS_ATTRIB_INDEX (1)
#define DST_TEXTURE_COORDS_ATTRIB_INDEX (0)
// Buffer object indices used for non color-renderable textures support.
#define COMPARISON_RESULT_BUFFER_OBJECT_INDEX (0)
#define SOURCE_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX (1)
#define DESTINATION_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX (2)
// Stores detailed information about:
// 1) what FBO effective internalformats can be used for glCopyTexImage2D(), assuming
// specific result texture's internalformat as passed by one of the arguments.
// 2) what internalformat the result texture object should use.
const GLenum conversionArray[] = {
/* GL_RGBA GL_RGB GL_LUMINANCE_ALPHA GL_LUMINANCE GL_ALPHA GL_R8 GL_R8_SNORM GL_RG8 GL_RG8_SNORM GL_RGB8 GL_RGB8_SNORM GL_RGB565 GL_RGBA4 GL_RGB5_A1 GL_RGBA8 GL_RGBA8_SNORM GL_RGB10_A2 GL_RGB10_A2UI GL_SRGB8 GL_SRGB8_ALPHA8 GL_R16F GL_RG16F GL_RGB16F GL_RGBA16F GL_R32F GL_RG32F GL_RGB32F GL_RGBA32F GL_R11F_G11F_B10F GL_RGB9_E5 GL_R8I GL_R8UI GL_R16I GL_R16UI GL_R32I GL_R32UI GL_RG8I GL_RG8UI GL_RG16I GL_RG16UI GL_RG32I GL_RG32UI GL_RGB8I GL_RGB8UI GL_RGB16I GL_RGB16UI GL_RGB32I GL_RGB32UI GL_RGBA8I GL_RGBA8UI GL_RGBA16I GL_RGBA16UI GL_RGBA32I GL_RGBA32UI */
/* GL_R8, */ GL_NONE, GL_NONE, GL_NONE, GL_LUMINANCE8_OES, GL_NONE, GL_R8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG8, */ GL_NONE, GL_NONE, GL_NONE, GL_LUMINANCE8_OES, GL_NONE, GL_R8, GL_NONE, GL_RG8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB8, */ GL_NONE, GL_RGB8, GL_NONE, GL_LUMINANCE8_OES, GL_NONE, GL_R8, GL_NONE, GL_RG8, GL_NONE, GL_RGB8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB565, */ GL_NONE, GL_RGB565, GL_NONE, GL_LUMINANCE8_OES, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB565, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA4, */ GL_RGBA4, GL_RGB565, GL_LUMINANCE8_ALPHA8_OES, GL_LUMINANCE8_OES, GL_ALPHA8_OES, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA4, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB5_A1, */ GL_RGB5_A1, GL_RGB565, GL_LUMINANCE8_ALPHA8_OES, GL_LUMINANCE8_OES, GL_ALPHA8_OES, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB5_A1, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA8, */ GL_RGBA8, GL_RGB8, GL_LUMINANCE8_ALPHA8_OES, GL_LUMINANCE8_OES, GL_ALPHA8_OES, GL_R8, GL_NONE, GL_RG8, GL_NONE, GL_RGB8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB10_A2, */ GL_NONE, GL_RGB8, GL_NONE, GL_LUMINANCE8_OES, GL_ALPHA8_OES, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB10_A2, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB10_A2UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB10_A2UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_SRGB8_ALPHA8, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_SRGB8, GL_SRGB8_ALPHA8, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R8I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R8UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R16I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R16UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R32I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R32UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG8I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG8UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG16I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG16I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG16UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG16UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG32I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG32I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG32UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG32UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA8I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA8I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA8UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA8UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA16I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG16I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB16I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA16I, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA16UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG16UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB16UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA16UI, GL_NONE, GL_NONE,
/* GL_RGBA32I, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG32I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB32I, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA32I, GL_NONE,
/* GL_RGBA32UI, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RG32UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGB32UI, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_RGBA32UI,
/* GL_R16F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG16F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16F, GL_RG16F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_R32F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RG32F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32F, GL_RG32F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB16F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16F, GL_RG16F, GL_RGB16F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA16F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGB32F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32F, GL_RG32F, GL_RGB32F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
/* GL_RGBA32F, */ GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
};
// Tells:
// 1) how many rows conversion_array uses.
// 2) what destination internalformat (NOT effective internalformat!)
// corresponds to each entry.
// NOTE: If you need to modify this array, make sure conversion-array
// is updated accordingly!
const GLenum copyTexImage2DInternalFormatOrdering[] = { GL_RGBA,
GL_RGB,
GL_LUMINANCE_ALPHA,
GL_LUMINANCE,
GL_ALPHA,
GL_R8,
GL_R8_SNORM,
GL_RG8,
GL_RG8_SNORM,
GL_RGB8,
GL_RGB8_SNORM,
GL_RGB565,
GL_RGBA4,
GL_RGB5_A1,
GL_RGBA8,
GL_RGBA8_SNORM,
GL_RGB10_A2,
GL_RGB10_A2UI,
GL_SRGB8,
GL_SRGB8_ALPHA8,
GL_R16F,
GL_RG16F,
GL_RGB16F,
GL_RGBA16F,
GL_R32F,
GL_RG32F,
GL_RGB32F,
GL_RGBA32F,
GL_R11F_G11F_B10F,
GL_RGB9_E5,
GL_R8I,
GL_R8UI,
GL_R16I,
GL_R16UI,
GL_R32I,
GL_R32UI,
GL_RG8I,
GL_RG8UI,
GL_RG16I,
GL_RG16UI,
GL_RG32I,
GL_RG32UI,
GL_RGB8I,
GL_RGB8UI,
GL_RGB16I,
GL_RGB16UI,
GL_RGB32I,
GL_RGB32UI,
GL_RGBA8I,
GL_RGBA8UI,
GL_RGBA16I,
GL_RGBA16UI,
GL_RGBA32I,
GL_RGBA32UI };
// Ordering as per Bug 9807 table for FBO effective internalformats
const GLenum fboEffectiveInternalFormatOrdering[] = {
GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGB10_A2UI,
GL_SRGB8_ALPHA8, GL_R8I, GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI, GL_RG8I, GL_RG8UI,
GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI, GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I,
GL_RGBA32UI, GL_R16F, GL_RG16F, GL_R32F, GL_RG32F, GL_RGB16F, GL_RGBA16F, GL_RGB32F, GL_RGBA32F,
};
// Tells how channels are ordered for a particular pixel.
enum ChannelOrder
{
CHANNEL_ORDER_ABGR,
CHANNEL_ORDER_BGR,
CHANNEL_ORDER_BGRA,
CHANNEL_ORDER_R,
CHANNEL_ORDER_RG,
CHANNEL_ORDER_RGB,
CHANNEL_ORDER_RGBA,
CHANNEL_ORDER_UNKNOWN
};
// Tells how many bits and what type is used for data representation
// for a single pixel channel.
enum ChannelDataType
{
CHANNEL_DATA_TYPE_NONE = 0,
CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS,
CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS,
CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS,
CHANNEL_DATA_TYPE_UNSIGNED_BYTE_1BIT,
CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS,
CHANNEL_DATA_TYPE_UNSIGNED_BYTE_4BITS,
CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS,
CHANNEL_DATA_TYPE_UNSIGNED_BYTE_6BITS,
CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS,
CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS,
CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS,
CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS,
CHANNEL_DATA_TYPE_FLOAT
};
// Structure holding uniform locations and object IDs.
// Those values are used to support non-color-renderable texture internalformat checks.
struct NonRenderableInternalformatSupportObjects
{
GLuint comparison_result_buffer_object_id;
GLuint dst_texture_pixels_buffer_object_id;
GLint dst_2D_texture_uniform_location;
GLint dst_Cube_texture_uniform_location;
GLuint fragment_shader_object_id;
GLuint program_object_id;
GLuint src_texture_pixels_buffer_object_id;
GLint src_2D_texture_uniform_location;
GLint src_2DArray_texture_uniform_location;
GLint src_3D_texture_uniform_location;
GLint src_Cube_texture_uniform_location;
GLuint transform_feedback_object_id;
GLuint vertex_shader_object_id;
GLint channels_to_compare_uniform_location;
GLint samplers_to_use_uniform_location;
GLuint src_texture_coordinates_buffer_object_id;
GLuint dst_texture_coordinates_buffer_object_id;
};
// Structure describing contents of a channel of a single pixel.
struct ChannelData
{
// Union that allows to access the data representation
// in a data_type-friendly manner
union {
signed char signed_byte_data;
signed int signed_integer_data;
signed short signed_short_data;
unsigned char unsigned_byte_data;
unsigned int unsigned_integer_data;
unsigned short unsigned_short_data;
float float_data;
};
// Data type used for channel representation
ChannelDataType data_type;
};
// Structure describing a single pixel.
struct PixelData
{
// Alpha channel data descriptor
ChannelData alpha;
// Blue channel data descriptor
ChannelData blue;
// Green channel data descriptor
ChannelData green;
// Red channel data descriptor
ChannelData red;
// For source pixels: GL internal-format used by all channels.
// For destination pixels: GL format to be used for gl.readPixels()
// operation in order to retrieve result data
// in a matching representation.
GLenum data_internalformat;
// For source pixels: GL type used by all channels.
// For destination pixels: GL type to be used for gl.readPixels()
// operation in order to retrieve result data
// in a matching representation.
GLenum data_type;
};
// To confirm contents of data stored in non-renderable internalformat, a special shader
// is used. This type definition tells which texture() function sampler should be used
// for sampling the texture data.
enum DataSamplerType
{
DATA_SAMPLER_FLOAT,
DATA_SAMPLER_INTEGER,
DATA_SAMPLER_UNSIGNED_INTEGER,
};
// When a special shader is used to check whether the copy succeeded we need to know which
// channels will have to be compared
enum PixelCompareChannel
{
PIXEL_COMPARE_CHANNEL_R = 0x1,
PIXEL_COMPARE_CHANNEL_G = 0x2,
PIXEL_COMPARE_CHANNEL_B = 0x4,
PIXEL_COMPARE_CHANNEL_A = 0x8,
PIXEL_COMPARE_CHANNEL_RG = PIXEL_COMPARE_CHANNEL_R | PIXEL_COMPARE_CHANNEL_G,
PIXEL_COMPARE_CHANNEL_RA = PIXEL_COMPARE_CHANNEL_R | PIXEL_COMPARE_CHANNEL_A,
PIXEL_COMPARE_CHANNEL_RGB = PIXEL_COMPARE_CHANNEL_RG | PIXEL_COMPARE_CHANNEL_B,
PIXEL_COMPARE_CHANNEL_RGBA = PIXEL_COMPARE_CHANNEL_RGB | PIXEL_COMPARE_CHANNEL_A,
};
// Structure describing a single conversion rule.
//
// For more details on meaning of these fields, please refer
// to doxygen of AddEntryToConversionDatabase() and similar.
struct ConversionDatabaseEntry
{
// Reference destination data expected for bottom-left corner
PixelData dst_bottomleft_corner;
// Reference destination data expected for bottom-right corner
PixelData dst_bottomright_corner;
// Reference destination data expected for top-left corner
PixelData dst_topleft_corner;
// Reference destination data expected for top-right corner
PixelData dst_topright_corner;
// Input bottom-left corner data to be used for conversion
PixelData src_bottomleft_corner;
// Input bottom-right corner data to be used for conversion
PixelData src_bottomright_corner;
// Input top-left corner data to be used for conversion
PixelData src_topleft_corner;
// Input top-right corner data to be used for conversion
PixelData src_topright_corner;
// What are the channels that we need to compare if gl.readPixels
// can't be used to read back the data
PixelCompareChannel channels_to_compare;
};
// Structure describing contents of an opaque conversion database handle.
class ConversionDatabase
{
public:
ConversionDatabase();
~ConversionDatabase();
void initializeDatabase();
bool isTypeSupportedByGLReadPixels(GLenum type);
bool isInternalFormatCompatibleWithType(GLenum type, GLenum internalformat);
bool convertNormalizedUnsignedFixedPoint(int* src_input_rgba_bits, int* src_attachment_rgba_bits,
int* dst_attachment_rgba_bits, int* dst_output_rgba_bits, int* src_rgba,
int* dst_rgba);
PixelData getAlpha8OESPixelData(GLenum type, unsigned char alpha);
PixelData getLuminance8OESPixelData(GLenum type, unsigned char luminance);
PixelData getLuminance8Alpha8OESPixelData(GLenum type, unsigned char luminance, unsigned char alpha);
PixelData getR16IPixelData(int is_source_pixel, GLenum type, int red);
PixelData getR16UIPixelData(int is_source_pixel, GLenum type, unsigned int red);
PixelData getR32IPixelData(int is_source_pixel, GLenum type, int red);
PixelData getR32UIPixelData(int is_source_pixel, GLenum type, unsigned int red);
PixelData getR8IPixelData(int is_source_pixel, GLenum type, int red);
PixelData getR8UIPixelData(int is_source_pixel, GLenum type, unsigned int red);
PixelData getR8PixelData(int is_source_pixel, GLenum type, unsigned char red);
PixelData getRG16IPixelData(int is_source_pixel, GLenum type, int red, int green);
PixelData getRG16UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green);
PixelData getRG32IPixelData(int is_source_pixel, GLenum type, int red, int green);
PixelData getRG32UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green);
PixelData getRG8IPixelData(int is_source_pixel, GLenum type, int red, int green);
PixelData getRG8UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green);
PixelData getRG8PixelData(int is_source_pixel, GLenum type, unsigned char red, unsigned char green);
PixelData getRGB10A2PixelData(GLenum type, unsigned short red, unsigned short green, unsigned short blue,
unsigned char alpha);
PixelData getRGB10A2UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue, unsigned int alpha);
PixelData getRGB16IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue);
PixelData getRGB16UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue);
PixelData getRGB32IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue);
PixelData getRGB32UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue);
PixelData getRGB5A1PixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue, unsigned int alpha);
PixelData getRGB565PixelData(int is_source_pixel, GLenum type, int red, int green, int blue);
PixelData getRGB8PixelData(int is_source_pixel, GLenum type, unsigned char red, unsigned char green,
unsigned char blue);
PixelData getRGB8IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue);
PixelData getRGB8UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue);
PixelData getRGBA16IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue, int alpha);
PixelData getRGBA16UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue, unsigned int alpha);
PixelData getRGBA32IPixelData(GLenum type, int red, int green, int blue, int alpha);
PixelData getRGBA32UIPixelData(GLenum type, unsigned int red, unsigned int green, unsigned int blue,
unsigned int alpha);
PixelData getRGBA8IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue, int alpha);
PixelData getRGBA8UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue, unsigned int alpha);
PixelData getRGBA4PixelData(int is_source_pixel, GLenum type, unsigned char red, unsigned char green,
unsigned char blue, unsigned char alpha);
PixelData getRGBA8PixelData(GLenum type, unsigned char red, unsigned char green, unsigned char blue,
unsigned char alpha);
PixelData getSRGB8Alpha8PixelData(GLenum type, unsigned char red, unsigned char green, unsigned char blue,
unsigned char alpha);
PixelData getSRGB8PixelData(int is_source_pixel, GLenum type, unsigned char red, unsigned char green,
unsigned char blue);
PixelData getR16FPixelData(int is_source_pixel, GLenum type, float red);
PixelData getR32FPixelData(int is_source_pixel, GLenum type, float red);
PixelData getRG16FPixelData(int is_source_pixel, GLenum type, float red, float green);
PixelData getRG32FPixelData(int is_source_pixel, GLenum type, float red, float green);
PixelData getRGB16FPixelData(int is_source_pixel, GLenum type, float red, float green, float blue);
PixelData getRGB32FPixelData(int is_source_pixel, GLenum type, float red, float green, float blue);
PixelData getRGBA16FPixelData(GLenum type, float red, float green, float blue, float alpha);
PixelData getRGBA32FPixelData(GLenum type, float red, float green, float blue, float alpha);
protected:
void addEntryToConversionDatabase(PixelData src_topleft, PixelData dst_topleft, PixelData src_topright,
PixelData dst_topright, PixelData src_bottomleft, PixelData dst_bottomleft,
PixelData src_bottomright, PixelData dst_bottomright,
PixelCompareChannel channels_to_compare);
void configureConversionDatabase();
public:
// An array of _conversion_database_entry instances,
// storing all known conversion rules.
std::vector<ConversionDatabaseEntry> entries;
// Amount of entries allocated in the "entries" array so far.
unsigned int n_entries_allocated;
// Amount of entries added to the "entries" array so far.
unsigned int n_entries_added;
};
ConversionDatabase::ConversionDatabase() : n_entries_allocated(0), n_entries_added(0)
{
}
ConversionDatabase::~ConversionDatabase()
{
}
/** Initializes database instance. The database will be filled by the
* function with all available conversion rules, so it is a mistake to call
* ConfigureConversionDatabase() function for a handle reported by this function.
*
* The handle should be released with ReleaseConversionDatabase() when no longer
* needed.
*
* @return Handle to the newly created conversion database.
**/
void ConversionDatabase::initializeDatabase()
{
// Return when database was initialized earlier.
if (!entries.empty())
return;
entries.resize(N_START_CONVERSION_DATABASE_ENTRIES);
n_entries_allocated = N_START_CONVERSION_DATABASE_ENTRIES;
n_entries_added = 0;
if (entries.empty())
TCU_FAIL("Out of memory while pre-allocating space for conversion database entries");
deMemset(&entries[0], DE_NULL, N_START_CONVERSION_DATABASE_ENTRIES * sizeof(ConversionDatabaseEntry));
// Add all predefined entries that the test implementation is aware of
configureConversionDatabase();
}
/** Tells whether @param type can be used for a gl.readPixels() call.
*
* @param type GL type to consider.
*
* @return true if the type should be accepted by a gl.readPixels() call,
* false otherwise.
*/
bool ConversionDatabase::isTypeSupportedByGLReadPixels(GLenum type)
{
return (type == GL_INT) || (type == GL_UNSIGNED_BYTE) || (type == GL_UNSIGNED_INT) || (type == GL_FLOAT) ||
(type == GL_HALF_FLOAT) || (type == GL_UNSIGNED_INT_2_10_10_10_REV);
}
/** Tells whether @param type can be used with @param internalformat internal format.
*
* @param type GLES type to consider.
* @param internalformat GLES internal format to consider.
*
* @return true if the type is compatible with specific internal format, false otherwise.
**/
bool ConversionDatabase::isInternalFormatCompatibleWithType(GLenum type, GLenum internalformat)
{
bool result = false;
switch (type)
{
case GL_INT:
{
result = (internalformat == GL_R8I) || (internalformat == GL_R16I) || (internalformat == GL_R32I) ||
(internalformat == GL_RG8I) || (internalformat == GL_RG16I) || (internalformat == GL_RG32I) ||
(internalformat == GL_RGB8I) || (internalformat == GL_RGB16I) || (internalformat == GL_RGB32I) ||
(internalformat == GL_RGBA8I) || (internalformat == GL_RGBA16I) || (internalformat == GL_RGBA32I);
break;
}
case GL_UNSIGNED_BYTE:
{
result = (internalformat == GL_RGB) || (internalformat == GL_RGBA) || (internalformat == GL_LUMINANCE_ALPHA) ||
(internalformat == GL_LUMINANCE) || (internalformat == GL_LUMINANCE8_OES) ||
(internalformat == GL_LUMINANCE8_ALPHA8_OES) || (internalformat == GL_ALPHA) ||
(internalformat == GL_ALPHA8_OES) || (internalformat == GL_R8) || (internalformat == GL_R8_SNORM) ||
(internalformat == GL_RG8) || (internalformat == GL_RG8_SNORM) || (internalformat == GL_RGB8) ||
(internalformat == GL_SRGB8) || (internalformat == GL_RGB565) || (internalformat == GL_RGB8_SNORM) ||
(internalformat == GL_RGBA8) || (internalformat == GL_SRGB8_ALPHA8) ||
(internalformat == GL_RGBA8_SNORM) || (internalformat == GL_RGB5_A1) || (internalformat == GL_RGBA4);
break;
}
case GL_UNSIGNED_INT:
{
result = (internalformat == GL_R8UI) || (internalformat == GL_R16UI) || (internalformat == GL_R32UI) ||
(internalformat == GL_RG8UI) || (internalformat == GL_RG16UI) || (internalformat == GL_RG32UI) ||
(internalformat == GL_RGB8UI) || (internalformat == GL_RGB10_A2UI) || (internalformat == GL_RGB16UI) ||
(internalformat == GL_RGB32UI) || (internalformat == GL_RGBA8UI) || (internalformat == GL_RGBA16UI) ||
(internalformat == GL_RGBA32UI);
break;
}
case GL_UNSIGNED_INT_2_10_10_10_REV:
{
result = (internalformat == GL_RGB10_A2) || (internalformat == GL_RGB10_A2UI);
break;
}
case GL_FLOAT:
{
result = (internalformat == GL_RGB) || (internalformat == GL_RGBA) || (internalformat == GL_R32F) ||
(internalformat == GL_RG32F) || (internalformat == GL_RGB32F) || (internalformat == GL_RGBA32F);
break;
}
case GL_HALF_FLOAT:
{
result = (internalformat == GL_RGB) || (internalformat == GL_RGBA) || (internalformat == GL_R16F) ||
(internalformat == GL_RG16F) || (internalformat == GL_RGB16F) || (internalformat == GL_RGBA16F);
break;
}
default:
{
TCU_FAIL("Unsupported type");
}
}
return result;
}
/** Converts normalized unsigned fixed-point RGBA pixel representations
* from one resolution to another, simulating the result that one would
* get if glCopyTexImage2D() call was used for a single pixel, read
* afterward with a gl.readPixels() call.
*
* @param src_input_rgba_bits Pointer to an array storing 4 integers, representing
* amount of bits per channel, as used by input data,
* that will be fed to a GL object using gl.texImage2D()
* call or similar. Cannot be NULL.
* @param src_attachment_rgba_bits Pointer to an array storing 4 integers, representing
* amount of bits per channel, as used by data storage
* of an object attached to read buffer. Cannot be NULL.
* @param dst_attachment_rgba_bits Pointer to an array storing 4 integers, representing
* amount of bits per channel, as used by data storage
* of a texture object that glCopyTexImage2D() call will
* initialize. Cannot be NULL.
* @param dst_output_rgba_bits Pointer to an array storing 4 integers, representing
* amount of bits per channel, as requested by the user
* using the gl.readPixels() call. Cannot be NULL.
* @param src_rgba Pointer to an array storing 4 values representing
* RGBA channel. It is assumed the values do not exceed
* allowed precision, described by @param src_input_rgba_bits.
* Cannot be NULL.
* @param dst_rgba Deref will be used to store result of the conversion.
* Cannot be NULL.
*
* @return 1 if successful, 0 otherwise.
* */
bool ConversionDatabase::convertNormalizedUnsignedFixedPoint(int* src_input_rgba_bits, int* src_attachment_rgba_bits,
int* dst_attachment_rgba_bits, int* dst_output_rgba_bits,
int* src_rgba, int* dst_rgba)
{
float a_f32 = 0.0f;
float b_f32 = 0.0f;
float dst_rgba_f[4] = { 0.0f };
float g_f32 = 0.0f;
float r_f32 = 0.0f;
int src_rgba_intermediate[4] = { src_rgba[0], src_rgba[1], src_rgba[2], src_rgba[3] };
// Reduce or crank up precision before casting to floats
int bit_diffs_src_intermediate[] = { abs(src_input_rgba_bits[0] - src_attachment_rgba_bits[0]),
abs(src_input_rgba_bits[1] - src_attachment_rgba_bits[1]),
abs(src_input_rgba_bits[2] - src_attachment_rgba_bits[2]),
abs(src_input_rgba_bits[3] - src_attachment_rgba_bits[3]) };
for (unsigned int n = 0; n < sizeof(bit_diffs_src_intermediate) / sizeof(bit_diffs_src_intermediate[0]); ++n)
{
float tmp = ((float)src_rgba_intermediate[n]) / ((1 << src_input_rgba_bits[n]) - 1);
if (tmp > 1.0f)
tmp = 1.0f;
tmp *= (float)((1 << src_attachment_rgba_bits[n]) - 1);
src_rgba_intermediate[n] = (int)(0.5 + tmp);
}
// The following equations correspond to equation 2.1 from ES spec 3.0.2
r_f32 = ((float)src_rgba_intermediate[0]) / (float)((1 << src_attachment_rgba_bits[0]) - 1);
g_f32 = ((float)src_rgba_intermediate[1]) / (float)((1 << src_attachment_rgba_bits[1]) - 1);
b_f32 = ((float)src_rgba_intermediate[2]) / (float)((1 << src_attachment_rgba_bits[2]) - 1);
a_f32 = ((float)src_rgba_intermediate[3]) / (float)((1 << src_attachment_rgba_bits[3]) - 1);
// Clamp to <0, 1>. Since we're dealing with unsigned ints on input, there's
// no way we could be lower than 0.
if (r_f32 > 1.0f)
r_f32 = 1.0f;
if (g_f32 > 1.0f)
g_f32 = 1.0f;
if (b_f32 > 1.0f)
b_f32 = 1.0f;
if (a_f32 > 1.0f)
a_f32 = 1.0f;
// The following equations are taken from table 4.5 & equation 2.3,
// ES spec 3.0.2
dst_rgba_f[0] = (r_f32 * (float)((1 << dst_attachment_rgba_bits[0]) - 1));
dst_rgba_f[1] = (g_f32 * (float)((1 << dst_attachment_rgba_bits[1]) - 1));
dst_rgba_f[2] = (b_f32 * (float)((1 << dst_attachment_rgba_bits[2]) - 1));
dst_rgba_f[3] = (a_f32 * (float)((1 << dst_attachment_rgba_bits[3]) - 1));
// As per spec:
//
// The conversion from a floating-point value f to the corresponding
// unsigned normalized fixed-point value c is defined by first clamping
// f to the range [0,1], then computing
//
// f' = convert_float_uint(f * (2^b-1), b) [2.3]
//
// where convert_float_uint(r,b) returns one of the two unsigned binary
// integer values with exactly b bits which are closest to the floating-point
// value r (where *rounding to nearest is preferred*)
//
// C casting truncates the remainder, so if dst_rgba_f[x] is larger than or
// equal to 0.5, we need to take a ceiling of the value.
for (unsigned int n = 0; n < 4 /* channels */; ++n)
{
if (deFloatMod(dst_rgba_f[n], 1.0f) >= 0.5f)
dst_rgba_f[n] = deFloatCeil(dst_rgba_f[n]);
}
// Expand the data or reduce its precision, depending on the type requested by the caller.
dst_rgba[0] = ((unsigned int)dst_rgba_f[0]);
dst_rgba[1] = ((unsigned int)dst_rgba_f[1]);
dst_rgba[2] = ((unsigned int)dst_rgba_f[2]);
dst_rgba[3] = ((unsigned int)dst_rgba_f[3]);
for (unsigned int n = 0; n < 4 /* channels */; ++n)
{
float tmp = ((float)dst_rgba[n]) / ((1 << dst_attachment_rgba_bits[n]) - 1);
if (tmp > 1.0f)
tmp = 1.0f;
tmp *= (float)((1 << dst_output_rgba_bits[n]) - 1);
dst_rgba[n] = (int)(0.5 + tmp);
}
return true;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_ALPHA8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getAlpha8OESPixelData(GLenum type, unsigned char alpha)
{
PixelData result;
// Sanity checks
DE_ASSERT(type == GL_UNSIGNED_BYTE);
// Carry on
deMemset(&result, 0, sizeof(result));
result.alpha.unsigned_byte_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
result.red.data_type = CHANNEL_DATA_TYPE_NONE;
result.data_internalformat = GL_ALPHA8_OES;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_LUMINANCE8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param luminance Luminance value. Will get cloned to blue/green/red channels.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getLuminance8OESPixelData(GLenum type, unsigned char luminance)
{
PixelData result;
/* Sanity checks */
DE_ASSERT(type == GL_UNSIGNED_BYTE);
/* Carry on */
deMemset(&result, 0, sizeof(result));
result.alpha.unsigned_byte_data = 255;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = luminance;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = luminance;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = luminance;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.data_internalformat = GL_LUMINANCE8_OES;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_LUMINANCE8_ALPHA8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param luminance Luminance value. Will be cloned to blue/green/red channels.
* @param alpha Alpha channel value.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getLuminance8Alpha8OESPixelData(GLenum type, unsigned char luminance, unsigned char alpha)
{
PixelData result;
/* Sanity checks */
DE_ASSERT(type == GL_UNSIGNED_BYTE);
/* Carry on */
deMemset(&result, 0, sizeof(result));
result.alpha.unsigned_byte_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = luminance;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = luminance;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = luminance;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.data_internalformat = GL_LUMINANCE8_ALPHA8_OES;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R16I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_SHORT for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR16IPixelData(int is_source_pixel, GLenum type, int red)
{
PixelData result;
/* Sanity checks */
if (is_source_pixel)
{
DE_ASSERT(type == GL_SHORT);
} /* if (is_source_pixel) */
else
{
DE_ASSERT(type == GL_INT);
}
/* Carry on */
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.red.signed_short_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
} /* if (is_source_pixel) */
else
{
result.alpha.signed_integer_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
}
result.data_internalformat = GL_R16I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R16UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_SHORT for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR16UIPixelData(int is_source_pixel, GLenum type, unsigned int red)
{
PixelData result;
/* Sanity checks */
if (is_source_pixel)
{
DE_ASSERT(type == GL_UNSIGNED_SHORT);
} /* if (is_source_pixels) */
else
{
DE_ASSERT(type == GL_UNSIGNED_INT);
}
deMemset(&result, 0, sizeof(result));
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.red.unsigned_short_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
} /* if (is_source_pixel) */
else
{
result.alpha.unsigned_integer_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
}
result.data_internalformat = GL_R16UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R32I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_INT.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR32IPixelData(int is_source_pixel, GLenum type, int red)
{
PixelData result;
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (!is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
result.red.signed_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.data_internalformat = GL_R32I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R32UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_INT.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR32UIPixelData(int is_source_pixel, GLenum type, unsigned int red)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (!is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
} /* if (!is_source_pixel) */
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
result.red.unsigned_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.data_internalformat = GL_R32UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R8I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_BYTE for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR8IPixelData(int is_source_pixel, GLenum type, int red)
{
PixelData result;
// Sanity checks
if (is_source_pixel)
DE_ASSERT(type == GL_BYTE);
else
DE_ASSERT(type == GL_INT);
// Carry on
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.red.signed_byte_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_R8I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R8UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR8UIPixelData(int is_source_pixel, GLenum type, unsigned int red)
{
PixelData result;
/* Sanity checks */
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_BYTE);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.red.unsigned_byte_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_R8UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must beGL_UNSIGNED_BYTE.
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR8PixelData(int is_source_pixel, GLenum type, unsigned char red)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_BYTE);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = 255;
}
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.data_type = CHANNEL_DATA_TYPE_NONE;
result.red.unsigned_byte_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.data_internalformat = GL_R8;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG16I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_SHORT for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG16IPixelData(int is_source_pixel, GLenum type, int red, int green)
{
PixelData result;
if (is_source_pixel)
{
DE_ASSERT(type == GL_SHORT);
}
else
{
DE_ASSERT(type == GL_INT);
}
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.signed_short_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.red.signed_short_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_RG16I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG16UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_SHORT for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG16UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_SHORT);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.signed_short_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.red.signed_short_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_RG16UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG32I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_INT.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG32IPixelData(int is_source_pixel, GLenum type, int red, int green)
{
PixelData result;
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
}
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.signed_integer_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.data_internalformat = GL_RG32I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG32UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_INT.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG32UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
}
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.unsigned_integer_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.data_internalformat = GL_RG32UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG8I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_BYTE for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG8IPixelData(int is_source_pixel, GLenum type, int red, int green)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_BYTE);
else
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.signed_byte_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.red.signed_byte_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
} /* if (is_source_pixel) */
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_RG8I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB8UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG8UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_BYTE);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.unsigned_byte_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_RG8UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG8PixelData(int is_source_pixel, GLenum type, unsigned char red, unsigned char green)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_BYTE);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = 255;
}
result.blue.data_type = CHANNEL_DATA_TYPE_NONE;
result.green.unsigned_byte_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.data_internalformat = GL_RG8;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB10_A2 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_INT_2_10_10_10_REV.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB10A2PixelData(GLenum type, unsigned short red, unsigned short green,
unsigned short blue, unsigned char alpha)
{
PixelData result;
DE_ASSERT(red <= 1023);
DE_ASSERT(green <= 1023);
DE_ASSERT(blue <= 1023);
DE_ASSERT(alpha <= 3);
DE_ASSERT(type == GL_UNSIGNED_INT_2_10_10_10_REV);
deMemset(&result, 0, sizeof(result));
result.alpha.unsigned_byte_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS;
result.blue.unsigned_short_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.green.unsigned_short_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.red.unsigned_short_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.data_internalformat = GL_RGB10_A2;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB10A2UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_INT_2_10_10_10_REV for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB10A2UIPixelData(int is_source_pixel, GLenum type, unsigned int red,
unsigned int green, unsigned int blue, unsigned int alpha)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_INT_2_10_10_10_REV);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.unsigned_byte_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS;
result.blue.unsigned_short_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.green.unsigned_short_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.red.unsigned_short_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
}
else
{
result.alpha.unsigned_integer_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
}
result.data_internalformat = GL_RGB10_A2UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB16I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_SHORT for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB16IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_SHORT);
else
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.blue.signed_short_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.green.signed_short_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.red.signed_short_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.blue.signed_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_RGB16I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB16UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_SHORT for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB16UIPixelData(int is_source_pixel, GLenum type, unsigned int red,
unsigned int green, unsigned int blue)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_SHORT);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.blue.unsigned_short_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.green.unsigned_short_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.red.unsigned_short_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.alpha.unsigned_integer_data = 1;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_RGB16UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB32I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_INT.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB32IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue)
{
PixelData result;
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
}
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.blue.signed_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
result.data_internalformat = GL_RGB32I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB32UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_INT.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB32UIPixelData(int is_source_pixel, GLenum type, unsigned int red,
unsigned int green, unsigned int blue)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
}
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
result.data_internalformat = GL_RGB32UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB5A1 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT_5_5_5_1 or
* GL_UNSIGNED_INT_2_10_10_10_REV for source pixels.
* 2) GL_UNSIGNED_BYTE for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB5A1PixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue, unsigned int alpha)
{
PixelData result;
if (is_source_pixel)
{
DE_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL_UNSIGNED_INT_2_10_10_10_REV);
}
else
{
DE_ASSERT(type == GL_UNSIGNED_BYTE);
}
deMemset(&result, 0, sizeof(result));
switch (type)
{
case GL_UNSIGNED_BYTE:
{
DE_ASSERT(red <= 255);
DE_ASSERT(green <= 255);
DE_ASSERT(blue <= 255);
DE_ASSERT(alpha <= 255);
// Fill the channel data structures
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
break;
}
case GL_UNSIGNED_SHORT_5_5_5_1:
{
DE_ASSERT(red <= 31);
DE_ASSERT(green <= 31);
DE_ASSERT(blue <= 31);
DE_ASSERT(alpha == 0 || alpha == 1);
// Fill the channel data structures
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_1BIT;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS;
result.red.unsigned_byte_data = red;
break;
}
case GL_UNSIGNED_INT_2_10_10_10_REV:
{
// Sanity checks
DE_ASSERT(red <= 1023);
DE_ASSERT(green <= 1023);
DE_ASSERT(blue <= 1023);
DE_ASSERT(alpha <= 3);
// Fill the channel data structures
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.blue.unsigned_short_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.green.unsigned_short_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
result.red.unsigned_short_data = red;
break;
}
}
result.data_internalformat = GL_RGB5_A1;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB565 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT_5_6_5 for source pixels.
* 2) GL_UNSIGNED_BYTE for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB565PixelData(int is_source_pixel, GLenum type, int red, int green, int blue)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_6_5);
else
DE_ASSERT(type == GL_UNSIGNED_BYTE);
deMemset(&result, 0, sizeof(result));
switch (type)
{
case GL_UNSIGNED_BYTE:
{
// Fill the channel data structures
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
break;
}
case GL_UNSIGNED_SHORT_5_6_5:
{
DE_ASSERT(red >= 0 && red <= 31);
DE_ASSERT(green >= 0 && green <= 63);
DE_ASSERT(blue >= 0 && blue <= 31);
// Fill the channel data structures
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_6BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS;
result.red.unsigned_byte_data = red;
break;
}
}
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = 255;
}
result.data_internalformat = GL_RGB565;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB8PixelData(int is_source_pixel, GLenum type, unsigned char red, unsigned char green,
unsigned char blue)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_BYTE);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = 255;
}
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
result.data_internalformat = GL_RGB8;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB8I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_BYTE for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB8IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_BYTE);
else
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.blue.signed_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.green.signed_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.red.signed_byte_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = 1;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.blue.signed_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_RGB8I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB8UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB8UIPixelData(int is_source_pixel, GLenum type, unsigned int red, unsigned int green,
unsigned int blue)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_BYTE);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = 1;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_RGB8UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA16I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_SHORT for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA16IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue,
int alpha)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_SHORT);
else
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.alpha.signed_short_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.blue.signed_short_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.green.signed_short_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS;
result.red.signed_short_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.blue.signed_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_RGBA16I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA16UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_SHORT for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA16UIPixelData(int is_source_pixel, GLenum type, unsigned int red,
unsigned int green, unsigned int blue, unsigned int alpha)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_SHORT);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.alpha.unsigned_short_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.blue.unsigned_short_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.green.unsigned_short_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS;
result.red.unsigned_short_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_RGBA16UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA32I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_INT.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA32IPixelData(GLenum type, int red, int green, int blue, int alpha)
{
PixelData result;
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.blue.signed_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
result.data_internalformat = GL_RGBA32I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA32UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_INT.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA32UIPixelData(GLenum type, unsigned int red, unsigned int green, unsigned int blue,
unsigned int alpha)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
result.data_internalformat = GL_RGBA32UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA8I internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_BYTE for source pixels.
* 2) GL_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA8IPixelData(int is_source_pixel, GLenum type, int red, int green, int blue,
int alpha)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_BYTE);
else
DE_ASSERT(type == GL_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.alpha.signed_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.blue.signed_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.green.signed_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS;
result.red.signed_byte_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.alpha.signed_integer_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.blue.signed_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.green.signed_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
result.red.signed_integer_data = red;
}
result.data_internalformat = GL_RGBA8I;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA8UI internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE for source pixels.
* 2) GL_UNSIGNED_INT for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA8UIPixelData(int is_source_pixel, GLenum type, unsigned int red,
unsigned int green, unsigned int blue, unsigned int alpha)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_BYTE);
else
DE_ASSERT(type == GL_UNSIGNED_INT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.alpha.unsigned_integer_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.blue.unsigned_integer_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.green.unsigned_integer_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
result.red.unsigned_integer_data = red;
}
result.data_internalformat = GL_RGBA8UI;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA4 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be:
* 1) GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT_4_4_4_4 for source pixels.
* 2) GL_UNSIGNED_BYTE for destination pixels.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA4PixelData(int is_source_pixel, GLenum type, unsigned char red,
unsigned char green, unsigned char blue, unsigned char alpha)
{
PixelData result;
if (is_source_pixel)
DE_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_4_4_4_4);
else
DE_ASSERT(type == GL_UNSIGNED_BYTE);
deMemset(&result, 0, sizeof(result));
switch (type)
{
case GL_UNSIGNED_BYTE:
{
// Fill the channel data structures
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
break;
}
case GL_UNSIGNED_SHORT_4_4_4_4:
{
DE_ASSERT(red <= 15);
DE_ASSERT(green <= 15);
DE_ASSERT(blue <= 15);
DE_ASSERT(alpha <= 15);
// Fill the channel data structures
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_4BITS;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_4BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_4BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_4BITS;
result.red.unsigned_byte_data = red;
break;
}
}
result.data_internalformat = GL_RGBA4;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA8PixelData(GLenum type, unsigned char red, unsigned char green, unsigned char blue,
unsigned char alpha)
{
PixelData result;
DE_ASSERT(type == GL_UNSIGNED_BYTE);
deMemset(&result, 0, sizeof(result));
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = alpha;
result.blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.blue.unsigned_byte_data = blue;
result.green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.green.unsigned_byte_data = green;
result.red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.red.unsigned_byte_data = red;
result.data_internalformat = GL_RGBA8;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_SRGB8_ALPHA8 internal format.
*
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getSRGB8Alpha8PixelData(GLenum type, unsigned char red, unsigned char green,
unsigned char blue, unsigned char alpha)
{
PixelData result = getRGBA8PixelData(type, red, green, blue, alpha);
result.data_internalformat = GL_SRGB8_ALPHA8;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_SRGB8 internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_UNSIGNED_BYTE.
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getSRGB8PixelData(int is_source_pixel, GLenum type, unsigned char red,
unsigned char green, unsigned char blue)
{
PixelData result = getSRGB8Alpha8PixelData(type, red, green, blue, 0);
if (is_source_pixel)
{
result.alpha.data_type = CHANNEL_DATA_TYPE_NONE;
result.alpha.unsigned_byte_data = 0;
}
else
{
result.alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
result.alpha.unsigned_byte_data = 255;
}
result.data_internalformat = GL_SRGB8;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R16F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_HALF_FLOAT
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR16FPixelData(int is_source_pixel, GLenum type, float red)
{
PixelData result;
DE_ASSERT(type == GL_HALF_FLOAT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
else
{
result.alpha.float_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
result.data_internalformat = GL_R16F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_R32F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_FLOAT
* @param red Value for red channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getR32FPixelData(int is_source_pixel, GLenum type, float red)
{
PixelData result;
DE_ASSERT(type == GL_FLOAT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
else
{
result.alpha.float_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
result.data_internalformat = GL_R32F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG16F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_HALF_FLOAT
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG16FPixelData(int is_source_pixel, GLenum type, float red, float green)
{
PixelData result;
DE_ASSERT(type == GL_HALF_FLOAT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
else
{
result.alpha.float_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
result.data_internalformat = GL_RG16F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RG32F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_FLOAT
* @param red Value for red channel.
* @param green Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRG32FPixelData(int is_source_pixel, GLenum type, float red, float green)
{
PixelData result;
DE_ASSERT(type == GL_FLOAT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
else
{
result.alpha.float_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
result.data_internalformat = GL_RG32F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB16F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_HALF_FLOAT
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for green channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB16FPixelData(int is_source_pixel, GLenum type, float red, float green, float blue)
{
PixelData result;
DE_ASSERT(type == GL_HALF_FLOAT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.blue.float_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
else
{
result.alpha.float_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.blue.float_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
result.data_internalformat = GL_RGB16F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGB32F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_FLOAT
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGB32FPixelData(int is_source_pixel, GLenum type, float red, float green, float blue)
{
PixelData result;
DE_ASSERT(type == GL_FLOAT);
deMemset(&result, 0, sizeof(result));
if (is_source_pixel)
{
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.blue.float_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
else
{
result.alpha.float_data = 1;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.blue.float_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
}
result.data_internalformat = GL_RGB32F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA16F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_HALF_FLOAT
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA16FPixelData(GLenum type, float red, float green, float blue, float alpha)
{
PixelData result;
DE_ASSERT(type == GL_HALF_FLOAT);
deMemset(&result, 0, sizeof(result));
result.alpha.float_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.blue.float_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.data_internalformat = GL_RGBA16F;
result.data_type = type;
return result;
}
/** Retrieves a PixelData instance describing a single pixel stored in
* GL_RGBA32F internal format.
*
* @param is_source_pixel 1 if the pixel is going to be used as conversion source,
* 0 otherwise.
* @param type GLES type the pixel uses. Must be GL_FLOAT
* @param red Value for red channel.
* @param green Value for green channel.
* @param blue Value for blue channel.
* @param alpha Value for alpha channel.
*
* @return Filled PixelData instance.
**/
PixelData ConversionDatabase::getRGBA32FPixelData(GLenum type, float red, float green, float blue, float alpha)
{
PixelData result;
DE_ASSERT(type == GL_FLOAT);
deMemset(&result, 0, sizeof(result));
result.alpha.float_data = alpha;
result.alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.red.float_data = red;
result.red.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.green.float_data = green;
result.green.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.blue.float_data = blue;
result.blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
result.data_internalformat = GL_RGBA32F;
result.data_type = type;
return result;
}
/** Adds a new conversion rule to a conversion database.
*
* Destination pixel datasets can only use one of the following types:
*
* GL_UNSIGNED_BYTE (for fixed-point source types);
* GL_INT (for signed integer types);
* GL_UNSIGNED_INT (for unsigned integer types);
* GL_UNSIGNED_INT_2_10_10_10_REV (for GL_RGB10_A2 type ONLY)
*
* The type used for destination storage configures arguments that
* will be passed to a gl.readPixels() call in verification stage IF
* source internalformat is color-renderable. If not, destination type
* determines how result & reference data should be compared using
* a special program object.
*
* It is illegal to:
*
* 1) add more than one conversion rule that uses the same source+destination
* internalformat+type combination.
* 2) use source pixels of different internalformats or types;
* 3) use destination pixels of different internalformats or types;
* 4) use pixel data instances using invalid internalformat or types.
*
* @param src_topleft Pixel-data instance describing source top-left corner.
* @param dst_topleft Pixel-data instance describing destination top-left corner.
* @param src_topright Pixel-data instance describing source top-right corner.
* @param dst_topright Pixel-data instance describing destination top-right corner.
* @param src_bottomleft Pixel-data instance describing source bottom-left corner.
* @param dst_bottomleft Pixel-data instance describing destination bottom-left corner.
* @param src_bottomright Pixel-data instance describing source bottom-right corner.
* @param dst_bottomright Pixel-data instance describing destination bottom-right corner.
**/
void ConversionDatabase::addEntryToConversionDatabase(PixelData src_topleft, PixelData dst_topleft,
PixelData src_topright, PixelData dst_topright,
PixelData src_bottomleft, PixelData dst_bottomleft,
PixelData src_bottomright, PixelData dst_bottomright,
PixelCompareChannel channels_to_compare)
{
GLenum dst_internalformat = GL_NONE;
GLenum dst_type = GL_NONE;
int is_dst_internalformat_valid = 0;
int is_dst_type_valid = 0;
GLenum src_internalformat = GL_NONE;
GLenum src_type = GL_NONE;
// Sanity checks: general
DE_ASSERT(src_topleft.data_internalformat != GL_NONE);
DE_ASSERT(dst_topleft.data_internalformat != GL_NONE);
if (src_topleft.data_internalformat == GL_NONE || dst_topleft.data_internalformat == GL_NONE)
return; // if (source / destination internalformats are GL_NONE)
DE_ASSERT(src_topleft.data_internalformat == src_topright.data_internalformat);
DE_ASSERT(src_topleft.data_internalformat == src_bottomleft.data_internalformat);
DE_ASSERT(src_topleft.data_internalformat == src_bottomright.data_internalformat);
DE_ASSERT(src_topleft.data_type == src_topright.data_type);
DE_ASSERT(src_topleft.data_type == src_bottomleft.data_type);
DE_ASSERT(src_topleft.data_type == src_bottomright.data_type);
if (src_topleft.data_internalformat != src_topright.data_internalformat ||
src_topleft.data_internalformat != src_bottomleft.data_internalformat ||
src_topleft.data_internalformat != src_bottomright.data_internalformat ||
src_topleft.data_type != src_topright.data_type || src_topleft.data_type != src_bottomleft.data_type ||
src_topleft.data_type != src_bottomright.data_type)
{
return;
} // if (source pixels' internalformats and/or types are not the same values)
DE_ASSERT(dst_topleft.data_internalformat == dst_topright.data_internalformat);
DE_ASSERT(dst_topleft.data_internalformat == dst_bottomleft.data_internalformat);
DE_ASSERT(dst_topleft.data_internalformat == dst_bottomright.data_internalformat);
DE_ASSERT(dst_topleft.data_type == dst_topright.data_type);
DE_ASSERT(dst_topleft.data_type == dst_bottomleft.data_type);
DE_ASSERT(dst_topleft.data_type == dst_bottomright.data_type);
if (dst_topleft.data_internalformat != dst_topright.data_internalformat ||
dst_topleft.data_internalformat != dst_bottomleft.data_internalformat ||
dst_topleft.data_internalformat != dst_bottomright.data_internalformat ||
dst_topleft.data_type != dst_topright.data_type || dst_topleft.data_type != dst_bottomleft.data_type ||
dst_topleft.data_type != dst_bottomright.data_type)
{
return;
} // if (destination pixels' internalformats and/or types are not the same values)
src_internalformat = src_topleft.data_internalformat;
src_type = src_topleft.data_type;
dst_internalformat = dst_topleft.data_internalformat;
dst_type = dst_topleft.data_type;
// Sanity checks: format used for destination storage
is_dst_type_valid = isTypeSupportedByGLReadPixels(dst_type);
is_dst_internalformat_valid = isInternalFormatCompatibleWithType(dst_type, dst_internalformat);
DE_ASSERT(is_dst_type_valid && is_dst_internalformat_valid);
if (!is_dst_type_valid || !is_dst_internalformat_valid)
TCU_FAIL("Requested destination type or internalformat is not compatible with validation requirements.");
// Sanity checks: make sure the conversion has not been already added
for (unsigned int n = 0; n < n_entries_added; ++n)
{
ConversionDatabaseEntry& entry_ptr = entries[n];
GLenum iterated_dst_internalformat = entry_ptr.dst_topleft_corner.data_internalformat;
GLenum iterated_dst_type = entry_ptr.dst_topleft_corner.data_type;
GLenum iterated_src_internalformat = entry_ptr.src_topleft_corner.data_internalformat;
GLenum iterated_src_type = entry_ptr.src_topleft_corner.data_type;
int is_new_rule = src_internalformat != iterated_src_internalformat ||
((src_internalformat == iterated_src_internalformat) && (src_type != iterated_src_type)) ||
((src_internalformat == iterated_src_internalformat) && (src_type == iterated_src_type) &&
(dst_internalformat != iterated_dst_internalformat)) ||
((src_internalformat == iterated_src_internalformat) && (src_type == iterated_src_type) &&
(dst_internalformat == iterated_dst_internalformat) && (dst_type != iterated_dst_type));
DE_ASSERT(is_new_rule);
if (!is_new_rule)
TCU_FAIL("This conversion rule already exists!");
}
// Make sure there's enough space to hold a new entry
if ((n_entries_added + 1) >= n_entries_allocated)
{
// Realloc is needed
n_entries_allocated <<= 1;
entries.resize(n_entries_allocated);
if (entries.empty())
TCU_FAIL("Out of memory while reallocating conversion database");
}
// Add the new entry
ConversionDatabaseEntry& entry_ptr = entries[n_entries_added];
entry_ptr.dst_bottomleft_corner = dst_bottomleft;
entry_ptr.dst_bottomright_corner = dst_bottomright;
entry_ptr.dst_topleft_corner = dst_topleft;
entry_ptr.dst_topright_corner = dst_topright;
entry_ptr.src_bottomleft_corner = src_bottomleft;
entry_ptr.src_bottomright_corner = src_bottomright;
entry_ptr.src_topleft_corner = src_topleft;
entry_ptr.src_topright_corner = src_topright;
entry_ptr.channels_to_compare = channels_to_compare;
++n_entries_added;
}
/** Adds all known conversion rules to a conversion database passed by argument.
*
* A conversion database stores exactly one conversion rule for each valid combination
* of source+destination internal-formats (with an exception that for each internalformat
* data may be represented with many different types!).
* These rules are then used by copy_tex_image_conversions_required conformance test to
* validate successfully executed conversions.
*
* A quick reminder:
*
* Source dataset corresponds to 2x2 image (using up to 4 channels) that the attachment bound to
* read buffer will use prior to glCopyTexImage2D() call. This image is defined by 4 Get*PixelData()
* calls with the first argument set to 1.
* Destination dataset corresponds to 2x2 image (using up to 4 channels) that the result texture
* object should match (within acceptable epsilon). This image is defined by 4 Get*PixelData() calls
* with the first argument set to 0.
*
* Source datasets are allowed to use any internalformat+type combination that is considered supported
* by GLES implementation.
* Destination datasets are only allowed to use specific types - please see AddEntryToConversionDatabase()
* doxygen for more details.
*
* @param database Conversion database handle.
**/
void ConversionDatabase::configureConversionDatabase()
{
int bits_1010102[4] = { 10, 10, 10, 2 };
int bits_4444[4] = { 4, 4, 4, 4 };
int bits_5551[4] = { 5, 5, 5, 1 };
int bits_565[4] = { 5, 6, 5, 0 };
int bits_888[4] = { 8, 8, 8, 0 };
int bits_8888[4] = { 8, 8, 8, 8 };
/* GL_R8 */
{
const unsigned char texel1[1] = { 255 };
const unsigned char texel2[1] = { 127 };
const unsigned char texel3[1] = { 63 };
const unsigned char texel4[1] = { 0 };
/* GL_R8 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(
getR8PixelData(1, GL_UNSIGNED_BYTE, texel1[0]), getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel1[0]),
getR8PixelData(1, GL_UNSIGNED_BYTE, texel2[0]), getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel2[0]),
getR8PixelData(1, GL_UNSIGNED_BYTE, texel3[0]), getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel3[0]),
getR8PixelData(1, GL_UNSIGNED_BYTE, texel4[0]), getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_R8 => GL_R8 */
addEntryToConversionDatabase(
getR8PixelData(1, GL_UNSIGNED_BYTE, texel1[0]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel1[0]),
getR8PixelData(1, GL_UNSIGNED_BYTE, texel2[0]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel2[0]),
getR8PixelData(1, GL_UNSIGNED_BYTE, texel3[0]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel3[0]),
getR8PixelData(1, GL_UNSIGNED_BYTE, texel4[0]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_RG8 */
{
const unsigned char texel1[2] = { 255, 127 };
const unsigned char texel2[2] = { 127, 63 };
const unsigned char texel3[2] = { 63, 0 };
const unsigned char texel4[2] = { 0, 255 };
/* GL_RG8 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(getRG8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel1[0]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel2[0]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel3[0]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RG8 => GL_R8 */
addEntryToConversionDatabase(
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel1[0]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel2[0]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel3[0]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1]), getR8PixelData(0, GL_UNSIGNED_BYTE, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RG8 => GL_RG8 */
addEntryToConversionDatabase(getRG8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getRG8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RGB8 */
{
const unsigned char texel1[3] = { 255, 127, 63 };
const unsigned char texel2[3] = { 127, 63, 0 };
const unsigned char texel3[3] = { 63, 0, 255 };
const unsigned char texel4[3] = { 0, 255, 127 };
/* GL_RGB8 => GL_RGB8 */
addEntryToConversionDatabase(getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGB8 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel1[0]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel2[0]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel3[0]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGB8 => GL_R8 */
addEntryToConversionDatabase(getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel1[0]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel2[0]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel3[0]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGB8 => GL_RG8 */
addEntryToConversionDatabase(getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getRGB8PixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
{ /* GL_RGB565 */
int texel565_1[4] = { 31, 63, 21, 0 };
int texel565_2[4] = { 21, 43, 11, 0 };
int texel565_3[4] = { 11, 23, 1, 0 };
int texel888_1[4] = { 255, 155, 55, 0 };
int texel888_2[4] = { 176, 76, 36, 0 };
int texel888_3[4] = { 88, 66, 44, 0 };
int texel888_4[4] = { 20, 10, 0, 0 };
int temp_565_to_888_bl[4] = { 0 };
int temp_565_to_888_tl[4] = { 0 };
int temp_565_to_888_tr[4] = { 0 };
int temp_888_through_565_to_888_bl[4] = { 0 };
int temp_888_through_565_to_888_br[4] = { 0 };
int temp_888_through_565_to_888_tl[4] = { 0 };
int temp_888_through_565_to_888_tr[4] = { 0 };
convertNormalizedUnsignedFixedPoint(bits_565, bits_888, bits_888, bits_888, texel565_1, temp_565_to_888_tl);
convertNormalizedUnsignedFixedPoint(bits_565, bits_888, bits_888, bits_888, texel565_2, temp_565_to_888_tr);
convertNormalizedUnsignedFixedPoint(bits_565, bits_888, bits_888, bits_888, texel565_3, temp_565_to_888_bl);
convertNormalizedUnsignedFixedPoint(bits_888, bits_565, bits_888, bits_888, texel888_1,
temp_888_through_565_to_888_tl);
convertNormalizedUnsignedFixedPoint(bits_888, bits_565, bits_888, bits_888, texel888_2,
temp_888_through_565_to_888_tr);
convertNormalizedUnsignedFixedPoint(bits_888, bits_565, bits_888, bits_888, texel888_3,
temp_888_through_565_to_888_bl);
convertNormalizedUnsignedFixedPoint(bits_888, bits_565, bits_888, bits_888, texel888_4,
temp_888_through_565_to_888_br);
/* GL_RGB565 => GL_RGB565 */
addEntryToConversionDatabase(
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, texel565_1[0], texel565_1[1], texel565_1[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_565_to_888_tl[0], temp_565_to_888_tl[1],
temp_565_to_888_tl[2]),
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, texel565_2[0], texel565_2[1], texel565_2[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_565_to_888_tr[0], temp_565_to_888_tr[1],
temp_565_to_888_tr[2]),
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, texel565_3[0], texel565_3[1], texel565_3[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_565_to_888_bl[0], temp_565_to_888_bl[1],
temp_565_to_888_bl[2]),
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, 0, 0, 0), getRGB565PixelData(0, GL_UNSIGNED_BYTE, 0, 0, 0),
PIXEL_COMPARE_CHANNEL_RGB);
addEntryToConversionDatabase(
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_1[0], texel888_1[1], texel888_1[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_888_through_565_to_888_tl[0],
temp_888_through_565_to_888_tl[1], temp_888_through_565_to_888_tl[2]),
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_2[0], texel888_2[1], texel888_2[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_888_through_565_to_888_tr[0],
temp_888_through_565_to_888_tr[1], temp_888_through_565_to_888_tr[2]),
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_3[0], texel888_3[1], texel888_3[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_888_through_565_to_888_bl[0],
temp_888_through_565_to_888_bl[1], temp_888_through_565_to_888_bl[2]),
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_4[0], texel888_4[1], texel888_4[2]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_888_through_565_to_888_br[0],
temp_888_through_565_to_888_br[1], temp_888_through_565_to_888_br[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGB565 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, texel565_1[0], texel565_1[1], texel565_1[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_565_to_888_tl[0]),
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, texel565_2[0], texel565_2[1], texel565_2[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_565_to_888_tr[0]),
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, texel565_3[0], texel565_3[1], texel565_3[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_565_to_888_bl[0]),
getRGB565PixelData(1, GL_UNSIGNED_SHORT_5_6_5, 0, 0, 0), getLuminance8OESPixelData(GL_UNSIGNED_BYTE, 0),
PIXEL_COMPARE_CHANNEL_R);
addEntryToConversionDatabase(
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_1[0], texel888_1[1], texel888_1[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_888_through_565_to_888_tl[0]),
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_2[0], texel888_2[1], texel888_2[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_888_through_565_to_888_tr[0]),
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_3[0], texel888_3[1], texel888_3[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_888_through_565_to_888_bl[0]),
getRGB565PixelData(1, GL_UNSIGNED_BYTE, texel888_4[0], texel888_4[1], texel888_4[2]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_888_through_565_to_888_br[0]), PIXEL_COMPARE_CHANNEL_R);
}
/* GL_RGBA4 */
{
int texel4444_1[4] = { 15, 9, 4, 0 };
int texel4444_2[4] = { 9, 4, 0, 15 };
int texel4444_3[4] = { 4, 0, 15, 9 };
int texel4444_4[4] = { 0, 15, 9, 4 };
int texel8888_1[4] = { 255, 159, 79, 0 };
int texel8888_2[4] = { 159, 79, 0, 255 };
int texel8888_3[4] = { 79, 0, 255, 159 };
int texel8888_4[4] = { 0, 255, 159, 79 };
int temp_4444_to_565_8888_tl[4] = { 0 };
int temp_4444_to_565_8888_tr[4] = { 0 };
int temp_4444_to_565_8888_bl[4] = { 0 };
int temp_4444_to_565_8888_br[4] = { 0 };
int temp_4444_to_8888_tl[4] = { 0 };
int temp_4444_to_8888_tr[4] = { 0 };
int temp_4444_to_8888_bl[4] = { 0 };
int temp_4444_to_8888_br[4] = { 0 };
int temp_8888_through_4444_to_565_tl[4] = { 0 };
int temp_8888_through_4444_to_565_tr[4] = { 0 };
int temp_8888_through_4444_to_565_bl[4] = { 0 };
int temp_8888_through_4444_to_565_br[4] = { 0 };
int temp_8888_through_4444_to_8888_tl[4] = { 0 };
int temp_8888_through_4444_to_8888_tr[4] = { 0 };
int temp_8888_through_4444_to_8888_bl[4] = { 0 };
int temp_8888_through_4444_to_8888_br[4] = { 0 };
int temp_8888_through_4444_565_to_8888_tl[4] = { 0 };
int temp_8888_through_4444_565_to_8888_tr[4] = { 0 };
int temp_8888_through_4444_565_to_8888_bl[4] = { 0 };
int temp_8888_through_4444_565_to_8888_br[4] = { 0 };
convertNormalizedUnsignedFixedPoint(bits_4444, bits_565, bits_8888, bits_8888, texel4444_1,
temp_4444_to_565_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_565, bits_8888, bits_8888, texel4444_2,
temp_4444_to_565_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_565, bits_8888, bits_8888, texel4444_3,
temp_4444_to_565_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_565, bits_8888, bits_8888, texel4444_4,
temp_4444_to_565_8888_br);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_8888, bits_8888, bits_8888, texel4444_1,
temp_4444_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_8888, bits_8888, bits_8888, texel4444_2,
temp_4444_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_8888, bits_8888, bits_8888, texel4444_3,
temp_4444_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_4444, bits_8888, bits_8888, bits_8888, texel4444_4,
temp_4444_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_565, texel8888_1,
temp_8888_through_4444_to_565_tl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_565, texel8888_2,
temp_8888_through_4444_to_565_tr);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_565, texel8888_3,
temp_8888_through_4444_to_565_bl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_565, texel8888_4,
temp_8888_through_4444_to_565_br);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_8888, bits_8888, texel8888_1,
temp_8888_through_4444_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_8888, bits_8888, texel8888_2,
temp_8888_through_4444_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_8888, bits_8888, texel8888_3,
temp_8888_through_4444_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_8888, bits_8888, texel8888_4,
temp_8888_through_4444_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_8888, texel8888_1,
temp_8888_through_4444_565_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_8888, texel8888_2,
temp_8888_through_4444_565_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_8888, texel8888_3,
temp_8888_through_4444_565_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_4444, bits_565, bits_8888, texel8888_4,
temp_8888_through_4444_565_to_8888_br);
/* GL_RGBA4 => GL_RGBA4 */
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_1[0], texel4444_1[1], texel4444_1[2],
texel4444_1[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_8888_tl[0], temp_4444_to_8888_tl[1],
temp_4444_to_8888_tl[2], temp_4444_to_8888_tl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_2[0], texel4444_2[1], texel4444_2[2],
texel4444_2[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_8888_tr[0], temp_4444_to_8888_tr[1],
temp_4444_to_8888_tr[2], temp_4444_to_8888_tr[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_3[0], texel4444_3[1], texel4444_3[2],
texel4444_3[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_8888_bl[0], temp_4444_to_8888_bl[1],
temp_4444_to_8888_bl[2], temp_4444_to_8888_bl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_4[0], texel4444_4[1], texel4444_4[2],
texel4444_4[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_8888_br[0], temp_4444_to_8888_br[1],
temp_4444_to_8888_br[2], temp_4444_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tl[0],
temp_8888_through_4444_to_8888_tl[1], temp_8888_through_4444_to_8888_tl[2],
temp_8888_through_4444_to_8888_tl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tr[0],
temp_8888_through_4444_to_8888_tr[1], temp_8888_through_4444_to_8888_tr[2],
temp_8888_through_4444_to_8888_tr[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_bl[0],
temp_8888_through_4444_to_8888_bl[1], temp_8888_through_4444_to_8888_bl[2],
temp_8888_through_4444_to_8888_bl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getRGBA4PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_br[0],
temp_8888_through_4444_to_8888_br[1], temp_8888_through_4444_to_8888_br[2],
temp_8888_through_4444_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
/* GL_RGBA4 => GL_RGB565 */
addEntryToConversionDatabase(getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_1[0], texel4444_1[1],
texel4444_1[2], texel4444_1[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_565_8888_tl[0],
temp_4444_to_565_8888_tl[1], temp_4444_to_565_8888_tl[2]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_2[0], texel4444_2[1],
texel4444_2[2], texel4444_2[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_565_8888_tr[0],
temp_4444_to_565_8888_tr[1], temp_4444_to_565_8888_tr[2]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_3[0], texel4444_3[1],
texel4444_3[2], texel4444_3[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_565_8888_bl[0],
temp_4444_to_565_8888_bl[1], temp_4444_to_565_8888_bl[2]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_4[0], texel4444_4[1],
texel4444_4[2], texel4444_4[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_4444_to_565_8888_br[0],
temp_4444_to_565_8888_br[1], temp_4444_to_565_8888_br[2]),
PIXEL_COMPARE_CHANNEL_RGB);
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_565_to_8888_tl[0],
temp_8888_through_4444_565_to_8888_tl[1], temp_8888_through_4444_565_to_8888_tl[2]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_565_to_8888_tr[0],
temp_8888_through_4444_565_to_8888_tr[1], temp_8888_through_4444_565_to_8888_tr[2]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_565_to_8888_bl[0],
temp_8888_through_4444_565_to_8888_bl[1], temp_8888_through_4444_565_to_8888_bl[2]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_4444_565_to_8888_br[0],
temp_8888_through_4444_565_to_8888_br[1], temp_8888_through_4444_565_to_8888_br[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA4 => GL_LUMINANCE8_ALPHA8_OES */
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_1[0], texel4444_1[1], texel4444_1[2],
texel4444_1[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_tl[0], temp_4444_to_8888_tl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_2[0], texel4444_2[1], texel4444_2[2],
texel4444_2[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_tr[0], temp_4444_to_8888_tr[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_3[0], texel4444_3[1], texel4444_3[2],
texel4444_3[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_bl[0], temp_4444_to_8888_bl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_4[0], texel4444_4[1], texel4444_4[2],
texel4444_4[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_br[0], temp_4444_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RA);
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_1[0], texel4444_1[1], texel4444_1[2], texel4444_1[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tl[0],
temp_8888_through_4444_to_8888_tl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_2[0], texel4444_2[1], texel4444_2[2], texel4444_2[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tr[0],
temp_8888_through_4444_to_8888_tr[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_3[0], texel4444_3[1], texel4444_3[2], texel4444_3[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_bl[0],
temp_8888_through_4444_to_8888_bl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_4[0], texel4444_4[1], texel4444_4[2], texel4444_4[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_br[0],
temp_8888_through_4444_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RA);
/* GL_RGBA4 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_1[0], texel4444_1[1],
texel4444_1[2], texel4444_1[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_tl[0]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_2[0], texel4444_2[1],
texel4444_2[2], texel4444_2[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_tr[0]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_3[0], texel4444_3[1],
texel4444_3[2], texel4444_3[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_bl[0]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_4[0], texel4444_4[1],
texel4444_4[2], texel4444_4[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_br[0]),
PIXEL_COMPARE_CHANNEL_R);
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_1[0], texel4444_1[1], texel4444_1[2], texel4444_1[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tl[0]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_2[0], texel4444_2[1], texel4444_2[2], texel4444_2[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tr[0]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_3[0], texel4444_3[1], texel4444_3[2], texel4444_3[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_bl[0]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_4[0], texel4444_4[1], texel4444_4[2], texel4444_4[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_br[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA4 => GL_ALPHA8_OES */
addEntryToConversionDatabase(getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_1[0], texel4444_1[1],
texel4444_1[2], texel4444_1[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_tl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_2[0], texel4444_2[1],
texel4444_2[2], texel4444_2[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_tr[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_3[0], texel4444_3[1],
texel4444_3[2], texel4444_3[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_bl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_SHORT_4_4_4_4, texel4444_4[0], texel4444_4[1],
texel4444_4[2], texel4444_4[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_4444_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_A);
addEntryToConversionDatabase(
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_1[0], texel4444_1[1], texel4444_1[2], texel4444_1[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_2[0], texel4444_2[1], texel4444_2[2], texel4444_2[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_tr[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_3[0], texel4444_3[1], texel4444_3[2], texel4444_3[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_bl[3]),
getRGBA4PixelData(1, GL_UNSIGNED_BYTE, texel4444_4[0], texel4444_4[1], texel4444_4[2], texel4444_4[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_4444_to_8888_br[3]), PIXEL_COMPARE_CHANNEL_A);
}
/* GL_RGB5_A1 */
{
int texel2101010_1[4] = { 1023, 703, 383, 2 };
int texel2101010_2[4] = { 703, 383, 0, 0 };
int texel2101010_3[4] = { 383, 0, 1023, 2 };
int texel2101010_4[4] = { 0, 1023, 703, 0 };
int texel5551_1[4] = { 31, 21, 11, 1 };
int texel5551_2[4] = { 21, 11, 0, 0 };
int texel5551_3[4] = { 11, 0, 31, 1 };
int texel5551_4[4] = { 0, 31, 21, 0 };
int texel8888_1[4] = { 255, 207, 95, 255 };
int texel8888_2[4] = { 207, 95, 0, 0 };
int texel8888_3[4] = { 95, 0, 255, 255 };
int texel8888_4[4] = { 0, 255, 207, 0 };
int temp_2101010rev_through_5551_to_8888_tl[4] = { 0 };
int temp_2101010rev_through_5551_to_8888_tr[4] = { 0 };
int temp_2101010rev_through_5551_to_8888_bl[4] = { 0 };
int temp_2101010rev_through_5551_to_8888_br[4] = { 0 };
int temp_2101010rev_through_5551_565_to_8888_tl[4] = { 0 };
int temp_2101010rev_through_5551_565_to_8888_tr[4] = { 0 };
int temp_2101010rev_through_5551_565_to_8888_bl[4] = { 0 };
int temp_2101010rev_through_5551_565_to_8888_br[4] = { 0 };
int temp_5551_to_8888_tl[4] = { 0 };
int temp_5551_to_8888_tr[4] = { 0 };
int temp_5551_to_8888_bl[4] = { 0 };
int temp_5551_to_8888_br[4] = { 0 };
int temp_5551_through_565_to_8888_tl[4] = { 0 };
int temp_5551_through_565_to_8888_tr[4] = { 0 };
int temp_5551_through_565_to_8888_bl[4] = { 0 };
int temp_5551_through_565_to_8888_br[4] = { 0 };
int temp_8888_through_5551_to_8888_tl[4] = { 0 };
int temp_8888_through_5551_to_8888_tr[4] = { 0 };
int temp_8888_through_5551_to_8888_bl[4] = { 0 };
int temp_8888_through_5551_to_8888_br[4] = { 0 };
int temp_8888_through_5551_565_to_8888_tl[4] = { 0 };
int temp_8888_through_5551_565_to_8888_tr[4] = { 0 };
int temp_8888_through_5551_565_to_8888_bl[4] = { 0 };
int temp_8888_through_5551_565_to_8888_br[4] = { 0 };
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_8888, bits_8888, texel2101010_1,
temp_2101010rev_through_5551_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_8888, bits_8888, texel2101010_2,
temp_2101010rev_through_5551_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_8888, bits_8888, texel2101010_3,
temp_2101010rev_through_5551_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_8888, bits_8888, texel2101010_4,
temp_2101010rev_through_5551_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_565, bits_8888, texel2101010_1,
temp_2101010rev_through_5551_565_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_565, bits_8888, texel2101010_2,
temp_2101010rev_through_5551_565_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_565, bits_8888, texel2101010_3,
temp_2101010rev_through_5551_565_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_1010102, bits_5551, bits_565, bits_8888, texel2101010_4,
temp_2101010rev_through_5551_565_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_8888, bits_8888, bits_8888, texel5551_1,
temp_5551_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_8888, bits_8888, bits_8888, texel5551_2,
temp_5551_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_8888, bits_8888, bits_8888, texel5551_3,
temp_5551_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_8888, bits_8888, bits_8888, texel5551_4,
temp_5551_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_8888, bits_8888, texel8888_1,
temp_8888_through_5551_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_8888, bits_8888, texel8888_2,
temp_8888_through_5551_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_8888, bits_8888, texel8888_3,
temp_8888_through_5551_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_8888, bits_8888, texel8888_4,
temp_8888_through_5551_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_565, bits_8888, texel8888_1,
temp_8888_through_5551_565_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_565, bits_8888, texel8888_2,
temp_8888_through_5551_565_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_565, bits_8888, texel8888_3,
temp_8888_through_5551_565_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_8888, bits_5551, bits_565, bits_8888, texel8888_4,
temp_8888_through_5551_565_to_8888_br);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_565, bits_8888, bits_8888, texel5551_1,
temp_5551_through_565_to_8888_tl);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_565, bits_8888, bits_8888, texel5551_2,
temp_5551_through_565_to_8888_tr);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_565, bits_8888, bits_8888, texel5551_3,
temp_5551_through_565_to_8888_bl);
convertNormalizedUnsignedFixedPoint(bits_5551, bits_565, bits_8888, bits_8888, texel5551_4,
temp_5551_through_565_to_8888_br);
/* GL_RGB5_A1 => GL_RGB5_A1 */
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tl[0],
temp_8888_through_5551_to_8888_tl[1], temp_8888_through_5551_to_8888_tl[2],
temp_8888_through_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tr[0],
temp_8888_through_5551_to_8888_tr[1], temp_8888_through_5551_to_8888_tr[2],
temp_8888_through_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_bl[0],
temp_8888_through_5551_to_8888_bl[1], temp_8888_through_5551_to_8888_bl[2],
temp_8888_through_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_br[0],
temp_8888_through_5551_to_8888_br[1], temp_8888_through_5551_to_8888_br[2],
temp_8888_through_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_1[0], texel5551_1[1], texel5551_1[2],
texel5551_1[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_5551_to_8888_tl[0], temp_5551_to_8888_tl[1],
temp_5551_to_8888_tl[2], temp_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_2[0], texel5551_2[1], texel5551_2[2],
texel5551_2[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_5551_to_8888_tr[0], temp_5551_to_8888_tr[1],
temp_5551_to_8888_tr[2], temp_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_3[0], texel5551_3[1], texel5551_3[2],
texel5551_3[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_5551_to_8888_bl[0], temp_5551_to_8888_bl[1],
temp_5551_to_8888_bl[2], temp_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_4[0], texel5551_4[1], texel5551_4[2],
texel5551_4[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_5551_to_8888_br[0], temp_5551_to_8888_br[1],
temp_5551_to_8888_br[2], temp_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_1[0], texel2101010_1[1],
texel2101010_1[2], texel2101010_1[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tl[0],
temp_2101010rev_through_5551_to_8888_tl[1], temp_2101010rev_through_5551_to_8888_tl[2],
temp_2101010rev_through_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_2[0], texel2101010_2[1],
texel2101010_2[2], texel2101010_2[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tr[0],
temp_2101010rev_through_5551_to_8888_tr[1], temp_2101010rev_through_5551_to_8888_tr[2],
temp_2101010rev_through_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_3[0], texel2101010_3[1],
texel2101010_3[2], texel2101010_3[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_bl[0],
temp_2101010rev_through_5551_to_8888_bl[1], temp_2101010rev_through_5551_to_8888_bl[2],
temp_2101010rev_through_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_4[0], texel2101010_4[1],
texel2101010_4[2], texel2101010_4[3]),
getRGB5A1PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_br[0],
temp_2101010rev_through_5551_to_8888_br[1], temp_2101010rev_through_5551_to_8888_br[2],
temp_2101010rev_through_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
/* GL_RGB5_A1 => GL_RGB565 */
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_565_to_8888_tl[0],
temp_8888_through_5551_565_to_8888_tl[1], temp_8888_through_5551_565_to_8888_tl[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_565_to_8888_tr[0],
temp_8888_through_5551_565_to_8888_tr[1], temp_8888_through_5551_565_to_8888_tr[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_565_to_8888_bl[0],
temp_8888_through_5551_565_to_8888_bl[1], temp_8888_through_5551_565_to_8888_bl[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_8888_through_5551_565_to_8888_br[0],
temp_8888_through_5551_565_to_8888_br[1], temp_8888_through_5551_565_to_8888_br[2]),
PIXEL_COMPARE_CHANNEL_RGB);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_1[0], texel5551_1[1], texel5551_1[2],
texel5551_1[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_5551_through_565_to_8888_tl[0],
temp_5551_through_565_to_8888_tl[1], temp_5551_through_565_to_8888_tl[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_2[0], texel5551_2[1], texel5551_2[2],
texel5551_2[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_5551_through_565_to_8888_tr[0],
temp_5551_through_565_to_8888_tr[1], temp_5551_through_565_to_8888_tr[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_3[0], texel5551_3[1], texel5551_3[2],
texel5551_3[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_5551_through_565_to_8888_bl[0],
temp_5551_through_565_to_8888_bl[1], temp_5551_through_565_to_8888_bl[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_4[0], texel5551_4[1], texel5551_4[2],
texel5551_4[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_5551_through_565_to_8888_br[0],
temp_5551_through_565_to_8888_br[1], temp_5551_through_565_to_8888_br[2]),
PIXEL_COMPARE_CHANNEL_RGB);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_1[0], texel2101010_1[1],
texel2101010_1[2], texel2101010_1[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_565_to_8888_tl[0],
temp_2101010rev_through_5551_565_to_8888_tl[1],
temp_2101010rev_through_5551_565_to_8888_tl[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_2[0], texel2101010_2[1],
texel2101010_2[2], texel2101010_2[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_565_to_8888_tr[0],
temp_2101010rev_through_5551_565_to_8888_tr[1],
temp_2101010rev_through_5551_565_to_8888_tr[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_3[0], texel2101010_3[1],
texel2101010_3[2], texel2101010_3[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_565_to_8888_bl[0],
temp_2101010rev_through_5551_565_to_8888_bl[1],
temp_2101010rev_through_5551_565_to_8888_bl[2]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_4[0], texel2101010_4[1],
texel2101010_4[2], texel2101010_4[3]),
getRGB565PixelData(0, GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_565_to_8888_br[0],
temp_2101010rev_through_5551_565_to_8888_br[1],
temp_2101010rev_through_5551_565_to_8888_br[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGB5_A1 => GL_LUMINANCE8_ALPHA8_OES */
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tl[0],
temp_8888_through_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tr[0],
temp_8888_through_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_bl[0],
temp_8888_through_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_br[0],
temp_8888_through_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RA);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_1[0], texel5551_1[1], texel5551_1[2],
texel5551_1[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_tl[0], temp_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_2[0], texel5551_2[1], texel5551_2[2],
texel5551_2[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_tr[0], temp_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_3[0], texel5551_3[1], texel5551_3[2],
texel5551_3[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_bl[0], temp_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_4[0], texel5551_4[1], texel5551_4[2],
texel5551_4[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_br[0], temp_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RA);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_1[0], texel2101010_1[1],
texel2101010_1[2], texel2101010_1[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tl[0],
temp_2101010rev_through_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_2[0], texel2101010_2[1],
texel2101010_2[2], texel2101010_2[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tr[0],
temp_2101010rev_through_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_3[0], texel2101010_3[1],
texel2101010_3[2], texel2101010_3[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_bl[0],
temp_2101010rev_through_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_4[0], texel2101010_4[1],
texel2101010_4[2], texel2101010_4[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_br[0],
temp_2101010rev_through_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_RA);
/* GL_RGB5_A1 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tl[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tr[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_bl[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_br[0]), PIXEL_COMPARE_CHANNEL_R);
addEntryToConversionDatabase(getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_1[0], texel5551_1[1],
texel5551_1[2], texel5551_1[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_tl[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_2[0], texel5551_2[1],
texel5551_2[2], texel5551_2[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_tr[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_3[0], texel5551_3[1],
texel5551_3[2], texel5551_3[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_bl[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_4[0], texel5551_4[1],
texel5551_4[2], texel5551_4[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_br[0]),
PIXEL_COMPARE_CHANNEL_R);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_1[0], texel2101010_1[1],
texel2101010_1[2], texel2101010_1[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tl[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_2[0], texel2101010_2[1],
texel2101010_2[2], texel2101010_2[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tr[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_3[0], texel2101010_3[1],
texel2101010_3[2], texel2101010_3[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_bl[0]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_4[0], texel2101010_4[1],
texel2101010_4[2], texel2101010_4[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_br[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RGB5_A1 => GL_ALPHA8_OES */
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_1[0], texel8888_1[1], texel8888_1[2], texel8888_1[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_2[0], texel8888_2[1], texel8888_2[2], texel8888_2[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_3[0], texel8888_3[1], texel8888_3[2], texel8888_3[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_BYTE, texel8888_4[0], texel8888_4[1], texel8888_4[2], texel8888_4[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_8888_through_5551_to_8888_br[3]), PIXEL_COMPARE_CHANNEL_A);
addEntryToConversionDatabase(getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_1[0], texel5551_1[1],
texel5551_1[2], texel5551_1[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_2[0], texel5551_2[1],
texel5551_2[2], texel5551_2[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_3[0], texel5551_3[1],
texel5551_3[2], texel5551_3[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_SHORT_5_5_5_1, texel5551_4[0], texel5551_4[1],
texel5551_4[2], texel5551_4[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_A);
addEntryToConversionDatabase(
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_1[0], texel2101010_1[1],
texel2101010_1[2], texel2101010_1[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_2[0], texel2101010_2[1],
texel2101010_2[2], texel2101010_2[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_tr[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_3[0], texel2101010_3[1],
texel2101010_3[2], texel2101010_3[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_bl[3]),
getRGB5A1PixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2101010_4[0], texel2101010_4[1],
texel2101010_4[2], texel2101010_4[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, temp_2101010rev_through_5551_to_8888_br[3]),
PIXEL_COMPARE_CHANNEL_A);
}
/* GL_RGBA8 */
{
const unsigned char texel1[4] = { 255, 127, 63, 0 };
const unsigned char texel2[4] = { 127, 63, 0, 255 };
const unsigned char texel3[4] = { 63, 0, 255, 127 };
const unsigned char texel4[4] = { 0, 255, 127, 63 };
/* GL_RGBA8 => GL_RGBA8 */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
/* GL_RGBA8 => GL_RGB8 */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB8PixelData(0, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA8 => GL_LUMINANCE8_ALPHA8_OES */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getLuminance8Alpha8OESPixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[3]),
PIXEL_COMPARE_CHANNEL_RA);
/* GL_RGBA8 => GL_LUMINANCE8_OES */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel1[0]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel2[0]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel3[0]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getLuminance8OESPixelData(GL_UNSIGNED_BYTE, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA8 => GL_ALPHA8_OES */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, texel1[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, texel2[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, texel3[3]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getAlpha8OESPixelData(GL_UNSIGNED_BYTE, texel4[3]), PIXEL_COMPARE_CHANNEL_A);
/* GL_RGBA8 => GL_R8 */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel1[0]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel2[0]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel3[0]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getR8PixelData(0, GL_UNSIGNED_BYTE, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA8 => GL_RG8 */
addEntryToConversionDatabase(getRGBA8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getRGBA8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG8PixelData(0, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RGB10_A2 */
{
const unsigned short texel1[4] = { 1023, 682, 341, 3 };
const unsigned short texel2[4] = { 682, 341, 0, 2 };
const unsigned short texel3[4] = { 341, 0, 1023, 1 };
const unsigned short texel4[4] = { 0, 1023, 682, 0 };
/* GL_RGB10_A2 => GL_RGB10_A2 */
addEntryToConversionDatabase(getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel1[0], texel1[1],
texel1[2], (unsigned char)texel1[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel1[0], texel1[1],
texel1[2], (unsigned char)texel1[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel2[0], texel2[1],
texel2[2], (unsigned char)texel2[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel2[0], texel2[1],
texel2[2], (unsigned char)texel2[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel3[0], texel3[1],
texel3[2], (unsigned char)texel3[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel3[0], texel3[1],
texel3[2], (unsigned char)texel3[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel4[0], texel4[1],
texel4[2], (unsigned char)texel4[3]),
getRGB10A2PixelData(GL_UNSIGNED_INT_2_10_10_10_REV, texel4[0], texel4[1],
texel4[2], (unsigned char)texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGB10_A2UI */
{
const unsigned short texel1[4] = { 1023, 682, 341, 3 };
const unsigned short texel2[4] = { 682, 341, 0, 2 };
const unsigned short texel3[4] = { 341, 0, 1023, 1 };
const unsigned short texel4[4] = { 0, 1023, 682, 0 };
/* GL_RGB10_A2UI => GL_RGB10_A2UI */
addEntryToConversionDatabase(
getRGB10A2UIPixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB10A2UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB10A2UIPixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB10A2UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB10A2UIPixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB10A2UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB10A2UIPixelData(1, GL_UNSIGNED_INT_2_10_10_10_REV, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB10A2UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_SRGB8_ALPHA8 */
{
const unsigned char texel1[4] = { 255, 127, 63, 0 };
const unsigned char texel2[4] = { 127, 63, 0, 255 };
const unsigned char texel3[4] = { 63, 0, 255, 127 };
const unsigned char texel4[4] = { 0, 255, 127, 63 };
/* GL_SRGB8_ALPHA8 => GL_SRGB8 */
addEntryToConversionDatabase(
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getSRGB8PixelData(0, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getSRGB8PixelData(0, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getSRGB8PixelData(0, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getSRGB8PixelData(0, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2]), PIXEL_COMPARE_CHANNEL_RGB);
/* GL_SRGB8_ALPHA8 => GL_SRGB8_ALPHA8 */
addEntryToConversionDatabase(
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getSRGB8Alpha8PixelData(GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_R8I */
{
const signed char texel1[1] = { 127 };
const signed char texel2[1] = { 42 };
const signed char texel3[1] = { -43 };
const signed char texel4[1] = { -127 };
/* GL_R8I => GL_R8I */
addEntryToConversionDatabase(getR8IPixelData(1, GL_BYTE, texel1[0]), getR8IPixelData(0, GL_INT, texel1[0]),
getR8IPixelData(1, GL_BYTE, texel2[0]), getR8IPixelData(0, GL_INT, texel2[0]),
getR8IPixelData(1, GL_BYTE, texel3[0]), getR8IPixelData(0, GL_INT, texel3[0]),
getR8IPixelData(1, GL_BYTE, texel4[0]), getR8IPixelData(0, GL_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_R8UI */
{
const unsigned char texel1[1] = { 255 };
const unsigned char texel2[1] = { 127 };
const unsigned char texel3[1] = { 63 };
const unsigned char texel4[1] = { 0 };
/* GL_R8UI => GL_R8UI */
addEntryToConversionDatabase(
getR8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0]), getR8UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getR8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0]), getR8UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getR8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0]), getR8UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getR8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0]), getR8UIPixelData(0, GL_UNSIGNED_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_R16I */
{
const signed short texel1[1] = { 32767 };
const signed short texel2[1] = { 10922 };
const signed short texel3[1] = { -10923 };
const signed short texel4[1] = { -32767 };
/* GL_R16I => GL_R16I */
addEntryToConversionDatabase(getR16IPixelData(1, GL_SHORT, texel1[0]), getR16IPixelData(0, GL_INT, texel1[0]),
getR16IPixelData(1, GL_SHORT, texel2[0]), getR16IPixelData(0, GL_INT, texel2[0]),
getR16IPixelData(1, GL_SHORT, texel3[0]), getR16IPixelData(0, GL_INT, texel3[0]),
getR16IPixelData(1, GL_SHORT, texel4[0]), getR16IPixelData(0, GL_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_R16UI */
{
const unsigned short texel1[1] = { 65535 };
const unsigned short texel2[1] = { 43690 };
const unsigned short texel3[1] = { 21845 };
const unsigned short texel4[1] = { 0 };
/* GL_R16UI => GL_R16UI */
addEntryToConversionDatabase(
getR16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0]), getR16UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getR16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0]), getR16UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getR16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0]), getR16UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getR16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0]), getR16UIPixelData(0, GL_UNSIGNED_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_R32I */
{
const int texel1[1] = { 2147483647l };
const int texel2[1] = { 715827883l };
const int texel3[1] = { -715827881l };
const int texel4[1] = { -2147483647l };
/* GL_R32I => GL_R32I */
addEntryToConversionDatabase(getR32IPixelData(1, GL_INT, texel1[0]), getR32IPixelData(0, GL_INT, texel1[0]),
getR32IPixelData(1, GL_INT, texel2[0]), getR32IPixelData(0, GL_INT, texel2[0]),
getR32IPixelData(1, GL_INT, texel3[0]), getR32IPixelData(0, GL_INT, texel3[0]),
getR32IPixelData(1, GL_INT, texel4[0]), getR32IPixelData(0, GL_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_R32UI */
{
const unsigned int texel1[1] = { 4294967295u };
const unsigned int texel2[1] = { 2863311530u };
const unsigned int texel3[1] = { 1431655765u };
const unsigned int texel4[1] = { 0 };
/* GL_R32UI => GL_R32UI */
addEntryToConversionDatabase(
getR32UIPixelData(1, GL_UNSIGNED_INT, texel1[0]), getR32UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getR32UIPixelData(1, GL_UNSIGNED_INT, texel2[0]), getR32UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getR32UIPixelData(1, GL_UNSIGNED_INT, texel3[0]), getR32UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getR32UIPixelData(1, GL_UNSIGNED_INT, texel4[0]), getR32UIPixelData(0, GL_UNSIGNED_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_RG8I */
{
const signed char texel1[2] = { 127, 42 };
const signed char texel2[2] = { 42, -43 };
const signed char texel3[2] = { -43, -127 };
const signed char texel4[2] = { -127, 127 };
/* GL_RG8I => GL_R8I */
addEntryToConversionDatabase(
getRG8IPixelData(1, GL_BYTE, texel1[0], texel1[1]), getR8IPixelData(0, GL_INT, texel1[0]),
getRG8IPixelData(1, GL_BYTE, texel2[0], texel2[1]), getR8IPixelData(0, GL_INT, texel2[0]),
getRG8IPixelData(1, GL_BYTE, texel3[0], texel3[1]), getR8IPixelData(0, GL_INT, texel3[0]),
getRG8IPixelData(1, GL_BYTE, texel4[0], texel4[1]), getR8IPixelData(0, GL_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RG8I => GL_RG8I */
addEntryToConversionDatabase(
getRG8IPixelData(1, GL_BYTE, texel1[0], texel1[1]), getRG8IPixelData(0, GL_INT, texel1[0], texel1[1]),
getRG8IPixelData(1, GL_BYTE, texel2[0], texel2[1]), getRG8IPixelData(0, GL_INT, texel2[0], texel2[1]),
getRG8IPixelData(1, GL_BYTE, texel3[0], texel3[1]), getRG8IPixelData(0, GL_INT, texel3[0], texel3[1]),
getRG8IPixelData(1, GL_BYTE, texel4[0], texel4[1]), getRG8IPixelData(0, GL_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RG8UI */
{
const unsigned char texel1[2] = { 255, 127 };
const unsigned char texel2[2] = { 127, 63 };
const unsigned char texel3[2] = { 63, 0 };
const unsigned char texel4[2] = { 0, 255 };
/* GL_RG8UI => GL_R8UI */
addEntryToConversionDatabase(getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RG8UI => GL_RG8UI */
addEntryToConversionDatabase(getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRG8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RG16I */
{
const short texel1[2] = { 32767, 10922 };
const short texel2[2] = { 10922, -10923 };
const short texel3[2] = { -10923, -32767 };
const short texel4[2] = { -32767, 32767 };
/* GL_RG16I => GL_R16I */
addEntryToConversionDatabase(
getRG16IPixelData(1, GL_SHORT, texel1[0], texel1[1]), getR16IPixelData(0, GL_INT, texel1[0]),
getRG16IPixelData(1, GL_SHORT, texel2[0], texel2[1]), getR16IPixelData(0, GL_INT, texel2[0]),
getRG16IPixelData(1, GL_SHORT, texel3[0], texel3[1]), getR16IPixelData(0, GL_INT, texel3[0]),
getRG16IPixelData(1, GL_SHORT, texel4[0], texel4[1]), getR16IPixelData(0, GL_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RG16I => GL_RG16I */
addEntryToConversionDatabase(
getRG16IPixelData(1, GL_SHORT, texel1[0], texel1[1]), getRG16IPixelData(0, GL_INT, texel1[0], texel1[1]),
getRG16IPixelData(1, GL_SHORT, texel2[0], texel2[1]), getRG16IPixelData(0, GL_INT, texel2[0], texel2[1]),
getRG16IPixelData(1, GL_SHORT, texel3[0], texel3[1]), getRG16IPixelData(0, GL_INT, texel3[0], texel3[1]),
getRG16IPixelData(1, GL_SHORT, texel4[0], texel4[1]), getRG16IPixelData(0, GL_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RG16UI */
{
const unsigned short texel1[2] = { 65535, 43690 };
const unsigned short texel2[2] = { 43690, 21845 };
const unsigned short texel3[2] = { 21845, 0 };
const unsigned short texel4[2] = { 0, 65535 };
/* GL_RG16UI => GL_R16UI */
addEntryToConversionDatabase(getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0], texel1[1]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0], texel2[1]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0], texel3[1]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0], texel4[1]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RG16UI => GL_RG16UI */
addEntryToConversionDatabase(getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0], texel1[1]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0], texel2[1]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0], texel3[1]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRG16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0], texel4[1]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RG32I */
{
const int texel1[2] = { 2147483647, 715827883l };
const int texel2[2] = { 715827883, -715827881l };
const int texel3[2] = { -715827881, -2147483647l };
const int texel4[2] = { -2147483647, 2147483647l };
/* GL_RG32I => GL_R32I */
addEntryToConversionDatabase(
getRG32IPixelData(1, GL_INT, texel1[0], texel1[1]), getR32IPixelData(0, GL_INT, texel1[0]),
getRG32IPixelData(1, GL_INT, texel2[0], texel2[1]), getR32IPixelData(0, GL_INT, texel2[0]),
getRG32IPixelData(1, GL_INT, texel3[0], texel3[1]), getR32IPixelData(0, GL_INT, texel3[0]),
getRG32IPixelData(1, GL_INT, texel4[0], texel4[1]), getR32IPixelData(0, GL_INT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RG32I => GL_RG32I */
addEntryToConversionDatabase(
getRG32IPixelData(1, GL_INT, texel1[0], texel1[1]), getRG32IPixelData(0, GL_INT, texel1[0], texel1[1]),
getRG32IPixelData(1, GL_INT, texel2[0], texel2[1]), getRG32IPixelData(0, GL_INT, texel2[0], texel2[1]),
getRG32IPixelData(1, GL_INT, texel3[0], texel3[1]), getRG32IPixelData(0, GL_INT, texel3[0], texel3[1]),
getRG32IPixelData(1, GL_INT, texel4[0], texel4[1]), getRG32IPixelData(0, GL_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RG32UI */
{
const unsigned int texel1[2] = { 4294967295u, 2863311530u };
const unsigned int texel2[2] = { 2863311530u, 1431655765u };
const unsigned int texel3[2] = { 1431655765u, 0 };
const unsigned int texel4[2] = { 0, 4294967295u };
/* GL_RG32UI => GL_R32UI */
addEntryToConversionDatabase(getRG32UIPixelData(1, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getRG32UIPixelData(1, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getRG32UIPixelData(1, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getRG32UIPixelData(1, GL_UNSIGNED_INT, texel4[0], texel4[1]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RG32UI => GL_RG32UI */
addEntryToConversionDatabase(getRG32UIPixelData(1, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRG32UIPixelData(1, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRG32UIPixelData(1, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRG32UIPixelData(1, GL_UNSIGNED_INT, texel4[0], texel4[1]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RGBA8I */
{
const signed char texel1[4] = { 127, 42, -43, -127 };
const signed char texel2[4] = { 42, -43, -127, 127 };
const signed char texel3[4] = { -43, -127, 127, 42 };
const signed char texel4[4] = { -127, 127, 42, -43 };
/* GL_RGBA8I => GL_R8I */
addEntryToConversionDatabase(getRGBA8IPixelData(1, GL_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getR8IPixelData(0, GL_INT, texel1[0]),
getRGBA8IPixelData(1, GL_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getR8IPixelData(0, GL_INT, texel2[0]),
getRGBA8IPixelData(1, GL_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getR8IPixelData(0, GL_INT, texel3[0]),
getRGBA8IPixelData(1, GL_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getR8IPixelData(0, GL_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA8I => GL_RG8I */
addEntryToConversionDatabase(getRGBA8IPixelData(1, GL_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG8IPixelData(0, GL_INT, texel1[0], texel1[1]),
getRGBA8IPixelData(1, GL_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG8IPixelData(0, GL_INT, texel2[0], texel2[1]),
getRGBA8IPixelData(1, GL_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG8IPixelData(0, GL_INT, texel3[0], texel3[1]),
getRGBA8IPixelData(1, GL_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG8IPixelData(0, GL_INT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA8I => GL_RGB8I */
addEntryToConversionDatabase(getRGBA8IPixelData(1, GL_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB8IPixelData(0, GL_INT, texel1[0], texel1[1], texel1[2]),
getRGBA8IPixelData(1, GL_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB8IPixelData(0, GL_INT, texel2[0], texel2[1], texel2[2]),
getRGBA8IPixelData(1, GL_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB8IPixelData(0, GL_INT, texel3[0], texel3[1], texel3[2]),
getRGBA8IPixelData(1, GL_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB8IPixelData(0, GL_INT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA8I => GL_RGBA8I */
addEntryToConversionDatabase(getRGBA8IPixelData(1, GL_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA8IPixelData(0, GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA8IPixelData(1, GL_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA8IPixelData(0, GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA8IPixelData(1, GL_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA8IPixelData(0, GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA8IPixelData(1, GL_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA8IPixelData(0, GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGBA8UI */
{
const unsigned char texel1[4] = { 255, 127, 63, 0 };
const unsigned char texel2[4] = { 127, 63, 0, 255 };
const unsigned char texel3[4] = { 63, 0, 255, 127 };
const unsigned char texel4[4] = { 0, 255, 127, 63 };
/* GL_RGBA8UI => GL_R8UI */
addEntryToConversionDatabase(
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getR8UIPixelData(0, GL_UNSIGNED_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA8UI => GL_RG8UI */
addEntryToConversionDatabase(
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG8UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA8UI => GL_RGB8UI */
addEntryToConversionDatabase(
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB8UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB8UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB8UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB8UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2]), PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA8UI => GL_RGBA8UI */
addEntryToConversionDatabase(
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA8UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA8UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA8UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA8UIPixelData(1, GL_UNSIGNED_BYTE, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA8UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGBA16I */
{
const short texel1[4] = { 32767, 10922, -10923, -32767 };
const short texel2[4] = { 10922, -10923, -32767, 32767 };
const short texel3[4] = { -10923, -32767, 32767, 10922 };
const short texel4[4] = { -32767, 32767, 10922, -10923 };
/* GL_RGBA16I => GL_R16I */
addEntryToConversionDatabase(getRGBA16IPixelData(1, GL_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getR16IPixelData(0, GL_INT, texel1[0]),
getRGBA16IPixelData(1, GL_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getR16IPixelData(0, GL_INT, texel2[0]),
getRGBA16IPixelData(1, GL_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getR16IPixelData(0, GL_INT, texel3[0]),
getRGBA16IPixelData(1, GL_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getR16IPixelData(0, GL_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA16I => GL_RG16I */
addEntryToConversionDatabase(getRGBA16IPixelData(1, GL_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG16IPixelData(0, GL_INT, texel1[0], texel1[1]),
getRGBA16IPixelData(1, GL_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG16IPixelData(0, GL_INT, texel2[0], texel2[1]),
getRGBA16IPixelData(1, GL_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG16IPixelData(0, GL_INT, texel3[0], texel3[1]),
getRGBA16IPixelData(1, GL_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG16IPixelData(0, GL_INT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA16I => GL_RGB16I */
addEntryToConversionDatabase(getRGBA16IPixelData(1, GL_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB16IPixelData(0, GL_INT, texel1[0], texel1[1], texel1[2]),
getRGBA16IPixelData(1, GL_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB16IPixelData(0, GL_INT, texel2[0], texel2[1], texel2[2]),
getRGBA16IPixelData(1, GL_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB16IPixelData(0, GL_INT, texel3[0], texel3[1], texel3[2]),
getRGBA16IPixelData(1, GL_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB16IPixelData(0, GL_INT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA16I => GL_RGBA16I */
addEntryToConversionDatabase(getRGBA16IPixelData(1, GL_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA16IPixelData(0, GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA16IPixelData(1, GL_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA16IPixelData(0, GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA16IPixelData(1, GL_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA16IPixelData(0, GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA16IPixelData(1, GL_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA16IPixelData(0, GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGBA16UI */
{
const unsigned short texel1[4] = { 65535, 43690, 21845, 0 };
const unsigned short texel2[4] = { 43690, 21845, 0, 65535 };
const unsigned short texel3[4] = { 21845, 0, 65535, 43690 };
const unsigned short texel4[4] = { 0, 65535, 43690, 21845 };
/* GL_RGBA16UI => GL_R16UI */
addEntryToConversionDatabase(
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getR16UIPixelData(0, GL_UNSIGNED_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA16UI => GL_RG16UI */
addEntryToConversionDatabase(
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG16UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA16UI => GL_RGB16UI */
addEntryToConversionDatabase(
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB16UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB16UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB16UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB16UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2]), PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA16UI => GL_RGBA16UI */
addEntryToConversionDatabase(
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA16UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA16UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA16UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA16UIPixelData(1, GL_UNSIGNED_SHORT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA16UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGBA32I */
{
const int texel1[4] = { 2147483647, 715827883, -715827881, -2147483647 };
const int texel2[4] = { 715827883, -715827881, -2147483647, 2147483647 };
const int texel3[4] = { -715827881, -2147483647, 2147483647, 715827883 };
const int texel4[4] = { -2147483647, 2147483647, 715827883, -715827881 };
/* GL_RGBA32I => GL_R32I */
addEntryToConversionDatabase(getRGBA32IPixelData(GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getR32IPixelData(0, GL_INT, texel1[0]),
getRGBA32IPixelData(GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getR32IPixelData(0, GL_INT, texel2[0]),
getRGBA32IPixelData(GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getR32IPixelData(0, GL_INT, texel3[0]),
getRGBA32IPixelData(GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getR32IPixelData(0, GL_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA32I => GL_RG32I */
addEntryToConversionDatabase(getRGBA32IPixelData(GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG32IPixelData(0, GL_INT, texel1[0], texel1[1]),
getRGBA32IPixelData(GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG32IPixelData(0, GL_INT, texel2[0], texel2[1]),
getRGBA32IPixelData(GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG32IPixelData(0, GL_INT, texel3[0], texel3[1]),
getRGBA32IPixelData(GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG32IPixelData(0, GL_INT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA32I => GL_RGB32I */
addEntryToConversionDatabase(getRGBA32IPixelData(GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB32IPixelData(0, GL_INT, texel1[0], texel1[1], texel1[2]),
getRGBA32IPixelData(GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB32IPixelData(0, GL_INT, texel2[0], texel2[1], texel2[2]),
getRGBA32IPixelData(GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB32IPixelData(0, GL_INT, texel3[0], texel3[1], texel3[2]),
getRGBA32IPixelData(GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB32IPixelData(0, GL_INT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA32I => GL_RGBA32I */
addEntryToConversionDatabase(getRGBA32IPixelData(GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA32IPixelData(GL_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA32IPixelData(GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA32IPixelData(GL_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA32IPixelData(GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA32IPixelData(GL_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA32IPixelData(GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA32IPixelData(GL_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGBA32UI */
{
const unsigned int texel1[4] = { 4294967295u, 2863311530u, 1431655765u, 0 };
const unsigned int texel2[4] = { 2863311530u, 1431655765u, 0, 4294967295u };
const unsigned int texel3[4] = { 1431655765u, 0, 4294967295u, 2863311530u };
const unsigned int texel4[4] = { 0, 4294967295u, 2863311530u, 1431655765u };
/* GL_RGBA32UI => GL_R32UI */
addEntryToConversionDatabase(getRGBA32UIPixelData(GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel1[0]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel2[0]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel3[0]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getR32UIPixelData(0, GL_UNSIGNED_INT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA32UI => GL_RG32UI */
addEntryToConversionDatabase(getRGBA32UIPixelData(GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG32UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA32UI => GL_RGB32UI */
addEntryToConversionDatabase(getRGBA32UIPixelData(GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB32UIPixelData(0, GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB32UIPixelData(0, GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB32UIPixelData(0, GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB32UIPixelData(0, GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA32UI => GL_RGBA32UI */
addEntryToConversionDatabase(getRGBA32UIPixelData(GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA32UIPixelData(GL_UNSIGNED_INT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_R16F */
{
const float texel1[1] = { 1 };
const float texel2[1] = { 4096 };
const float texel3[1] = { -4096 };
const float texel4[1] = { 32000 };
/* GL_R16F => GL_R16F */
addEntryToConversionDatabase(
getR16FPixelData(1, GL_HALF_FLOAT, texel1[0]), getR16FPixelData(0, GL_HALF_FLOAT, texel1[0]),
getR16FPixelData(1, GL_HALF_FLOAT, texel2[0]), getR16FPixelData(0, GL_HALF_FLOAT, texel2[0]),
getR16FPixelData(1, GL_HALF_FLOAT, texel3[0]), getR16FPixelData(0, GL_HALF_FLOAT, texel3[0]),
getR16FPixelData(1, GL_HALF_FLOAT, texel4[0]), getR16FPixelData(0, GL_HALF_FLOAT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_RG16F */
{
const float texel1[2] = { 1, 0 };
const float texel2[2] = { 4096, -4096 };
const float texel3[2] = { -32000, 32000 };
const float texel4[2] = { 1.5f, -4.7f };
/* GL_RG16F => GL_R16F */
addEntryToConversionDatabase(
getRG16FPixelData(1, GL_HALF_FLOAT, texel1[0], texel1[1]), getR16FPixelData(0, GL_HALF_FLOAT, texel1[0]),
getRG16FPixelData(1, GL_HALF_FLOAT, texel2[0], texel2[1]), getR16FPixelData(0, GL_HALF_FLOAT, texel2[0]),
getRG16FPixelData(1, GL_HALF_FLOAT, texel3[0], texel3[1]), getR16FPixelData(0, GL_HALF_FLOAT, texel3[0]),
getRG16FPixelData(1, GL_HALF_FLOAT, texel4[0], texel4[1]), getR16FPixelData(0, GL_HALF_FLOAT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RG16F => GL_RG16F */
addEntryToConversionDatabase(getRG16FPixelData(1, GL_HALF_FLOAT, texel1[0], texel1[1]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel1[0], texel1[1]),
getRG16FPixelData(1, GL_HALF_FLOAT, texel2[0], texel2[1]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel2[0], texel2[1]),
getRG16FPixelData(1, GL_HALF_FLOAT, texel3[0], texel3[1]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel3[0], texel3[1]),
getRG16FPixelData(1, GL_HALF_FLOAT, texel4[0], texel4[1]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_R32F */
{
const float texel1[1] = { 1 };
const float texel2[1] = { 4096 };
const float texel3[1] = { -4096 };
const float texel4[1] = { 32000 };
/* GL_R32F => GL_R32F */
addEntryToConversionDatabase(getR32FPixelData(1, GL_FLOAT, texel1[0]), getR32FPixelData(0, GL_FLOAT, texel1[0]),
getR32FPixelData(1, GL_FLOAT, texel2[0]), getR32FPixelData(0, GL_FLOAT, texel2[0]),
getR32FPixelData(1, GL_FLOAT, texel3[0]), getR32FPixelData(0, GL_FLOAT, texel3[0]),
getR32FPixelData(1, GL_FLOAT, texel4[0]), getR32FPixelData(0, GL_FLOAT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
}
/* GL_RG32F */
{
const float texel1[2] = { 1, 0 };
const float texel2[2] = { 4096, -4096 };
const float texel3[2] = { -32000, 32000 };
const float texel4[2] = { 1.5f, -4.7f };
/* GL_RG32F => GL_R32F */
addEntryToConversionDatabase(
getRG32FPixelData(1, GL_FLOAT, texel1[0], texel1[1]), getR32FPixelData(0, GL_FLOAT, texel1[0]),
getRG32FPixelData(1, GL_FLOAT, texel2[0], texel2[1]), getR32FPixelData(0, GL_FLOAT, texel2[0]),
getRG32FPixelData(1, GL_FLOAT, texel3[0], texel3[1]), getR32FPixelData(0, GL_FLOAT, texel3[0]),
getRG32FPixelData(1, GL_FLOAT, texel4[0], texel4[1]), getR32FPixelData(0, GL_FLOAT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RG32F => GL_RG32F */
addEntryToConversionDatabase(
getRG32FPixelData(1, GL_FLOAT, texel1[0], texel1[1]), getRG32FPixelData(0, GL_FLOAT, texel1[0], texel1[1]),
getRG32FPixelData(1, GL_FLOAT, texel2[0], texel2[1]), getRG32FPixelData(0, GL_FLOAT, texel2[0], texel2[1]),
getRG32FPixelData(1, GL_FLOAT, texel3[0], texel3[1]), getRG32FPixelData(0, GL_FLOAT, texel3[0], texel3[1]),
getRG32FPixelData(1, GL_FLOAT, texel4[0], texel4[1]), getRG32FPixelData(0, GL_FLOAT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
}
/* GL_RGB16F */
{
const float texel1[3] = { 1, 0, -1 };
const float texel2[3] = { 4096, -4096, 127.5f };
const float texel3[3] = { -32000, 32000, -456.7f };
const float texel4[3] = { 1.5f, -4.7f, 123.6f };
/* GL_RGB16F => GL_R16F */
addEntryToConversionDatabase(getRGB16FPixelData(1, GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2]),
getR16FPixelData(0, GL_HALF_FLOAT, texel1[0]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2]),
getR16FPixelData(0, GL_HALF_FLOAT, texel2[0]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2]),
getR16FPixelData(0, GL_HALF_FLOAT, texel3[0]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2]),
getR16FPixelData(0, GL_HALF_FLOAT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGB16F => GL_RG16F */
addEntryToConversionDatabase(getRGB16FPixelData(1, GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel1[0], texel1[1]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel2[0], texel2[1]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel3[0], texel3[1]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGB16F => GL_RGB16F */
addEntryToConversionDatabase(getRGB16FPixelData(1, GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2]),
getRGB16FPixelData(1, GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
}
/* GL_RGBA16F */
{
const float texel1[4] = { 1, 0, -1, 0.25f };
const float texel2[4] = { 4096, -4096, 127.5f, 0.5f };
const float texel3[4] = { -32000, 32000, -456.7f, 0.75f };
const float texel4[4] = { 1.5f, -4.7f, 123.6f, 1 };
/* GL_RGBA16F => GL_R16F */
addEntryToConversionDatabase(getRGBA16FPixelData(GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getR16FPixelData(0, GL_HALF_FLOAT, texel1[0]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getR16FPixelData(0, GL_HALF_FLOAT, texel2[0]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getR16FPixelData(0, GL_HALF_FLOAT, texel3[0]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getR16FPixelData(0, GL_HALF_FLOAT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA16F => GL_RG16F */
addEntryToConversionDatabase(getRGBA16FPixelData(GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel1[0], texel1[1]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel2[0], texel2[1]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel3[0], texel3[1]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG16FPixelData(0, GL_HALF_FLOAT, texel4[0], texel4[1]),
PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA16F => GL_RGB16F */
addEntryToConversionDatabase(getRGBA16FPixelData(GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB16FPixelData(0, GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA16F => GL_RGBA16F */
addEntryToConversionDatabase(getRGBA16FPixelData(GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA16FPixelData(GL_HALF_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
/* GL_RGB32F */
{
const float texel1[3] = { 1, 0, -1 };
const float texel2[3] = { 4096, -4096, 127.5f };
const float texel3[3] = { -32000, 32000, -456.7f };
const float texel4[3] = { 1.5f, -4.7f, 123.6f };
/* GL_RGB32F => GL_R32F */
addEntryToConversionDatabase(
getRGB32FPixelData(1, GL_FLOAT, texel1[0], texel1[1], texel1[2]), getR32FPixelData(0, GL_FLOAT, texel1[0]),
getRGB32FPixelData(1, GL_FLOAT, texel2[0], texel2[1], texel2[2]), getR32FPixelData(0, GL_FLOAT, texel2[0]),
getRGB32FPixelData(1, GL_FLOAT, texel3[0], texel3[1], texel3[2]), getR32FPixelData(0, GL_FLOAT, texel3[0]),
getRGB32FPixelData(1, GL_FLOAT, texel4[0], texel4[1], texel4[2]), getR32FPixelData(0, GL_FLOAT, texel4[0]),
PIXEL_COMPARE_CHANNEL_R);
/* GL_RGB32F => GL_RG32F */
addEntryToConversionDatabase(getRGB32FPixelData(1, GL_FLOAT, texel1[0], texel1[1], texel1[2]),
getRG32FPixelData(0, GL_FLOAT, texel1[0], texel1[1]),
getRGB32FPixelData(1, GL_FLOAT, texel2[0], texel2[1], texel2[2]),
getRG32FPixelData(0, GL_FLOAT, texel2[0], texel2[1]),
getRGB32FPixelData(1, GL_FLOAT, texel3[0], texel3[1], texel3[2]),
getRG32FPixelData(0, GL_FLOAT, texel3[0], texel3[1]),
getRGB32FPixelData(1, GL_FLOAT, texel4[0], texel4[1], texel4[2]),
getRG32FPixelData(0, GL_FLOAT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGB32F => GL_RGB32F */
addEntryToConversionDatabase(getRGB32FPixelData(1, GL_FLOAT, texel1[0], texel1[1], texel1[2]),
getRGB32FPixelData(0, GL_FLOAT, texel1[0], texel1[1], texel1[2]),
getRGB32FPixelData(1, GL_FLOAT, texel2[0], texel2[1], texel2[2]),
getRGB32FPixelData(0, GL_FLOAT, texel2[0], texel2[1], texel2[2]),
getRGB32FPixelData(1, GL_FLOAT, texel3[0], texel3[1], texel3[2]),
getRGB32FPixelData(0, GL_FLOAT, texel3[0], texel3[1], texel3[2]),
getRGB32FPixelData(1, GL_FLOAT, texel4[0], texel4[1], texel4[2]),
getRGB32FPixelData(0, GL_FLOAT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
}
/* GL_RGBA32F */
{
const float texel1[4] = { 1, 0, -1, 0.25f };
const float texel2[4] = { 4096, -4096, 127.5f, 0.5f };
const float texel3[4] = { -32000, 32000, -456.7f, 0.75f };
const float texel4[4] = { 1.5f, -4.7f, 123.6f, 1 };
/* GL_RGBA32F => GL_R32F */
addEntryToConversionDatabase(getRGBA32FPixelData(GL_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getR32FPixelData(0, GL_FLOAT, texel1[0]),
getRGBA32FPixelData(GL_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getR32FPixelData(0, GL_FLOAT, texel2[0]),
getRGBA32FPixelData(GL_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getR32FPixelData(0, GL_FLOAT, texel3[0]),
getRGBA32FPixelData(GL_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getR32FPixelData(0, GL_FLOAT, texel4[0]), PIXEL_COMPARE_CHANNEL_R);
/* GL_RGBA32F => GL_RG32F */
addEntryToConversionDatabase(getRGBA32FPixelData(GL_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRG32FPixelData(0, GL_FLOAT, texel1[0], texel1[1]),
getRGBA32FPixelData(GL_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRG32FPixelData(0, GL_FLOAT, texel2[0], texel2[1]),
getRGBA32FPixelData(GL_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRG32FPixelData(0, GL_FLOAT, texel3[0], texel3[1]),
getRGBA32FPixelData(GL_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRG32FPixelData(0, GL_FLOAT, texel4[0], texel4[1]), PIXEL_COMPARE_CHANNEL_RG);
/* GL_RGBA32F => GL_RGB32F */
addEntryToConversionDatabase(getRGBA32FPixelData(GL_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGB32FPixelData(0, GL_FLOAT, texel1[0], texel1[1], texel1[2]),
getRGBA32FPixelData(GL_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGB32FPixelData(0, GL_FLOAT, texel2[0], texel2[1], texel2[2]),
getRGBA32FPixelData(GL_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGB32FPixelData(0, GL_FLOAT, texel3[0], texel3[1], texel3[2]),
getRGBA32FPixelData(GL_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGB32FPixelData(0, GL_FLOAT, texel4[0], texel4[1], texel4[2]),
PIXEL_COMPARE_CHANNEL_RGB);
/* GL_RGBA32F => GL_RGBA32F */
addEntryToConversionDatabase(getRGBA32FPixelData(GL_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA32FPixelData(GL_FLOAT, texel1[0], texel1[1], texel1[2], texel1[3]),
getRGBA32FPixelData(GL_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA32FPixelData(GL_FLOAT, texel2[0], texel2[1], texel2[2], texel2[3]),
getRGBA32FPixelData(GL_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA32FPixelData(GL_FLOAT, texel3[0], texel3[1], texel3[2], texel3[3]),
getRGBA32FPixelData(GL_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
getRGBA32FPixelData(GL_FLOAT, texel4[0], texel4[1], texel4[2], texel4[3]),
PIXEL_COMPARE_CHANNEL_RGBA);
}
}
class TestBase : public deqp::TestCase
{
public:
TestBase(deqp::Context& context, GLenum source_attachment_type, GLenum destination_attachment_type);
virtual ~TestBase();
protected:
bool getFormatAndTypeCompatibleWithInternalformat(GLenum internalformat, int index, GLenum* out_format,
GLenum* out_type) const;
bool getFormatForInternalformat(GLenum internalformat, GLenum* out_format) const;
GLenum getFBOEffectiveInternalFormatAtIndex(unsigned int index) const;
GLenum getCopyTexImage2DInternalFormatAtIndex(unsigned int index) const;
const char* getTargetName(GLenum target) const;
GLenum getGeneralTargetForDetailedTarget(GLenum target);
GLuint generateGLObject(GLenum object_type);
bool configureGLObject(int is_source_gl_object, GLenum object_target, GLint object_id, GLenum internal_format,
GLenum format, GLenum type, void* data);
void destroyGLObject(GLenum target, GLuint object_id);
bool isValidRBOInternalFormat(GLenum internalformat) const;
bool isColorRenderableInternalFormat(GLenum internalformat) const;
bool isDepthRenderableInternalFormat(GLenum internalformat) const;
bool isDepthStencilRenderableInternalFormat(GLenum internalformat) const;
bool isFBOEffectiveInternalFormatCompatibleWithDestinationInternalFormat(GLenum src_internalformat,
GLenum dst_internalformat) const;
const char* getInternalformatString(GLenum internalformat);
protected:
GLenum m_source_attachment_type;
GLenum m_destination_attachment_type;
};
TestBase::TestBase(deqp::Context& context, GLenum source_attachment_type, GLenum destination_attachment_type)
: deqp::TestCase(context, "", "")
, m_source_attachment_type(source_attachment_type)
, m_destination_attachment_type(destination_attachment_type)
{
static std::map<GLenum, std::string> attachment_name_map;
if (attachment_name_map.empty())
{
attachment_name_map[GL_TEXTURE_2D] = "texture2d";
attachment_name_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_X] = "cubemap_negx";
attachment_name_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_Y] = "cubemap_negy";
attachment_name_map[GL_TEXTURE_CUBE_MAP_NEGATIVE_Z] = "cubemap_negz";
attachment_name_map[GL_TEXTURE_CUBE_MAP_POSITIVE_X] = "cubemap_posx";
attachment_name_map[GL_TEXTURE_CUBE_MAP_POSITIVE_Y] = "cubemap_posy";
attachment_name_map[GL_TEXTURE_CUBE_MAP_POSITIVE_Z] = "cubemap_posz";
attachment_name_map[GL_TEXTURE_2D_ARRAY] = "texture_array";
attachment_name_map[GL_TEXTURE_3D] = "texture3d";
attachment_name_map[GL_RENDERBUFFER] = "renderbuffer";
}
m_name = attachment_name_map[m_source_attachment_type] + "_" + attachment_name_map[m_destination_attachment_type];
}
TestBase::~TestBase()
{
}
/** For every valid GLES internalformat, gl.readPixels() can often work with a variety of different
* format+type combinations. This function allows to enumerate valid pairs for user-specified
* internal formats.
*
* Enumeration should start from 0 and continue until the function starts reporting failure.
*
* @param internalformat GLES internal format to consider.
* @param index Index of format+type pair to look up.
* @param out_format Deref will be used to store compatible GLES format. Cannot be NULL.
* @param out_type Deref will be used to store compatible GLES type. Cannot be NULL.
*
* @return true if successful and relevant format & type information has been stored under
* dereferences of corresponding arguments, false otherwise.
**/
bool TestBase::getFormatAndTypeCompatibleWithInternalformat(GLenum internalformat, int index, GLenum* out_format,
GLenum* out_type) const
{
const glu::ContextInfo& contextInfo = m_context.getContextInfo();
bool is_ext_texture_storage_supported = contextInfo.isExtensionSupported("GL_EXT_texture_storage");
bool is_ext_texture_type_2_10_10_10_rev_supported =
contextInfo.isExtensionSupported("GL_EXT_texture_type_2_10_10_10_REV");
DE_ASSERT(out_format != NULL);
DE_ASSERT(out_type != NULL);
if (!getFormatForInternalformat(internalformat, out_format))
TCU_FAIL("No format known for requested internalformat");
switch (internalformat)
{
case GL_ALPHA:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_LUMINANCE:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_R8:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_LUMINANCE_ALPHA:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RG8:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_SRGB:
case GL_RGB:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else if (index == 1)
*out_type = GL_UNSIGNED_SHORT_5_6_5;
else if (index == 2)
*out_type = GL_UNSIGNED_INT_2_10_10_10_REV;
else if (index == 3)
*out_type = GL_HALF_FLOAT;
else if (index == 4)
*out_type = GL_FLOAT;
else
return false;
break;
}
case GL_SRGB8:
case GL_RGB8:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RGB565:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT_5_6_5;
else if (index == 1)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RGBA:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else if (index == 1)
*out_type = GL_UNSIGNED_SHORT_4_4_4_4;
else if (index == 2)
*out_type = GL_UNSIGNED_SHORT_5_5_5_1;
else if (index == 3)
*out_type = GL_HALF_FLOAT;
else if (index == 4)
*out_type = GL_FLOAT;
else
return false;
break;
}
case GL_RGBA4:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT_4_4_4_4;
else if (index == 1)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RGB5_A1:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT_5_5_5_1;
else if (index == 1)
*out_type = GL_UNSIGNED_BYTE;
else if (index == 2)
*out_type = GL_UNSIGNED_INT_2_10_10_10_REV;
else
return false;
break;
}
case GL_RGBA8:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RGB10_A2:
{
if (index == 0)
*out_type = GL_UNSIGNED_INT_2_10_10_10_REV;
else
return false;
break;
}
case GL_RGB10_A2UI:
{
if (index == 0)
{
*out_type = GL_UNSIGNED_INT_2_10_10_10_REV;
} /* if (index == 0) */
else
{
return false;
}
break;
}
case GL_SRGB8_ALPHA8:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_R8I:
{
if (index == 0)
*out_type = GL_BYTE;
else
return false;
break;
}
case GL_R8UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_R16I:
{
if (index == 0)
*out_type = GL_SHORT;
else
return false;
break;
}
case GL_R16UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT;
else
return false;
break;
}
case GL_R32I:
{
if (index == 0)
*out_type = GL_INT;
else
return false;
break;
}
case GL_R32UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_INT;
else
return false;
break;
}
case GL_RG8I:
{
if (index == 0)
*out_type = GL_BYTE;
else
return false;
break;
}
case GL_RG8UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RG16I:
{
if (index == 0)
*out_type = GL_SHORT;
else
return false;
break;
}
case GL_RG16UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT;
else
return false;
break;
}
case GL_RG32I:
{
if (index == 0)
*out_type = GL_INT;
else
return false;
break;
}
case GL_RG32UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_INT;
else
return false;
break;
}
case GL_RGB8I:
{
if (index == 0)
*out_type = GL_BYTE;
else
return false;
break;
}
case GL_RGB8UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RGB16I:
{
if (index == 0)
*out_type = GL_SHORT;
else
return false;
break;
}
case GL_RGB16UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT;
else
return false;
break;
}
case GL_RGB32I:
{
if (index == 0)
*out_type = GL_INT;
else
return false;
break;
}
case GL_RGB32UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_INT;
else
return false;
break;
}
case GL_RGBA8I:
{
if (index == 0)
*out_type = GL_BYTE;
else
return false;
break;
}
case GL_RGBA8UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_BYTE;
else
return false;
break;
}
case GL_RGBA16I:
{
if (index == 0)
*out_type = GL_SHORT;
else
return false;
break;
}
case GL_RGBA16UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_SHORT;
else
return false;
break;
}
case GL_RGBA32I:
{
if (index == 0)
*out_type = GL_INT;
else
return false;
break;
}
case GL_RGBA32UI:
{
if (index == 0)
*out_type = GL_UNSIGNED_INT;
else
return false;
break;
}
case GL_R16F:
{
if (index == 0)
*out_type = GL_HALF_FLOAT;
else
return false;
break;
}
case GL_RG16F:
{
if (index == 0)
*out_type = GL_HALF_FLOAT;
else
return false;
break;
}
case GL_R32F:
{
if (index == 0)
*out_type = GL_FLOAT;
else
return false;
break;
}
case GL_RG32F:
{
if (index == 0)
*out_type = GL_FLOAT;
else
return false;
break;
}
case GL_RGB16F:
{
if (index == 0)
*out_type = GL_HALF_FLOAT;
else
return false;
break;
}
case GL_RGBA16F:
{
if (index == 0)
*out_type = GL_HALF_FLOAT;
else
return false;
break;
}
case GL_RGB32F:
{
if (index == 0)
*out_type = GL_FLOAT;
else
return false;
break;
}
case GL_RGBA32F:
{
if (index == 0)
*out_type = GL_FLOAT;
else
return false;
break;
}
case GL_RGB10_EXT:
{
if (index == 0)
{
if (is_ext_texture_type_2_10_10_10_rev_supported && is_ext_texture_storage_supported)
{
*out_type = GL_UNSIGNED_INT_2_10_10_10_REV;
} /* if (is_ext_texture_type_2_10_10_10_rev_supported) */
else
{
return false;
}
} /* if (index == 0) */
else
{
return false;
}
break;
}
case GL_ALPHA8_EXT:
{
// TODO: No extension available at the time of writing.
return false;
}
case GL_LUMINANCE8_EXT:
{
// TODO: No extension available at the time of writing.
return false;
}
case GL_LUMINANCE8_ALPHA8_EXT:
{
// TODO: No extension available at the time of writing.
return false;
}
default:
{
TCU_FAIL("Unsupported internalformat");
}
} // switch (internalformat)
return true;
}
/** Retrieves GLES format compatible for user-specified GLES internal format.
*
* @param internalformat GLES internalformat to consider.
* @param out_format Deref will be used to store the result. Cannot be NULL.
*
* @return true if successful, false otherwise.
**/
bool TestBase::getFormatForInternalformat(GLenum internalformat, GLenum* out_format) const
{
DE_ASSERT(out_format != NULL);
// Find out the format for user-provided internalformat
switch (internalformat)
{
case GL_ALPHA:
*out_format = GL_ALPHA;
break;
case GL_LUMINANCE_ALPHA:
*out_format = GL_LUMINANCE_ALPHA;
break;
case GL_LUMINANCE:
case GL_LUMINANCE8_OES:
*out_format = GL_LUMINANCE;
break;
case GL_R8:
case GL_R8_SNORM:
case GL_R16F:
case GL_R32F:
*out_format = GL_RED;
break;
case GL_R8UI:
case GL_R8I:
case GL_R16UI:
case GL_R16I:
case GL_R32UI:
case GL_R32I:
*out_format = GL_RED_INTEGER;
break;
case GL_RG8:
case GL_RG8_SNORM:
case GL_RG16F:
case GL_RG32F:
*out_format = GL_RG;
break;
case GL_RG8UI:
case GL_RG8I:
case GL_RG16UI:
case GL_RG16I:
case GL_RG32UI:
case GL_RG32I:
*out_format = GL_RG_INTEGER;
break;
case GL_RGB:
case GL_RGB8:
case GL_SRGB8:
case GL_RGB565:
case GL_RGB8_SNORM:
case GL_R11F_G11F_B10F:
case GL_RGB9_E5:
case GL_RGB16F:
case GL_RGB32F:
*out_format = GL_RGB;
break;
case GL_RGB8UI:
case GL_RGB8I:
case GL_RGB16UI:
case GL_RGB16I:
case GL_RGB32UI:
case GL_RGB32I:
*out_format = GL_RGB_INTEGER;
break;
case GL_RGBA:
case GL_RGBA8:
case GL_SRGB8_ALPHA8:
case GL_RGBA8_SNORM:
case GL_RGB5_A1:
case GL_RGBA4:
case GL_RGB10_A2:
case GL_RGBA16F:
case GL_RGBA32F:
*out_format = GL_RGBA;
break;
case GL_RGBA8UI:
case GL_RGBA8I:
case GL_RGB10_A2UI:
case GL_RGBA16UI:
case GL_RGBA16I:
case GL_RGBA32I:
case GL_RGBA32UI:
*out_format = GL_RGBA_INTEGER;
break;
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32F:
*out_format = GL_DEPTH_COMPONENT;
break;
case GL_DEPTH24_STENCIL8:
case GL_DEPTH32F_STENCIL8:
*out_format = GL_DEPTH_STENCIL;
break;
default:
TCU_FAIL("Internalformat not recognized");
return false;
} // switch (internalformat)
return true;
}
/** Retrieves FBO effective internal format at user-specified index.
*
* Pays extra care not to reach outside of fbo_effective_internal_format_ordering array.
*
* @param index Index to look up the internal format at.
*
* @return Requested information or GL_NONE if failed or 0xFFFFFFFF if index is
* outside allowed range.
**/
GLenum TestBase::getFBOEffectiveInternalFormatAtIndex(unsigned int index) const
{
const unsigned int n_effective_internalformats = DE_LENGTH_OF_ARRAY(fboEffectiveInternalFormatOrdering);
DE_ASSERT(index < n_effective_internalformats);
if (index < n_effective_internalformats)
return fboEffectiveInternalFormatOrdering[index];
// Return glitch
m_testCtx.getLog() << tcu::TestLog::Message
<< "GetFBOEffectiveInternalFormatAtIndex - Invalid index requested: " << index
<< tcu::TestLog::EndMessage;
return static_cast<GLenum>(0xFFFFFFFF);
}
/** Retrieves glCopyTexImage2D() internal format at user-specified index.
*
* Pays extra care not to reach outside of copy_tex_image_2d_internal_format_orderingarray.
*
* @param index Index to look up the internal format at.
*
* @return Requested information or GL_NONE if failed or 0xFFFFFFFF if index is outside
* allowed range.
**/
GLenum TestBase::getCopyTexImage2DInternalFormatAtIndex(unsigned int index) const
{
const unsigned int n_internalformats = DE_LENGTH_OF_ARRAY(copyTexImage2DInternalFormatOrdering);
DE_ASSERT(index < n_internalformats);
if (index < n_internalformats)
return copyTexImage2DInternalFormatOrdering[index];
// Return glitch
m_testCtx.getLog() << tcu::TestLog::Message
<< "GetCopyTexImage2DInternalFormatAtIndex - Invalid index requested: " << index
<< tcu::TestLog::EndMessage;
return static_cast<GLenum>(0xFFFFFFFF);
}
/** Retrieves a string representing name of target passed by argument.
*
* @param target GLES target to retrieve a string for.
*
* @return A relevant string or "?" (without double quotation marks)
* if type is unrecognized.
**/
const char* TestBase::getTargetName(GLenum target) const
{
const char* result = "?";
switch (target)
{
case GL_RENDERBUFFER:
result = "GL_RENDERBUFFER";
break;
case GL_TEXTURE_2D:
result = "GL_TEXTURE_2D";
break;
case GL_TEXTURE_2D_ARRAY:
result = "GL_TEXTURE_2D_ARRAY";
break;
case GL_TEXTURE_3D:
result = "GL_TEXTURE_3D";
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
result = "GL_TEXTURE_CUBE_MAP_NEGATIVE_X";
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
result = "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y";
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
result = "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z";
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
result = "GL_TEXTURE_CUBE_MAP_POSITIVE_X";
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
result = "GL_TEXTURE_CUBE_MAP_POSITIVE_Y";
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
result = "GL_TEXTURE_CUBE_MAP_POSITIVE_Z";
break;
}
return result;
}
/** Returns a general texture target for cube-map texture targets or
* user-specified target otherwise.
*
* @param target GLES target to consider. Allowed values:
* 1) GL_RENDERBUFFER,
* 2) GL_TEXTURE_2D,
* 3) GL_TEXTURE_2D_ARRAY,
* 4) GL_TEXTURE_3D,
* 5) GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
* 6) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
* 7) GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
* 8) GL_TEXTURE_CUBE_MAP_POSITIVE_X,
* 9) GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
* 10) GL_TEXTURE_CUBE_MAP_POSITIVE_Z.
*
* @return General texture target or used-specified target
* if successful, GL_NONE otherwise.
*/
GLenum TestBase::getGeneralTargetForDetailedTarget(GLenum target)
{
GLenum result = GL_NONE;
switch (target)
{
case GL_RENDERBUFFER:
case GL_TEXTURE_2D:
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
{
result = target;
break;
} // renderbuffer & 2D/3D texture targets
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
{
result = GL_TEXTURE_CUBE_MAP;
break;
} // cube-map texture targets
default:
{
TCU_FAIL("Unrecognized target");
}
}
return result;
}
/** Generates a GL object of an user-requested type.
*
* NOTE: It is expected no error is reported by OpenGL ES prior to
* the call.
*
* @param object_type Type of a GL object to create. Allowed values:
* 1) GL_RENDERBUFFER,
* 2) GL_TEXTURE_2D,
* 3) GL_TEXTURE_2D_ARRAY,
* 4) GL_TEXTURE_3D,
* 5) GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
* 6) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
* 7) GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
* 8) GL_TEXTURE_CUBE_MAP_POSITIVE_X,
* 9) GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
* 10) GL_TEXTURE_CUBE_MAP_POSITIVE_Z.
*
* @return GLES ID (different than zero) of the created object if
* successful, zero otherwise.
*/
GLuint TestBase::generateGLObject(GLenum object_type)
{
const Functions& gl = m_context.getRenderContext().getFunctions();
GLenum error_code = GL_NO_ERROR;
GLuint result = 0;
switch (object_type)
{
case GL_RENDERBUFFER:
{
gl.genRenderbuffers(1, &result);
break;
}
case GL_TEXTURE_2D:
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
{
gl.genTextures(1, &result);
break;
}
default:
TCU_FAIL("Unsupported source attachment type");
}
// check if all is good with our new object
error_code = gl.getError();
if (error_code != GL_NO_ERROR)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "Could not generate a renderbuffer OR texture object. GL reported error: [" << error_code
<< "]" << tcu::TestLog::EndMessage;
return 0;
}
return result;
}
/** Sets up a GL object and binds it to either GL_DRAW_FRAMEBUFFER
* (if @param is_source_gl_object is 0) or GL_READ_FRAMEBUFFER zeroth
* color attachment.
*
* NOTE: The function assumes the object at @param object_id of @param
* object_target type has already been generated!
*
* @param is_source_gl_object 1 if the object should be bound to
* GL_DRAW_FRAMEBUFFER target once configured,
* 0 to bound the object to GL_READ_FRAMEBUFFER
* target instead.
* @param object_target Type of the object to configure. Allowed values:
* 1) GL_RENDERBUFFER,
* 2) GL_TEXTURE_2D,
* 3) GL_TEXTURE_2D_ARRAY,
* 4) GL_TEXTURE_3D,
* 5) GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
* 6) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
* 7) GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
* 8) GL_TEXTURE_CUBE_MAP_POSITIVE_X,
* 9) GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
* 10) GL_TEXTURE_CUBE_MAP_POSITIVE_Z.
* @param object_id GLES ID of the object to configure.
* @param internal_format Internal-format of the data under @param data.
* @param format Format of the data under @param data.
* @param type Type the data @param data is represented with.
* @param data Buffer with the data to fill the object with.
* Cannot be NULL.
*
* @return true if successful, false otherwise.,
**/
bool TestBase::configureGLObject(int is_source_gl_object, GLenum object_target, GLint object_id, GLenum internal_format,
GLenum format, GLenum type, void* data)
{
const Functions& gl = m_context.getRenderContext().getFunctions();
GLenum fbo_target = (is_source_gl_object == 0) ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER;
bool result = true;
// Special case for GL_HALF_FLOAT -> input data is in GL_FLOAT
if (type == GL_HALF_FLOAT)
type = GL_FLOAT;
switch (object_target)
{
case GL_RENDERBUFFER:
{
GLint current_draw_fbo_id = 0;
GLint current_read_fbo_id = 0;
GLuint temporary_draw_fbo_id = 0;
GLuint temporary_read_fbo_id = 0;
GLuint temporary_to_id = 0;
// Retrieve current draw/read fbo bindings
gl.getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_draw_fbo_id);
gl.getIntegerv(GL_READ_FRAMEBUFFER_BINDING, &current_read_fbo_id);
// Set up the RBO */
gl.bindRenderbuffer(GL_RENDERBUFFER, object_id);
gl.renderbufferStorage(GL_RENDERBUFFER, internal_format, TEXTURE_WIDTH, TEXTURE_HEIGHT);
// Generate a temporary 2D texture object and copy the data into it
gl.genTextures(1, &temporary_to_id);
gl.bindTexture(GL_TEXTURE_2D, temporary_to_id);
gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, internal_format, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0 /* border */,
format, type, data);
// Set up a temporary read FBO with the texture object attached to zeroth color attachment..
gl.genFramebuffers(1, &temporary_read_fbo_id);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, temporary_read_fbo_id);
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temporary_to_id,
0 /* level */);
// and another one we'll bind to draw framebuffer target with the renderbuffer object attached
gl.genFramebuffers(1, &temporary_draw_fbo_id);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, temporary_draw_fbo_id);
gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, object_id);
// Blit the texture contents into the renderbuffer.
gl.blitFramebuffer(0 /* srcX0 */, 0 /* srcY0 */, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0 /* dstX0 */, 0 /* dstY0 */,
TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Restore pre-call configuration
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo_id);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo_id);
// Get rid of the temporary objects
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.deleteTextures(1, &temporary_to_id);
gl.deleteFramebuffers(1, &temporary_draw_fbo_id);
gl.deleteFramebuffers(1, &temporary_read_fbo_id);
// Update the pre-call framebuffer's attachment configuration
gl.framebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, object_id);
break;
}
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
{
const GLenum cm_targets[] = { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z };
GLenum general_target = getGeneralTargetForDetailedTarget(object_target);
unsigned int n_cm_target = 0;
// Set up base mipmap for our source texture.
gl.bindTexture(general_target, object_id);
// Set up *all* faces of a cube-map (as per Bugzilla #9689 & #9807),
// so that the CM texture is cube complete.
for (n_cm_target = 0; n_cm_target < sizeof(cm_targets) / sizeof(cm_targets[0]); ++n_cm_target)
{
gl.texImage2D(cm_targets[n_cm_target], 0 /* level */, internal_format, TEXTURE_WIDTH, TEXTURE_HEIGHT,
0 /* border */, format, type, data);
}
gl.texParameterf(general_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameterf(general_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameterf(general_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameterf(general_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Set up the FBO attachment
if (is_source_gl_object)
gl.framebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0, object_target, object_id, 0);
gl.bindTexture(general_target, 0);
break;
}
case GL_TEXTURE_2D:
{
// Set up base mipmap for our source texture.
gl.bindTexture(object_target, object_id);
gl.texImage2D(object_target, 0 /* level */, internal_format, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0 /* border */,
format, type, data);
gl.texParameterf(object_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameterf(object_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameterf(object_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameterf(object_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Set up the FBO attachment
if (is_source_gl_object)
gl.framebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0, object_target, object_id, 0);
gl.bindTexture(object_target, 0);
break;
}
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
{
// Set up base mipmap for our source texture.
gl.bindTexture(object_target, object_id);
gl.texImage3D(object_target, 0 /* level */, internal_format, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH,
0 /* border */, format, type, NULL);
gl.texSubImage3D(object_target, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
TEXTURE_HEIGHT, 1 /* depth */, format, type, data);
gl.texParameterf(object_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameterf(object_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameterf(object_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameterf(object_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.texParameterf(object_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
DE_ASSERT(is_source_gl_object);
// Set up the FBO attachment. Make sure there is an actual difference from gl.framebufferTexture2D()
// and use the second layer of the texture.
gl.framebufferTextureLayer(fbo_target, GL_COLOR_ATTACHMENT0, object_id, 0 /* level */, 1 /* layer */);
gl.bindTexture(object_target, 0);
break;
}
default:
{
// ASSERTION FAILURE: unsupported source attachment type
DE_ASSERT(0);
result = false;
}
} /* switch (source_attachment_type) */
if (result)
{
GLenum error_code = gl.getError();
if (error_code != GL_NO_ERROR)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Could not set up a GL object ["
<< (is_source_gl_object ? "source" : "destination") << "] of format ["
<< getInternalformatString(internal_format) << "] to be used as "
<< getTargetName(object_target) << " attachment for the test. GL reported error ["
<< error_code << "]";
return false;
}
}
return result;
}
/** Releases a GL object. If @param target represents a texture,
* the object is unbound from the target prior to a gl.deleteTextures()
* call.
*
* @param target Type of the object to release. Allowed values:
* 1) GL_RENDERBUFFER,
* 2) GL_TEXTURE_2D,
* 3) GL_TEXTURE_2D_ARRAY,
* 4) GL_TEXTURE_3D,
* 5) GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
* 6) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
* 7) GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
* 8) GL_TEXTURE_CUBE_MAP_POSITIVE_X,
* 9) GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
* 10) GL_TEXTURE_CUBE_MAP_POSITIVE_Z.
*
* @param object_id GLES ID of the object to release.
*/
void TestBase::destroyGLObject(GLenum target, GLuint object_id)
{
const Functions& gl = m_context.getRenderContext().getFunctions();
switch (target)
{
case GL_RENDERBUFFER:
{
gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
gl.deleteRenderbuffers(1, &object_id);
break;
}
case GL_TEXTURE_2D:
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
{
GLenum general_attachment_type = getGeneralTargetForDetailedTarget(target);
gl.bindTexture(general_attachment_type, 0);
gl.deleteTextures(1, &object_id);
break;
}
default:
{
TCU_FAIL("Unsupported attachment type.");
}
}
}
/** Tells whether @param internalformat can be used for
* a gl.renderbufferStorage*() call.
*
* @param internalformat Internalformat to consider.
*
* @return true if the internal format can be used for the call,
* false otherwise.
**/
bool TestBase::isValidRBOInternalFormat(GLenum internalformat) const
{
// Internal format can be used for gl.renderbufferStorage()
// call if it's either color-, depth- or stencil-renderable.
return isColorRenderableInternalFormat(internalformat) || isDepthRenderableInternalFormat(internalformat) ||
isDepthStencilRenderableInternalFormat(internalformat);
}
/** Tells whether internal format @param internalformat is color-renderable.
*
* @param internalformat GLES internal format to consider.
*
* @return true if @param internalformat is color-renderable, false otherwise
**/
bool TestBase::isColorRenderableInternalFormat(GLenum internalformat) const
{
const glu::ContextInfo& contextInfo = m_context.getContextInfo();
bool supports_fp_textures = contextInfo.isExtensionSupported("GL_EXT_color_buffer_float");
bool supports_half_fp_textures = contextInfo.isExtensionSupported("GL_EXT_color_buffer_half_float");
// Floating-point textures are only supported if
// implementation supports GL_EXT_color_buffer_float extension
if (!supports_fp_textures && (internalformat == GL_R32F || internalformat == GL_RG32F ||
internalformat == GL_RGB32F || internalformat == GL_RGBA32F))
{
return false;
}
// Half floating-point textures are only supported if
// implementation supports GL_EXT_color_buffer_half_float extension
if (!supports_half_fp_textures && (internalformat == GL_R16F || internalformat == GL_RG16F ||
internalformat == GL_RGB16F || internalformat == GL_RGBA16F))
{
return false;
}
switch (internalformat)
{
case GL_RGB:
case GL_RGBA:
case GL_R8:
case GL_RG8:
case GL_RGB8:
case GL_RGB565:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGB10_A2UI:
case GL_SRGB8_ALPHA8:
case GL_R8I:
case GL_R8UI:
case GL_R16I:
case GL_R16UI:
case GL_R32I:
case GL_R32UI:
case GL_RG8I:
case GL_RG8UI:
case GL_RG16I:
case GL_RG16UI:
case GL_RG32I:
case GL_RG32UI:
case GL_RGBA8I:
case GL_RGBA8UI:
case GL_RGBA16I:
case GL_RGBA16UI:
case GL_RGBA32I:
case GL_RGBA32UI:
// GLES3.0 color-renderable internalformats
return true;
case GL_R16F:
case GL_R32F:
case GL_RG16F:
case GL_RG32F:
case GL_RGB16F:
// GL_RGB32F not supported
case GL_RGBA16F:
case GL_RGBA32F:
// Since we passed the above checks, we can assume
// the internalformats are color-renderable
return true;
default:
return false;
}
return false;
}
/** Tells whether internal format @param internalformat is depth-renderable.
*
* @param internalformat GLES internal format to consider.
*
* @return true if @param internalformat is depth-renderable, false otherwise
**/
bool TestBase::isDepthRenderableInternalFormat(GLenum internalformat) const
{
switch (internalformat)
{
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32F:
return true;
}
return false;
}
/** Tells whether internal format @param internalformat is depth+stencil-renderable.
*
* @param internalformat GLES internal format to consider.
*
* @return true if @param internalformat is depth+stencil-renderable, false otherwise
**/
bool TestBase::isDepthStencilRenderableInternalFormat(GLenum internalformat) const
{
switch (internalformat)
{
case GL_DEPTH24_STENCIL8:
case GL_DEPTH32F_STENCIL8:
return true;
}
return false;
}
/** Tells whether OpenGL ES 3.0 implementations should accept copying texture image data from
* a read buffer using @param src_internalformat internalformat-based storage to a texture object
* using an internal format @param dst_internalformat.
*
* @param src_internalformat Internal format to be used for source object's data storage.
* @param dst_internalformat Internal format to be used for destination texture object's data storage.
*
* @return true if the operation is expected to execute successfully, false otherwise.
*/
bool TestBase::isFBOEffectiveInternalFormatCompatibleWithDestinationInternalFormat(GLenum src_internalformat,
GLenum dst_internalformat) const
{
const unsigned int n_copyteximage_internalformats = DE_LENGTH_OF_ARRAY(copyTexImage2DInternalFormatOrdering);
unsigned int n_dst_internalformat = 0;
const unsigned int n_effective_internalformats = DE_LENGTH_OF_ARRAY(fboEffectiveInternalFormatOrdering);
unsigned int n_src_internalformat = 0;
bool result = false;
// Find out which index does the source internalformat use
while (n_src_internalformat < n_effective_internalformats)
{
GLenum internalformat_at_n = getFBOEffectiveInternalFormatAtIndex(n_src_internalformat);
if (internalformat_at_n == src_internalformat)
break;
else
++n_src_internalformat;
}
DE_ASSERT(n_src_internalformat != n_effective_internalformats);
if (n_src_internalformat == n_effective_internalformats)
return false;
// Find out which index does the target internalformat use
while (n_dst_internalformat < n_copyteximage_internalformats)
{
GLenum internalformat_at_n = getCopyTexImage2DInternalFormatAtIndex(n_dst_internalformat);
if (internalformat_at_n == dst_internalformat)
break;
else
++n_dst_internalformat;
}
DE_ASSERT(n_dst_internalformat != n_copyteximage_internalformats);
if (n_dst_internalformat == n_copyteximage_internalformats)
return false;
// Find out if the conversion is allowed
unsigned int conversion_array_index = n_copyteximage_internalformats * n_src_internalformat + n_dst_internalformat;
DE_ASSERT(conversion_array_index < (sizeof(conversionArray) / sizeof(GLenum)));
if (conversion_array_index < (sizeof(conversionArray) / sizeof(GLenum)))
result = (conversionArray[conversion_array_index] != GL_NONE);
return result;
}
/** Retrieves a string representing name of internal format passed by argument.
*
* @param internalformat GLES internal format to retrieve a string for.
*
* @return A relevant string or "?" (without double quotation marks)
* if type is unrecognized.
**/
const char* TestBase::getInternalformatString(GLenum internalformat)
{
switch (internalformat)
{
case GL_ALPHA:
return "GL_ALPHA";
case GL_ALPHA8_OES:
return "GL_ALPHA8";
case GL_LUMINANCE:
return "GL_LUMINANCE";
case GL_LUMINANCE8_OES:
return "GL_LUMINANCE8";
case GL_LUMINANCE8_ALPHA8_OES:
return "GL_LUMINANCE8_ALPHA8";
case GL_LUMINANCE_ALPHA:
return "GL_LUMINANCE_ALPHA";
case GL_R11F_G11F_B10F:
return "GL_R11F_G11F_B10F";
case GL_R16F:
return "GL_R16F";
case GL_R16I:
return "GL_R16I";
case GL_R16UI:
return "GL_R16UI";
case GL_R32F:
return "GL_R32F";
case GL_R32I:
return "GL_R32I";
case GL_R32UI:
return "GL_R32UI";
case GL_R8:
return "GL_R8";
case GL_R8I:
return "GL_R8I";
case GL_R8UI:
return "GL_R8UI";
case GL_R8_SNORM:
return "GL_R8_SNORM";
case GL_RG16F:
return "GL_RG16F";
case GL_RG16I:
return "GL_RG16I";
case GL_RG16UI:
return "GL_RG16UI";
case GL_RG32F:
return "GL_RG32F";
case GL_RG32I:
return "GL_RG32I";
case GL_RG32UI:
return "GL_RG32UI";
case GL_RG8:
return "GL_RG8";
case GL_RG8I:
return "GL_RG8I";
case GL_RG8UI:
return "GL_RG8UI";
case GL_RG8_SNORM:
return "GL_RG8_SNORM";
case GL_RGB:
return "GL_RGB";
case GL_RGB10_A2:
return "GL_RGB10_A2";
case GL_RGB10_A2UI:
return "GL_RGB10_A2UI";
case GL_RGB16F:
return "GL_RGB16F";
case GL_RGB16I:
return "GL_RGB16I";
case GL_RGB16UI:
return "GL_RGB16UI";
case GL_RGB32F:
return "GL_RGB32F";
case GL_RGB32I:
return "GL_RGB32I";
case GL_RGB32UI:
return "GL_RGB32UI";
case GL_RGB5_A1:
return "GL_RGB5_A1";
case GL_RGB8:
return "GL_RGB8";
case GL_RGB8I:
return "GL_RGB8I";
case GL_RGB8UI:
return "GL_RGB8UI";
case GL_RGB8_SNORM:
return "GL_RGB8_SNORM";
case GL_RGB9_E5:
return "GL_RGB9_E5";
case GL_RGBA:
return "GL_RGBA";
case GL_RGBA16I:
return "GL_RGBA16I";
case GL_RGBA16UI:
return "GL_RGBA16UI";
case GL_RGBA4:
return "GL_RGBA4";
case GL_RGBA32I:
return "GL_RGBA32I";
case GL_RGBA32UI:
return "GL_RGBA32UI";
case GL_RGBA8I:
return "GL_RGBA8I";
case GL_RGBA8UI:
return "GL_RGBA8UI";
case GL_RGB565:
return "GL_RGB565";
case GL_RGBA16F:
return "GL_RGBA16F";
case GL_RGBA32F:
return "GL_RGBA32F";
case GL_RGBA8:
return "GL_RGBA8";
case GL_RGBA8_SNORM:
return "GL_RGBA8_SNORM";
case GL_SRGB8:
return "GL_SRGB8";
case GL_SRGB8_ALPHA8:
return "GL_SRGB8_ALPHA8";
}
return "GL_NONE";
}
/* SPECIFICATION:
*
* This conformance test verifies that glCopyTexImage2D() implementation accepts
* internalformats that are compatible with effective internalformat of current
* read buffer.
*
* The test starts from creating two framebuffer objects, that it accordingly binds
* to GL_DRAW_FRAMEBUFFER and GL_READ_FRAMEBUFFER targets. It then enters two-level loop:
*
* a) First level determines source attachment type: this could either be a 2D texture/cube-map
* face mip-map, a specific mip-map of a slice coming from a 2D texture array OR a 3D texture,
* or finally a render-buffer. All of these can be bound to an attachment point that is
* later pointed to by read buffer configuration.
* b) Second level configures attachment type of destination. Since glCopyTexImage2D()
* specification limits accepted targets, only 2D texture or cube-map face targets are
* accepted.
*
* For each viable source/destination configuration, the test then enters another two-level loop:
*
* I) First sub-level determines what internal format should be used for the source attachment.
* All texture formats required from a conformant GLES3.0 implementation are iterated over.
* II) Second sub-level determines internal format that should be passed as a parameter to
* a glCopyTexImage2D() call.
*
* For each internal format pair, the test creates and configures a corresponding GL object and
* attaches it to the read framebuffer. The test also uses a pre-generated texture object ID that
* will be re-configured with each glCopyTexImage2D() call.
*
* Source data is a 2x2 array consisting of up to 4 channels with different values, represented
* in an iteration-specific format and type. For more details, please see implementation of
* ConfigureConversionDatabase() entry-point.
*
* The test then loops over all supported format+type combinations for the internal-format considered
* and feeds them into actual glCopyTexImage2D() call. It is against the specification for the call
* to fail at this point. Should this be the case, the test is considered to fail but will continue
* iterating over all the loops to make sure all problems are reported within a single run.
*
* Once the call is determined to have finished successfully, the test attempts to read the result data.
* This needs to be handled in two ways:
*
* - if internalformat is color-renderable, we can attach the result texture to the read framebuffer object
* and do a glReadPixels() call. For some combinations of internalformat and attachment types the implementations
* are allowed to report unsupported framebuffer configuration, in which case the test will proceed with testing
* remaining source/destination/internalformat combinations and will not consider this an error.
* - if internalformat is not color-renderable, we need to bind the result texture to a texture unit and
* use a program object to determine whether the data made available are valid. THIS CASE IS NOT IMPLEMENTED
* YET!
*
* Once the data are downloaded, they are compared against reference texture data. Should the rendered output
* diverge outside the allowed epsilon, the test will report an error but will continue iterating to make sure
* all source/destination/internalformat combinations are covered.
*/
class RequiredCase : public TestBase
{
public:
RequiredCase(deqp::Context& context, de::SharedPtr<ConversionDatabase> database, GLenum sourceAttachmentTypes,
GLenum destinationAttachmentTypes);
virtual ~RequiredCase();
void deinit(void);
tcu::TestNode::IterateResult iterate(void);
protected:
bool execute(GLenum src_internalformat, GLenum dst_internalformat,
NonRenderableInternalformatSupportObjects* objects_ptr);
bool bindTextureToTargetToSpecificTextureUnit(GLuint to_id, GLenum texture_target, GLenum texture_unit);
bool setUniformValues(GLint source_2D_texture_uniform_location, GLenum source_2D_texture_unit,
GLint source_2DArray_texture_uniform_location, GLenum source_2DArray_texture_unit,
GLint source_3D_texture_uniform_location, GLenum source_3D_texture_unit,
GLint source_Cube_texture_uniform_location, GLenum source_Cube_texture_unit,
GLint destination_2D_texture_uniform_location, GLenum destination_2D_texture_unit,
GLint destination_Cube_texture_uniform_location, GLenum destination_Cube_texture_unit,
GLint channels_to_compare_uniform_location, GLint channels_to_compare,
GLint samplers_to_use_uniform_location, GLint samplers_to_use);
bool copyDataFromBufferObject(GLuint bo_id, std::vector<GLint>& retrieved_data);
bool findEntryInConversionDatabase(unsigned int index, GLenum src_internalformat, GLenum src_type,
GLenum copyteximage2d_internalformat, GLenum* out_result_internalformat,
GLenum* out_dst_type, PixelData* out_src_topleft, PixelData* out_src_topright,
PixelData* out_src_bottomleft, PixelData* out_src_bottomright,
PixelData* out_dst_topleft, PixelData* out_dst_topright,
PixelData* out_dst_bottomleft, PixelData* out_dst_bottomright,
PixelCompareChannel* out_channels_to_compare);
int getIndexOfCopyTexImage2DInternalFormat(GLenum internalformat);
int getIndexOfFramebufferEffectiveInternalFormat(GLenum internalformat);
bool compareExpectedResultsByReadingPixels(PixelData source_tl_pixel_data, PixelData source_tr_pixel_data,
PixelData source_bl_pixel_data, PixelData source_br_pixel_data,
PixelData reference_tl_pixel_data, PixelData reference_tr_pixel_data,
PixelData reference_bl_pixel_data, PixelData reference_br_pixel_data,
GLenum read_type, GLenum result_internalformat);
unsigned int getSizeOfPixel(GLenum format, GLenum type);
bool getPixelDataFromRawData(void* raw_data, GLenum raw_data_format, GLenum raw_data_type, PixelData* out_result);
bool comparePixelData(PixelData downloaded_pixel, PixelData reference_pixel, PixelData source_pixel,
GLenum result_internalformat, bool has_test_failed_already);
bool getNumberOfBitsForInternalFormat(GLenum internalformat, int* out_rgba_bits);
bool getRawDataFromPixelData(std::vector<char>& result, PixelData topleft, PixelData topright, PixelData bottomleft,
PixelData bottomright);
bool getNumberOfBitsForChannelDataType(ChannelDataType channel_data_type, int* out_n_bits);
bool getChannelOrderForInternalformatAndType(GLenum internalformat, GLenum type, ChannelOrder* out_channel_order);
bool generateObjectsToSupportNonColorRenderableInternalformats();
bool prepareSupportForNonRenderableTexture(NonRenderableInternalformatSupportObjects& objects,
DataSamplerType src_texture_sampler_type,
DataSamplerType dst_texture_sampler_type, GLenum source_attachment_type,
GLenum destination_attachment_type);
bool calculateBufferDataSize(DataSamplerType sampler_type, GLuint* buffer_data_size_ptr);
const float* getTexCoordinates(GLenum attachment_type) const;
bool prepareProgramAndShaderObjectsToSupportNonRenderableTexture(GLuint program_object_id,
GLuint fragment_shader_object_id,
GLuint vertex_shader_object_id,
DataSamplerType src_texture_sampler_type,
DataSamplerType dst_texture_sampler_type);
bool setSourceForShaderObjectsUsedForNonRenderableTextureSupport(GLuint fragment_shader_object_id,
GLuint vertex_shader_object_id,
DataSamplerType src_texture_sampler_type,
DataSamplerType dst_texture_sampler_type);
bool compileAndCheckShaderCompilationStatus(GLuint shader_object_id);
bool linkAndCheckProgramLinkStatus(GLuint program_object_id);
bool getUniformLocations(GLuint program_object_id, GLint* source_2D_texture_uniform_location_ptr,
GLint* source_2DArray_texture_uniform_location_ptr,
GLint* source_3D_texture_uniform_location_ptr,
GLint* source_Cube_texture_uniform_location_ptr,
GLint* destination_2D_texture_uniform_location_ptr,
GLint* destination_Cube_texture_uniform_location_ptr,
GLint* channels_to_compare_uniform_location_ptr,
GLint* samplers_to_use_uniform_location_ptr);
void displayPixelComparisonFailureMessage(GLint source_pixel_r, GLint source_pixel_g, GLint source_pixel_b,
GLint source_pixel_a, GLenum source_internalformat, GLenum source_type,
GLint reference_pixel_r, GLint reference_pixel_g, GLint reference_pixel_b,
GLint reference_pixel_a, GLenum reference_internalformat,
GLenum reference_type, GLint result_pixel_r, GLint result_pixel_g,
GLint result_pixel_b, GLint result_pixel_a, GLenum result_internalformat,
GLenum result_type, GLint max_epsilon_r, GLint max_epsilon_g,
GLint max_epsilon_b, GLint max_epsilon_a);
DataSamplerType getDataSamplerTypeForInternalformat(GLenum internalformat);
bool isInternalFormatCompatibleWithFPSampler(GLenum internalformat);
bool isInternalFormatCompatibleWithIntegerSampler(GLenum internalformat);
bool isInternalFormatCompatibleWithUnsignedIntegerSampler(GLenum internalformat);
void destroyObjectsSupportingNonRenderableInternalformats(NonRenderableInternalformatSupportObjects& objects);
void unbindAndDestroyBufferObject(GLuint bo_id);
void destroyTransformFeedbackObject(GLuint transform_feedback_object_id);
void destroyProgramAndShaderObjects(GLuint program_object_id, GLuint fragment_shader_id, GLuint vertex_shader_id);
void unbindColorAttachments();
void restoreBindings(GLenum src_attachment_point, GLenum dst_attachment_point, GLint bound_draw_fbo_id,
GLint bound_read_fbo_id);
private:
GLuint m_dst_object_id;
GLuint m_src_object_id;
de::SharedPtr<ConversionDatabase> m_conversion_database;
// Some of the internalformats considered during the test are not renderable, meaning
// we cannot use glReadPixels() to retrieve their contents.
// Instead, a special program object needs to be used to perform the verification in
// actual shader.
// We create a program object for possible each float/int/uint->float/int/uint combination.
// All objects created during the process are stored in a dedicated
// _non_renderable_internalformat_support_objects instance and released once the test ends.
NonRenderableInternalformatSupportObjects m_f_src_f_dst_internalformat;
NonRenderableInternalformatSupportObjects m_i_src_i_dst_internalformat;
NonRenderableInternalformatSupportObjects m_ui_src_ui_dst_internalformat;
};
RequiredCase::RequiredCase(deqp::Context& context, de::SharedPtr<ConversionDatabase> database,
GLenum sourceAttachmentTypes, GLenum destinationAttachmentTypes)
: TestBase(context, sourceAttachmentTypes, destinationAttachmentTypes)
, m_dst_object_id(0)
, m_src_object_id(0)
, m_conversion_database(database)
{
deMemset(&m_f_src_f_dst_internalformat, 0, sizeof(m_f_src_f_dst_internalformat));
deMemset(&m_i_src_i_dst_internalformat, 0, sizeof(m_i_src_i_dst_internalformat));
deMemset(&m_ui_src_ui_dst_internalformat, 0, sizeof(m_ui_src_ui_dst_internalformat));
}
RequiredCase::~RequiredCase()
{
}
void RequiredCase::deinit(void)
{
// free shared pointer
m_conversion_database.clear();
// Release the source object before we continue
if (m_src_object_id != 0)
{
destroyGLObject(m_source_attachment_type, m_src_object_id);
m_src_object_id = 0;
}
if (m_dst_object_id != 0)
{
destroyGLObject(m_destination_attachment_type, m_dst_object_id);
m_dst_object_id = 0;
}
destroyObjectsSupportingNonRenderableInternalformats(m_f_src_f_dst_internalformat);
destroyObjectsSupportingNonRenderableInternalformats(m_i_src_i_dst_internalformat);
destroyObjectsSupportingNonRenderableInternalformats(m_ui_src_ui_dst_internalformat);
}
tcu::TestNode::IterateResult RequiredCase::iterate(void)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
GLuint draw_fbo_id = 0;
GLuint read_fbo_id = 0;
gl.genFramebuffers(1, &draw_fbo_id);
gl.genFramebuffers(1, &read_fbo_id);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fbo_id);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo_id);
// We will be reading from zeroth color attachment
gl.readBuffer(GL_COLOR_ATTACHMENT0);
// Make sure the pixel storage is configured accordingly to our data sets!
gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei");
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
// Sanity checks
DE_ASSERT(m_destination_attachment_type == GL_TEXTURE_2D ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
// Determine general attachment type
GLenum general_attachment_type = getGeneralTargetForDetailedTarget(m_source_attachment_type);
if (general_attachment_type == GL_NONE)
return STOP;
// Set up source object
m_src_object_id = generateGLObject(m_source_attachment_type);
if (m_src_object_id == 0)
return STOP;
// Set up destination object
m_dst_object_id = generateGLObject(m_destination_attachment_type);
if (m_dst_object_id == 0)
return STOP;
// Generate all objects required to execute the non-renderable internalformat tests.
// Can't use the shader on GL_RENDERBUFFER as source.
if (m_source_attachment_type != GL_RENDERBUFFER && !generateObjectsToSupportNonColorRenderableInternalformats())
{
return STOP;
}
m_conversion_database.get()->initializeDatabase();
// Run through all FBO internal formats.
bool result = true;
const int n_dst_internal_formats = DE_LENGTH_OF_ARRAY(copyTexImage2DInternalFormatOrdering);
const int n_fbo_internal_formats = DE_LENGTH_OF_ARRAY(fboEffectiveInternalFormatOrdering);
for (int n_fbo_internal_format = 0; n_fbo_internal_format < n_fbo_internal_formats; ++n_fbo_internal_format)
{
GLenum fbo_internalformat = fboEffectiveInternalFormatOrdering[n_fbo_internal_format];
// Run through all destination internal formats.
for (int n_dst_internal_format = 0; n_dst_internal_format < n_dst_internal_formats; ++n_dst_internal_format)
{
GLenum dst_internalformat = copyTexImage2DInternalFormatOrdering[n_dst_internal_format];
switch (getDataSamplerTypeForInternalformat(fbo_internalformat))
{
case DATA_SAMPLER_FLOAT:
{
switch (getDataSamplerTypeForInternalformat(dst_internalformat))
{
case DATA_SAMPLER_FLOAT:
{
if (!execute(fbo_internalformat, dst_internalformat, &m_f_src_f_dst_internalformat))
{
// At least one conversion was invalid or failed. Test should fail,
// but let's continue iterating over internalformats.
result = false;
}
break;
}
case DATA_SAMPLER_INTEGER:
case DATA_SAMPLER_UNSIGNED_INTEGER:
{
// There shouldn't be any valid conversion formats in this case. Just pass NULL for the non-renderable case's objects.
// The test will fail if we try to verify the copy for different data type formats
if (!execute(fbo_internalformat, dst_internalformat, NULL))
{
// At least one conversion was invalid or failed. Test should
// fail, but let's continue iterating over internalformats.
result = false;
}
break;
}
default:
{
// Unrecognized destination internalformat
DE_ASSERT(0);
break;
}
} // switch (GetDataSamplerTypeForInternalformat(dst_internalformat) )
break;
}
case DATA_SAMPLER_INTEGER:
{
switch (getDataSamplerTypeForInternalformat(dst_internalformat))
{
case DATA_SAMPLER_INTEGER:
{
if (!execute(fbo_internalformat, dst_internalformat, &m_i_src_i_dst_internalformat))
{
// At least one conversion was invalid or failed. Test should fail,
// but let's continue iterating over internalformats.
result = false;
}
break;
}
case DATA_SAMPLER_FLOAT:
case DATA_SAMPLER_UNSIGNED_INTEGER:
{
// There shouldn't be any valid conversion formats in this case. Just pass NULL for the non-renderable case's objects.
// The test will fail if we try to verify the copy for different data type formats
if (!execute(fbo_internalformat, dst_internalformat, NULL))
{
// At least one conversion was invalid or failed. Test should fail,
// but let's continue iterating over internalformats.
result = false;
}
break;
}
default:
{
// Unrecognized destination internalformat
DE_ASSERT(0);
break;
}
} // switch (GetDataSamplerTypeForInternalformat(dst_internalformat) )
break;
} // case DATA_SAMPLER_INTEGER:
case DATA_SAMPLER_UNSIGNED_INTEGER:
{
switch (getDataSamplerTypeForInternalformat(dst_internalformat))
{
case DATA_SAMPLER_UNSIGNED_INTEGER:
{
if (!execute(fbo_internalformat, dst_internalformat, &m_ui_src_ui_dst_internalformat))
{
// At least one conversion was invalid or failed. Test should fail,
// but let's continue iterating over internalformats.
result = false;
}
break;
}
case DATA_SAMPLER_FLOAT:
case DATA_SAMPLER_INTEGER:
{
// There shouldn't be any valid conversion formats in this case. Just pass NULL for the non-renderable case's objects.
// The test will fail if we try to verify the copy for different data type formats
if (!execute(fbo_internalformat, dst_internalformat, NULL))
{
// At least one conversion was invalid or failed. Test should fail,
// but let's continue iterating over internalformats.
result = false;
}
break;
}
default:
{
// Unrecognized destination internalformat?
DE_ASSERT(0);
break;
}
} // switch (GetDataSamplerTypeForInternalformat(dst_internalformat) )
break;
} // case DATA_SAMPLER_UNSIGNED_INTEGER
default:
{
// Unrecognized source internalformat
DE_ASSERT(0);
break;
}
} // switch (GetDataSamplerTypeForInternalformat(fbo_internalformat) )
} // for (all destination internalformats)
} // for (all FBO internalformats)
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
return STOP;
}
/** This function verifies if glCopyTexImage2D() implementation performs conversions as
* per GLES3.0.3 spec, and that the result data is valid. For more detailed description,
* please see specification of copy_tex_image_conversions_required conformance test.
*
* @param conversion_database Conversion database handle. Cannot be NULL.
* @param source_attachment_type Tells what GL object (or which texture target)
* should be used as a read buffer for
* a glCopyTexImage2D) call. Allowed values:
* 1) GL_TEXTURE_2D,
* 2) GL_TEXTURE_2D_ARRAY,
* 3) GL_TEXTURE_3D,
* 4) GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
* 5) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
* 6) GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
* 7) GL_TEXTURE_CUBE_MAP_POSITIVE_X,
* 8) GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
* 9) GL_TEXTURE_CUBE_MAP_POSITIVE_Z.
* @param destination_attachment_type Tells which texture target should be used for
* a glCopyTexImage2D() call. Allowed values:
* 1) GL_TEXTURE_2D,
* 2) GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
* 3) GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
* 4) GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
* 5) GL_TEXTURE_CUBE_MAP_POSITIVE_X,
* 6) GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
* 7) GL_TEXTURE_CUBE_MAP_POSITIVE_Z.
* @param src_internalformat GLES internalformat that read buffer should use.
* @param dst_internalformat GLES internalformat that should be used for glReadPixels() call.
* This should NOT be the expected effective internalformat!
* @param objects_ptr Deref where generated object ids are stored
* (objects which were generated to support non-color-renderable internalformats).
* Cannot be NULL.
*
* @return true if successful, false otherwise.
*/
bool RequiredCase::execute(GLenum src_internalformat, GLenum dst_internalformat,
NonRenderableInternalformatSupportObjects* objects_ptr)
{
GLenum fbo_completeness = GL_NONE;
GLenum general_destination_attachment_type = GL_NONE;
int n_format_type_pair = 0;
GLenum src_format = GL_NONE;
GLenum src_type = GL_NONE;
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// If we're using a renderbuffer as a source, make sure the internalformat
// we'll try to use to store data in it is actually renderable
if (m_destination_attachment_type == GL_RENDERBUFFER && !isValidRBOInternalFormat(src_internalformat))
return true;
// Only accept source internal formats that are color renderable
if (!isColorRenderableInternalFormat(src_internalformat))
return true;
// Retrieve general destination attachment type before we continue
if ((general_destination_attachment_type = getGeneralTargetForDetailedTarget(m_destination_attachment_type)) ==
GL_NONE)
{
return false;
}
// Good. Check if the conversion is required - if so, we can run the test!
if (!isFBOEffectiveInternalFormatCompatibleWithDestinationInternalFormat(src_internalformat, dst_internalformat))
return true;
bool result = true;
std::vector<char> fbo_data(4);
// Try using all compatible format+type pairs
while (getFormatAndTypeCompatibleWithInternalformat(src_internalformat, n_format_type_pair, &src_format, &src_type))
{
// Try to find a rule in the conversion database, so that we know what data we should fill
// the source attachment with.
// There may be many entries for a single source internal format + type pair, so
// iterate until the find() function fails.
GLenum effective_internalformat = GL_NONE;
int n_conversion_rule = 0;
PixelData result_bottomleft_pixel_data;
PixelData result_bottomright_pixel_data;
PixelData result_topleft_pixel_data;
PixelData result_topright_pixel_data;
GLenum result_type = GL_NONE;
PixelData src_bottomleft_pixel_data;
PixelData src_bottomright_pixel_data;
PixelData src_topleft_pixel_data;
PixelData src_topright_pixel_data;
PixelCompareChannel channels_to_compare;
while (findEntryInConversionDatabase(
n_conversion_rule, src_internalformat, src_type, dst_internalformat, &effective_internalformat,
&result_type, &src_topleft_pixel_data, &src_topright_pixel_data, &src_bottomleft_pixel_data,
&src_bottomright_pixel_data, &result_topleft_pixel_data, &result_topright_pixel_data,
&result_bottomleft_pixel_data, &result_bottomright_pixel_data, &channels_to_compare))
{
#if 0
m_testCtx.getLog() << tcu::TestLog::Message
<< "Testing [src "
<< getInternalformatString(src_internalformat)
<< " " << glu::getTypeStr(src_type).toString()
<< "]=>[" << getInternalformatString(dst_internalformat) << "effective: "
<< getInternalformatString(effective_internalformat) << "] read with type: ["
<< glu::getTypeStr(result_type).toString() << ", src target: [" << GetTargetName(m_source_attachment_type)
<< "], dst target: " << GetTargetName(m_destination_attachment_type)
<< tcu::TestLog::EndMessage;
#endif
// Retrieve source data we can have uploaded to the source attachment
if (!getRawDataFromPixelData(fbo_data, src_topleft_pixel_data, src_topright_pixel_data,
src_bottomleft_pixel_data, src_bottomright_pixel_data))
{
unbindColorAttachments();
return false;
}
// Set up source attachment
if (!configureGLObject(1, m_source_attachment_type, m_src_object_id, src_internalformat, src_format,
src_type, &fbo_data[0]))
{
unbindColorAttachments();
return false;
}
// Make sure the source FBO configuration is supported.
fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
{
if (fbo_completeness == GL_FRAMEBUFFER_UNSUPPORTED)
{
// The implementation does not allow us to use source data built using this internal-format,
// using this particular attachment type. Break out of the loop, there's no need to carry on
// trying.
break;
}
else
{
m_testCtx.getLog() << tcu::TestLog::Message << "FBO error - incompleteness reason ["
<< fbo_completeness << "]" << tcu::TestLog::EndMessage;
// This should never happen. Consider test failed
unbindColorAttachments();
return false;
}
}
// Ask the implementation to perform the conversion!
switch (m_destination_attachment_type)
{
case GL_TEXTURE_2D:
{
gl.bindTexture(m_destination_attachment_type, m_dst_object_id);
gl.copyTexImage2D(m_destination_attachment_type, 0, dst_internalformat, 0 /* x */, 0 /* y */,
TEXTURE_WIDTH, TEXTURE_HEIGHT, 0 /* border */);
gl.texParameterf(m_destination_attachment_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameterf(m_destination_attachment_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameterf(m_destination_attachment_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameterf(m_destination_attachment_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.bindTexture(m_destination_attachment_type, 0);
break;
}
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
{
unsigned int j = 0;
GLuint dst_format, dst_type;
getFormatAndTypeCompatibleWithInternalformat(dst_internalformat, 0, &dst_format, &dst_type);
gl.bindTexture(general_destination_attachment_type, m_dst_object_id);
// Initialize all faces so that the texture is CM complete
// It's needed in case we need to use a shader to verify the copy operation
for (j = GL_TEXTURE_CUBE_MAP_POSITIVE_X; j <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; j++)
{
if (j == m_destination_attachment_type)
{
// Do the copy to the destination face
gl.copyTexImage2D(j, 0, dst_internalformat, 0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT,
0 /* border */);
}
else
{
// Clear the remaining faces to catch "copy to the wrong face" errors
static std::vector<char> zero_data(TEXTURE_WIDTH * TEXTURE_HEIGHT * 4 * sizeof(float), 0);
gl.texImage2D(j, 0, dst_internalformat, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, dst_format, dst_type,
&zero_data[0]);
}
}
gl.texParameterf(general_destination_attachment_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameterf(general_destination_attachment_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameterf(general_destination_attachment_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameterf(general_destination_attachment_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.bindTexture(general_destination_attachment_type, 0);
break;
} // cube-map texture target cases
default:
{
// Unsupported destination attachment type
DE_ASSERT(0);
}
} // switch (destination_attachment_type)
// Has the conversion succeeded as expected?
GLenum error_code = gl.getError();
if (error_code != GL_NO_ERROR)
{
m_testCtx.getLog() << tcu::TestLog::Message << "glCopyTexImage2D() reported an error for ["
<< getInternalformatString(src_internalformat) << "]=>["
<< getInternalformatString(dst_internalformat)
<< "] internalformat conversion [target=" << getTargetName(m_source_attachment_type)
<< "], as opposed to ES specification requirements!" << tcu::TestLog::EndMessage;
// This test is now considered failed
result = false;
}
else
{
// Conversion succeeded. We now need to compare the data stored by OpenGL ES with reference data.
if (isColorRenderableInternalFormat(effective_internalformat))
{
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_destination_attachment_type,
m_dst_object_id, 0);
fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
{
// Per spec:
// Although the GL defines a wide variety of internal formats for framebuffer-
// attachable image, such as texture images and renderbuffer images, some imple-
// mentations may not support rendering to particular combinations of internal for-
// mats. If the combination of formats of the images attached to a framebuffer object
// are not supported by the implementation, then the framebuffer is not complete un-
// der the clause labeled FRAMEBUFFER_UNSUPPORTED.
if (fbo_completeness != GL_FRAMEBUFFER_UNSUPPORTED)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "Framebuffer is considered incomplete [reason: " << fbo_completeness
<< "] - cannot proceed with the test case" << tcu::TestLog::EndMessage;
result = false;
}
}
else
{
if (!compareExpectedResultsByReadingPixels(
src_topleft_pixel_data, src_topright_pixel_data, src_bottomleft_pixel_data,
src_bottomright_pixel_data, result_topleft_pixel_data, result_topright_pixel_data,
result_bottomleft_pixel_data, result_bottomright_pixel_data, result_type,
effective_internalformat))
{
// This test is now considered failed
result = false;
}
}
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_destination_attachment_type, 0,
0);
} // if (IsColorRenderableInternalFormat(effective_internalformat) )
else if (m_source_attachment_type != GL_RENDERBUFFER)
{
// We cannot use glReadPixels()-approach to test this internalformat.
// The approach to be taken for non-color-renderable internalformats will
// be to use a special vertex shader to verify texture data. Outcome of the
// comparison will be captured using transform feedback.
GLint bound_draw_fbo_id = 0;
GLint bound_read_fbo_id = 0;
int compare_result_index = 0;
std::vector<GLint> copied_compare_result_data;
std::vector<GLint> copied_dst_texture_data;
std::vector<GLint> copied_src_texture_data;
GLenum dst_attachment_point = GL_TEXTURE2;
GLenum src_attachment_point = GL_TEXTURE1;
GLint samplers_to_use = 0;
// unique sampler values
GLint src_2D_texture_attachment = GL_TEXTURE3;
GLint src_2DArray_texture_attachment = GL_TEXTURE4;
GLint src_3D_texture_attachment = GL_TEXTURE5;
GLint src_Cube_texture_attachment = GL_TEXTURE6;
GLint dst_2D_texture_attachment = GL_TEXTURE7;
GLint dst_Cube_texture_attachment = GL_TEXTURE8;
if (m_source_attachment_type == GL_TEXTURE_2D_ARRAY)
{
samplers_to_use = TEXTURE_2D_ARRAY_SAMPLER_TYPE;
src_2DArray_texture_attachment = src_attachment_point;
}
else if (m_source_attachment_type == GL_TEXTURE_3D)
{
samplers_to_use = TEXTURE_3D_SAMPLER_TYPE;
src_3D_texture_attachment = src_attachment_point;
}
else if (m_source_attachment_type != GL_TEXTURE_2D)
{
samplers_to_use = TEXTURE_CUBE_SAMPLER_TYPE;
src_Cube_texture_attachment = src_attachment_point;
}
else
src_2D_texture_attachment = src_attachment_point;
if (m_destination_attachment_type != GL_TEXTURE_2D)
{
samplers_to_use = (samplers_to_use | (TEXTURE_CUBE_SAMPLER_TYPE << 8));
dst_Cube_texture_attachment = dst_attachment_point;
}
else
dst_2D_texture_attachment = dst_attachment_point;
// We will get a NULL pointer here if src and dst data type are different
// (NORM -> INT, UNSIGNED INT -> INT etc.). It's not allowed by the spec.
if (objects_ptr == NULL)
{
m_testCtx.getLog()
<< tcu::TestLog::Message << "Source and destination should be of the same data type - "
"cannot proceed with the test case"
<< tcu::TestLog::EndMessage;
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
// Retrieve currently bound framebuffer (draw and read) object IDs.
// If there is any FBO bound, glDraw*() function uses it, which is not wanted in this situation.
// What we do here is: unbinding FBOs, issue draw calls, bind FBOs again.
gl.getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &bound_draw_fbo_id);
gl.getIntegerv(GL_READ_FRAMEBUFFER_BINDING, &bound_read_fbo_id);
// Use default framebuffer object for this case purposes.
gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
// Bind source texture object to specific texture unit.
if (!bindTextureToTargetToSpecificTextureUnit(m_src_object_id, m_source_attachment_type,
src_attachment_point))
{
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
// Bind destination texture object to specific texture unit.
if (!bindTextureToTargetToSpecificTextureUnit(m_dst_object_id, m_destination_attachment_type,
dst_attachment_point))
{
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
// Set active program object.
gl.useProgram(objects_ptr->program_object_id);
if (!setUniformValues(objects_ptr->src_2D_texture_uniform_location, src_2D_texture_attachment,
objects_ptr->src_2DArray_texture_uniform_location,
src_2DArray_texture_attachment, objects_ptr->src_3D_texture_uniform_location,
src_3D_texture_attachment, objects_ptr->src_Cube_texture_uniform_location,
src_Cube_texture_attachment, objects_ptr->dst_2D_texture_uniform_location,
dst_2D_texture_attachment, objects_ptr->dst_Cube_texture_uniform_location,
dst_Cube_texture_attachment,
objects_ptr->channels_to_compare_uniform_location, channels_to_compare,
objects_ptr->samplers_to_use_uniform_location, samplers_to_use))
{
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, COMPARISON_RESULT_BUFFER_OBJECT_INDEX,
objects_ptr->comparison_result_buffer_object_id);
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, SOURCE_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX,
objects_ptr->src_texture_pixels_buffer_object_id);
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, DESTINATION_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX,
objects_ptr->dst_texture_pixels_buffer_object_id);
// Enable texture corrdinates (vertex attribs 0 & 1)
gl.enableVertexAttribArray(SRC_TEXTURE_COORDS_ATTRIB_INDEX);
gl.enableVertexAttribArray(DST_TEXTURE_COORDS_ATTRIB_INDEX);
// Begin transform feedback operations.
gl.enable(GL_RASTERIZER_DISCARD);
// Issue transform feedback operations.
gl.beginTransformFeedback(GL_POINTS);
error_code = gl.getError();
if (GL_NO_ERROR != error_code)
{
m_testCtx.getLog()
<< tcu::TestLog::Message << "An error [" << error_code
<< "] occurred after glBeginTransformFeedback() call." << tcu::TestLog::EndMessage;
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
gl.drawArrays(GL_POINTS, 0, NUMBER_OF_POINTS_TO_DRAW);
error_code = gl.getError();
if (GL_NO_ERROR != error_code)
{
m_testCtx.getLog() << tcu::TestLog::Message << "An error [" << error_code
<< "] occurred after glDrawArrays() call." << tcu::TestLog::EndMessage;
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
gl.endTransformFeedback();
error_code = gl.getError();
if (GL_NO_ERROR != error_code)
{
m_testCtx.getLog()
<< tcu::TestLog::Message << "An error [" << error_code
<< "] occurred after glEndTransformFeedback() call." << tcu::TestLog::EndMessage;
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
// Restore default active program object.
gl.useProgram(0);
// Make sure no error was generated at this point.
error_code = gl.getError();
if (GL_NO_ERROR != error_code)
{
m_testCtx.getLog()
<< tcu::TestLog::Message << "An error [" << error_code
<< "] occurred while working with transform feedback object." << tcu::TestLog::EndMessage;
result = false;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id,
bound_read_fbo_id);
continue;
}
gl.disable(GL_RASTERIZER_DISCARD);
// Let's read the buffer data now.
copyDataFromBufferObject(objects_ptr->comparison_result_buffer_object_id,
copied_compare_result_data);
copyDataFromBufferObject(objects_ptr->src_texture_pixels_buffer_object_id, copied_src_texture_data);
copyDataFromBufferObject(objects_ptr->dst_texture_pixels_buffer_object_id, copied_dst_texture_data);
// Check the results.
for (compare_result_index = 0; compare_result_index < NUMBER_OF_POINTS_TO_DRAW;
compare_result_index++)
{
if (copied_compare_result_data[compare_result_index] != 1)
{
int index_in_vec4_array = compare_result_index * NUMBER_OF_ELEMENTS_IN_VEC4;
// Returned result indicates that textures are different.
// Print texture object contents as well.
displayPixelComparisonFailureMessage(copied_src_texture_data[index_in_vec4_array],
copied_src_texture_data[index_in_vec4_array + 1],
copied_src_texture_data[index_in_vec4_array + 2],
copied_src_texture_data[index_in_vec4_array + 3],
src_internalformat, src_type, 0, 0, 0, 0, GL_NONE,
GL_NONE, copied_dst_texture_data[index_in_vec4_array],
copied_dst_texture_data[index_in_vec4_array + 1],
copied_dst_texture_data[index_in_vec4_array + 2],
copied_dst_texture_data[index_in_vec4_array + 3],
dst_internalformat, result_type, 0, 0, 0, 0);
// Report failure.
result = false;
}
}
fbo_completeness = GL_FRAMEBUFFER_COMPLETE;
restoreBindings(src_attachment_point, dst_attachment_point, bound_draw_fbo_id, bound_read_fbo_id);
} // if (source_attachment_type != GL_RENDERBUFFER && destination_attachment_type != GL_RENDERBUFFER)
} // if (no error was reported by GLES)
n_conversion_rule++;
}
// There should be at least ONE conversion rule defined
// for each valid FBO effective internalformat =>copyteximage2d internalformat defined!
// NOTE: This assertion can fail IF GLES implementation does not support particular FBO attachment combination.
// Make sure the check is not performed, should GL_FRAMEBUFFER_UNSUPPORTED fbo status be reported.
if (fbo_completeness != GL_FRAMEBUFFER_UNSUPPORTED)
{
if (n_conversion_rule == 0)
{
m_testCtx.getLog() << tcu::TestLog::Message << "No conversion rule for [src "
<< getInternalformatString(src_internalformat) << " "
<< glu::getTypeStr(src_type).toString() << "]=>["
<< getInternalformatString(dst_internalformat)
<< "effective: " << getInternalformatString(effective_internalformat)
<< "] read with type: [" << glu::getTypeStr(result_type).toString()
<< ", src target: [" << getTargetName(m_source_attachment_type)
<< "], dst target: " << getTargetName(m_destination_attachment_type)
<< tcu::TestLog::EndMessage;
}
}
// Check next format+type combination
n_format_type_pair++;
// If we're copying from a renderbuffer, we don't really care about compatible format+type pairs, as
// the effective internalformat is explicitly configured by glRenderbufferStorage() call.
if (m_source_attachment_type == GL_RENDERBUFFER)
{
break;
} // if (general_attachment_type == GL_RENDERBUFFER)
} // while (internalformat has n-th legal format+type pair)
unbindColorAttachments();
return result;
}
/** Binds texture object to a given texture target of a specified texture unit.
*
* @param to_id Valid texture object ID to be bound.
* @param texture_target Valid texture target to which @param to_id will be bound.
* @param texture_unit Texture unit to which @param to_id will be bound.
*
* @return GTFtrue if successful, GTFfalse otherwise.
*/
bool RequiredCase::bindTextureToTargetToSpecificTextureUnit(GLuint to_id, GLenum texture_target, GLenum texture_unit)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Set active texture unit.
gl.activeTexture(texture_unit);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
if (texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_X || texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y || texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z || texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
{
texture_target = GL_TEXTURE_CUBE_MAP;
}
// Bind texture object to specific texture target of specified texture unit.
gl.bindTexture(texture_target, to_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
// Restore default active texture unit.
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
return true;
}
/** Sets values of uniforms, that will later be used to perform data check-up for non-renderable internalformats.
*
* @param source_2D_texture_uniform_location Location for source 2D texture sample uniform.
* @param source_2D_texture_unit Texture unit which the source 2D texture object is bound to.
* Will be used to set value for @param source_2D_texture_uniform_location.
* @param source_2DArray_texture_uniform_location Location for source 2DArray texture sample uniform.
* @param source_2DArray_texture_unit Texture unit which the source 2DArray texture object is bound to.
* Will be used to set value for @param source_2DArray_texture_uniform_location.
* @param source_3D_texture_uniform_location Location for source 3D texture sample uniform.
* @param source_3D_texture_unit Texture unit which the source 3D texture object is bound to.
* Will be used to set value for @param source_Cube_texture_uniform_location.
* @param source_Cube_texture_uniform_location Location for source Cube texture sample uniform.
* @param source_Cube_texture_unit Texture unit which the source 2D texture object is bound to.
* Will be used to set value for @param source_2D_texture_uniform_location.
* @param destination_2D_texture_uniform_location Location for destination texture sample uniform.
* @param destination_2D_texture_unit Texture unit which the destination texture object is bound to.
* Will be used to set value for @param destination_2D_texture_uniform_location.
* @param destination_Cube_texture_uniform_location Location for destination texture sample uniform.
* @param destination_Cube_texture_unit Texture unit which the destination texture object is bound to.
* Will be used to set value for @param destination_Cube_texture_uniform_location.
* @param channels_to_compare_uniform_location Location for components to compare value uniform.
* @param channels_to_compare Components to compare value.
* @param samplers_to_use_uniform_location Location for samplers to use value uniform.
* @param samplers_to_use samplers to use value.
*
* @return GTFtrue if the operation succeeded (no error was generated),
* GTFfalse otherwise.
*/
bool RequiredCase::setUniformValues(GLint source_2D_texture_uniform_location, GLenum source_2D_texture_unit,
GLint source_2DArray_texture_uniform_location, GLenum source_2DArray_texture_unit,
GLint source_3D_texture_uniform_location, GLenum source_3D_texture_unit,
GLint source_Cube_texture_uniform_location, GLenum source_Cube_texture_unit,
GLint destination_2D_texture_uniform_location, GLenum destination_2D_texture_unit,
GLint destination_Cube_texture_uniform_location,
GLenum destination_Cube_texture_unit, GLint channels_to_compare_uniform_location,
GLint channels_to_compare, GLint samplers_to_use_uniform_location,
GLint samplers_to_use)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
if (source_2D_texture_uniform_location == -1 || source_2DArray_texture_uniform_location == -1 ||
source_3D_texture_uniform_location == -1 || source_Cube_texture_uniform_location == -1 ||
destination_2D_texture_uniform_location == -1 || destination_Cube_texture_uniform_location == -1 ||
channels_to_compare_uniform_location == -1 || samplers_to_use_uniform_location == -1)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Cannot set uniform values for invalid uniform locations."
<< tcu::TestLog::EndMessage;
return false;
} // if (input uniform locations are invalid)
// We are now ready to set uniform values.
gl.uniform1i(destination_2D_texture_uniform_location, destination_2D_texture_unit - GL_TEXTURE0);
gl.uniform1i(destination_Cube_texture_uniform_location, destination_Cube_texture_unit - GL_TEXTURE0);
gl.uniform1i(source_2D_texture_uniform_location, source_2D_texture_unit - GL_TEXTURE0);
gl.uniform1i(source_2DArray_texture_uniform_location, source_2DArray_texture_unit - GL_TEXTURE0);
gl.uniform1i(source_3D_texture_uniform_location, source_3D_texture_unit - GL_TEXTURE0);
gl.uniform1i(source_Cube_texture_uniform_location, source_Cube_texture_unit - GL_TEXTURE0);
gl.uniform1i(channels_to_compare_uniform_location, channels_to_compare);
gl.uniform1i(samplers_to_use_uniform_location, samplers_to_use);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
return true;
}
/** Retrieves and copies data stored in buffer object into allocated memory buffer.
* It is user's responsibility to free allocated memory.
*
* @param bo_id Valid buffer object ID from which data is retrieved.
* @param retrieved_data_ptr_ptr Deref will be used to store retrieved buffer object data.
*
* @return GTFtrue if successful, GTFfalse otherwise.
*/
bool RequiredCase::copyDataFromBufferObject(GLuint bo_id, std::vector<GLint>& retrieved_data)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
GLint buffer_size = 0;
gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
gl.getBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &buffer_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBufferParameteriv");
GLint* buffer_data_ptr = NULL;
buffer_data_ptr = (GLint*)gl.mapBufferRange(GL_ARRAY_BUFFER, 0, buffer_size, GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange");
if (buffer_data_ptr == NULL)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Could not map buffer object." << tcu::TestLog::EndMessage;
return false;
}
// Copy retrieved buffer data.
retrieved_data.resize(buffer_size / sizeof(GLint));
std::memcpy(&retrieved_data[0], buffer_data_ptr, buffer_size);
gl.unmapBuffer(GL_ARRAY_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer");
return true;
}
/** Allocates a buffer of sufficient size to hold 2x2 texture data represented
* with @param read_type GL type, issues a glReadPixels() call and then compares
* retrieved data with reference data (provided by the caller using reference_*
* arguments).
* Should it happen that the call resulted in an indirect conversion, the function
* calculates an epsilon, taking differences in amount of bits that were used to
* represent the data during any stage of the conversion into consideration.
*
* @param source_tl_pixel_data Describes pixel data that was used to build source
* object's contents (top-left corner).
* @param source_tr_pixel_data Describes pixel data that was used to build source
* object's contents (top-right corner).
* @param source_bl_pixel_data Describes pixel data that was used to build source
* object's contents (bottom-left corner).
* @param source_br_pixel_data Describes pixel data that was used to build source
* object's contents (bottom-right corner).
* @param reference_tl_pixel_data Describes ideal result pixel data. (top-left corner).
* @param reference_tr_pixel_data Describes ideal result pixel data. (top-right corner).
* @param reference_bl_pixel_data Describes ideal result pixel data. (bottom-left corner).
* @param reference_br_pixel_data Describes ideal result pixel data. (bottom-right corner).
* @param read_type GL type that will be used for glReadPixels() call. This
* type should be directly related with data type used in
* all reference_* pixel data arguments.
* @param result_internalformat Effective internal-format, expected to be used by the
* implementation to hold destination object's data.
* @param src_format GL format used for source object's data storage.
* @param src_type GL type used for source object's data storage.
* @param src_attachment_type Object type or texture target of the source object.
* @param dst_attachment_type Object type or texture target of the destination object.
*
* @return GTFtrue if all read pixels were correct, GTFfalse otherwise
**/
bool RequiredCase::compareExpectedResultsByReadingPixels(PixelData source_tl_pixel_data, PixelData source_tr_pixel_data,
PixelData source_bl_pixel_data, PixelData source_br_pixel_data,
PixelData reference_tl_pixel_data,
PixelData reference_tr_pixel_data,
PixelData reference_bl_pixel_data,
PixelData reference_br_pixel_data, GLenum read_type,
GLenum result_internalformat)
{
char* data_traveller_ptr = NULL;
int n = 0;
unsigned int n_bytes_per_result_pixel = 0;
GLenum read_format = GL_NONE;
bool result = true;
PixelData* reference_pixels[] = {
&reference_bl_pixel_data, &reference_br_pixel_data, &reference_tl_pixel_data, &reference_tr_pixel_data,
};
PixelData* source_pixels[] = { &source_bl_pixel_data, &source_br_pixel_data, &source_tl_pixel_data,
&source_tr_pixel_data };
PixelData result_pixels[4];
// Determine which read format should be used for reading.
// Note that GLES3 accepts GL_RGBA_INTEGER format for GL_RGB10_A2UI internalformat
// and GL_RGBA for GL_RGB10_A2 - handle this in a special case.
if (((read_type == GL_UNSIGNED_INT_2_10_10_10_REV) && (result_internalformat == GL_RGB10_A2UI)) ||
(read_type == GL_UNSIGNED_INT) || (read_type == GL_INT))
{
read_format = GL_RGBA_INTEGER;
}
else
{
read_format = GL_RGBA;
}
// Update read_type for GL_HALF_FLOAT
if (read_type == GL_HALF_FLOAT)
{
read_type = GL_FLOAT;
}
// Allocate data buffer
n_bytes_per_result_pixel = getSizeOfPixel(read_format, read_type);
std::vector<char> data(TEXTURE_WIDTH * TEXTURE_HEIGHT * n_bytes_per_result_pixel);
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Retrieve the data.
gl.readPixels(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, read_format, read_type, &data[0]);
// Was the operation successful?
GLenum error_code = gl.getError();
if (error_code != GL_NO_ERROR)
{
m_testCtx.getLog() << tcu::TestLog::Message << "glReadPixels() failed with error: [" << error_code << "]"
<< tcu::TestLog::EndMessage;
return false;
}
// Convert the data we read back to pixel data structures
data_traveller_ptr = &data[0];
for (n = 0; n < DE_LENGTH_OF_ARRAY(reference_pixels); ++n)
{
PixelData* result_pixel_ptr = result_pixels + n;
if (!getPixelDataFromRawData(data_traveller_ptr, read_format, read_type, result_pixel_ptr))
{
m_testCtx.getLog() << tcu::TestLog::Message << "GetPixelDataFromRawData failed!"
<< tcu::TestLog::EndMessage;
// Could not convert raw data to pixel data instance!
DE_ASSERT(0);
return false;
} // if (raw data->pixel data conversion failed)
// Move the data traveller
data_traveller_ptr += n_bytes_per_result_pixel;
} // for (all pixels)
// Compare each pixel with reference data. For debugging purposes, compare every single pixel,
// even if at least one comparison has already failed.
DE_ASSERT(DE_LENGTH_OF_ARRAY(reference_pixels) == DE_LENGTH_OF_ARRAY(result_pixels));
for (n = 0; n < DE_LENGTH_OF_ARRAY(reference_pixels); ++n)
{
result &= comparePixelData(result_pixels[n], *(reference_pixels[n]), *(source_pixels[n]), result_internalformat,
(result == 0));
} // For each pixel
if (result == false)
{
// Log a separator line for clarity
m_testCtx.getLog() << tcu::TestLog::Message << "<-- Erroneous test case finishes." << tcu::TestLog::EndMessage;
}
return result;
}
/** Retrieves size (expressed in bytes) of a single pixel represented by
* a @param format format + @param type type pair.
*
* @param format GLES format to consider.
* @param type GLES type to consider.
*
* @return Size of the pixel or 0 if either of the arguments was not recognized.
**/
unsigned int RequiredCase::getSizeOfPixel(GLenum format, GLenum type)
{
int result = 0;
switch (format)
{
case GL_RED:
result = 1;
break;
case GL_RED_INTEGER:
result = 1;
break;
case GL_RG:
result = 2;
break;
case GL_RG_INTEGER:
result = 2;
break;
case GL_RGB:
result = 3;
break;
case GL_RGB_INTEGER:
result = 3;
break;
case GL_RGBA:
result = 4;
break;
case GL_RGBA_INTEGER:
result = 4;
break;
case GL_DEPTH_COMPONENT:
result = 1;
break;
case GL_DEPTH_STENCIL:
result = 2;
break;
case GL_LUMINANCE_ALPHA:
result = 2;
break;
case GL_LUMINANCE:
result = 1;
break;
case GL_ALPHA:
result = 1;
break;
default:
{
DE_ASSERT(0);
result = 0;
}
}
switch (type)
{
case GL_UNSIGNED_BYTE:
result *= 1;
break;
case GL_BYTE:
result *= 1;
break;
case GL_UNSIGNED_SHORT:
result *= 2;
break;
case GL_SHORT:
result *= 2;
break;
case GL_UNSIGNED_INT:
result *= 4;
break;
case GL_INT:
result *= 4;
break;
case GL_HALF_FLOAT:
result *= 2;
break;
case GL_FLOAT:
result *= 4;
break;
case GL_UNSIGNED_SHORT_5_6_5:
result = 2;
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
result = 2;
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
result = 2;
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
result = 4;
break;
case GL_UNSIGNED_INT_10F_11F_11F_REV:
result = 4;
break;
case GL_UNSIGNED_INT_5_9_9_9_REV:
result = 4;
break;
case GL_UNSIGNED_INT_24_8:
result = 4;
break;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
result = 8;
break;
default:
{
DE_ASSERT(0);
result = 0;
}
}
return result;
}
/** Takes a pointer with raw data representation and converts it to
* four instances of _pixel_data corresponding to four corners of a
* quad used for verification purposes. Assumes 2x2 resolution.
*
* @param raw_data Pointer to a buffer storing the data.
* @param raw_data_format Format of the data stored under @param raw_data.
* @param raw_data_type Type of the data stored under @param raw_data.
* @param out_result Deref will be used to store four _pixel_data instances.
* Cannot be NULL, must be capacious enough to hold four
* instances of the structure.
*
* @return GTFtrue if successful, GTFfalse otherwise.
**/
bool RequiredCase::getPixelDataFromRawData(void* raw_data, GLenum raw_data_format, GLenum raw_data_type,
PixelData* out_result)
{
// Sanity checks: format should be equal to one of the values supported
// by glReadPixels()
DE_ASSERT(raw_data_format == GL_RGBA || raw_data_format == GL_RGBA_INTEGER);
if (raw_data_format != GL_RGBA && raw_data_format != GL_RGBA_INTEGER)
{
return false;
}
// Sanity checks: type should be equal to one of the values supported
// by glReadPixels()
DE_ASSERT(raw_data_type == GL_UNSIGNED_BYTE || raw_data_type == GL_UNSIGNED_INT || raw_data_type == GL_INT ||
raw_data_type == GL_FLOAT || raw_data_type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT);
if (raw_data_type != GL_UNSIGNED_BYTE && raw_data_type != GL_UNSIGNED_INT && raw_data_type != GL_INT &&
raw_data_type != GL_FLOAT && raw_data_type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT)
{
return false;
}
// Reset the result structure
deMemset(out_result, 0, sizeof(PixelData));
out_result->data_internalformat = raw_data_format;
out_result->data_type = raw_data_type;
// Fill the fields, depending on user-provided format+type pair
if (raw_data_format == GL_RGBA && raw_data_type == GL_UNSIGNED_BYTE)
{
char* raw_data_ptr = reinterpret_cast<char*>(raw_data);
out_result->alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
out_result->blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
out_result->green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
out_result->red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS;
out_result->red.unsigned_byte_data = raw_data_ptr[0];
out_result->green.unsigned_byte_data = raw_data_ptr[1];
out_result->blue.unsigned_byte_data = raw_data_ptr[2];
out_result->alpha.unsigned_byte_data = raw_data_ptr[3];
}
else if (raw_data_format == GL_RGBA_INTEGER && raw_data_type == GL_UNSIGNED_INT)
{
unsigned int* raw_data_ptr = reinterpret_cast<unsigned int*>(raw_data);
out_result->alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
out_result->blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
out_result->green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
out_result->red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS;
out_result->red.unsigned_integer_data = raw_data_ptr[0];
out_result->green.unsigned_integer_data = raw_data_ptr[1];
out_result->blue.unsigned_integer_data = raw_data_ptr[2];
out_result->alpha.unsigned_integer_data = raw_data_ptr[3];
}
else if (raw_data_format == GL_RGBA_INTEGER && raw_data_type == GL_INT)
{
signed int* raw_data_ptr = reinterpret_cast<signed int*>(raw_data);
out_result->alpha.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
out_result->blue.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
out_result->green.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
out_result->red.data_type = CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS;
out_result->red.signed_integer_data = raw_data_ptr[0];
out_result->green.signed_integer_data = raw_data_ptr[1];
out_result->blue.signed_integer_data = raw_data_ptr[2];
out_result->alpha.signed_integer_data = raw_data_ptr[3];
}
else if (raw_data_format == GL_RGBA && raw_data_type == GL_FLOAT)
{
float* raw_data_ptr = reinterpret_cast<float*>(raw_data);
out_result->alpha.data_type = CHANNEL_DATA_TYPE_FLOAT;
out_result->blue.data_type = CHANNEL_DATA_TYPE_FLOAT;
out_result->green.data_type = CHANNEL_DATA_TYPE_FLOAT;
out_result->red.data_type = CHANNEL_DATA_TYPE_FLOAT;
out_result->red.float_data = raw_data_ptr[0];
out_result->green.float_data = raw_data_ptr[1];
out_result->blue.float_data = raw_data_ptr[2];
out_result->alpha.float_data = raw_data_ptr[3];
} /* if (raw_data_format == GL_RGBA && raw_data_type == GL_FLOAT) */
else
{
signed int* raw_data_ptr = (signed int*)raw_data;
DE_ASSERT(raw_data_format == GL_RGBA && raw_data_type == GL_UNSIGNED_INT_2_10_10_10_REV);
out_result->alpha.data_type = CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS;
out_result->blue.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
out_result->green.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
out_result->red.data_type = CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS;
out_result->alpha.unsigned_byte_data = ((*raw_data_ptr) >> 30) & ((1 << 2) - 1);
out_result->blue.unsigned_short_data = ((*raw_data_ptr) >> 20) & ((1 << 10) - 1);
out_result->green.unsigned_short_data = ((*raw_data_ptr) >> 10) & ((1 << 10) - 1);
out_result->red.unsigned_short_data = ((*raw_data_ptr)) & ((1 << 10) - 1);
}
return true;
}
/** Checks if downloaded pixel data is valid. Should the rendered values differ
* outside allowed range, the function logs detailed information about the problem.
*
* @param downloaded_pixel Instance of _pixel_data describing a pixel
* that was rendered by the implementation.
* @param reference_pixel Instance of _pixel_data describing ideal
* pixel data.
* @param source_pixel Instance of _pixel_data describing the pixel
* prior to conversion.
* @param result_internalformat Internal format the implementation is expected
* to be using for the converted data.
* @param src_attachment_type Type of the source object used for the conversion.
* @param dst_attachment_type Type of the destination object used for the conversion.
* @param has_test_failed_already 1 if any of the other pixels making up the test 2x2
* data-set has already been determined to be corrupt.
* 0 otherwise.
* @param src_internalformat Internal-format used for source object's data storage.
* @param src_datatype Type used for source object's data storage.
*
* @return 1 if the pixels match, 0 otherwise.
**/
bool RequiredCase::comparePixelData(PixelData downloaded_pixel, PixelData reference_pixel, PixelData source_pixel,
GLenum result_internalformat, bool has_test_failed_already)
{
ChannelData* channel_data[12] = { 0 };
int max_epsilon[4] = { 0 };
int has_pixel_failed = 0;
int n_channel = 0;
bool result = true;
int result_rgba_bits[4] = { 0 };
int source_rgba_bits[4] = { 0 };
// Form channel data so we can later analyse channels one after another in a loop
channel_data[0] = &downloaded_pixel.red;
channel_data[1] = &reference_pixel.red;
channel_data[2] = &source_pixel.red;
channel_data[3] = &downloaded_pixel.green;
channel_data[4] = &reference_pixel.green;
channel_data[5] = &source_pixel.green;
channel_data[6] = &downloaded_pixel.blue;
channel_data[7] = &reference_pixel.blue;
channel_data[8] = &source_pixel.blue;
channel_data[9] = &downloaded_pixel.alpha;
channel_data[10] = &reference_pixel.alpha;
channel_data[11] = &source_pixel.alpha;
// Retrieve number of bits used for source and result data.
getNumberOfBitsForInternalFormat(source_pixel.data_internalformat, source_rgba_bits);
getNumberOfBitsForInternalFormat(result_internalformat, result_rgba_bits);
// Time for actual comparison!
for (unsigned int n = 0; n < sizeof(channel_data) / sizeof(channel_data[0]);
n += 3 /* downloaded + reference + source pixel combinations */, ++n_channel)
{
ChannelData* downloaded_channel_ptr = channel_data[n];
ChannelData* reference_channel_ptr = channel_data[n + 1];
// Calculate maximum epsilon
int max_n_bits = 0;
int min_n_bits = std::numeric_limits<int>::max();
int n_dst_bits = result_rgba_bits[n_channel];
int n_reading_bits = 0;
int n_source_bits = source_rgba_bits[n_channel];
getNumberOfBitsForChannelDataType(downloaded_channel_ptr->data_type, &n_reading_bits);
if (max_n_bits < n_dst_bits && n_dst_bits != 0)
{
max_n_bits = n_dst_bits;
} /* if (max_n_bits < n_dst_bits && n_dst_bits != 0) */
if (max_n_bits < n_reading_bits && n_reading_bits != 0)
{
max_n_bits = n_reading_bits;
}
if (max_n_bits < n_source_bits && n_source_bits != 0)
{
max_n_bits = n_source_bits;
}
if (n_dst_bits != 0)
{
min_n_bits = n_dst_bits;
}
if (min_n_bits > n_reading_bits && n_reading_bits != 0)
{
min_n_bits = n_reading_bits;
}
if (min_n_bits > n_source_bits && n_source_bits != 0)
{
min_n_bits = n_source_bits;
}
if (max_n_bits != min_n_bits && max_n_bits != 0)
{
DE_ASSERT(min_n_bits != std::numeric_limits<int>::max());
// Allow rounding in either direction
max_epsilon[n_channel] = deCeilFloatToInt32(((1 << max_n_bits) - 1.0f) / ((1 << min_n_bits) - 1));
}
else
{
max_epsilon[n_channel] = 0;
}
// At the moment, we only care about data types that correspond to GL types usable for glReadPixels() calls.
// Please feel free to expand this switch() with support for data types you need.
switch (downloaded_channel_ptr->data_type)
{
case CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS:
{
int delta = (downloaded_channel_ptr->signed_integer_data - reference_channel_ptr->signed_integer_data);
if (abs(delta) > max_epsilon[n_channel])
{
if (result)
{
has_pixel_failed = 1;
result = false;
}
}
break;
}
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS:
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS:
{
int delta = (downloaded_channel_ptr->unsigned_byte_data - reference_channel_ptr->unsigned_byte_data);
if (abs(delta) > max_epsilon[n_channel])
{
if (result)
{
has_pixel_failed = 1;
result = false;
}
}
break;
}
case CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS:
{
int delta = static_cast<int>(downloaded_channel_ptr->unsigned_integer_data -
reference_channel_ptr->unsigned_integer_data);
if (abs(delta) > max_epsilon[n_channel])
{
if (result)
{
has_pixel_failed = 1;
result = false;
}
}
break;
}
case CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS:
{
int delta = (downloaded_channel_ptr->unsigned_short_data - reference_channel_ptr->unsigned_short_data);
if (abs(delta) > max_epsilon[n_channel])
{
if (result)
{
has_pixel_failed = 1;
result = false;
}
}
break;
} /* case CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS: */
case CHANNEL_DATA_TYPE_FLOAT:
{
int delta = deChopFloatToInt32(downloaded_channel_ptr->float_data - reference_channel_ptr->float_data);
if (abs(delta) > max_epsilon[n_channel])
{
if (result)
{
has_pixel_failed = 1;
result = false;
}
}
break;
}
default:
{
// Unrecognized data type
DE_ASSERT(0);
}
}
if (has_pixel_failed && !has_test_failed_already)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Erroneous test case starts-->" << tcu::TestLog::EndMessage;
has_test_failed_already = true;
}
} // for (all channels)
if (!result)
{
displayPixelComparisonFailureMessage(
channel_data[2] != NULL ? channel_data[2]->unsigned_integer_data : 0,
channel_data[5] != NULL ? channel_data[5]->unsigned_integer_data : 0,
channel_data[8] != NULL ? channel_data[8]->unsigned_integer_data : 0,
channel_data[11] != NULL ? channel_data[11]->unsigned_integer_data : 0, source_pixel.data_internalformat,
source_pixel.data_type, channel_data[1] != NULL ? channel_data[1]->unsigned_integer_data : 0,
channel_data[4] != NULL ? channel_data[4]->unsigned_integer_data : 0,
channel_data[7] != NULL ? channel_data[7]->unsigned_integer_data : 0,
channel_data[10] != NULL ? channel_data[10]->unsigned_integer_data : 0, reference_pixel.data_internalformat,
reference_pixel.data_type, channel_data[0] != NULL ? channel_data[0]->unsigned_integer_data : 0,
channel_data[3] != NULL ? channel_data[3]->unsigned_integer_data : 0,
channel_data[6] != NULL ? channel_data[6]->unsigned_integer_data : 0,
channel_data[9] != NULL ? channel_data[9]->unsigned_integer_data : 0, result_internalformat,
downloaded_pixel.data_type, max_epsilon[0], max_epsilon[1], max_epsilon[2], max_epsilon[3]);
}
return result;
}
/** Retrieves number of bits used for a single pixel, were it
* stored in @param internalformat internal format.
*
* @param internalformat GLES internal format to consider.
* @param out_rgba_bits Deref will be used to store 4 integers
* describing amount of bits that the internal
* format uses for subsequently R, G, B and A
* channels. Cannot be NULL.
*
* @return GTFtrue if successful, GTFfalse otherwise.
**/
bool RequiredCase::getNumberOfBitsForInternalFormat(GLenum internalformat, int* out_rgba_bits)
{
deMemset(out_rgba_bits, 0, sizeof(int) * 4);
switch (internalformat)
{
case GL_LUMINANCE8_OES:
out_rgba_bits[0] = 8;
break;
case GL_R16I:
out_rgba_bits[0] = 16;
break;
case GL_R16UI:
out_rgba_bits[0] = 16;
break;
case GL_R32I:
out_rgba_bits[0] = 32;
break;
case GL_R32UI:
out_rgba_bits[0] = 32;
break;
case GL_R8:
out_rgba_bits[0] = 8;
break;
case GL_R8_SNORM:
out_rgba_bits[0] = 8;
break;
case GL_R8I:
out_rgba_bits[0] = 8;
break;
case GL_R8UI:
out_rgba_bits[0] = 8;
break;
case GL_RG16UI:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
break;
case GL_RG16I:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
break;
case GL_RG32I:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
break;
case GL_RG32UI:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
break;
case GL_RG8:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
break;
case GL_RG8_SNORM:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
break;
case GL_RG8I:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
break;
case GL_RG8UI:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
break;
case GL_RGB10_A2:
out_rgba_bits[0] = 10;
out_rgba_bits[1] = 10;
out_rgba_bits[2] = 10;
out_rgba_bits[3] = 2;
break;
case GL_RGB10_A2UI:
out_rgba_bits[0] = 10;
out_rgba_bits[1] = 10;
out_rgba_bits[2] = 10;
out_rgba_bits[3] = 2;
break;
case GL_RGB16I:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
out_rgba_bits[2] = 16;
break;
case GL_RGB16UI:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
out_rgba_bits[2] = 16;
break;
case GL_RGB32I:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
out_rgba_bits[2] = 32;
break;
case GL_RGB32UI:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
out_rgba_bits[2] = 32;
break;
case GL_RGB5_A1:
out_rgba_bits[0] = 5;
out_rgba_bits[1] = 5;
out_rgba_bits[2] = 5;
out_rgba_bits[3] = 1;
break;
case GL_RGB565:
out_rgba_bits[0] = 5;
out_rgba_bits[1] = 6;
out_rgba_bits[2] = 5;
break;
case GL_RGB8:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
break;
case GL_RGB8_SNORM:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
break;
case GL_RGB8I:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
break;
case GL_RGB8UI:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
break;
case GL_RGBA16I:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
out_rgba_bits[2] = 16;
out_rgba_bits[3] = 16;
break;
case GL_RGBA16UI:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
out_rgba_bits[2] = 16;
out_rgba_bits[3] = 16;
break;
case GL_RGBA32I:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
out_rgba_bits[2] = 32;
out_rgba_bits[3] = 32;
break;
case GL_RGBA32UI:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
out_rgba_bits[2] = 32;
out_rgba_bits[3] = 32;
break;
case GL_RGBA4:
out_rgba_bits[0] = 4;
out_rgba_bits[1] = 4;
out_rgba_bits[2] = 4;
out_rgba_bits[3] = 4;
break;
case GL_RGBA8:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
out_rgba_bits[3] = 8;
break;
case GL_RGBA8_SNORM:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
out_rgba_bits[3] = 8;
break;
case GL_RGBA8I:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
out_rgba_bits[3] = 8;
break;
case GL_RGBA8UI:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
out_rgba_bits[3] = 8;
break;
case GL_SRGB8:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
break;
case GL_SRGB8_ALPHA8:
out_rgba_bits[0] = 8;
out_rgba_bits[1] = 8;
out_rgba_bits[2] = 8;
out_rgba_bits[3] = 8;
break;
case GL_R16F:
out_rgba_bits[0] = 16;
break;
case GL_RG16F:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
break;
case GL_RGB16F:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
out_rgba_bits[2] = 16;
break;
case GL_RGBA16F:
out_rgba_bits[0] = 16;
out_rgba_bits[1] = 16;
out_rgba_bits[2] = 16;
out_rgba_bits[3] = 16;
break;
case GL_R32F:
out_rgba_bits[0] = 32;
break;
case GL_RG32F:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
break;
case GL_RGB32F:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
out_rgba_bits[2] = 32;
break;
case GL_RGBA32F:
out_rgba_bits[0] = 32;
out_rgba_bits[1] = 32;
out_rgba_bits[2] = 32;
out_rgba_bits[3] = 32;
break;
default:
{
DE_ASSERT(0);
return false;
}
}
return true;
}
/** Browses the conversion database provided by user and looks for conversion rules
* that match the following requirements:
*
* 1) Source object's data internal format equal to @param src_internalformat.
* 2) Source object's data type equal to @param src_type.
* 3) Internal format used for glCopyTexImage2D() call equal to @param copyteximage2d_internalformat.
*
* The function allows to find as many conversion rules matching these requirements as
* available. For any triple, caller should use incrementing values of @param index,
* starting from 0.
*
* Source dataset corresponds to 2x2 image (using up to 4 channels) that the attachment bound to
* read buffer will use prior to glCopyTexImage2D() call.
* Destination dataset corresponds to 2x2 image (using up to 4 channels) that the result texture object
* should match (within acceptable epsilon).
*
* @param index Index of conversion rule the caller is interested in reading.
* @param src_internalformat Source object's data internal format to assume.
* @param src_type Source object's data type to assume.
* @param copyteximage2d_internalformat Internal format to be used for glCopyTexImage2D() call.
* @param out_result_internalformat Deref will be used to store internal format that GLES implementation
* should use for storage of the converted data. Cannot be NULL.
* @param out_dst_type Deref will be used to store type that GLES implementation should use
* for storage of the converted data. Cannot be NULL.
* @param out_src_topleft Deref will be used to store _pixel_data instance describing top-left
* corner of the source dataset. Cannot be NULL.
* @param out_src_topright Deref will be used to store _pixel_data instance describing top-right
* corner of the source dataset. Cannot be NULL.
* @param out_src_bottomleft Deref will be used to store _pixel_data instance describing bottom-left
* corner of the source dataset. Cannot be NULL.
* @param out_src_bottomright Deref will be used to store _pixel_data instance describing bottom-right
* corner of the source dataset. Cannot be NULL.
* @param out_dst_topleft Deref will be used to store _pixel_data instance describing top-left
* corner of the destination dataset.
* @param out_dst_topright Deref will be used to store _pixel_data instance describing top-right
* corner of the destination dataset.
* @param out_dst_bottomleft Deref will be used to store _pixel_data instance describing bottom-left
* corner of the destination dataset.
* @param out_dst_bottomright Deref will be used to store _pixel_data instance describing bottom-right
* corner of the destination dataset.
*
* @return GTFtrue if @param index -th conversion rule was found, GTFfalse otherwise.
**/
bool RequiredCase::findEntryInConversionDatabase(unsigned int index, GLenum src_internalformat, GLenum src_type,
GLenum copyteximage2d_internalformat,
GLenum* out_result_internalformat, GLenum* out_dst_type,
PixelData* out_src_topleft, PixelData* out_src_topright,
PixelData* out_src_bottomleft, PixelData* out_src_bottomright,
PixelData* out_dst_topleft, PixelData* out_dst_topright,
PixelData* out_dst_bottomleft, PixelData* out_dst_bottomright,
PixelCompareChannel* out_channels_to_compare)
{
const int conversion_array_width =
sizeof(copyTexImage2DInternalFormatOrdering) / sizeof(copyTexImage2DInternalFormatOrdering[0]);
int copyteximage2d_index = -1;
int fbo_effective_internalformat_index = -1;
unsigned int n_entry = 0;
unsigned int n_matching_entries = 0;
GLenum result_internalformat = GL_NONE;
int result_internalformat_index = -1;
/* Sanity checks */
DE_ASSERT(out_src_topleft != NULL);
DE_ASSERT(out_src_topright != NULL);
DE_ASSERT(out_src_bottomleft != NULL);
DE_ASSERT(out_src_bottomright != NULL);
DE_ASSERT(out_dst_topleft != NULL);
DE_ASSERT(out_dst_topright != NULL);
DE_ASSERT(out_dst_bottomleft != NULL);
DE_ASSERT(out_dst_bottomright != NULL);
// Retrieve internalformat that converted data will be stored in
copyteximage2d_index = getIndexOfCopyTexImage2DInternalFormat(copyteximage2d_internalformat);
fbo_effective_internalformat_index = getIndexOfFramebufferEffectiveInternalFormat(src_internalformat);
DE_ASSERT(copyteximage2d_index != -1 && fbo_effective_internalformat_index != -1);
if (copyteximage2d_index == -1 || fbo_effective_internalformat_index == -1)
return false;
result_internalformat_index = fbo_effective_internalformat_index * conversion_array_width + copyteximage2d_index;
DE_ASSERT(result_internalformat_index < DE_LENGTH_OF_ARRAY(conversionArray));
if (result_internalformat_index >= DE_LENGTH_OF_ARRAY(conversionArray))
return false;
result_internalformat = conversionArray[result_internalformat_index];
DE_ASSERT(result_internalformat != GL_NONE);
if (result_internalformat == GL_NONE)
return false;
// We use the simplest approach possible to keep the code as readable as possible.
for (n_entry = 0; n_entry < m_conversion_database->n_entries_added; ++n_entry)
{
ConversionDatabaseEntry& entry_ptr = m_conversion_database->entries[n_entry];
if (entry_ptr.src_bottomleft_corner.data_internalformat == src_internalformat &&
entry_ptr.src_bottomleft_corner.data_type == src_type &&
entry_ptr.dst_bottomleft_corner.data_internalformat == result_internalformat)
{
/* Is it the n-th match we're being asked for? */
if (index == n_matching_entries)
{
/* Indeed! */
*out_src_topleft = entry_ptr.src_topleft_corner;
*out_src_topright = entry_ptr.src_topright_corner;
*out_src_bottomleft = entry_ptr.src_bottomleft_corner;
*out_src_bottomright = entry_ptr.src_bottomright_corner;
*out_dst_topleft = entry_ptr.dst_topleft_corner;
*out_dst_topright = entry_ptr.dst_topright_corner;
*out_dst_bottomleft = entry_ptr.dst_bottomleft_corner;
*out_dst_bottomright = entry_ptr.dst_bottomright_corner;
*out_result_internalformat = entry_ptr.dst_topleft_corner.data_internalformat;
*out_dst_type = entry_ptr.dst_topleft_corner.data_type;
*out_channels_to_compare = entry_ptr.channels_to_compare;
return true;
}
else
{
++n_matching_entries;
}
}
}
return false;
}
/** Retrieves index under which user-specified internalformat can be found in
* copy_tex_image_2d_internal_format_ordering array.
*
* @param internalformat GLES internal format to look for.
*
* @return Index >= 0 if successful, -1 otherwise.
**/
int RequiredCase::getIndexOfCopyTexImage2DInternalFormat(GLenum internalformat)
{
int max_index = DE_LENGTH_OF_ARRAY(copyTexImage2DInternalFormatOrdering);
for (int index = 0; index < max_index; ++index)
{
if (copyTexImage2DInternalFormatOrdering[index] == internalformat)
return index;
}
return -1;
}
/** Retrieves index under which user-specified internalformat can be found in
* fbo_effective_internal_format_ordering array.
*
* @param internalformat GLES internal format to look for.
*
* @return Index >= 0 if successful, -1 otherwise.
**/
int RequiredCase::getIndexOfFramebufferEffectiveInternalFormat(GLenum internalformat)
{
int max_index = DE_LENGTH_OF_ARRAY(fboEffectiveInternalFormatOrdering);
for (int index = 0; index < max_index; ++index)
{
if (fboEffectiveInternalFormatOrdering[index] == internalformat)
return index;
}
return -1;
}
/** Takes four pixels (described by _pixel_data structures) making up
* the 2x2 texture used for source objects, and converts the representation
* to raw data that can later be fed to glTexImage2D(), glTexImage3D() etc.
* calls.
*
* NOTE: It is caller's responsibility to free the returned buffer when no
* longer used. Use free() function to deallocate the resource.
*
* @param topleft Instance of _pixel_data describing top-left corner.
* @param topright Instance of _pixel_data describing top-right corner.
* @param bottomleft Instance of _pixel_data describing bottom-left corner.
* @param bottomright Instance of _pixel_data describing bottom-right corner.
*
* @return Pointer to the buffer or NULL if failed.
**/
bool RequiredCase::getRawDataFromPixelData(std::vector<char>& result, PixelData topleft, PixelData topright,
PixelData bottomleft, PixelData bottomright)
{
ChannelOrder channel_order = CHANNEL_ORDER_UNKNOWN;
GLenum format = GL_NONE;
GLenum internalformat = topleft.data_internalformat;
unsigned int n_bytes_needed = 0;
unsigned int n_bytes_per_pixel = 0;
unsigned int n_pixel = 0;
const PixelData* pixels[] = { &bottomleft, &bottomright, &topleft, &topright };
char* result_traveller = DE_NULL;
GLenum type = topleft.data_type;
// Sanity checks
DE_ASSERT(topleft.data_internalformat == topright.data_internalformat);
DE_ASSERT(topleft.data_internalformat == bottomleft.data_internalformat);
DE_ASSERT(topleft.data_internalformat == bottomright.data_internalformat);
DE_ASSERT(topleft.data_type == topright.data_type);
DE_ASSERT(topleft.data_type == bottomleft.data_type);
DE_ASSERT(topleft.data_type == bottomright.data_type);
// Allocate the buffer
if (!getFormatForInternalformat(internalformat, &format))
{
DE_ASSERT(0);
return false;
} // if (no format known for requested internalformat)
if (!getChannelOrderForInternalformatAndType(internalformat, type, &channel_order))
{
DE_ASSERT(0);
return false;
} // if (no channel order known for internalformat+type combination)
// special case for GL_HALF_FLOAT, treat it as a FLOAT
if (type == GL_HALF_FLOAT)
n_bytes_per_pixel = getSizeOfPixel(format, GL_FLOAT);
else
n_bytes_per_pixel = getSizeOfPixel(format, type);
n_bytes_needed = TEXTURE_WIDTH * TEXTURE_HEIGHT * n_bytes_per_pixel;
if (n_bytes_needed == 0)
{
DE_ASSERT(0);
return false;
}
result.resize(n_bytes_needed);
// Fill the raw data buffer with data.
result_traveller = &result[0];
for (n_pixel = 0; n_pixel < sizeof(pixels) / sizeof(pixels[0]); ++n_pixel)
{
const ChannelData* channels[] = { NULL, NULL, NULL, NULL }; /* We need up to four channels */
int n_bits_for_channel_0 = 0;
int n_bits_for_channel_1 = 0;
int n_bits_for_channel_2 = 0;
int n_bits_for_channel_3 = 0;
const PixelData* pixel_ptr = pixels[n_pixel];
switch (channel_order)
{
case CHANNEL_ORDER_ABGR:
{
channels[0] = &pixel_ptr->alpha;
channels[1] = &pixel_ptr->blue;
channels[2] = &pixel_ptr->green;
channels[3] = &pixel_ptr->red;
break;
}
case CHANNEL_ORDER_BGR:
{
channels[0] = &pixel_ptr->blue;
channels[1] = &pixel_ptr->green;
channels[2] = &pixel_ptr->red;
break;
}
case CHANNEL_ORDER_BGRA:
{
channels[0] = &pixel_ptr->blue;
channels[1] = &pixel_ptr->green;
channels[2] = &pixel_ptr->red;
channels[3] = &pixel_ptr->alpha;
break;
}
case CHANNEL_ORDER_R:
{
channels[0] = &pixel_ptr->red;
break;
}
case CHANNEL_ORDER_RG:
{
channels[0] = &pixel_ptr->red;
channels[1] = &pixel_ptr->green;
break;
}
case CHANNEL_ORDER_RGB:
{
channels[0] = &pixel_ptr->red;
channels[1] = &pixel_ptr->green;
channels[2] = &pixel_ptr->blue;
break;
}
case CHANNEL_ORDER_RGBA:
{
channels[0] = &pixel_ptr->red;
channels[1] = &pixel_ptr->green;
channels[2] = &pixel_ptr->blue;
channels[3] = &pixel_ptr->alpha;
break;
}
default:
{
// Unrecognized channel order
DE_ASSERT(0);
}
}
// Pack the channel data, depending on channel sizes
if (((channels[0] != NULL) &&
!getNumberOfBitsForChannelDataType(channels[0]->data_type, &n_bits_for_channel_0)) ||
((channels[1] != NULL) &&
!getNumberOfBitsForChannelDataType(channels[1]->data_type, &n_bits_for_channel_1)) ||
((channels[2] != NULL) &&
!getNumberOfBitsForChannelDataType(channels[2]->data_type, &n_bits_for_channel_2)) ||
((channels[3] != NULL) &&
!getNumberOfBitsForChannelDataType(channels[3]->data_type, &n_bits_for_channel_3)))
{
// Unrecognized data type
DE_ASSERT(0);
return false;
} // if (could not determine number of bits making up any of the channels)
// NOTE: We will read HALF_FLOAT data as FLOAT data (32 bit) to avoid conversion before passing the data to GL
if (channels[0] != NULL && channels[1] != NULL && channels[2] != NULL && channels[3] != NULL)
{
// RGBA32
if (type == GL_HALF_FLOAT || ((n_bits_for_channel_0 == 32) && (n_bits_for_channel_1 == 32) &&
(n_bits_for_channel_2 == 32) && (n_bits_for_channel_3 == 32)))
{
unsigned int* result_traveller32 = (unsigned int*)result_traveller;
*result_traveller32 = channels[0]->unsigned_integer_data;
result_traveller32++;
*result_traveller32 = channels[1]->unsigned_integer_data;
result_traveller32++;
*result_traveller32 = channels[2]->unsigned_integer_data;
result_traveller32++;
*result_traveller32 = channels[3]->unsigned_integer_data;
result_traveller += 4 * 4;
}
else
// RGBA16
if (n_bits_for_channel_0 == 16 && n_bits_for_channel_1 == 16 && n_bits_for_channel_2 == 16 &&
n_bits_for_channel_3 == 16)
{
unsigned short* result_traveller16 = (unsigned short*)result_traveller;
*result_traveller16 = channels[0]->unsigned_short_data;
result_traveller16++;
*result_traveller16 = channels[1]->unsigned_short_data;
result_traveller16++;
*result_traveller16 = channels[2]->unsigned_short_data;
result_traveller16++;
*result_traveller16 = channels[3]->unsigned_short_data;
result_traveller += 8;
}
else
// RGBA4
if (n_bits_for_channel_0 == 4 && n_bits_for_channel_1 == 4 && n_bits_for_channel_2 == 4 &&
n_bits_for_channel_3 == 4)
{
unsigned short* result_traveller16 = (unsigned short*)result_traveller;
*result_traveller16 = (channels[0]->unsigned_byte_data << 12) + (channels[1]->unsigned_byte_data << 8) +
(channels[2]->unsigned_byte_data << 4) + channels[3]->unsigned_byte_data;
result_traveller += 2;
}
else
// RGBA8
if (n_bits_for_channel_0 == 8 && n_bits_for_channel_1 == 8 && n_bits_for_channel_2 == 8 &&
n_bits_for_channel_3 == 8)
{
*result_traveller = channels[0]->unsigned_byte_data;
result_traveller++;
*result_traveller = channels[1]->unsigned_byte_data;
result_traveller++;
*result_traveller = channels[2]->unsigned_byte_data;
result_traveller++;
*result_traveller = channels[3]->unsigned_byte_data;
result_traveller++;
}
else
// RGB5A1
if (n_bits_for_channel_0 == 5 && n_bits_for_channel_1 == 5 && n_bits_for_channel_2 == 5 &&
n_bits_for_channel_3 == 1)
{
unsigned short* result_traveller16 = (unsigned short*)result_traveller;
*result_traveller16 = (channels[0]->unsigned_byte_data << 11) + (channels[1]->unsigned_byte_data << 6) +
(channels[2]->unsigned_byte_data << 1) + channels[3]->unsigned_byte_data;
result_traveller += 2;
}
else
// RGB10A2_REV
if (n_bits_for_channel_0 == 2 && n_bits_for_channel_1 == 10 && n_bits_for_channel_2 == 10 &&
n_bits_for_channel_3 == 10)
{
unsigned int* result_traveller32 = (unsigned int*)result_traveller;
DE_ASSERT(channels[0]->data_type == CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS);
DE_ASSERT(channels[1]->data_type == CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS);
DE_ASSERT(channels[2]->data_type == CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS);
DE_ASSERT(channels[3]->data_type == CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS);
*result_traveller32 = (channels[0]->unsigned_byte_data << 30) +
(channels[1]->unsigned_short_data << 20) +
(channels[2]->unsigned_short_data << 10) + channels[3]->unsigned_short_data;
result_traveller += 4;
}
else
{
// Unsupported bit layout
DE_ASSERT(0);
return false;
}
}
else if (channels[0] != NULL && channels[1] != NULL && channels[2] != NULL)
{
// RGB32
if ((type == GL_HALF_FLOAT) ||
((n_bits_for_channel_0 == 32) && (n_bits_for_channel_1 == 32) && (n_bits_for_channel_2 == 32)))
{
unsigned int* result_traveller32 = (unsigned int*)result_traveller;
*result_traveller32 = channels[0]->unsigned_integer_data;
result_traveller32++;
*result_traveller32 = channels[1]->unsigned_integer_data;
result_traveller32++;
*result_traveller32 = channels[2]->unsigned_integer_data;
result_traveller += 3 * 4;
}
else
// RGB8
if (n_bits_for_channel_0 == 8 && n_bits_for_channel_1 == 8 && n_bits_for_channel_2 == 8)
{
*result_traveller = channels[0]->unsigned_byte_data;
result_traveller++;
*result_traveller = channels[1]->unsigned_byte_data;
result_traveller++;
*result_traveller = channels[2]->unsigned_byte_data;
result_traveller++;
}
else
// RGB565
if (n_bits_for_channel_0 == 5 && n_bits_for_channel_1 == 6 && n_bits_for_channel_2 == 5)
{
unsigned short* result_traveller16 = (unsigned short*)result_traveller;
*result_traveller16 = (channels[0]->unsigned_byte_data << 11) + (channels[1]->unsigned_byte_data << 5) +
(channels[2]->unsigned_byte_data);
result_traveller += 2;
}
else
{
// Unsupported bit layout
DE_ASSERT(0);
return false;
}
}
else if (channels[0] != NULL && channels[1] != NULL)
{
// RG32
if ((type == GL_HALF_FLOAT) || ((n_bits_for_channel_0 == 32) && (n_bits_for_channel_1 == 32)))
{
unsigned int* result_traveller32 = (unsigned int*)result_traveller;
*result_traveller32 = channels[0]->unsigned_integer_data;
result_traveller32++;
*result_traveller32 = channels[1]->unsigned_integer_data;
result_traveller += 8;
}
else
// RG16
if (n_bits_for_channel_0 == 16 && n_bits_for_channel_1 == 16)
{
unsigned short* result_traveller16 = (unsigned short*)result_traveller;
*result_traveller16 = channels[0]->unsigned_short_data;
result_traveller16++;
*result_traveller16 = channels[1]->unsigned_short_data;
result_traveller += 4;
}
else
// RG8
if (n_bits_for_channel_0 == 8 && n_bits_for_channel_1 == 8)
{
*result_traveller = channels[0]->unsigned_byte_data;
result_traveller++;
*result_traveller = channels[1]->unsigned_byte_data;
result_traveller++;
}
else
{
// Unsupported bit layout
DE_ASSERT(0);
return false;
}
}
else if (channels[0] != NULL)
{
// R32
if (type == GL_HALF_FLOAT || n_bits_for_channel_0 == 32)
{
unsigned int* result_traveller32 = (unsigned int*)result_traveller;
*result_traveller32 = channels[0]->unsigned_integer_data;
result_traveller += 4;
}
else
// R16
if (n_bits_for_channel_0 == 16)
{
unsigned short* result_traveller16 = (unsigned short*)result_traveller;
*result_traveller16 = channels[0]->unsigned_short_data;
result_traveller += 2;
}
else
// R8
if (n_bits_for_channel_0 == 8)
{
*result_traveller = channels[0]->unsigned_byte_data;
result_traveller++;
}
else
{
// Unsupported bit layout
DE_ASSERT(0);
return false;
}
}
else
{
// Unrecognized channel data layout.
DE_ASSERT(0);
return false;
}
} // for (all pixels)
return true;
}
/** Retrieves number of bits used for a single channel, were it stored in
* @param channel_data_type internal channel data type.
*
* @param channel_data_type Channel data type to consider.
* @param out_n_bits Deref will be used to store the amount of bits.
* Cannot be NULL.
*
* @return GTFtrue if successful, GTFfalse otherwise.
**/
bool RequiredCase::getNumberOfBitsForChannelDataType(ChannelDataType channel_data_type, int* out_n_bits)
{
DE_ASSERT(out_n_bits != NULL);
switch (channel_data_type)
{
case CHANNEL_DATA_TYPE_SIGNED_BYTE_8BITS:
*out_n_bits = 8;
return true;
case CHANNEL_DATA_TYPE_SIGNED_INTEGER_32BITS:
*out_n_bits = 32;
return true;
case CHANNEL_DATA_TYPE_SIGNED_SHORT_16BITS:
*out_n_bits = 16;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_1BIT:
*out_n_bits = 1;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_2BITS:
*out_n_bits = 2;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_4BITS:
*out_n_bits = 4;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_5BITS:
*out_n_bits = 5;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_6BITS:
*out_n_bits = 6;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_BYTE_8BITS:
*out_n_bits = 8;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_INTEGER_32BITS:
*out_n_bits = 32;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_SHORT_10BITS:
*out_n_bits = 10;
return true;
case CHANNEL_DATA_TYPE_UNSIGNED_SHORT_16BITS:
*out_n_bits = 16;
return true;
case CHANNEL_DATA_TYPE_FLOAT:
*out_n_bits = 32;
return true;
case CHANNEL_DATA_TYPE_NONE:
return true;
}
// Unrecognized channel data type
DE_ASSERT(0);
return false;
}
/** Retrieves information on channel order for user-specified internal format+type
* combination.
*
* @param internalformat GLES internal format to consider.
* @param type GLES type to consider.
* @param out_channel_order Deref will be used to store requested information.
* Cannot be NULL.
*
* @return GTFtrue if successful, GTFfalse otherwise.
**/
bool RequiredCase::getChannelOrderForInternalformatAndType(GLenum internalformat, GLenum type,
ChannelOrder* out_channel_order)
{
GLenum format = GL_NONE;
DE_ASSERT(out_channel_order != NULL);
// Determine the order
if (!getFormatForInternalformat(internalformat, &format))
{
DE_ASSERT(0);
return false;
}
switch (format)
{
case GL_RED:
case GL_RED_INTEGER:
// Only one order is sane
*out_channel_order = CHANNEL_ORDER_R;
return true;
case GL_RG:
case GL_RG_INTEGER:
// Only one order is sane
*out_channel_order = CHANNEL_ORDER_RG;
return true;
case GL_RGB:
case GL_RGB_INTEGER:
// Two options here
if (type == GL_UNSIGNED_INT_10F_11F_11F_REV || type == GL_UNSIGNED_INT_5_9_9_9_REV)
*out_channel_order = CHANNEL_ORDER_BGR;
else
*out_channel_order = CHANNEL_ORDER_RGB;
return true;
case GL_RGBA:
case GL_RGBA_INTEGER:
// Two options here
if (type == GL_UNSIGNED_INT_2_10_10_10_REV)
*out_channel_order = CHANNEL_ORDER_ABGR;
else
*out_channel_order = CHANNEL_ORDER_RGBA;
return true;
default:
// Unrecognized format?
DE_ASSERT(0);
return false;
}
return false;
}
/** Creates objects required to support non color-renderable internalformats of texture objects.
* There are different objects created for each combination of float/integer/unsigned integer internalformats
* of source and destination texture objects created.
*
* @param f_src_f_dst_internalformat_ptr Deref will be used to store created object IDs for
* float source and float destination texture object.
* Cannot be NULL.
* @param i_src_i_dst_internalformat_ptr Deref will be used to store created object IDs for
* integer source and integer destination texture object.
* Cannot be NULL.
* @param ui_src_ui_dst_internalformat_ptr Deref will be used to store created object IDs for
* unsigned integer source and unsigned integer destination texture object.
* Cannot be NULL.
* @param source_attachment_type Tells what GL object (or which texture target)
* should be used as a read buffer for a glCopyTexImage2D call.
* @param destination_attachment_type Tells which texture target should be used for
* a glCopyTexImage2D() call.
*
* @return true if successful, false otherwise.
*/
bool RequiredCase::generateObjectsToSupportNonColorRenderableInternalformats()
{
// if (failed to prepare objects for float->float shader-based checks)
if (!prepareSupportForNonRenderableTexture(m_f_src_f_dst_internalformat, DATA_SAMPLER_FLOAT, DATA_SAMPLER_FLOAT,
m_source_attachment_type, m_destination_attachment_type))
{
return false;
}
// if (failed to prepare objects for int->int shader-based checks)
if (!prepareSupportForNonRenderableTexture(m_i_src_i_dst_internalformat, DATA_SAMPLER_INTEGER, DATA_SAMPLER_INTEGER,
m_source_attachment_type, m_destination_attachment_type))
{
return false;
}
// if (failed to prepare objects for uint->uint shader-based checks)
if (!prepareSupportForNonRenderableTexture(m_ui_src_ui_dst_internalformat, DATA_SAMPLER_UNSIGNED_INTEGER,
DATA_SAMPLER_UNSIGNED_INTEGER, m_source_attachment_type,
m_destination_attachment_type))
{
return false;
}
return true;
}
/** Creates and prepares buffer and program objects to be used for non-renderable texture support.
* In case the destination texture's internalformat is not renderable,
* glReadPixels() cannot be issued to retrieve texture object data.
* Instead, a program object is used to retrieve and compare source and destination texture data.
* This function creates and prepares all objects needed to support this approach.
*
* @param objects_ptr Deref will be used for storing generated object ids. Cannot be NULL.
* @param src_texture_sampler_type Type of the sampler to be used for sampling source texture (float/int/uint).
* @param dst_texture_sampler_type Type of the sampler to be used for sampling destination texture (float/int/uint).
* @param source_attachment_type
* @param destination_attachment_type
*
* @return true if the operation succeeded (no error was generated),
* false otherwise.
*/
bool RequiredCase::prepareSupportForNonRenderableTexture(NonRenderableInternalformatSupportObjects& objects,
DataSamplerType src_texture_sampler_type,
DataSamplerType dst_texture_sampler_type,
GLenum source_attachment_type,
GLenum destination_attachment_type)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
const GLuint compare_result_size = NUMBER_OF_POINTS_TO_DRAW * sizeof(GLint);
GLuint destination_buffer_data_size = 0;
GLuint source_buffer_data_size = 0;
const GLchar* varying_names[] = { "compare_result", "src_texture_pixel_values", "dst_texture_pixel_values" };
const GLsizei varying_names_count = DE_LENGTH_OF_ARRAY(varying_names);
// Create program and shader objects.
objects.program_object_id = gl.createProgram();
objects.fragment_shader_object_id = gl.createShader(GL_FRAGMENT_SHADER);
objects.vertex_shader_object_id = gl.createShader(GL_VERTEX_SHADER);
// Generate buffer and transform feedback objects.
gl.genTransformFeedbacks(1, &objects.transform_feedback_object_id);
gl.genBuffers(1, &objects.comparison_result_buffer_object_id);
gl.genBuffers(1, &objects.src_texture_pixels_buffer_object_id);
gl.genBuffers(1, &objects.dst_texture_pixels_buffer_object_id);
gl.genBuffers(1, &objects.src_texture_coordinates_buffer_object_id);
gl.genBuffers(1, &objects.dst_texture_coordinates_buffer_object_id);
// Calculate texture data size depending on source and destination sampler types.
if (!calculateBufferDataSize(src_texture_sampler_type, &source_buffer_data_size))
return false;
if (!calculateBufferDataSize(dst_texture_sampler_type, &destination_buffer_data_size))
return false;
// Initialize buffer objects storage.
gl.bindBuffer(GL_ARRAY_BUFFER, objects.comparison_result_buffer_object_id);
gl.bufferData(GL_ARRAY_BUFFER, compare_result_size, NULL, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
gl.bindBuffer(GL_ARRAY_BUFFER, objects.src_texture_pixels_buffer_object_id);
gl.bufferData(GL_ARRAY_BUFFER, source_buffer_data_size, NULL, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
gl.bindBuffer(GL_ARRAY_BUFFER, objects.dst_texture_pixels_buffer_object_id);
gl.bufferData(GL_ARRAY_BUFFER, destination_buffer_data_size, NULL, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
// Initialize texture coordinates
gl.bindBuffer(GL_ARRAY_BUFFER, objects.src_texture_coordinates_buffer_object_id);
gl.bufferData(GL_ARRAY_BUFFER, TEXTURE_COORDINATES_ARRAY_SIZE, getTexCoordinates(source_attachment_type),
GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
gl.vertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
gl.bindBuffer(GL_ARRAY_BUFFER, objects.dst_texture_coordinates_buffer_object_id);
gl.bufferData(GL_ARRAY_BUFFER, TEXTURE_COORDINATES_ARRAY_SIZE, getTexCoordinates(destination_attachment_type),
GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
// Bind buffer objects to GL_TRANSFORM_FEEDBACK target at specific indices.
gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, COMPARISON_RESULT_BUFFER_OBJECT_INDEX,
objects.comparison_result_buffer_object_id, 0, compare_result_size);
gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, SOURCE_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX,
objects.src_texture_pixels_buffer_object_id, 0, source_buffer_data_size);
gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, DESTINATION_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX,
objects.dst_texture_pixels_buffer_object_id, 0, destination_buffer_data_size);
// Specify values for transform feedback.
gl.transformFeedbackVaryings(objects.program_object_id, varying_names_count, varying_names, GL_SEPARATE_ATTRIBS);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings");
// Prepare program and shader objects.
if (!prepareProgramAndShaderObjectsToSupportNonRenderableTexture(
objects.program_object_id, objects.fragment_shader_object_id, objects.vertex_shader_object_id,
src_texture_sampler_type, dst_texture_sampler_type))
{
return false;
}
// Retrieve uniform locations.
if (!getUniformLocations(objects.program_object_id, &objects.src_2D_texture_uniform_location,
&objects.src_2DArray_texture_uniform_location, &objects.src_3D_texture_uniform_location,
&objects.src_Cube_texture_uniform_location, &objects.dst_2D_texture_uniform_location,
&objects.dst_Cube_texture_uniform_location, &objects.channels_to_compare_uniform_location,
&objects.samplers_to_use_uniform_location))
{
return false;
}
return true;
}
/** Calculate size needed for texture object data storage to successfully
* capture all the data needed.
* For simplicity, we assume all internalformats of our concern use four
* components. It's not a dreadful waste of memory, given amount of data
* we will be checking for later on anyway.
*
* @param _data_sampler_type Type of the sampler used to read the data.
* @param texture_data_size_ptr Deref will be used to stored calculated result.
* Cannot be NULL.
*
* @return true if successful, false otherwise.
*/
bool RequiredCase::calculateBufferDataSize(DataSamplerType sampler_type, GLuint* buffer_data_size_ptr)
{
if (buffer_data_size_ptr == NULL)
{
m_testCtx.getLog() << tcu::TestLog::Message << "NULL pointer passed as a deref to store calculated result."
<< tcu::TestLog::EndMessage;
return false;
}
switch (sampler_type)
{
case DATA_SAMPLER_FLOAT:
*buffer_data_size_ptr = NUMBER_OF_POINTS_TO_DRAW * NUMBER_OF_ELEMENTS_IN_VEC4 * sizeof(GLfloat);
return true;
case DATA_SAMPLER_INTEGER:
*buffer_data_size_ptr = NUMBER_OF_POINTS_TO_DRAW * NUMBER_OF_ELEMENTS_IN_VEC4 * sizeof(GLint);
return true;
case DATA_SAMPLER_UNSIGNED_INTEGER:
*buffer_data_size_ptr = NUMBER_OF_POINTS_TO_DRAW * NUMBER_OF_ELEMENTS_IN_VEC4 * sizeof(GLuint);
return true;
default:
m_testCtx.getLog() << tcu::TestLog::Message << "Unrecognized data sampler type." << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** Texture coordinates to use when glReadPixels can't be used to read back the data.
* Different coordinates for different attachment types.
*
* @param attachment_type Texture attachment type
*
* @return Array of 4 3-tuples of texture coordinates to use
*/
const float* RequiredCase::getTexCoordinates(GLenum attachment_type) const
{
static const float texture_coordinates[7][NUMBER_OF_POINTS_TO_DRAW * 4] = {
// 2D texture, 3D texture and 2D array
{ 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0 },
// Cube Map NEGATIVE_X
{ -1, .99f, -.99f, 0, -1, .99f, .99f, 0, -1, -.99f, .99f, 0, -1, -.99f, -.99f, 0 },
// Cube Map NEGATIVE_Y
{ -.99f, -1, .99f, 0, .99f, -1, .99f, 0, .99f, -1, -.99f, 0, -.99f, -1, -.99f, 0 },
// Cube Map NEGATIVE_Z
{ .99f, .99f, -1, 0, -.99f, .99f, -1, 0, -.99f, -.99f, -1, 0, .99f, -.99f, -1, 0 },
// Cube Map POSITIVE_X
{ 1, .99f, .99f, 0, 1, .99f, -.99f, 0, 1, -.99f, -.99f, 0, 1, -.99f, .99f, 0 },
// Cube Map POSITIVE_Y
{ -.99f, 1, -.99f, 0, .99f, 1, -.99f, 0, .99f, 1, .99f, 0, -.99f, 1, .99f, 0 },
// Cube Map POSITIVE_Z
{ -.99f, .99f, 1, 0, .99f, .99f, 1, 0, .99f, -.99f, 1, 0, -.99f, -.99f, 1, 0 },
};
switch (attachment_type)
{
case GL_TEXTURE_2D:
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
return texture_coordinates[0];
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
return texture_coordinates[1];
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
return texture_coordinates[2];
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return texture_coordinates[3];
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
return texture_coordinates[4];
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
return texture_coordinates[5];
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
return texture_coordinates[6];
default:
DE_ASSERT(!"Invalid attachment type!");
return NULL;
}
}
/** Sets source for shader objects, compiles them and attaches to program object.
* Program object can be used to verify whether copying texture image works correctly if
* non-renderable internalformats are considered.
* If all the operations succeeded, the program object is activated.
*
* @param program_object_id ID of a program object to be initialized.
* The value must be a valid program object ID.
* @param fragment_shader_object_id ID of a fragment shader object to be initialized.
* The value must be a valid fragment shader object ID.
* @param vertex_shader_object_id ID of a vertex shader object to be initialized.
* The value must be a valid vertex shader object ID.
* @param src_texture_sampler_type Sampler to be used for sampling source texture object.
* @param dst_texture_sampler_type Sampler to be used for sampling destination texture object.
*
* @return true if the operation succeeded, false otherwise.
*/
bool RequiredCase::prepareProgramAndShaderObjectsToSupportNonRenderableTexture(GLuint program_object_id,
GLuint fragment_shader_object_id,
GLuint vertex_shader_object_id,
DataSamplerType src_texture_sampler_type,
DataSamplerType dst_texture_sampler_type)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Attach shader objects to program object.
gl.attachShader(program_object_id, fragment_shader_object_id);
gl.attachShader(program_object_id, vertex_shader_object_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader");
if (!setSourceForShaderObjectsUsedForNonRenderableTextureSupport(
fragment_shader_object_id, vertex_shader_object_id, src_texture_sampler_type, dst_texture_sampler_type))
{
return false;
}
if (!compileAndCheckShaderCompilationStatus(fragment_shader_object_id))
return false;
if (!compileAndCheckShaderCompilationStatus(vertex_shader_object_id))
return false;
if (!linkAndCheckProgramLinkStatus(program_object_id))
return false;
return true;
}
/** Assigns source code to fragment/vertex shaders which will then be used to verify texture data..
*
* @param fragment_shader_object_id ID of an already created fragment shader.
* @param vertex_shader_object_id ID of an already created vertex shader.
* @param src_texture_sampler_type Type of sampler to be used for sampling source texture object (float/int/uint).
* @param dst_texture_sampler_type Type of sampler to be used for sampling destination texture object (float/int/uint).
*
* @return true if successful, false otherwise.
*/
bool RequiredCase::setSourceForShaderObjectsUsedForNonRenderableTextureSupport(GLuint fragment_shader_object_id,
GLuint vertex_shader_object_id,
DataSamplerType src_texture_sampler_type,
DataSamplerType dst_texture_sampler_type)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
std::map<std::string, std::string> specializationMap;
const GLchar* fragment_shader_source = { "#version 300 es\n"
"void main()\n"
"{}\n" };
static std::string shader_source[3];
const GLchar* vertex_shader_source = NULL;
const GLchar* source = "#version 300 es\n"
"\n"
" uniform highp ${SAMPLER_PREFIX}sampler2D dst_texture2D;\n"
" uniform highp ${SAMPLER_PREFIX}samplerCube dst_textureCube;\n"
" uniform highp ${SAMPLER_PREFIX}sampler2D src_texture2D;\n"
" uniform highp ${SAMPLER_PREFIX}sampler3D src_texture3D;\n"
" uniform highp ${SAMPLER_PREFIX}sampler2DArray src_texture2DArray;\n"
" uniform highp ${SAMPLER_PREFIX}samplerCube src_textureCube;\n"
" uniform int channels_to_compare;\n"
" uniform int samplers_to_use;\n"
"layout(location = 0) in vec4 dst_texture_coord;\n"
"layout(location = 1) in vec4 src_texture_coord;\n"
"${OUT_QUALIFIER} out ${OUT_TYPE} dst_texture_pixel_values;\n"
"${OUT_QUALIFIER} out ${OUT_TYPE} src_texture_pixel_values;\n"
"flat out int compare_result;\n"
"\n"
"void main()\n"
"{\n"
" ${OUT_TYPE} src_texture_data;\n"
" ${OUT_TYPE} dst_texture_data;\n"
" const ${EPSILON_TYPE} epsilon = ${EPSILON_VALUE};\n"
" int result = 1;\n"
" bool compare_red = (channels_to_compare & 0x1) != 0;\n"
" bool compare_green = (channels_to_compare & 0x2) != 0;\n"
" bool compare_blue = (channels_to_compare & 0x4) != 0;\n"
" bool compare_alpha = (channels_to_compare & 0x8) != 0;\n"
" int src_sampler = samplers_to_use & 0xff;\n"
" int dst_sampler = samplers_to_use >> 8;\n"
"\n"
" if (src_sampler == 0)\n"
" {\n"
" src_texture_data = texture(src_texture2D, src_texture_coord.xy);\n"
" }\n"
" else if (src_sampler == 1)\n"
" {\n"
" src_texture_data = texture(src_texture3D, src_texture_coord.xyz);\n"
" }\n"
" else if (src_sampler == 2)\n"
" {\n"
" src_texture_data = texture(src_texture2DArray, src_texture_coord.xyz);\n"
" }\n"
" else\n"
" {\n"
" src_texture_data = texture(src_textureCube, src_texture_coord.xyz);\n"
" }\n"
"\n"
" if (dst_sampler == 0)\n"
" {\n"
" dst_texture_data = texture(dst_texture2D, dst_texture_coord.xy);\n"
" }\n"
" else\n"
" {\n"
" dst_texture_data = texture(dst_textureCube, dst_texture_coord.xyz);\n"
" }\n"
"\n"
" if (compare_red && ${FN}(src_texture_data.x - dst_texture_data.x) > epsilon)\n"
" {\n"
" result = 0;\n"
" }\n"
" if (compare_green && ${FN}(src_texture_data.y - dst_texture_data.y) > epsilon)\n"
" {\n"
" result = 0;\n"
" }\n"
" if (compare_blue && ${FN}(src_texture_data.z - dst_texture_data.z) > epsilon)\n"
" {\n"
" result = 0;\n"
" }\n"
" if (compare_alpha && ${FN}(src_texture_data.w - dst_texture_data.w) > epsilon)\n"
" {\n"
" result = 0;\n"
" }\n"
"\n"
" compare_result = result;\n"
" dst_texture_pixel_values = dst_texture_data;\n"
" src_texture_pixel_values = src_texture_data;\n"
"}\n";
switch (src_texture_sampler_type)
{
case DATA_SAMPLER_FLOAT:
{
switch (dst_texture_sampler_type)
{
case DATA_SAMPLER_FLOAT:
{
specializationMap["SAMPLER_PREFIX"] = " ";
specializationMap["OUT_QUALIFIER"] = " ";
specializationMap["OUT_TYPE"] = " vec4";
specializationMap["EPSILON_TYPE"] = "float";
specializationMap["EPSILON_VALUE"] = "(1.0/255.0)";
specializationMap["FN"] = "abs";
shader_source[0] = tcu::StringTemplate(source).specialize(specializationMap);
vertex_shader_source = shader_source[0].c_str();
break;
}
default:
{
m_testCtx.getLog() << tcu::TestLog::Message << "Unrecognized sampler type for destination texture object."
<< tcu::TestLog::EndMessage;
return false;
}
}
break;
}
case DATA_SAMPLER_INTEGER:
{
switch (dst_texture_sampler_type)
{
case DATA_SAMPLER_INTEGER:
{
specializationMap["SAMPLER_PREFIX"] = "i";
specializationMap["OUT_QUALIFIER"] = "flat";
specializationMap["OUT_TYPE"] = "ivec4";
specializationMap["EPSILON_TYPE"] = "int";
specializationMap["EPSILON_VALUE"] = "0";
specializationMap["FN"] = "abs";
shader_source[1] = tcu::StringTemplate(source).specialize(specializationMap);
vertex_shader_source = shader_source[1].c_str();
break;
}
default:
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "Unrecognized type of internalformat of destination texture object."
<< tcu::TestLog::EndMessage;
return false;
}
}
break;
}
case DATA_SAMPLER_UNSIGNED_INTEGER:
{
switch (dst_texture_sampler_type)
{
case DATA_SAMPLER_UNSIGNED_INTEGER:
{
specializationMap["SAMPLER_PREFIX"] = "u";
specializationMap["OUT_QUALIFIER"] = "flat";
specializationMap["OUT_TYPE"] = "uvec4";
specializationMap["EPSILON_TYPE"] = "uint";
specializationMap["EPSILON_VALUE"] = "0u";
specializationMap["FN"] = "";
shader_source[2] = tcu::StringTemplate(source).specialize(specializationMap);
vertex_shader_source = shader_source[2].c_str();
break;
}
default:
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "Unrecognized type of internalformat of destination texture object."
<< tcu::TestLog::EndMessage;
return false;
}
}
break;
}
default:
{
m_testCtx.getLog() << tcu::TestLog::Message << "Unrecognized type of internalformat of source texture object."
<< tcu::TestLog::EndMessage;
return false;
}
}
// Set shader source for fragment shader object.
gl.shaderSource(fragment_shader_object_id, 1 /* part */, &fragment_shader_source, NULL);
GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource");
// Set shader source for vertex shader object.
gl.shaderSource(vertex_shader_object_id, 1 /* part */, &vertex_shader_source, NULL);
GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource");
return true;
}
/** Compiles a shader object and returns compilation status.
*
* @param shader_object_id ID of a shader object to be compiled.
*
* @return true in case operation succeeded (no error was generated and compilation was successful),
* false otherwise.
*/
bool RequiredCase::compileAndCheckShaderCompilationStatus(GLuint shader_object_id)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Compile shader object.
gl.compileShader(shader_object_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader");
// Check if compilation was successful.
GLint shader_compile_status = GL_FALSE;
gl.getShaderiv(shader_object_id, GL_COMPILE_STATUS, &shader_compile_status);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv");
if (GL_FALSE == shader_compile_status)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Shader object compilation failed." << tcu::TestLog::EndMessage;
// Retrieve shader info log in case of failed compilation.
GLint info_log_length = 0;
gl.getShaderiv(shader_object_id, GL_INFO_LOG_LENGTH, &info_log_length);
if (info_log_length != 0)
{
std::vector<char> log(info_log_length + 1, 0);
gl.getShaderInfoLog(shader_object_id, info_log_length, NULL, &log[0]);
m_testCtx.getLog() << tcu::TestLog::Message << "Shader info log = [" << &log[0] << "]"
<< tcu::TestLog::EndMessage;
}
return false;
}
return true;
}
/** Links a program object and returns link status.
*
* @param program_object_id ID of a program object to be linked.
*
* @return true in case of the operation succeeded (no error was generated and linking end up with success),
* false otherwise.
*/
bool RequiredCase::linkAndCheckProgramLinkStatus(GLuint program_object_id)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
gl.linkProgram(program_object_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram");
// Check if link opearation was successful.
GLint program_link_status = GL_FALSE;
gl.getProgramiv(program_object_id, GL_LINK_STATUS, &program_link_status);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv");
if (GL_FALSE == program_link_status)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
// Retrieve program info log in case of failed linking.
GLint info_log_length = 0;
gl.getProgramiv(program_object_id, GL_INFO_LOG_LENGTH, &info_log_length);
if (info_log_length != 0)
{
std::vector<char> log(info_log_length + 1, 0);
gl.getProgramInfoLog(program_object_id, info_log_length, NULL, &log[0]);
m_testCtx.getLog() << tcu::TestLog::Message << "Program info log = [" << &log[0] << "]"
<< tcu::TestLog::EndMessage;
}
return false;
}
return true;
}
/** Retrieve locations of uniforms (source and destination texture samples)
* and store them in derefs.
*
* @param program_object_id ID of a program object for which uniform locations are to be retrieved.
* @param source_2D_texture_uniform_location_ptr Deref used to store uniform location for a 2D source texture.
* Cannot be NULL.
* @param source_2DArray_texture_uniform_location_ptr Deref used to store uniform location for a 2DArray source texture.
* Cannot be NULL.
* @param source_3D_texture_uniform_location_ptr Deref used to store uniform location for a 3D source texture.
* Cannot be NULL.
* @param source_Cube_texture_uniform_location_ptr Deref used to store uniform location for a Cube source texture.
* Cannot be NULL.
* @param destination_2D_texture_uniform_location_ptr Deref used to store uniform location for a 2D destination texture.
* Cannot be NULL.
* @param destination_Cube_texture_uniform_location_ptr Deref used to store uniform location for a Cube destination texture.
* Cannot be NULL.
* @param channels_to_compare_uniform_location_ptr Deref used to store uniform location for a channels_to_compare.
* Cannot be NULL.
* @param samplers_to_use_uniform_location_ptr Deref used to store uniform location for a samplers_to_use.
* Cannot be NULL.
*
* @return true if the operation succeeded (no error was generated and valid uniform locations were returned),
* false otherwise.
*/
bool RequiredCase::getUniformLocations(GLuint program_object_id, GLint* source_2D_texture_uniform_location_ptr,
GLint* source_2DArray_texture_uniform_location_ptr,
GLint* source_3D_texture_uniform_location_ptr,
GLint* source_Cube_texture_uniform_location_ptr,
GLint* destination_2D_texture_uniform_location_ptr,
GLint* destination_Cube_texture_uniform_location_ptr,
GLint* channels_to_compare_uniform_location_ptr,
GLint* samplers_to_use_uniform_location_ptr)
{
if (source_2D_texture_uniform_location_ptr == NULL || source_2DArray_texture_uniform_location_ptr == NULL ||
source_3D_texture_uniform_location_ptr == NULL || source_Cube_texture_uniform_location_ptr == NULL ||
destination_2D_texture_uniform_location_ptr == NULL || destination_Cube_texture_uniform_location_ptr == NULL ||
channels_to_compare_uniform_location_ptr == NULL || samplers_to_use_uniform_location_ptr == NULL)
{
m_testCtx.getLog() << tcu::TestLog::Message << "NULL pointers passed." << tcu::TestLog::EndMessage;
return false;
}
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Set active program object.
gl.useProgram(program_object_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
GLint destination_2D_texture_uniform_location = -1;
destination_2D_texture_uniform_location = gl.getUniformLocation(program_object_id, "dst_texture2D");
if (destination_2D_texture_uniform_location == -1)
return false;
GLint destination_Cube_texture_uniform_location = -1;
destination_Cube_texture_uniform_location = gl.getUniformLocation(program_object_id, "dst_textureCube");
if (destination_Cube_texture_uniform_location == -1)
return false;
GLint source_2D_texture_uniform_location = -1;
source_2D_texture_uniform_location = gl.getUniformLocation(program_object_id, "src_texture2D");
if (source_2D_texture_uniform_location == -1)
return false;
GLint source_2DArray_texture_uniform_location = -1;
source_2DArray_texture_uniform_location = gl.getUniformLocation(program_object_id, "src_texture2DArray");
if (source_2DArray_texture_uniform_location == -1)
return false;
GLint source_3D_texture_uniform_location = -1;
source_3D_texture_uniform_location = gl.getUniformLocation(program_object_id, "src_texture3D");
if (source_3D_texture_uniform_location == -1)
return false;
GLint source_Cube_texture_uniform_location = -1;
source_Cube_texture_uniform_location = gl.getUniformLocation(program_object_id, "src_textureCube");
if (source_Cube_texture_uniform_location == -1)
return false;
GLint channels_to_compare_uniform_location = -1;
channels_to_compare_uniform_location = gl.getUniformLocation(program_object_id, "channels_to_compare");
if (channels_to_compare_uniform_location == -1)
return false;
GLint samplers_to_use_uniform_location = -1;
samplers_to_use_uniform_location = gl.getUniformLocation(program_object_id, "samplers_to_use");
if (samplers_to_use_uniform_location == -1)
return false;
// We are now ready to store retrieved locations.
*source_2D_texture_uniform_location_ptr = source_2D_texture_uniform_location;
*source_2DArray_texture_uniform_location_ptr = source_2DArray_texture_uniform_location;
*source_3D_texture_uniform_location_ptr = source_3D_texture_uniform_location;
*source_Cube_texture_uniform_location_ptr = source_Cube_texture_uniform_location;
*destination_2D_texture_uniform_location_ptr = destination_2D_texture_uniform_location;
*destination_Cube_texture_uniform_location_ptr = destination_Cube_texture_uniform_location;
*channels_to_compare_uniform_location_ptr = channels_to_compare_uniform_location;
*samplers_to_use_uniform_location_ptr = samplers_to_use_uniform_location;
// Restore default settings.
gl.useProgram(0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
return true;
}
/** Display error message with detailed information.
* The function should be issued only when pixel comparison failed.
*
* @param src_attachment_type Source attachment type.
* @param dst_attachment_type Destination attachment type.
* @param source_pixel_r R channel source pixel value.
* @param source_pixel_g G channel source pixel value.
* @param source_pixel_b B channel source pixel value.
* @param source_pixel_a A channel source pixel value.
* @param source_internalformat Source internalformat.
* @param source_type Source type.
* @param reference_pixel_r R channel reference pixel value.
* @param reference_pixel_g G channel reference pixel value.
* @param reference_pixel_b B channel reference pixel value.
* @param reference_pixel_a A channel reference pixel value.
* @param reference_internalformat Reference internalformat.
* @param reference_type Reference type.
* @param result_pixel_r R channel result pixel value.
* @param result_pixel_g G channel result pixel value.
* @param result_pixel_b B channel result pixel value.
* @param result_pixel_a A channel result pixel value.
* @param result_internalformat Result internalformat.
* @param result_type Type internalformat.
* @param max_epsilon_r Maximum value for an epsilon used for comparison R channel pixel values.
* @param max_epsilon_g Maximum value for an epsilon used for comparison G channel pixel values.
* @param max_epsilon_b Maximum value for an epsilon used for comparison B channel pixel values.
* @param max_epsilon_a Maximum value for an epsilon used for comparison A channel pixel values.
*/
void RequiredCase::displayPixelComparisonFailureMessage(
GLint source_pixel_r, GLint source_pixel_g, GLint source_pixel_b, GLint source_pixel_a,
GLenum source_internalformat, GLenum source_type, GLint reference_pixel_r, GLint reference_pixel_g,
GLint reference_pixel_b, GLint reference_pixel_a, GLenum reference_internalformat, GLenum reference_type,
GLint result_pixel_r, GLint result_pixel_g, GLint result_pixel_b, GLint result_pixel_a,
GLenum result_internalformat, GLenum result_type, GLint max_epsilon_r, GLint max_epsilon_g, GLint max_epsilon_b,
GLint max_epsilon_a)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Conversion failed for source ["
<< getTargetName(m_source_attachment_type) << "] and destination ["
<< getTargetName(m_destination_attachment_type) << "FBO attachment types."
<< "\nSource pixel: [" << source_pixel_r << ", " << source_pixel_g << ", "
<< source_pixel_b << ", " << source_pixel_a << "]\nSource internalformat: ["
<< getInternalformatString(source_internalformat) << "]\nSource type: ["
<< glu::getTypeStr(source_type).toString() << "]\nReference pixel: ["
<< reference_pixel_r << ", " << reference_pixel_g << ", " << reference_pixel_b << ", "
<< reference_pixel_a << "]\nReference internalformat: ["
<< getInternalformatString(reference_internalformat) << "]\nReference type: ["
<< glu::getTypeStr(reference_type).toString() << "]\nResult pixel: ["
<< result_pixel_r << ", " << result_pixel_g << ", " << result_pixel_b << ", " << result_pixel_a
<< "]\nResult internalformat: [" << getInternalformatString(result_internalformat)
<< "]\nType used for glReadPixels(): [" << glu::getTypeStr(result_type).toString()
<< "]\nMaximum epsilon: [" << max_epsilon_r << ", " << max_epsilon_g << ", "
<< max_epsilon_b << ", " << max_epsilon_a << "]" << tcu::TestLog::EndMessage;
}
/** Returns sampler type (float/integer/unsigned integer) that should be used for
* sampling a texture using data stored in specific internalformat.
*
* @param internalformat Internalformat to use for the query.
*
* @return Sampler type to9 be used..
*/
DataSamplerType RequiredCase::getDataSamplerTypeForInternalformat(GLenum internalformat)
{
if (isInternalFormatCompatibleWithFPSampler(internalformat))
return DATA_SAMPLER_FLOAT;
else if (isInternalFormatCompatibleWithIntegerSampler(internalformat))
return DATA_SAMPLER_INTEGER;
else if (isInternalFormatCompatibleWithUnsignedIntegerSampler(internalformat))
return DATA_SAMPLER_UNSIGNED_INTEGER;
else
{
// Unrecognized internal format
DE_ASSERT(0);
}
return DATA_SAMPLER_FLOAT;
}
/** Tells whether internal format @param internalformat is compatible with a floating-point
* texture sampling function.
*
* @param internalformat GLES internal format to consider.
*
* @return true if yes, false otherwise.
**/
bool RequiredCase::isInternalFormatCompatibleWithFPSampler(GLenum internalformat)
{
switch (internalformat)
{
// FP texture() GLSL function should be used for sampling textures using
// the following internalformats
case GL_ALPHA:
case GL_ALPHA8_OES:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH24_STENCIL8:
case GL_LUMINANCE:
case GL_LUMINANCE8_OES:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE8_ALPHA8_OES:
case GL_R8:
case GL_R8_SNORM:
case GL_RG8:
case GL_RG8_SNORM:
case GL_RGB:
case GL_RGB5_A1:
case GL_RGB10_A2:
case GL_RGB565:
case GL_RGB8:
case GL_RGB8_SNORM:
case GL_RGBA:
case GL_RGBA4:
case GL_RGBA8:
case GL_RGBA8_SNORM:
case GL_SRGB8:
case GL_SRGB8_ALPHA8:
// These are strictly floating-point internal formats
case GL_DEPTH_COMPONENT32F:
case GL_DEPTH32F_STENCIL8:
case GL_R11F_G11F_B10F:
case GL_R16F:
case GL_R32F:
case GL_RG16F:
case GL_RG32F:
case GL_RGB16F:
case GL_RGB32F:
case GL_RGB9_E5:
case GL_RGBA16F:
case GL_RGBA32F:
return true;
}
return false;
}
/** Tells whether internal format @param internalformat is compatible with integer
* texture sampling function.
*
* @param internalformat GLES internal format to consider.
*
* @return true if yes, false otherwise.
**/
bool RequiredCase::isInternalFormatCompatibleWithIntegerSampler(GLenum internalformat)
{
switch (internalformat)
{
case GL_R16I:
case GL_R32I:
case GL_R8I:
case GL_RG16I:
case GL_RG32I:
case GL_RG8I:
case GL_RGB16I:
case GL_RGB32I:
case GL_RGB8I:
case GL_RGBA16I:
case GL_RGBA32I:
case GL_RGBA8I:
return true;
}
return false;
}
/** Tells whether internal format @param internalformat is compatible with unsigned integer
* texture sampling function.
*
* @param internalformat GLES internal format to consider.
*
* @return true if yes, false otherwise.
**/
bool RequiredCase::isInternalFormatCompatibleWithUnsignedIntegerSampler(GLenum internalformat)
{
switch (internalformat)
{
case GL_R16UI:
case GL_R32UI:
case GL_R8UI:
case GL_RG16UI:
case GL_RG32UI:
case GL_RG8UI:
case GL_RGB10_A2UI:
case GL_RGB16UI:
case GL_RGB32UI:
case GL_RGB8UI:
case GL_RGBA16UI:
case GL_RGBA32UI:
case GL_RGBA8UI:
return true;
}
return false;
}
/** Deletes all objects which were created to support non-renderable texture internalformats.
*
* @param objects Reference to generated object.
*/
void RequiredCase::destroyObjectsSupportingNonRenderableInternalformats(
NonRenderableInternalformatSupportObjects& objects)
{
unbindAndDestroyBufferObject(objects.comparison_result_buffer_object_id);
unbindAndDestroyBufferObject(objects.src_texture_pixels_buffer_object_id);
unbindAndDestroyBufferObject(objects.dst_texture_pixels_buffer_object_id);
unbindAndDestroyBufferObject(objects.src_texture_coordinates_buffer_object_id);
unbindAndDestroyBufferObject(objects.dst_texture_coordinates_buffer_object_id);
destroyTransformFeedbackObject(objects.transform_feedback_object_id);
destroyProgramAndShaderObjects(objects.program_object_id, objects.fragment_shader_object_id,
objects.vertex_shader_object_id);
objects.comparison_result_buffer_object_id = 0;
objects.dst_texture_pixels_buffer_object_id = 0;
objects.dst_2D_texture_uniform_location = -1;
objects.dst_Cube_texture_uniform_location = -1;
objects.fragment_shader_object_id = 0;
objects.transform_feedback_object_id = 0;
objects.program_object_id = 0;
objects.src_2D_texture_uniform_location = -1;
objects.src_2DArray_texture_uniform_location = -1;
objects.src_3D_texture_uniform_location = -1;
objects.src_Cube_texture_uniform_location = -1;
objects.src_texture_pixels_buffer_object_id = 0;
objects.vertex_shader_object_id = 0;
objects.channels_to_compare_uniform_location = -1;
objects.samplers_to_use_uniform_location = -1;
objects.src_texture_coordinates_buffer_object_id = 0;
objects.dst_texture_coordinates_buffer_object_id = 0;
}
/** Unbind and destroy buffer object which was created for transform feedback purposes.
*
* @param bo_id ID of a buffer object (which was created for transform feedback purposes) to be deleted.
* If not zero, it is assumed that the value corresponds to valid buffer object ID.
*/
void RequiredCase::unbindAndDestroyBufferObject(GLuint bo_id)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Set zero buffer object to be used for GL_TRANSFORM_FEEDBACK_BUFFER.
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, COMPARISON_RESULT_BUFFER_OBJECT_INDEX, 0);
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, SOURCE_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX, 0);
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, DESTINATION_TEXTURE_PIXELS_BUFFER_OBJECT_INDEX, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
if (bo_id != 0)
{
gl.deleteBuffers(1, &bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
}
}
/** Unbind and destroy transform feedback object.
*
* @param transform_feedback_object_id ID of a transform feedback object to be deleted.
* If not zero, it is assumed that the value corresponds
* to valid transform feedback object ID.
*/
void RequiredCase::destroyTransformFeedbackObject(GLuint transform_feedback_object_id)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Set zero transform feedback object to be used.
gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
if (transform_feedback_object_id != 0)
{
gl.deleteTransformFeedbacks(1, &transform_feedback_object_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDestroyTransformFeedbackObject");
}
}
/** Destroy program and shader objects.
*
* @param program_object_id ID of a program object to be deleted.
* If not zero, it is assumed that the value corresponds to valid program object ID.
* @param fragment_shader_id ID of a fragment shader object to be deleted.
* If not zero, it is assumed that the value corresponds to valid shader object ID.
* @param vertex_shader_id ID of a vertex shader object to be deleted.
* If not zero, it is assumed that the value corresponds to valid shader object ID.
*/
void RequiredCase::destroyProgramAndShaderObjects(GLuint program_object_id, GLuint fragment_shader_id,
GLuint vertex_shader_id)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Use zero program object.
gl.useProgram(0);
// Try to destroy fragment shader object.
if (fragment_shader_id != 0)
{
gl.deleteShader(fragment_shader_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader");
}
// Try to destroy vertex shader object.
if (vertex_shader_id != 0)
{
gl.deleteShader(vertex_shader_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader");
}
// Try to destroy program object.
if (program_object_id != 0)
{
gl.deleteProgram(program_object_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram");
}
}
void RequiredCase::unbindColorAttachments()
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
switch (m_source_attachment_type)
{
case GL_RENDERBUFFER:
gl.framebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
break;
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_3D:
gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
break;
default:
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_source_attachment_type, 0, 0);
break;
}
if (gl.getError() != GL_NO_ERROR)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Could not unbind texture objects from read/draw framebuffers"
<< tcu::TestLog::EndMessage;
}
}
void RequiredCase::restoreBindings(GLenum src_attachment_point, GLenum dst_attachment_point, GLint bound_draw_fbo_id,
GLint bound_read_fbo_id)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
gl.disableVertexAttribArray(SRC_TEXTURE_COORDS_ATTRIB_INDEX);
gl.disableVertexAttribArray(DST_TEXTURE_COORDS_ATTRIB_INDEX);
gl.activeTexture(src_attachment_point);
gl.bindTexture(getGeneralTargetForDetailedTarget(m_source_attachment_type), 0);
gl.activeTexture(dst_attachment_point);
gl.bindTexture(getGeneralTargetForDetailedTarget(m_destination_attachment_type), 0);
gl.activeTexture(GL_TEXTURE0);
// Restore previous framebuffer bindings.
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, bound_draw_fbo_id);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, bound_read_fbo_id);
}
/* SPECIFICATION:
*
* This conformance test verifies that glCopyTexImage2D() implementation does NOT
* accept internalformats that are incompatible with effective internalformat of
* current read buffer.
*
* The test starts from creating a framebuffer object, which is then bound to
* GL_READ_FRAMEBUFFER target. It then enters two-level loop:
*
* a) First level determines source attachment type: this could either be a 2D texture/cube-map
* face mip-map, a specific mip-map of a slice coming from a 2D texture array OR a 3D texture,
* or finally a render-buffer. All of these can be bound to an attachment point that is
* later pointed to by read buffer configuration.
* b) Second level configures attachment type of destination. Since glCopyTexImage2D()
* specification limits accepted targets, only 2D texture or cube-map face targets are
* accepted.
*
* For each viable source/destination configuration, the test then enters another two-level loop:
*
* I) First sub-level determines what internal format should be used for the source attachment.
* All texture formats required from a conformant GLES3.0 implementation are iterated over.
* II) Second sub-level determines internal format that should be passed as a parameter to
* a glCopyTexImage2D() call.
*
* For each internal format pair, the test creates and configures a corresponding GL object and
* attaches it to the read framebuffer. The test also uses a pre-generated texture object that
* should be re-configured with each glCopyTexImage2D) call.
*
* The test then loops over all supported format+type combinations for the internal-format considered
* and feeds them into actual glCopyTexImage2D() call. Since we're dealing with a negative test, these
* calls are only made if a source/destination internalformat combination is spec-wise invalid and
* should result in an error. If the implementation accepts a pair that would require indirect
* conversions outside scope of the specification, the test should fail.
*/
class ForbiddenCase : public TestBase
{
public:
ForbiddenCase(deqp::Context& context, GLenum source_attachment_types, GLenum destination_attachment_types);
virtual ~ForbiddenCase();
virtual tcu::TestNode::IterateResult iterate(void);
protected:
bool execute(GLenum src_internal_format, GLenum dst_internal_format, GLuint src_object_id, GLuint dst_object_id);
};
ForbiddenCase::ForbiddenCase(deqp::Context& context, GLenum source_attachment_types,
GLenum destination_attachment_types)
: TestBase(context, source_attachment_types, destination_attachment_types)
{
}
ForbiddenCase::~ForbiddenCase()
{
}
tcu::TestNode::IterateResult ForbiddenCase::iterate(void)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
const Functions& gl = renderContext.getFunctions();
// Create a FBO we will be using throughout the test
GLuint fbo_id = 0;
gl.genFramebuffers(1, &fbo_id);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_id);
// We will be reading from zeroth color attachment
gl.readBuffer(GL_COLOR_ATTACHMENT0);
// Make sure the pixel storage is configured accordingly to our data sets
gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei");
// Sanity checks
DE_ASSERT(m_destination_attachment_type == GL_TEXTURE_2D ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
// Determine general attachment type
GLenum general_attachment_type = getGeneralTargetForDetailedTarget(m_source_attachment_type);
if (general_attachment_type == GL_NONE)
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
// Set up source object
GLuint src_object_id = generateGLObject(m_source_attachment_type);
if (src_object_id == 0)
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
// Set up destination object
GLuint dst_object_id = generateGLObject(m_destination_attachment_type);
if (dst_object_id == 0)
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
// Run through all FBO internal formats
bool result = true;
int dstInternalFormatsCount = DE_LENGTH_OF_ARRAY(copyTexImage2DInternalFormatOrdering);
const int fboInternalFormatsCount = DE_LENGTH_OF_ARRAY(fboEffectiveInternalFormatOrdering);
for (int fboInternalFormatIndex = 0; fboInternalFormatIndex < fboInternalFormatsCount; ++fboInternalFormatIndex)
{
GLenum fboInternalIormat = fboEffectiveInternalFormatOrdering[fboInternalFormatIndex];
// Run through all destination internal formats
for (int dstInternalFormatUndex = 0; dstInternalFormatUndex < dstInternalFormatsCount; ++dstInternalFormatUndex)
{
GLenum dstInternalFormat = copyTexImage2DInternalFormatOrdering[dstInternalFormatUndex];
if (!execute(fboInternalIormat, dstInternalFormat, src_object_id, dst_object_id))
{
// At least one conversion was invalid or failed. Test should
// fail, but let's continue iterating over internalformats.
result = false;
}
}
}
// Release GL objects before we continue
if (dst_object_id != 0)
destroyGLObject(m_destination_attachment_type, dst_object_id);
if (src_object_id != 0)
destroyGLObject(m_source_attachment_type, src_object_id);
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
/** This function verifies if glCopyTexImage2D() implementation forbids conversions that
* are considered forbidden by GLES3.0.3 spec. For more detailed description, please
* consult specification of copy_tex_image_conversions_forbidden conformance test.
*
* @param src_internalformat GLES internalformat that read buffer should use.
* @param src_object_id ID of the source GL object of @param source_attachment_type
* type.
* @param dst_internalformat GLES internalformat that should be used for gl.readPixels() call.
* This should NOT be the expected effective internalformat!
* @param dst_object_id ID of the destination GL object of
* @param destination_attachment_type type.
*
* @return true if successful, false otherwise.
*/
bool ForbiddenCase::execute(GLenum src_internal_format, GLenum dst_internal_format, GLuint src_object_id,
GLuint dst_object_id)
{
// Allocate the max possible size for the texture data (4 compoenents of 4 bytes each)
static char fbo_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4 * 4];
GLenum fbo_format = GL_NONE;
GLenum fbo_type = GL_NONE;
GLenum general_destination_attachment_type = getGeneralTargetForDetailedTarget(m_destination_attachment_type);
int n_src_pair = 0;
bool result = true;
// Sanity checks
DE_ASSERT(m_destination_attachment_type == GL_TEXTURE_2D ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
m_destination_attachment_type == GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
// Skip the internalformat if it's non-renderable and we're trying to set up a renderbuffer source.
if (m_source_attachment_type == GL_RENDERBUFFER && !isValidRBOInternalFormat(src_internal_format))
return true;
// Try using all compatible format+type pairs for
const Functions& gl = m_context.getRenderContext().getFunctions();
while (getFormatAndTypeCompatibleWithInternalformat(src_internal_format, n_src_pair, &fbo_format, &fbo_type))
{
// Do not test internal formats that are not deemed renderable by GLES implementation we're testing
if (!isColorRenderableInternalFormat(src_internal_format))
break;
// Set up data to be used for source. Note we don't really care much about the data anyway because we want to run
// negative tests, but in case the conversion is incorrectly allowed, we do not want this fact to be covered by
// missing source attachment data
if (!configureGLObject(1, m_source_attachment_type, src_object_id, src_internal_format, fbo_format, fbo_type,
fbo_data))
return false;
// Good. Check if the conversion is forbidden - if so, we can run a negative test! */
if (!isFBOEffectiveInternalFormatCompatibleWithDestinationInternalFormat(src_internal_format,
dst_internal_format))
{
#if 0
m_testCtx.getLog() << tcu::TestLog::Message
<< "Testing conversion [" << getInternalformatString(src_internal_format)
<< "]=>[" << getInternalformatString(dst_internal_format)
<< "] for source target [" << GetTargetName(m_source_attachment_type)
<< "] and destination target [" << GetTargetName(m_destination_attachment_type) << "]",
<< tcu::TestLog::EndMessage;
#endif
// Ask the implementation to perform the conversion!
gl.bindTexture(general_destination_attachment_type, dst_object_id);
gl.copyTexImage2D(m_destination_attachment_type, 0, dst_internal_format, 0 /* x */, 0 /* y */,
TEXTURE_WIDTH, TEXTURE_HEIGHT, 0 /* border */);
gl.bindTexture(general_destination_attachment_type, 0);
// Has the conversion failed as expected?
GLenum error_code = gl.getError();
if (error_code == GL_NO_ERROR)
{
m_testCtx.getLog() << tcu::TestLog::Message << "[" << getInternalformatString(src_internal_format)
<< "]=>[" << getInternalformatString(dst_internal_format)
<< "] conversion [src target=" << getTargetName(m_source_attachment_type)
<< ", dst target=" << getTargetName(m_destination_attachment_type)
<< "] supported contrary to GLES3.0 spec." << tcu::TestLog::EndMessage;
// This test is now considered failed
result = false;
}
else if (error_code != GL_INVALID_OPERATION)
{
m_testCtx.getLog() << tcu::TestLog::Message << "[" << getInternalformatString(src_internal_format)
<< "]=>[" << getInternalformatString(dst_internal_format)
<< "] conversion [src target=" << getTargetName(m_source_attachment_type)
<< ", dst target=" << getTargetName(m_destination_attachment_type) << "] caused ["
<< error_code << "] error instead of GL_INVALID_OPERATION."
<< tcu::TestLog::EndMessage;
// This test is now considered failed
result = false;
}
}
n_src_pair++;
// If we're copying from a renderbuffer, we don't really care about compatible format+type pairs, as
// the effective internalformat is explicitly configured by gl.renderbufferStorage() call.
if (m_source_attachment_type == GL_RENDERBUFFER)
break;
} // for (all compatible format+type pairs)
return result;
}
CopyTexImageConversionsTests::CopyTexImageConversionsTests(deqp::Context& context)
: TestCaseGroup(context, "copy_tex_image_conversions", "")
{
}
void CopyTexImageConversionsTests::init()
{
// Types of objects that can be used as source attachments for conversion process
const GLenum sourceAttachmentTypes[] = { GL_TEXTURE_2D,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_3D,
GL_RENDERBUFFER };
// Types of objects that can be used as destination attachments for conversion process
const GLenum destinationAttachmentTypes[] = {
GL_TEXTURE_2D,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
};
// Set up conversion database
de::SharedPtr<ConversionDatabase> conversionDatabase(new ConversionDatabase());
TestCaseGroup* requiredGroup = new deqp::TestCaseGroup(m_context, "required", "");
TestCaseGroup* forbiddenGroup = new deqp::TestCaseGroup(m_context, "forbidden", "");
for (int srcAttachmentIndex = 0; srcAttachmentIndex < DE_LENGTH_OF_ARRAY(sourceAttachmentTypes);
++srcAttachmentIndex)
{
GLenum srcAttachmentType = sourceAttachmentTypes[srcAttachmentIndex];
for (int dstAttachmentIndex = 0; dstAttachmentIndex < DE_LENGTH_OF_ARRAY(destinationAttachmentTypes);
++dstAttachmentIndex)
{
GLenum dstAttachmentType = destinationAttachmentTypes[dstAttachmentIndex];
requiredGroup->addChild(
new RequiredCase(m_context, conversionDatabase, srcAttachmentType, dstAttachmentType));
forbiddenGroup->addChild(new ForbiddenCase(m_context, srcAttachmentType, dstAttachmentType));
}
}
addChild(forbiddenGroup);
addChild(requiredGroup);
}
} // es3cts namespace