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