#ifndef _GL4CCOPYIMAGETESTS_HPP #define _GL4CCOPYIMAGETESTS_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 gl4cCopyImageTests.hpp * \brief CopyImageSubData functional tests. */ /*-------------------------------------------------------------------*/ #include "glcTestCase.hpp" #include "glwDefs.hpp" namespace gl4cts { namespace CopyImage { /** Implements functional test. Description follows: * * This test verifies that CopyImageSubData function works as expected. * * Steps: * - create source and destination image objects; * - fill both image objects with different content, also each pixel should * be unique; * - execute CopyImageSubData on both image objects, to copy region from * source image to a region in destination image; * - inspect content of both image objects; * * Test pass if: * - no part of destination image, that is outside of destination region, * was modified, * - destination region contains data from source region, * - source image contents were not modified. * * Use TexImage* routines to create textures. It is required that textures are * complete, therefore TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL have to be * updated with TexParameter manually. * * Use draw operation to update contents of Renderbuffers. * * Tested image dimensions should be NxM where N and M are <7:15>. * * Multi-layered targets should have twelve slices. * * Test with the following mipmap levels: * - 0, * - 1, * - 2. * * Test with the following region locations: * - all four corners, * - all four edge centres, * - image centre, * - whole image. * * Tested region dimensions should be NxN where N is <1:7>. Depth should be * selected so as to affect all image slices. In cases when one image has * single layer and second is multi-layered, than copy operation and inspection * must be repeated for each layer. * * This test should iterate over: * - all valid internal format combinations, * - all valid object target combinations, * - all mipmap level combinations, * - all image dimensions combinations, * - all valid copied regions combinations, * - all valid copied region dimensions combinations. * * Moreover this test should also execute CopyImageSubData to copy image to * itself. In this case it expected that source image will be modified. * * * Implementation notes * There are some configuration preprocessor flags available in cpp file. **/ class FunctionalTest : public deqp::TestCase { public: FunctionalTest(deqp::Context& context); virtual ~FunctionalTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct targetDesc { glw::GLenum m_target; glw::GLuint m_width; glw::GLuint m_height; glw::GLuint m_level; glw::GLenum m_internal_format; glw::GLenum m_format; glw::GLenum m_type; }; struct testCase { targetDesc m_dst; glw::GLuint m_dst_x; glw::GLuint m_dst_y; targetDesc m_src; glw::GLuint m_src_x; glw::GLuint m_src_y; glw::GLuint m_width; glw::GLuint m_height; }; /* Private methods */ void calculateDimmensions(glw::GLenum target, glw::GLuint level, glw::GLuint width, glw::GLuint height, glw::GLuint* out_widths, glw::GLuint* out_heights, glw::GLuint* out_depths) const; void clean(); void cleanPixels(glw::GLubyte** pixels) const; bool compareImages(const targetDesc& left_desc, const glw::GLubyte* left_data, glw::GLuint left_x, glw::GLuint left_y, glw::GLuint left_layer, glw::GLuint left_level, const targetDesc& right_desc, const glw::GLubyte* right_data, glw::GLuint right_x, glw::GLuint right_y, glw::GLuint right_layer, glw::GLuint right_level, glw::GLuint region_width, glw::GLuint region_height) const; bool copyAndVerify(const testCase& test_case, const glw::GLubyte** dst_pixels, const glw::GLubyte** src_pixels); void getCleanRegions(const testCase& test_case, glw::GLuint dst_level, glw::GLuint out_corners[4][4], glw::GLuint& out_n_corners) const; void getPixels(glw::GLuint name, const targetDesc& desc, glw::GLuint level, glw::GLubyte* out_pixels) const; void prepareDstPxls(const targetDesc& desc, glw::GLubyte** out_pixels) const; void prepareSrcPxls(const targetDesc& desc, glw::GLenum dst_internal_format, glw::GLubyte** out_pixels) const; void prepareTestCases(glw::GLenum dst_internal_format, glw::GLenum dst_target, glw::GLenum src_internal_format, glw::GLenum src_target); glw::GLuint prepareTexture(const targetDesc& desc, const glw::GLubyte** pixels, glw::GLuint& out_buf_id); bool verify(const testCase& test_case, glw::GLuint dst_layer, const glw::GLubyte** dst_pixels, glw::GLuint src_layer, const glw::GLubyte** src_pixels, glw::GLuint depth); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_rb_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements functional test. Description follows: * * Smoke test: * Tests if function CopyImageSubData accepts and works correctly with: * - all internal formats, * - all valid targets. * Point of the test is to check each internal format and target separately. * * Steps: * - create source and destination image objects using same format and * target for both; * - fill 0 level mipmap of both image objects with different content, also * each pixel should be unique; * - make both image objects complete; * - execute CopyImageSubData on both image objects, to copy contents from * source image to a destination image; * - inspect content of both image objects; * * Test pass if: * - destination image contains data from source image, * - source image contents were not modified. * * Repeat steps for all internal formats, using TEXTURE_2D target. * * Repeat steps for all valid targets, using RGBA32UI internal format. **/ class SmokeTest : public deqp::TestCase { public: SmokeTest(deqp::Context& context); virtual ~SmokeTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_target; glw::GLenum m_internal_format; glw::GLenum m_format; glw::GLenum m_type; }; /* Private methods */ void clean(); void cleanPixels(glw::GLubyte*& pixels) const; bool compareImages(const testCase& test_case, const glw::GLubyte* left_data, const glw::GLubyte* right_data) const; bool copyAndVerify(const testCase& test_case, const glw::GLubyte* src_pixels); void getPixels(glw::GLuint name, const testCase& test_case, glw::GLubyte* out_pixels) const; void prepareDstPxls(const testCase& test_case, glw::GLubyte*& out_pixels) const; void prepareSrcPxls(const testCase& test_case, glw::GLubyte*& out_pixels) const; glw::GLuint prepareTexture(const testCase& test_case, const glw::GLubyte* pixels, glw::GLuint& out_buf_id); bool verify(const testCase& test_case, const glw::GLubyte* src_pixels); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_rb_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; /* Constants */ static const glw::GLuint m_width; static const glw::GLuint m_height; static const glw::GLuint m_depth; }; /** Implements negative test A. Description follows: * * [A] * * Verify that GL_INVALID_ENUM error is generated if either or * is set to any of the proxy texture targets, GL_TEXTURE_BUFFER * or one of the cube-map face selectors. **/ class InvalidTargetTest : public deqp::TestCase { public: InvalidTargetTest(deqp::Context& context); virtual ~InvalidTargetTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_src_target; glw::GLenum m_dst_target; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test B. Description follows: * * [B] * * Verify that usage of a non-matching target for either the source or * destination objects results in a GL_INVALID_ENUM error. **/ class TargetMismatchTest : public deqp::TestCase { public: TargetMismatchTest(deqp::Context& context); virtual ~TargetMismatchTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_tex_target; glw::GLenum m_src_target; glw::GLenum m_dst_target; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test C. Description follows: * * [C] * * Verify that INVALID_OPERATION is generated when the texture provided * to CopyImageSubData is incomplete **/ class IncompleteTexTest : public deqp::TestCase { public: IncompleteTexTest(deqp::Context& context); virtual ~IncompleteTexTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_tex_target; bool m_is_dst_complete; bool m_is_src_complete; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test D. Description follows: * * [D] * * Verify that usage of source/destination objects, internal formats of which * are not compatible, results in GL_INVALID_OPERATION error. **/ class IncompatibleFormatsTest : public deqp::TestCase { public: IncompatibleFormatsTest(deqp::Context& context); virtual ~IncompatibleFormatsTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_tex_target; glw::GLenum m_dst_internal_format; glw::GLenum m_dst_format; glw::GLenum m_dst_type; glw::GLenum m_src_internal_format; glw::GLenum m_src_format; glw::GLenum m_src_type; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test E. Description follows: * * [E] * * Verify that usage of source/destination objects, internal formats of which * do not match in terms of number of samples they can hold, results in * GL_INVALID_OPERATION error. **/ class SamplesMismatchTest : public deqp::TestCase { public: SamplesMismatchTest(deqp::Context& context); virtual ~SamplesMismatchTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_src_target; glw::GLsizei m_src_n_samples; glw::GLenum m_dst_target; glw::GLsizei m_dst_n_samples; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_tex_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test F. Description follows: * * [F] * * Verify that usage of a pair of objects, one of which is defined by * compressed data and the other one has a non-compressed representation, * results in a GL_INVALID_OPERATION error, if the block size of compressed * image is not equal to the texel size of the compressed image. **/ class IncompatibleFormatsCompressionTest : public deqp::TestCase { public: IncompatibleFormatsCompressionTest(deqp::Context& context); virtual ~IncompatibleFormatsCompressionTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_tex_target; glw::GLenum m_dst_internal_format; glw::GLenum m_dst_format; glw::GLenum m_dst_type; glw::GLenum m_src_internal_format; glw::GLenum m_src_format; glw::GLenum m_src_type; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_tex_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test G. Description follows: * * [G] * * Verify that usage of an invalid or argument * generates GL_INVALID_VALUE error. For the purpose of the test, make sure * to iterate over the set of all objects that can be used as source or * destination objects. **/ class InvalidObjectTest : public deqp::TestCase { public: InvalidObjectTest(deqp::Context& context); virtual ~InvalidObjectTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_dst_target; bool m_dst_valid; glw::GLenum m_src_target; bool m_src_valid; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_name; glw::GLuint m_src_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test H. Description follows: * * [H] * * Make sure that GL_INVALID_VALUE error is generated if argument * refers to a non-existent mip-map level for either the source or the * destination object. In particular, make sure that using any value other * than 0 for render-buffers is considered an erroneous action. **/ class NonExistentMipMapTest : public deqp::TestCase { public: NonExistentMipMapTest(deqp::Context& context); virtual ~NonExistentMipMapTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_tex_target; glw::GLuint m_src_level; glw::GLuint m_dst_level; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_tex_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements negative test I. Description follows: * * [I] * * Make sure that using source/destination subregions that exceed the * boundaries of the relevant object generates a GL_INVALID_VALUE error. **/ class ExceedingBoundariesTest : public deqp::TestCase { public: ExceedingBoundariesTest(deqp::Context& context); virtual ~ExceedingBoundariesTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLenum m_tex_target; glw::GLuint m_depth; glw::GLuint m_height; glw::GLuint m_src_x; glw::GLuint m_src_y; glw::GLuint m_src_z; glw::GLuint m_dst_x; glw::GLuint m_dst_y; glw::GLuint m_dst_z; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_tex_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; /* Private constants */ static const glw::GLuint m_region_depth; static const glw::GLuint m_region_height; static const glw::GLuint m_region_width; }; /** Implements negative test J. Description follows: * * [J] * * Assume the source and/or the destination object(s) use(s) a compressed * internal format. Make sure that copy operations requested to operate on * subregions that do not meet the alignment constraints of the internal * format in question, generate GL_INVALID_VALUE error. **/ class InvalidAlignmentTest : public deqp::TestCase { public: InvalidAlignmentTest(deqp::Context& context); virtual ~InvalidAlignmentTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLuint m_height; glw::GLuint m_width; glw::GLuint m_src_x; glw::GLuint m_src_y; glw::GLuint m_dst_x; glw::GLuint m_dst_y; glw::GLenum m_expected_result; }; /* Private methods */ void clean(); /* Private fields */ glw::GLuint m_dst_tex_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; std::vector m_test_cases; }; /** Implements functional test. Description follows: * * [B] * 1. Create a single level integer texture, with BASE_LEVEL and MAX_LEVEL set to 0. * 2. Leave the mipmap filters at the default of GL_NEAREST_MIPMAP_LINEAR and GL_LINEAR. * 3. Do glCopyImageSubData to or from that texture. * 4. Make sure it succeeds and does not raise GL_INVALID_OPERATION. **/ class IntegerTexTest : public deqp::TestCase { public: IntegerTexTest(deqp::Context& context); virtual ~IntegerTexTest() { } /* Implementation of tcu::TestNode methods */ virtual IterateResult iterate(void); private: /* Private types */ struct testCase { glw::GLint m_internal_format; glw::GLuint m_type; }; /* Private methods */ unsigned int createTexture(int width, int height, glw::GLint internalFormat, glw::GLuint type, const void* data, int minFilter, int magFilter); void clean(); /* Private fields */ glw::GLuint m_dst_buf_name; glw::GLuint m_dst_tex_name; glw::GLuint m_src_buf_name; glw::GLuint m_src_tex_name; glw::GLuint m_test_case_index; }; } class CopyImageTests : public deqp::TestCaseGroup { public: CopyImageTests(deqp::Context& context); ~CopyImageTests(void); virtual void init(void); private: CopyImageTests(const CopyImageTests& other); CopyImageTests& operator=(const CopyImageTests& other); }; } /* namespace gl4cts */ #endif // _GL4CCOPYIMAGETESTS_HPP