#ifndef _GL3CTEXTURESWIZZLETESTS_HPP #define _GL3CTEXTURESWIZZLETESTS_HPP /*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2015-2016 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 * \brief */ /*-------------------------------------------------------------------*/ /** * \file gl3cTextureSwizzleTests.hpp * \brief Declares test classes for "Texture Swizzle" functionality. */ /*-------------------------------------------------------------------*/ #include "glcTestCase.hpp" #include "glwDefs.hpp" #include "glwEnums.hpp" #include "tcuDefs.hpp" #include "tcuVector.hpp" #include namespace gl3cts { namespace TextureSwizzle { class Utils { public: /** Store information about program object * **/ struct programInfo { programInfo(deqp::Context& context); ~programInfo(); void build(const glw::GLchar* fragment_shader_code, const glw::GLchar* vertex_shader_code); void compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const; void link() const; deqp::Context& m_context; glw::GLuint m_fragment_shader_id; glw::GLuint m_program_object_id; glw::GLuint m_vertex_shader_id; }; /* Public static methods */ static void replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text, std::string& string); }; /** Implements APIErrors test, description follows: * * Verifies that errors are generated as expected. * * Check if: * - INVALID_OPERATION is generated by TexParameter* routines when is * one of [TEXTURE_SWIZZLE_R, TEXTURE_SWIZZLE_G, TEXTURE_SWIZZLE_B, * TEXTURE_SWIZZLE_A] and is not one of [RED, GREEN, BLUE, ALPHA, ZERO, * ONE]; * - INVALID_OPERATION is generated by TexParameter*v routines when is * TEXTURE_SWIZZLE_RGBA and any of four values pointed by is not one of * [RED, GREEN, BLUE, ALPHA, ZERO, ONE]. **/ class APIErrorsTest : public deqp::TestCase { public: /* Public methods */ APIErrorsTest(deqp::Context& context); virtual void deinit(); virtual tcu::TestNode::IterateResult iterate(); private: /* Private methods */ void verifyError(const glw::GLenum expected_error); /* Private fields */ glw::GLuint m_id; }; /** Implements IntialState test, description follows: * * Verifies that intial state is as expected. * * Steps: * - create a texture; * - verify that query for TEXTURE_SWIZZLE_R results with RED; * - verify that query for TEXTURE_SWIZZLE_G results with GREEN; * - verify that query for TEXTURE_SWIZZLE_B results with BLUE; * - verify that query for TEXTURE_SWIZZLE_A results with ALPHA; * - verify that query for TEXTURE_SWIZZLE_RGBA results with [RED, GREEN, BLUE, * ALPHA]. * * Use GetTexParameter to query states. If GL_ARB_direct_state_access is * supported than repeat the steps with GetTextureParameter. * Repeat the steps for all supported texture targets. **/ class IntialStateTest : public deqp::TestCase { public: /* Public methods */ IntialStateTest(deqp::Context& context); virtual void deinit(); virtual tcu::TestNode::IterateResult iterate(); private: /* Private methods */ void verifyValues(const glw::GLenum texture_target); /* Private fields */ glw::GLuint m_id; }; /** Implements Smoke test, description follows: * * Verifies that all swizzle combinations work with all texture access * routines. * * Steps: * - prepare a source texture so that each channel is filled with specific * value; * - for each TEXTURE_SWIZZLE state combination: * * for each channel [R, G, B, A]: * + prepare a 2D single channeled texture with format matching sampled * channel and set it up as output color in framebuffer; * + prepare a program that will implement the following snippet in vertex * stage and output the value of result: * * result = texture(source).C; * * + set swizzle states with channel specific enums; * + draw a full-screen quad; * + verify that the output texture is filled with correct value; * + set swizzle states with RGBA enum; * + draw a full-screen quad; * + verify that the output texture is filled with correct value; * + prepare a program that will implement the following snippet in * fragment stage and output the value of result: * * result = texture(source).C; * * + set swizzle states with channel specific enums; * + draw a full-screen quad; * + verify that the output texture is filled with correct value; * + set swizzle states with RGBA enum; * + draw a full-screen quad; * + verify that the output texture is filled with correct value. * * Value is correct when: * - it matches value assigned to the specified channel; * - it is one for missing alpha channel; * - it is zero for missing channel; * - it is one for ONE; * - it is zero for ZERO. * * Before any draw output texture should be cleared. * Source texture should be RGBA32UI 2D_ARRAY 1x1 of length 1 with * single mipmap at level 0. * Dimenssions of destination texture should be 8x8. * Repeat the steps for the following texture access routines: * - textureProj, * - textureLod, * - textureOffset, * - texelFetch, * - texelFetchOffset, * - textureProjOffset, * - textureLodOffset, * - textureProjLod, * - textureProjLodOffset, * - textureGrad, * - textureGradOffset, * - textureProjGrad, * - textureProjGradOffset. **/ class SmokeTest : public deqp::TestCase { public: /* Public methods */ SmokeTest(deqp::Context& context); SmokeTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description); virtual void deinit(); virtual tcu::TestNode::IterateResult iterate(); protected: /* Protected types */ struct testCase { size_t m_channel_index; size_t m_source_texture_format_index; size_t m_source_texture_target_index; size_t m_texture_access_index; glw::GLint m_texture_swizzle_red; glw::GLint m_texture_swizzle_green; glw::GLint m_texture_swizzle_blue; glw::GLint m_texture_swizzle_alpha; glw::GLint m_texture_sizes[4]; }; /* Protected methods */ void captureAndVerify(const testCase& test_case, size_t output_format_index, glw::GLint output_channel_size, size_t index_of_swizzled_channel); void deinitOutputTexture(); void deinitTextures(); void draw(glw::GLenum target, const glw::GLint* texture_swizzle, bool use_rgba_enum); void executeTestCase(const testCase& test_case); virtual bool fillSourceTexture(size_t format_idx, size_t target_idx); std::string getFragmentShader(const testCase& test_case, size_t output_format_index, bool is_tested_stage); std::string getVertexShader(const testCase& test_case, bool is_tested_stage); bool isTargetSupported(size_t target_idx); bool isTargetSuppByAccess(size_t access_idx, size_t target_idx); bool isTargetSuppByFormat(size_t format_idx, size_t target_idx); void logTestCaseDetials(const testCase& test_case); void prepareAndTestProgram(const testCase& test_case, size_t output_format_index, glw::GLint output_channel_size, size_t index_of_swizzled_channel, bool test_vertex_stage); std::string prepareArguments(const testCase& test_case); std::string prepareCoordinates(const testCase& test_case); std::string prepareDerivatives(const testCase& test_case, size_t index); std::string prepareOffsets(const testCase& test_case); void prepareOutputTexture(size_t format_idx); std::string prepareSample(); void prepareSourceTexture(size_t format_idx, size_t target_idx, glw::GLint out_sizes[4]); void testInit(); virtual void verifyOutputImage(const testCase& test_case, size_t output_format_index, glw::GLint output_channel_size, size_t index_of_swizzled_channel, const glw::GLubyte* data); /* Protected fields */ bool m_is_ms_supported; glw::GLuint m_prepare_fbo_id; glw::GLuint m_out_tex_id; glw::GLuint m_source_tex_id; glw::GLuint m_test_fbo_id; glw::GLuint m_vao_id; /* Protected constants */ static const glw::GLsizei m_depth; static const glw::GLsizei m_height; static const glw::GLsizei m_width; static const glw::GLsizei m_output_height; static const glw::GLsizei m_output_width; }; /** Implements Functional test, description follows: * * Verifies that swizzle is respected for textures of different formats and * targets. * * Modify Smoke in the following aspects: * - repeat the steps for all supported sized internal formats and * texture targets; * - repeat the steps for the texture_swizzle combinations listed below; * - use only texelFetch routine. * * List of texture_swizzle combinations to test: * - ABGR, * - 01RA, * - 0000, * - 1111, * - BBBB. * * Depth-stencil textures can be sampled only via RED channel. Test should set * DEPTH_STENCIL_TEXTURE_MODE to select which channel will be accessed. * * For multisampled targets maximum supported number of samples should be used * and fetch should be done to last sample. * * Support of multisampled targets by TexParameter* routines was introduced in * extension GL_ARB_texture_storage_multisample, which is part of core * specification since 4.3. Therefore texture_swizzle functionality may be used * with multisampled targets only if either context is at least 4.3 or * extension GL_ARB_texture_storage_multisample is supported. **/ class FunctionalTest : public SmokeTest { public: /* Public methods */ FunctionalTest(deqp::Context& context); virtual tcu::TestNode::IterateResult iterate(); protected: /* Protected methods */ virtual bool fillSourceTexture(size_t format_idx, size_t target_idx); bool fillMSTexture(size_t format_idx, size_t target_idx); void prepareProgram(size_t format_idx, Utils::programInfo& program); std::string prepareValues(size_t format_idx); virtual void verifyOutputImage(const testCase& test_case, size_t output_format_index, glw::GLint output_channel_size, size_t index_of_swizzled_channel, const glw::GLubyte* data); private: /* Private types */ class wrongResults : public std::exception { public: wrongResults(const FunctionalTest::testCase& test_case) : m_test_case(test_case) { } virtual ~wrongResults() throw() { } virtual const char* what() const throw() { return "Found pixel with wrong value"; } FunctionalTest::testCase m_test_case; }; }; } /** Group class for GPU Shader 5 conformance tests */ class TextureSwizzleTests : public deqp::TestCaseGroup { public: /* Public methods */ TextureSwizzleTests(deqp::Context& context); virtual ~TextureSwizzleTests() { } virtual void init(void); private: /* Private methods */ TextureSwizzleTests(const TextureSwizzleTests&); TextureSwizzleTests& operator=(const TextureSwizzleTests&); }; } /* gl3cts namespace */ #endif // _GL3CTEXTURESWIZZLETESTS_HPP