/*------------------------------------------------------------------------- * 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 #include #include 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 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) { if (src_input_rgba_bits[n] != 0) { 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 if (src_attachment_rgba_bits[0] != 0) r_f32 = ((float)src_rgba_intermediate[0]) / (float)((1 << src_attachment_rgba_bits[0]) - 1); if (src_attachment_rgba_bits[1] != 0) g_f32 = ((float)src_rgba_intermediate[1]) / (float)((1 << src_attachment_rgba_bits[1]) - 1); if (src_attachment_rgba_bits[2] != 0) b_f32 = ((float)src_rgba_intermediate[2]) / (float)((1 << src_attachment_rgba_bits[2]) - 1); if (src_attachment_rgba_bits[3] != 0) 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) { if (dst_attachment_rgba_bits[n] != 0) { 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 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(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(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, ¤t_draw_fbo_id); gl.getIntegerv(GL_READ_FRAMEBUFFER_BINDING, ¤t_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 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& 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& 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 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 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 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 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 copied_compare_result_data; std::vector copied_dst_texture_data; std::vector 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& 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 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(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(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(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(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::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::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(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& 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 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 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 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(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