1 #ifndef _GL4CCOPYIMAGETESTS_HPP 2 #define _GL4CCOPYIMAGETESTS_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 2015-2016 The Khronos Group Inc. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ /*! 22 * \file gl4cCopyImageTests.hpp 23 * \brief CopyImageSubData functional tests. 24 */ /*-------------------------------------------------------------------*/ 25 26 #include "glcTestCase.hpp" 27 #include "glwDefs.hpp" 28 29 namespace gl4cts 30 { 31 namespace CopyImage 32 { 33 /** Implements functional test. Description follows: 34 * 35 * This test verifies that CopyImageSubData function works as expected. 36 * 37 * Steps: 38 * - create source and destination image objects; 39 * - fill both image objects with different content, also each pixel should 40 * be unique; 41 * - execute CopyImageSubData on both image objects, to copy region from 42 * source image to a region in destination image; 43 * - inspect content of both image objects; 44 * 45 * Test pass if: 46 * - no part of destination image, that is outside of destination region, 47 * was modified, 48 * - destination region contains data from source region, 49 * - source image contents were not modified. 50 * 51 * Use TexImage* routines to create textures. It is required that textures are 52 * complete, therefore TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL have to be 53 * updated with TexParameter manually. 54 * 55 * Use draw operation to update contents of Renderbuffers. 56 * 57 * Tested image dimensions should be NxM where N and M are <7:15>. 58 * 59 * Multi-layered targets should have twelve slices. 60 * 61 * Test with the following mipmap levels: 62 * - 0, 63 * - 1, 64 * - 2. 65 * 66 * Test with the following region locations: 67 * - all four corners, 68 * - all four edge centres, 69 * - image centre, 70 * - whole image. 71 * 72 * Tested region dimensions should be NxN where N is <1:7>. Depth should be 73 * selected so as to affect all image slices. In cases when one image has 74 * single layer and second is multi-layered, than copy operation and inspection 75 * must be repeated for each layer. 76 * 77 * This test should iterate over: 78 * - all valid internal format combinations, 79 * - all valid object target combinations, 80 * - all mipmap level combinations, 81 * - all image dimensions combinations, 82 * - all valid copied regions combinations, 83 * - all valid copied region dimensions combinations. 84 * 85 * Moreover this test should also execute CopyImageSubData to copy image to 86 * itself. In this case it expected that source image will be modified. 87 * 88 * 89 * Implementation notes 90 * There are some configuration preprocessor flags available in cpp file. 91 **/ 92 class FunctionalTest : public deqp::TestCase 93 { 94 public: 95 FunctionalTest(deqp::Context& context); ~FunctionalTest()96 virtual ~FunctionalTest() 97 { 98 } 99 100 /* Implementation of tcu::TestNode methods */ 101 virtual IterateResult iterate(void); 102 103 private: 104 /* Private types */ 105 struct targetDesc 106 { 107 glw::GLenum m_target; 108 glw::GLuint m_width; 109 glw::GLuint m_height; 110 glw::GLuint m_level; 111 glw::GLenum m_internal_format; 112 glw::GLenum m_format; 113 glw::GLenum m_type; 114 }; 115 116 struct testCase 117 { 118 targetDesc m_dst; 119 glw::GLuint m_dst_x; 120 glw::GLuint m_dst_y; 121 targetDesc m_src; 122 glw::GLuint m_src_x; 123 glw::GLuint m_src_y; 124 glw::GLuint m_width; 125 glw::GLuint m_height; 126 }; 127 128 /* Private methods */ 129 void calculateDimmensions(glw::GLenum target, glw::GLuint level, glw::GLuint width, glw::GLuint height, 130 glw::GLuint* out_widths, glw::GLuint* out_heights, glw::GLuint* out_depths) const; 131 132 void clean(); 133 void cleanPixels(glw::GLubyte** pixels) const; 134 135 bool compareImages(const targetDesc& left_desc, const glw::GLubyte* left_data, glw::GLuint left_x, 136 glw::GLuint left_y, glw::GLuint left_layer, glw::GLuint left_level, const targetDesc& right_desc, 137 const glw::GLubyte* right_data, glw::GLuint right_x, glw::GLuint right_y, 138 glw::GLuint right_layer, glw::GLuint right_level, glw::GLuint region_width, 139 glw::GLuint region_height) const; 140 141 bool copyAndVerify(const testCase& test_case, const glw::GLubyte** dst_pixels, const glw::GLubyte** src_pixels); 142 143 void getCleanRegions(const testCase& test_case, glw::GLuint dst_level, glw::GLuint out_corners[4][4], 144 glw::GLuint& out_n_corners) const; 145 146 void getPixels(glw::GLuint name, const targetDesc& desc, glw::GLuint level, glw::GLubyte* out_pixels) const; 147 148 void prepareDstPxls(const targetDesc& desc, glw::GLubyte** out_pixels) const; 149 150 void prepareSrcPxls(const targetDesc& desc, glw::GLenum dst_internal_format, glw::GLubyte** out_pixels) const; 151 152 void prepareTestCases(glw::GLenum dst_internal_format, glw::GLenum dst_target, glw::GLenum src_internal_format, 153 glw::GLenum src_target); 154 155 glw::GLuint prepareTexture(const targetDesc& desc, const glw::GLubyte** pixels, glw::GLuint& out_buf_id); 156 157 bool verify(const testCase& test_case, glw::GLuint dst_layer, const glw::GLubyte** dst_pixels, 158 glw::GLuint src_layer, const glw::GLubyte** src_pixels, glw::GLuint depth); 159 160 /* Private fields */ 161 glw::GLuint m_dst_buf_name; 162 glw::GLuint m_dst_tex_name; 163 glw::GLuint m_rb_name; 164 glw::GLuint m_src_buf_name; 165 glw::GLuint m_src_tex_name; 166 glw::GLuint m_test_case_index; 167 std::vector<testCase> m_test_cases; 168 }; 169 170 /** Implements functional test. Description follows: 171 * 172 * Smoke test: 173 * Tests if function CopyImageSubData accepts and works correctly with: 174 * - all internal formats, 175 * - all valid targets. 176 * Point of the test is to check each internal format and target separately. 177 * 178 * Steps: 179 * - create source and destination image objects using same format and 180 * target for both; 181 * - fill 0 level mipmap of both image objects with different content, also 182 * each pixel should be unique; 183 * - make both image objects complete; 184 * - execute CopyImageSubData on both image objects, to copy contents from 185 * source image to a destination image; 186 * - inspect content of both image objects; 187 * 188 * Test pass if: 189 * - destination image contains data from source image, 190 * - source image contents were not modified. 191 * 192 * Repeat steps for all internal formats, using TEXTURE_2D target. 193 * 194 * Repeat steps for all valid targets, using RGBA32UI internal format. 195 **/ 196 class SmokeTest : public deqp::TestCase 197 { 198 public: 199 SmokeTest(deqp::Context& context); ~SmokeTest()200 virtual ~SmokeTest() 201 { 202 } 203 204 /* Implementation of tcu::TestNode methods */ 205 virtual IterateResult iterate(void); 206 207 private: 208 /* Private types */ 209 struct testCase 210 { 211 glw::GLenum m_target; 212 glw::GLenum m_internal_format; 213 glw::GLenum m_format; 214 glw::GLenum m_type; 215 }; 216 217 /* Private methods */ 218 void clean(); 219 void cleanPixels(glw::GLubyte*& pixels) const; 220 221 bool compareImages(const testCase& test_case, const glw::GLubyte* left_data, const glw::GLubyte* right_data) const; 222 223 bool copyAndVerify(const testCase& test_case, const glw::GLubyte* src_pixels); 224 225 void getPixels(glw::GLuint name, const testCase& test_case, glw::GLubyte* out_pixels) const; 226 227 void prepareDstPxls(const testCase& test_case, glw::GLubyte*& out_pixels) const; 228 229 void prepareSrcPxls(const testCase& test_case, glw::GLubyte*& out_pixels) const; 230 231 glw::GLuint prepareTexture(const testCase& test_case, const glw::GLubyte* pixels, glw::GLuint& out_buf_id); 232 233 bool verify(const testCase& test_case, const glw::GLubyte* src_pixels); 234 235 /* Private fields */ 236 glw::GLuint m_dst_buf_name; 237 glw::GLuint m_dst_tex_name; 238 glw::GLuint m_rb_name; 239 glw::GLuint m_src_buf_name; 240 glw::GLuint m_src_tex_name; 241 glw::GLuint m_test_case_index; 242 std::vector<testCase> m_test_cases; 243 244 /* Constants */ 245 static const glw::GLuint m_width; 246 static const glw::GLuint m_height; 247 static const glw::GLuint m_depth; 248 }; 249 250 /** Implements negative test A. Description follows: 251 * 252 * [A] 253 * * Verify that GL_INVALID_ENUM error is generated if either <srcTarget> or 254 * <dstTarget> is set to any of the proxy texture targets, GL_TEXTURE_BUFFER 255 * or one of the cube-map face selectors. 256 **/ 257 class InvalidTargetTest : public deqp::TestCase 258 { 259 public: 260 InvalidTargetTest(deqp::Context& context); ~InvalidTargetTest()261 virtual ~InvalidTargetTest() 262 { 263 } 264 265 /* Implementation of tcu::TestNode methods */ 266 virtual IterateResult iterate(void); 267 268 private: 269 /* Private types */ 270 struct testCase 271 { 272 glw::GLenum m_src_target; 273 glw::GLenum m_dst_target; 274 glw::GLenum m_expected_result; 275 }; 276 277 /* Private methods */ 278 void clean(); 279 280 /* Private fields */ 281 glw::GLuint m_dst_buf_name; 282 glw::GLuint m_dst_tex_name; 283 glw::GLuint m_src_buf_name; 284 glw::GLuint m_src_tex_name; 285 glw::GLuint m_test_case_index; 286 std::vector<testCase> m_test_cases; 287 }; 288 289 /** Implements negative test B. Description follows: 290 * 291 * [B] 292 * * Verify that usage of a non-matching target for either the source or 293 * destination objects results in a GL_INVALID_ENUM error. 294 **/ 295 class TargetMismatchTest : public deqp::TestCase 296 { 297 public: 298 TargetMismatchTest(deqp::Context& context); ~TargetMismatchTest()299 virtual ~TargetMismatchTest() 300 { 301 } 302 303 /* Implementation of tcu::TestNode methods */ 304 virtual IterateResult iterate(void); 305 306 private: 307 /* Private types */ 308 struct testCase 309 { 310 glw::GLenum m_tex_target; 311 glw::GLenum m_src_target; 312 glw::GLenum m_dst_target; 313 glw::GLenum m_expected_result; 314 }; 315 316 /* Private methods */ 317 void clean(); 318 319 /* Private fields */ 320 glw::GLuint m_dst_buf_name; 321 glw::GLuint m_dst_tex_name; 322 glw::GLuint m_src_buf_name; 323 glw::GLuint m_src_tex_name; 324 glw::GLuint m_test_case_index; 325 std::vector<testCase> m_test_cases; 326 }; 327 328 /** Implements negative test C. Description follows: 329 * 330 * [C] 331 * * Verify that INVALID_OPERATION is generated when the texture provided 332 * to CopyImageSubData is incomplete 333 **/ 334 class IncompleteTexTest : public deqp::TestCase 335 { 336 public: 337 IncompleteTexTest(deqp::Context& context); ~IncompleteTexTest()338 virtual ~IncompleteTexTest() 339 { 340 } 341 342 /* Implementation of tcu::TestNode methods */ 343 virtual IterateResult iterate(void); 344 345 private: 346 /* Private types */ 347 struct testCase 348 { 349 glw::GLenum m_tex_target; 350 bool m_is_dst_complete; 351 bool m_is_src_complete; 352 glw::GLenum m_expected_result; 353 }; 354 355 /* Private methods */ 356 void clean(); 357 358 /* Private fields */ 359 glw::GLuint m_dst_buf_name; 360 glw::GLuint m_dst_tex_name; 361 glw::GLuint m_src_buf_name; 362 glw::GLuint m_src_tex_name; 363 glw::GLuint m_test_case_index; 364 std::vector<testCase> m_test_cases; 365 }; 366 367 /** Implements negative test D. Description follows: 368 * 369 * [D] 370 * * Verify that usage of source/destination objects, internal formats of which 371 * are not compatible, results in GL_INVALID_OPERATION error. 372 **/ 373 class IncompatibleFormatsTest : public deqp::TestCase 374 { 375 public: 376 IncompatibleFormatsTest(deqp::Context& context); ~IncompatibleFormatsTest()377 virtual ~IncompatibleFormatsTest() 378 { 379 } 380 381 /* Implementation of tcu::TestNode methods */ 382 virtual IterateResult iterate(void); 383 384 private: 385 /* Private types */ 386 struct testCase 387 { 388 glw::GLenum m_tex_target; 389 glw::GLenum m_dst_internal_format; 390 glw::GLenum m_dst_format; 391 glw::GLenum m_dst_type; 392 glw::GLenum m_src_internal_format; 393 glw::GLenum m_src_format; 394 glw::GLenum m_src_type; 395 glw::GLenum m_expected_result; 396 }; 397 398 /* Private methods */ 399 void clean(); 400 401 /* Private fields */ 402 glw::GLuint m_dst_buf_name; 403 glw::GLuint m_dst_tex_name; 404 glw::GLuint m_src_buf_name; 405 glw::GLuint m_src_tex_name; 406 glw::GLuint m_test_case_index; 407 std::vector<testCase> m_test_cases; 408 }; 409 410 /** Implements negative test E. Description follows: 411 * 412 * [E] 413 * * Verify that usage of source/destination objects, internal formats of which 414 * do not match in terms of number of samples they can hold, results in 415 * GL_INVALID_OPERATION error. 416 **/ 417 class SamplesMismatchTest : public deqp::TestCase 418 { 419 public: 420 SamplesMismatchTest(deqp::Context& context); ~SamplesMismatchTest()421 virtual ~SamplesMismatchTest() 422 { 423 } 424 425 /* Implementation of tcu::TestNode methods */ 426 virtual IterateResult iterate(void); 427 428 private: 429 /* Private types */ 430 struct testCase 431 { 432 glw::GLenum m_src_target; 433 glw::GLsizei m_src_n_samples; 434 glw::GLenum m_dst_target; 435 glw::GLsizei m_dst_n_samples; 436 glw::GLenum m_expected_result; 437 }; 438 439 /* Private methods */ 440 void clean(); 441 442 /* Private fields */ 443 glw::GLuint m_dst_tex_name; 444 glw::GLuint m_src_tex_name; 445 glw::GLuint m_test_case_index; 446 std::vector<testCase> m_test_cases; 447 }; 448 449 /** Implements negative test F. Description follows: 450 * 451 * [F] 452 * * Verify that usage of a pair of objects, one of which is defined by 453 * compressed data and the other one has a non-compressed representation, 454 * results in a GL_INVALID_OPERATION error, if the block size of compressed 455 * image is not equal to the texel size of the compressed image. 456 **/ 457 class IncompatibleFormatsCompressionTest : public deqp::TestCase 458 { 459 public: 460 IncompatibleFormatsCompressionTest(deqp::Context& context); ~IncompatibleFormatsCompressionTest()461 virtual ~IncompatibleFormatsCompressionTest() 462 { 463 } 464 465 /* Implementation of tcu::TestNode methods */ 466 virtual IterateResult iterate(void); 467 468 private: 469 /* Private types */ 470 struct testCase 471 { 472 glw::GLenum m_tex_target; 473 glw::GLenum m_dst_internal_format; 474 glw::GLenum m_dst_format; 475 glw::GLenum m_dst_type; 476 glw::GLenum m_src_internal_format; 477 glw::GLenum m_src_format; 478 glw::GLenum m_src_type; 479 glw::GLenum m_expected_result; 480 }; 481 482 /* Private methods */ 483 void clean(); 484 485 /* Private fields */ 486 glw::GLuint m_dst_tex_name; 487 glw::GLuint m_src_tex_name; 488 glw::GLuint m_test_case_index; 489 std::vector<testCase> m_test_cases; 490 }; 491 492 /** Implements negative test G. Description follows: 493 * 494 * [G] 495 * * Verify that usage of an invalid <srcTarget> or <dstTarget> argument 496 * generates GL_INVALID_VALUE error. For the purpose of the test, make sure 497 * to iterate over the set of all objects that can be used as source or 498 * destination objects. 499 **/ 500 class InvalidObjectTest : public deqp::TestCase 501 { 502 public: 503 InvalidObjectTest(deqp::Context& context); ~InvalidObjectTest()504 virtual ~InvalidObjectTest() 505 { 506 } 507 508 /* Implementation of tcu::TestNode methods */ 509 virtual IterateResult iterate(void); 510 511 private: 512 /* Private types */ 513 struct testCase 514 { 515 glw::GLenum m_dst_target; 516 bool m_dst_valid; 517 glw::GLenum m_src_target; 518 bool m_src_valid; 519 glw::GLenum m_expected_result; 520 }; 521 522 /* Private methods */ 523 void clean(); 524 525 /* Private fields */ 526 glw::GLuint m_dst_name; 527 glw::GLuint m_src_name; 528 glw::GLuint m_test_case_index; 529 std::vector<testCase> m_test_cases; 530 }; 531 532 /** Implements negative test H. Description follows: 533 * 534 * [H] 535 * * Make sure that GL_INVALID_VALUE error is generated if <level> argument 536 * refers to a non-existent mip-map level for either the source or the 537 * destination object. In particular, make sure that using any value other 538 * than 0 for render-buffers is considered an erroneous action. 539 **/ 540 class NonExistentMipMapTest : public deqp::TestCase 541 { 542 public: 543 NonExistentMipMapTest(deqp::Context& context); ~NonExistentMipMapTest()544 virtual ~NonExistentMipMapTest() 545 { 546 } 547 548 /* Implementation of tcu::TestNode methods */ 549 virtual IterateResult iterate(void); 550 551 private: 552 /* Private types */ 553 struct testCase 554 { 555 glw::GLenum m_tex_target; 556 glw::GLuint m_src_level; 557 glw::GLuint m_dst_level; 558 glw::GLenum m_expected_result; 559 }; 560 561 /* Private methods */ 562 void clean(); 563 564 /* Private fields */ 565 glw::GLuint m_dst_tex_name; 566 glw::GLuint m_src_tex_name; 567 glw::GLuint m_test_case_index; 568 std::vector<testCase> m_test_cases; 569 }; 570 571 /** Implements negative test I. Description follows: 572 * 573 * [I] 574 * * Make sure that using source/destination subregions that exceed the 575 * boundaries of the relevant object generates a GL_INVALID_VALUE error. 576 **/ 577 class ExceedingBoundariesTest : public deqp::TestCase 578 { 579 public: 580 ExceedingBoundariesTest(deqp::Context& context); ~ExceedingBoundariesTest()581 virtual ~ExceedingBoundariesTest() 582 { 583 } 584 585 /* Implementation of tcu::TestNode methods */ 586 virtual IterateResult iterate(void); 587 588 private: 589 /* Private types */ 590 struct testCase 591 { 592 glw::GLenum m_tex_target; 593 glw::GLuint m_depth; 594 glw::GLuint m_height; 595 glw::GLuint m_src_x; 596 glw::GLuint m_src_y; 597 glw::GLuint m_src_z; 598 glw::GLuint m_dst_x; 599 glw::GLuint m_dst_y; 600 glw::GLuint m_dst_z; 601 glw::GLenum m_expected_result; 602 }; 603 604 /* Private methods */ 605 void clean(); 606 607 /* Private fields */ 608 glw::GLuint m_dst_tex_name; 609 glw::GLuint m_src_tex_name; 610 glw::GLuint m_test_case_index; 611 std::vector<testCase> m_test_cases; 612 613 /* Private constants */ 614 static const glw::GLuint m_region_depth; 615 static const glw::GLuint m_region_height; 616 static const glw::GLuint m_region_width; 617 }; 618 619 /** Implements negative test J. Description follows: 620 * 621 * [J] 622 * * Assume the source and/or the destination object(s) use(s) a compressed 623 * internal format. Make sure that copy operations requested to operate on 624 * subregions that do not meet the alignment constraints of the internal 625 * format in question, generate GL_INVALID_VALUE error. 626 **/ 627 class InvalidAlignmentTest : public deqp::TestCase 628 { 629 public: 630 InvalidAlignmentTest(deqp::Context& context); ~InvalidAlignmentTest()631 virtual ~InvalidAlignmentTest() 632 { 633 } 634 635 /* Implementation of tcu::TestNode methods */ 636 virtual IterateResult iterate(void); 637 638 private: 639 /* Private types */ 640 struct testCase 641 { 642 glw::GLuint m_height; 643 glw::GLuint m_width; 644 glw::GLuint m_src_x; 645 glw::GLuint m_src_y; 646 glw::GLuint m_dst_x; 647 glw::GLuint m_dst_y; 648 glw::GLenum m_expected_result; 649 }; 650 651 /* Private methods */ 652 void clean(); 653 654 /* Private fields */ 655 glw::GLuint m_dst_tex_name; 656 glw::GLuint m_src_tex_name; 657 glw::GLuint m_test_case_index; 658 std::vector<testCase> m_test_cases; 659 }; 660 661 /** Implements functional test. Description follows: 662 * 663 * [B] 664 * 1. Create a single level integer texture, with BASE_LEVEL and MAX_LEVEL set to 0. 665 * 2. Leave the mipmap filters at the default of GL_NEAREST_MIPMAP_LINEAR and GL_LINEAR. 666 * 3. Do glCopyImageSubData to or from that texture. 667 * 4. Make sure it succeeds and does not raise GL_INVALID_OPERATION. 668 **/ 669 class IntegerTexTest : public deqp::TestCase 670 { 671 public: 672 IntegerTexTest(deqp::Context& context); ~IntegerTexTest()673 virtual ~IntegerTexTest() 674 { 675 } 676 677 /* Implementation of tcu::TestNode methods */ 678 virtual IterateResult iterate(void); 679 680 private: 681 /* Private types */ 682 struct testCase 683 { 684 glw::GLint m_internal_format; 685 glw::GLuint m_type; 686 }; 687 688 /* Private methods */ 689 unsigned int createTexture(int width, int height, glw::GLint internalFormat, glw::GLuint type, const void* data, 690 int minFilter, int magFilter); 691 void clean(); 692 693 /* Private fields */ 694 glw::GLuint m_dst_buf_name; 695 glw::GLuint m_dst_tex_name; 696 glw::GLuint m_src_buf_name; 697 glw::GLuint m_src_tex_name; 698 glw::GLuint m_test_case_index; 699 }; 700 } 701 702 class CopyImageTests : public deqp::TestCaseGroup 703 { 704 public: 705 CopyImageTests(deqp::Context& context); 706 ~CopyImageTests(void); 707 708 virtual void init(void); 709 710 private: 711 CopyImageTests(const CopyImageTests& other); 712 CopyImageTests& operator=(const CopyImageTests& other); 713 }; 714 } /* namespace gl4cts */ 715 716 #endif // _GL4CCOPYIMAGETESTS_HPP 717