/*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2014-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 es31cTextureStorageMultisampleDependenciesTests.cpp * \brief Implements conformance tests that verify dependencies of * multisample textures on other parts of core ES3.1 API * (ES3.1 only) */ /*-------------------------------------------------------------------*/ #include "es31cTextureStorageMultisampleDependenciesTests.hpp" #include "gluContextInfo.hpp" #include "gluDefs.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "tcuRenderTarget.hpp" #include "tcuTestLog.hpp" #include #include #include #include namespace glcts { /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesFBOIncompleteness1Test::MultisampleTextureDependenciesFBOIncompleteness1Test( Context& context) : TestCase(context, "fbo_with_attachments_of_varying_amount_of_samples", "FBOs with multisample texture attachments, whose amount" " of samples differs between attachments, should be " "considered incomplete") , fbo_id(0) , to_id_multisample_2d_array(0) { memset(to_ids_multisample_2d, 0, sizeof(to_ids_multisample_2d)); } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesFBOIncompleteness1Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_ids_multisample_2d[0] != 0) { gl.deleteTextures(1, to_ids_multisample_2d + 0); to_ids_multisample_2d[0] = 0; } if (to_ids_multisample_2d[1] != 0) { gl.deleteTextures(1, to_ids_multisample_2d + 1); to_ids_multisample_2d[1] = 0; } if (to_id_multisample_2d_array != 0) { gl.deleteTextures(1, &to_id_multisample_2d_array); to_id_multisample_2d_array = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness1Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); bool are_2d_ms_array_tos_supported = m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); /* Set up texture objects */ gl.genTextures(1, to_ids_multisample_2d); if (are_2d_ms_array_tos_supported) { gl.genTextures(1, &to_id_multisample_2d_array); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array); } else { gl.genTextures(1, to_ids_multisample_2d + 1); } GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); /* Query possible sample count values for both texture targets and format used in test */ glw::GLint num_sample_counts_2dms = 1; glw::GLint num_sample_counts_2dms_a = 1; gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_2dms); if (are_2d_ms_array_tos_supported) { gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_2dms_a); } std::vector sample_counts_2dms(num_sample_counts_2dms); std::vector sample_counts_2dms_a(num_sample_counts_2dms_a); gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, num_sample_counts_2dms, &sample_counts_2dms[0]); if (are_2d_ms_array_tos_supported) { gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, GL_RGBA8, GL_SAMPLES, num_sample_counts_2dms_a, &sample_counts_2dms_a[0]); } GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set query internal formats"); /* This will store actual sample counts to be used in test */ glw::GLint samples_attachment_1 = 0; glw::GLint samples_attachment_2 = 0; /* Choose two different sample counts, supported by implementation */ if (are_2d_ms_array_tos_supported) { for (glw::GLint i_2dms = 0; i_2dms < num_sample_counts_2dms; i_2dms++) { for (glw::GLint i_2dms_a = 0; i_2dms_a < num_sample_counts_2dms_a; i_2dms_a++) { if (sample_counts_2dms[i_2dms] != sample_counts_2dms_a[i_2dms_a] && sample_counts_2dms[i_2dms] != 1 && sample_counts_2dms_a[i_2dms_a] != 1) { /* found two differing non-1 sample counts ! */ samples_attachment_1 = sample_counts_2dms[i_2dms]; samples_attachment_2 = sample_counts_2dms_a[i_2dms_a]; } } } } /* if (are_2d_ms_array_tos_supported) */ else { for (glw::GLuint index = 1; index < sample_counts_2dms.size(); ++index) { if (sample_counts_2dms[index - 1] != 1 && sample_counts_2dms[index] != 1 && sample_counts_2dms[index - 1] != sample_counts_2dms[index]) { samples_attachment_1 = sample_counts_2dms[index - 1]; samples_attachment_2 = sample_counts_2dms[index]; break; } } } if (samples_attachment_1 == 0 || samples_attachment_2 == 0) { /* It may be the case implementation support only one sample count on both targets with used format. In such case cannot perform the test - cannot make FBO incomplete due to sample count mismatch */ m_testCtx.setTestResult( QP_TEST_RESULT_NOT_SUPPORTED, "Can't test incomplete FBO due to mismatch sample count: only 1 sample count available"); return STOP; } for (int n_texture_2d = 0; n_texture_2d < (are_2d_ms_array_tos_supported ? 1 : 2); ++n_texture_2d) { gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_ids_multisample_2d[n_texture_2d]); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed."); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, (n_texture_2d == 0) ? samples_attachment_1 : samples_attachment_2, GL_RGBA8, 2, /* width */ 2, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target"); } if (are_2d_ms_array_tos_supported) { gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samples_attachment_2, /* samples */ GL_RGBA8, 2, /* width */ 2, /* height */ 2, /* depth */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR( gl.getError(), "gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target"); } /* Set up a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Set up FBO attachments */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_ids_multisample_2d[0], 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment"); if (are_2d_ms_array_tos_supported) { gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_multisample_2d_array, 0, /* level */ 0); /* layer */ } else { gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, to_ids_multisample_2d[1], 0); /* level */ } GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first color attachment"); /* Make sure the draw framebuffer is considered incomplete */ glw::GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status << "as opposed to expected status: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesFBOIncompleteness2Test::MultisampleTextureDependenciesFBOIncompleteness2Test( Context& context) : TestCase(context, "fbo_with_single_and_multisample_attachments", "FBOs with multisample texture and normal 2D texture attachments " "should be considered incomplete") , fbo_id(0) , to_id_2d(0) , to_id_multisample_2d(0) , to_id_multisample_2d_array(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesFBOIncompleteness2Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id_2d != 0) { gl.deleteTextures(1, &to_id_2d); to_id_2d = 0; } if (to_id_multisample_2d != 0) { gl.deleteTextures(1, &to_id_multisample_2d); to_id_multisample_2d = 0; } if (to_id_multisample_2d_array != 0) { gl.deleteTextures(1, &to_id_multisample_2d_array); to_id_multisample_2d_array = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness2Test::iterate() { bool are_2d_ms_array_tos_supported = m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up texture objects */ gl.genTextures(1, &to_id_2d); gl.genTextures(1, &to_id_multisample_2d); if (are_2d_ms_array_tos_supported) { gl.genTextures(1, &to_id_multisample_2d_array); } gl.bindTexture(GL_TEXTURE_2D, to_id_2d); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d); if (are_2d_ms_array_tos_supported) { gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); gl.texImage2D(GL_TEXTURE_2D, 0, /* level */ GL_RGB565, 2, /* width */ 2, /* height */ 0, /* border */ GL_RGB, /* format */ GL_UNSIGNED_BYTE, /* type */ NULL); /* pixels */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed for GL_TEXTURE_2D texture target"); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ GL_RGB565, 2, /* width */ 2, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target"); if (are_2d_ms_array_tos_supported) { gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */ GL_RGB565, 2, /* width */ 2, /* height */ 2, /* depth */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR( gl.getError(), "gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target"); } /* Set up a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Set up FBO attachments */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_id_2d, 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment"); gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d, 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first color attachment"); /* Make sure the draw framebuffer is considered incomplete */ glw::GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status << "as opposed to expected status: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* Detach the first color attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, 0, /* texture */ 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not detach first color attachment from the draw FBO"); /* Verify the FBO is now considered complete */ fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_status != GL_FRAMEBUFFER_COMPLETE) { m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status << "as opposed to expected status: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } if (are_2d_ms_array_tos_supported) { /* Attach the arrayed multisample texture object */ gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_multisample_2d_array, 0, /* level */ 0); /* layer */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first color attachment"); /* Make sure the draw framebuffer is considered incomplete */ fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Draw framebuffer's completeness status is: " << fbo_status << "as opposed to expected status: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } } /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesFBOIncompleteness3Test::MultisampleTextureDependenciesFBOIncompleteness3Test( Context& context) : TestCase(context, "fbo_with_fixed_and_varying_sample_locations_attachments", "FBOs with multisample texture attachments of different fixed " "sample location settings should be considered incomplete") , fbo_id(0) , to_id_2d_multisample_color_1(0) , to_id_2d_multisample_color_2(0) , to_id_2d_multisample_depth(0) , to_id_2d_multisample_depth_stencil(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesFBOIncompleteness3Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id_2d_multisample_color_1 != 0) { gl.deleteTextures(1, &to_id_2d_multisample_color_1); to_id_2d_multisample_color_1 = 0; } if (to_id_2d_multisample_color_2 != 0) { gl.deleteTextures(1, &to_id_2d_multisample_color_2); to_id_2d_multisample_color_2 = 0; } if (to_id_2d_multisample_depth != 0) { gl.deleteTextures(1, &to_id_2d_multisample_depth); to_id_2d_multisample_depth = 0; } if (to_id_2d_multisample_depth_stencil != 0) { gl.deleteTextures(1, &to_id_2d_multisample_depth_stencil); to_id_2d_multisample_depth_stencil = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness3Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Only execute if GL_MAX_SAMPLES pname value >= 2 */ glw::GLint gl_max_samples_value = 0; gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() generated an error for GL_MAX_SAMPLES pname"); if (gl_max_samples_value < 2) { throw tcu::NotSupportedError("GL_MAX_SAMPLES pname value < 2, skipping"); } /* Only execute if GL_RGBA8, GL_DEPTH_COMPONENT16, GL_DEPTH24_STENCIL8 internalformats * can be rendered to with at least 2 samples per fragment. */ glw::GLint depth_component16_internalformat_max_samples = 0; glw::GLint depth24_stencil8_internalformat_max_samples = 0; glw::GLint rgba8_internalformat_max_samples = 0; gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH_COMPONENT16, GL_SAMPLES, 1, /* bufSize */ &depth_component16_internalformat_max_samples); gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH24_STENCIL8, GL_SAMPLES, 1, /* bufSize */ &depth24_stencil8_internalformat_max_samples); gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, 1, /* bufSize */ &rgba8_internalformat_max_samples); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for at least one GL_SAMPLES query"); if (depth_component16_internalformat_max_samples < 2) { throw tcu::NotSupportedError("GL_SAMPLES is lower than 2 for GL_DEPTH_COMPONENT16 internalformat"); } if (depth24_stencil8_internalformat_max_samples < 2) { throw tcu::NotSupportedError("GL_SAMPLES is lower than 2 for GL_DEPTH24_STENCIL8 internalformat"); } if (rgba8_internalformat_max_samples < 2) { throw tcu::NotSupportedError("GL_SAMPLES is lower than 2 for GL_RGBA8 internalformat"); } /* Set up texture objects */ gl.genTextures(1, &to_id_2d_multisample_color_1); gl.genTextures(1, &to_id_2d_multisample_color_2); gl.genTextures(1, &to_id_2d_multisample_depth); gl.genTextures(1, &to_id_2d_multisample_depth_stencil); GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed"); /* Set up a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Set up first GL_RGBA8 multisample texture storage */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color_1); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ GL_RGBA8, 2, /* width */ 2, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up first GL_RGBA8 multisample texture storage."); /* Set up second GL_RGBA8 multisample texture storage */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color_2); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ GL_RGBA8, 2, /* width */ 2, /* height */ GL_TRUE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up second GL_RGBA8 multisample texture storage."); /* Set up GL_DEPTH_COMPONENT16 multisample texture storage */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_depth); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ GL_DEPTH_COMPONENT16, 2, /* width */ 2, /* height */ GL_TRUE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up GL_DEPTH_COMPONENT16 multisample texture storage."); /* Set up GL_DEPTH24_STENCIL8 multisample texture storage */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_depth_stencil); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ GL_DEPTH24_STENCIL8, 2, /* width */ 2, /* height */ GL_TRUE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up GL_DEPTH24_STENCIL8 multisample texture storage."); /* Set up FBO's zeroth color attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color_1, 0); /* level */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color_2, 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up FBO color attachments"); /* FBO should now be considered incomplete */ glw::GLenum fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* Detach the first color attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, /* texture */ 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not detach FBO's first color attachment"); /* Configure FBO's depth attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_depth, 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBO's depth attachment"); /* FBO should now be considered incomplete */ fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* Detach depth attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */ 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not detach FBO's depth attachment"); /* Configure FBO's depth+stencil attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_depth_stencil, 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBO's depth+stencil attachment"); /* FBO should now be considered incomplete */ fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesFBOIncompleteness4Test::MultisampleTextureDependenciesFBOIncompleteness4Test( Context& context) : TestCase(context, "fbo_with_different_fixedsamplelocations_texture_and_renderbuffer_attachments", "FBOs with multisample texture attachments of different 'fixed sample location' " "settings and with multisampled renderbuffers (of the same amount of samples)" "should be considered incomplete") , fbo_id(0) , rbo_id(0) , to_id_2d_multisample_array_color(0) , to_id_2d_multisample_color(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesFBOIncompleteness4Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (rbo_id != 0) { gl.bindRenderbuffer(GL_RENDERBUFFER, 0); gl.deleteRenderbuffers(1, &rbo_id); } if (to_id_2d_multisample_color != 0) { gl.deleteTextures(1, &to_id_2d_multisample_color); to_id_2d_multisample_color = 0; } if (to_id_2d_multisample_array_color != 0) { gl.deleteTextures(1, &to_id_2d_multisample_array_color); to_id_2d_multisample_array_color = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness4Test::iterate() { bool are_2d_ms_array_tos_supported = m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Only execute if GL_MAX_SAMPLES pname value >= 3 */ glw::GLint gl_max_samples_value = 0; gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() generated an error for GL_MAX_SAMPLES pname"); if (gl_max_samples_value < 3) { throw tcu::NotSupportedError("GL_MAX_SAMPLES pname value < 3, skipping"); } /* Set up texture objects */ if (are_2d_ms_array_tos_supported) { gl.genTextures(1, &to_id_2d_multisample_array_color); } gl.genTextures(1, &to_id_2d_multisample_color); GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed"); /* Set up a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Set up a renderbuffer object */ gl.genRenderbuffers(1, &rbo_id); gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object"); /* Set up first GL_RGBA8 multisample texture storage */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */ GL_RGBA8, 2, /* width */ 2, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up GL_RGBA8 multisample texture storage."); if (are_2d_ms_array_tos_supported) { /* Set up second GL_RGBA8 multisample texture storage */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_2d_multisample_array_color); gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */ GL_RGBA8, 2, /* width */ 2, /* height */ 2, /* depth */ GL_TRUE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up second GL_RGBA8 multisample texture storage."); } /* Set up renderbuffer storage */ gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 3, /* samples */ GL_RGBA8, 2, /* width */ 2); /* height */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up renderbuffer storage."); /* Set up FBO's zeroth color attachment */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_id_2d_multisample_color, 0); /* level */ /* Make sure FBO is considered complete at this point */ glw::GLenum fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness << " expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } if (are_2d_ms_array_tos_supported) { /* Set up FBO's first color attachment */ gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_2d_multisample_array_color, 0, /* level */ 0); /* layer */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up FBO color attachments"); /* FBO should now be considered incomplete */ fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } } /* Set up FBO's second color attachment */ gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rbo_id); /* FBO should now be considered incomplete */ fbo_completeness = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported:" << fbo_completeness << " expected: GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesFBOIncompleteness5Test::MultisampleTextureDependenciesFBOIncompleteness5Test( Context& context) : TestCase(context, "fbo_with_renderbuffer_and_multisample_texture_attachments_with_different_number_of_samples", "FBOs with renderbuffer and multisample texture attachments, where amount " "of samples used for multisample texture attachments differs from the " "amount of samples used for renderbuffer attachments, should be considered " "incomplete") , fbo_id(0) , rbo_id(0) , to_id_multisample_2d(0) , to_id_multisample_2d_array(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesFBOIncompleteness5Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (rbo_id != 0) { gl.bindRenderbuffer(GL_RENDERBUFFER, 0); gl.deleteRenderbuffers(1, &rbo_id); } if (to_id_multisample_2d != 0) { gl.deleteTextures(1, &to_id_multisample_2d); to_id_multisample_2d = 0; } if (to_id_multisample_2d_array != 0) { gl.deleteTextures(1, &to_id_multisample_2d_array); to_id_multisample_2d_array = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesFBOIncompleteness5Test::iterate() { bool are_multisample_2d_array_tos_supported = m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Retrieve GL_MAX_INTEGER_SAMPLES and GL_MAX_SAMPLES values */ glw::GLint gl_max_integer_samples_value = 0; glw::GLint gl_max_samples_value = 0; gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value); gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() generated an error"); /* Set up texture objects */ gl.genTextures(1, &to_id_multisample_2d); if (are_multisample_2d_array_tos_supported) { gl.genTextures(1, &to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed"); /* Set up a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Set up a renderbuffer object */ gl.genRenderbuffers(1, &rbo_id); gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object"); /* Bind texture objects to relevant texture targets */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d); if (are_multisample_2d_array_tos_supported) { gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glBindTexture() call failed."); /* Iterate through internalformats. Current internalformat will be used * by the 2D multisample attachment */ const glw::GLenum internalformats[] = { GL_R8, GL_RGB565, GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_R8I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_2d_multisample_internalformat = 0; n_2d_multisample_internalformat < n_internalformats; ++n_2d_multisample_internalformat) { glw::GLenum internalformat_2d_multisample = internalformats[n_2d_multisample_internalformat]; /* Query sample counts supported for 2DMS texture on given internal format */ glw::GLint num_sample_counts_2dms; gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat_2d_multisample, GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_2dms); std::vector sample_counts_2dms(num_sample_counts_2dms); gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat_2d_multisample, GL_SAMPLES, num_sample_counts_2dms, &sample_counts_2dms[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve sample counts supported for 2DMS"); /* Iterate again through the internalformats. This internalformat will be used * by the 2D multisample array attacmhent. * * NOTE: Under implementations which do not support 2DMS Array textures, we will * not attach the 2DMS Array textures to the FBO at all. This fits the conformance * test idea and does not break existing test implementation. * However, since 2DMS Array textures are unavailable, we only run a single inner * loop iteration. More iterations would not bring anything to the table at all. */ for (unsigned int n_2d_multisample_array_internalformat = 0; n_2d_multisample_array_internalformat < ((are_multisample_2d_array_tos_supported) ? n_internalformats : 1); ++n_2d_multisample_array_internalformat) { glw::GLenum internalformat_2d_multisample_array = internalformats[n_2d_multisample_array_internalformat]; glw::GLint num_sample_counts_2dms_array = 1; std::vector sample_counts_2dms_array(num_sample_counts_2dms_array); if (are_multisample_2d_array_tos_supported) { /* Query sample counts supported for 2DMS_ARRAY texture on given internal format */ gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, internalformat_2d_multisample_array, GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_2dms_array); sample_counts_2dms_array.resize(num_sample_counts_2dms_array); gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, internalformat_2d_multisample_array, GL_SAMPLES, num_sample_counts_2dms_array, &sample_counts_2dms_array[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve sample counts supported for 2DMS_ARRAY"); } else { /* Add a single entry to the 2d ms sample count array */ num_sample_counts_2dms_array = 1; sample_counts_2dms_array[0] = 0; } /* One more iteration for renderbuffer attachment */ for (unsigned int n_rbo_internalformat = 0; n_rbo_internalformat < n_internalformats; ++n_rbo_internalformat) { glw::GLenum internalformat_rbo = internalformats[n_rbo_internalformat]; /* Query sample counts supported for RBO on given internal format */ glw::GLint num_sample_counts_rbo; gl.getInternalformativ(GL_RENDERBUFFER, internalformat_rbo, GL_NUM_SAMPLE_COUNTS, 1, &num_sample_counts_rbo); std::vector sample_counts_rbo(num_sample_counts_rbo); gl.getInternalformativ(GL_RENDERBUFFER, internalformat_rbo, GL_SAMPLES, num_sample_counts_rbo, &sample_counts_rbo[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve sample counts supported for rbo"); /* Now iterate over all samples argument we will use for the 2D multisample attachment */ for (int i_2dms = 0; i_2dms < num_sample_counts_2dms; ++i_2dms) { int samples_2d_multisample = sample_counts_2dms[i_2dms]; /* ..and yet another iteration for the 2D multisample array attachment */ for (int i_2dms_array = 0; i_2dms_array < num_sample_counts_2dms_array; ++i_2dms_array) { int samples_2d_multisample_array = sample_counts_2dms_array[i_2dms_array]; /* Finally, iterate over values to be used for samples argument of * a glRenderbufferStorageMultisample() call. */ for (int i_rbo = 0; i_rbo < num_sample_counts_rbo; ++i_rbo) { int samples_rbo = sample_counts_rbo[i_rbo]; /* This is a negative test. Hence, skip an iteration where all the * samples arguments used for the multisample 2d/multisample 2d array/rbo * triple match. */ if (((samples_rbo == samples_2d_multisample) && (samples_rbo == samples_2d_multisample_array)) || (samples_rbo == 1) || (samples_2d_multisample == 1) || (samples_2d_multisample_array == 1)) { /* Skip the iteration */ continue; } /* Set up 2D multisample texture storage. */ gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples_2d_multisample, internalformat_2d_multisample, 2, /* width */ 2, /* height */ GL_FALSE); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed."); if (are_multisample_2d_array_tos_supported) { /* Set up 2D multisample array texture storage. */ gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samples_2d_multisample_array, internalformat_2d_multisample_array, 2, /* width */ 2, /* height */ 2, /* depth */ GL_FALSE); GLU_EXPECT_NO_ERROR(gl.getError(), "gltexStorage3DMultisample() call failed."); } /* Set up renderbuffer storage */ gl.renderbufferStorageMultisample(GL_RENDERBUFFER, samples_rbo, internalformat_rbo, 2, /* width */ 2); /* height */ GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorageMultisample() call failed."); /* Set up FBO's color attachments */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d, 0); /* level */ GLU_EXPECT_NO_ERROR( gl.getError(), "glFramebufferTexture2D() call failed for GL_COLOR_ATTACHMENT0 color attachment."); if (are_multisample_2d_array_tos_supported) { gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, to_id_multisample_2d_array, 0, /* level */ 0); /* layer */ GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed for " "GL_COLOR_ATTACHMENT1 color attachment."); } gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rbo_id); GLU_EXPECT_NO_ERROR( gl.getError(), "glFramebufferRenderbuffer() call failed for GL_COLOR_ATTACHMENT2 color attachment."); /* Make sure the FBO is incomplete */ glw::GLenum fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (fbo_completeness_status != GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { m_testCtx.getLog() << tcu::TestLog::Message << "Invalid FBO completeness status reported [" << fbo_completeness_status << "]" " instead of expected GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE." << " Sample count 2D_MS:" << samples_2d_multisample << " Sample count 2D_MS_ARRAY:" << samples_2d_multisample_array << " Sample count RBO:" << samples_rbo << tcu::TestLog::EndMessage; TCU_FAIL("Invalid FBO completeness status reported."); } /* Re-create texture objects */ gl.deleteTextures(1, &to_id_multisample_2d); if (are_multisample_2d_array_tos_supported) { gl.deleteTextures(1, &to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glDeleteTextures() call failed."); gl.genTextures(1, &to_id_multisample_2d); if (are_multisample_2d_array_tos_supported) { gl.genTextures(1, &to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glGenTextures() call failed."); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d); if (are_multisample_2d_array_tos_supported) { gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "At least one glBindTexture() call failed."); } /* for (all samples argument values to be used for renderbuffer attachment) */ } /* for (all samples argument values to be used for 2D multisample array attachment) */ } /* for (all samples argument values to be used for 2D multisample attachment) */ } /* for (all internalformats used by renderbuffer attachment) */ } /* for (all internalformats used by 2D multisample array attachment) */ } /* for (all internalformats used by 2D multisample attachment) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test:: MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test(Context& context) : TestCase(context, "framebuffer_texture2d_used_with_invalid_texture_target", "Checks GL_INVALID_OPERATION is reported if 2D or cube-map texture " "target is used with a multisample 2D texture for a " "glFramebufferTexture2D() call") , fbo_id(0) , to_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id != 0) { gl.deleteTextures(1, &to_id); to_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Generate and bind a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls1Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* For storing internalformat specific maximum number of samples */ glw::GLint gl_max_internalformat_samples = 0; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_INTEGER_SAMPLES and/or GL_MAX_SAMPLES values"); /* Iterate through all internalformats to be used for the test */ const glw::GLenum internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) { glw::GLenum internalformat = internalformats[n_internalformat]; bool is_color_renderable = false; bool is_depth_stencil_renderable = false; if (internalformat == GL_DEPTH24_STENCIL8) { is_depth_stencil_renderable = true; } else if (internalformat != GL_DEPTH_COMPONENT32F) { is_color_renderable = true; } /* Determine a value to be used for samples argument in subsequent * glTexStorage2DMultisample() call. */ gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve maximum supported amount of samples for internal format"); glw::GLint samples = gl_max_internalformat_samples; /* Skip formats that are not multisampled in the implementation */ if (samples <= 1) { continue; } /* Set the texture object storage up */ gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 1, /* width */ 1, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call generated an unexpected error."); /* Try to issue the invalid glFramebufferTexture2D() call */ glw::GLenum attachment = (is_color_renderable) ? GL_COLOR_ATTACHMENT0 : (is_depth_stencil_renderable) ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, to_id, 0); /* level */ /* Make sure GL_INVALID_OPERATION error was generated */ glw::GLenum error_code = gl.getError(); if (error_code != GL_INVALID_OPERATION) { m_testCtx.getLog() << tcu::TestLog::Message << "An unexpected error code " << error_code << " instead of GL_INVALID_OPERATION was generated by an invalid glFramebufferTexture2D() call" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid error code reported by glFramebufferTexture2D() call."); } /* Re-create the texture object */ gl.deleteTextures(1, &to_id); gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object."); } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test:: MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test(Context& context) : TestCase(context, "framebuffer_texture2d_used_with_invalid_level", "Checks GL_INVALID_VALUE is reported if glFramebufferTexture2D() " "is called with invalid level argument.") , fbo_id(0) , to_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id != 0) { gl.deleteTextures(1, &to_id); to_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Generate and bind a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTexture2DCalls2Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* For storing format specific maximum number of samples */ glw::GLint gl_max_internalformat_samples = 0; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_INTEGER_SAMPLES and/or GL_MAX_SAMPLE values"); /* Iterate through all internalformats to be used for the test */ const glw::GLenum internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) { glw::GLenum internalformat = internalformats[n_internalformat]; bool is_color_renderable = false; bool is_depth_renderable = false; if (internalformat == GL_DEPTH_COMPONENT32F) { is_depth_renderable = true; } else if (internalformat != GL_DEPTH24_STENCIL8) { is_color_renderable = true; } /* Determine a value to be used for samples argument in subsequent * glTexStorage2DMultisample() call. */ gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve maximum supported amount of samples for internal format"); glw::GLint samples = gl_max_internalformat_samples; /* Skip formats that are not multisampled in implementation */ if (samples <= 1) { continue; } /* Set the texture object storage up */ gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 1, /* width */ 1, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call generated an unexpected error."); /* Try to issue the invalid glFramebufferTexture2D() call */ glw::GLenum attachment = (is_color_renderable) ? GL_COLOR_ATTACHMENT0 : (is_depth_renderable) ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT; /* From spec: * * If textarget is TEXTURE_2D_MULTISAMPLE, then level must be zero. If textarget * is one of the cube map face targets from table 3.21, then level must be greater * than or equal to zero and less than or equal to log2 of the value of MAX_CUBE_- * MAP_TEXTURE_SIZE. If textarget is TEXTURE_2D, level must be greater than or * equal to zero and no larger than log2 of the value of MAX_TEXTURE_SIZE. */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D_MULTISAMPLE, to_id, 1); /* level */ /* Make sure GL_INVALID_VALUE error was generated */ glw::GLenum error_code = gl.getError(); if (error_code != GL_INVALID_VALUE) { m_testCtx.getLog() << tcu::TestLog::Message << "An unexpected error code " << error_code << " instead of GL_INVALID_VALUE was generated by an invalid glFramebufferTexture2D() call" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid error code reported by glFramebufferTexture2D() call."); } /* Re-create the texture object */ gl.deleteTextures(1, &to_id); gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object."); } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test:: MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test(Context& context) : TestCase(context, "framebuffer_texture_layer_used_for_invalid_texture_target", "Checks GL_INVALID_OPERATION is reported if 2D multisample texture is used for a " "glFramebufferTextureLayer() call") , fbo_id(0) , to_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id != 0) { gl.deleteTextures(1, &to_id); to_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Generate and bind a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */ gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls1Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* For storing format specific maximum number of samples */ glw::GLint gl_max_internalformat_samples = 0; /* Iterate through all internalformats to be used for the test */ const glw::GLenum internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) { glw::GLenum internalformat = internalformats[n_internalformat]; bool is_color_renderable = false; bool is_depth_renderable = false; if (internalformat == GL_DEPTH_COMPONENT32F) { is_depth_renderable = true; } else if (internalformat != GL_DEPTH24_STENCIL8) { is_color_renderable = true; } /* Determine a value to be used for samples argument in subsequent * glTexStorage2DMultisample() call. */ gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve maximum supported amount of samples for internal format"); glw::GLint samples = gl_max_internalformat_samples; /* Skip formats that are not multisampled in implementation */ if (samples <= 1) { continue; } /* Set the texture object storage up */ gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 2, /* width */ 2, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call generated an unexpected error."); /* Try to issue the invalid glFramebufferTextureLayer() call */ glw::GLenum attachment = (is_color_renderable) ? GL_COLOR_ATTACHMENT0 : (is_depth_renderable) ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT; gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, to_id, 0, /* level */ 0); /* layer */ /* Make sure GL_INVALID_OPERATION error was generated */ glw::GLenum error_code = gl.getError(); if (error_code != GL_INVALID_OPERATION) { m_testCtx.getLog() << tcu::TestLog::Message << "An unexpected error code " << error_code << " instead of GL_INVALID_OPERATION was generated by an invalid glFramebufferTextureLayer() call" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid error code reported by glFramebufferTextureLayer() call."); } /* Re-create the texture object */ gl.deleteTextures(1, &to_id); gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object."); } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test:: MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test(Context& context) : TestCase(context, "framebuffer_texture_layer_used_with_invalid_level_argument", "Checks GL_INVALID_VALUE error is reported if a glFramebufferTextureLayer() call" " is made with level exceeding amount of layers defined for a 2D multisample" " array texture") , fbo_id(0) , to_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id != 0) { gl.deleteTextures(1, &to_id); to_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Generate and bind a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); /* Generate and bind a texture object to GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target */ gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidFramebufferTextureLayerCalls2Test::iterate() { if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array")) { m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "OES_texture_storage_multisample_2d_array"); return STOP; } const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* For storing format specific maximum number of samples */ glw::GLint gl_max_internalformat_samples = 0; /* Iterate through all internalformats to be used for the test */ const glw::GLenum internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) { glw::GLenum internalformat = internalformats[n_internalformat]; bool is_color_renderable = false; bool is_depth_renderable = false; if (internalformat == GL_DEPTH_COMPONENT32F) { is_depth_renderable = true; } else if (internalformat != GL_DEPTH24_STENCIL8) { is_color_renderable = true; } /* Determine a value to be used for samples argument in subsequent * glTexStorage2DMultisample() call. */ gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples); /* Get MAX_TEXTURE_SIZE and calculate max level */ glw::GLint gl_max_texture_size = 0; gl.getIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_texture_size); const glw::GLint max_level = glw::GLint(log(double(gl_max_texture_size)) / log(2.0)); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve maximum supported amount of samples for internal format"); glw::GLint samples = gl_max_internalformat_samples; /* Set the texture object storage up */ gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, samples, internalformat, 2, /* width */ 2, /* height */ 2, /* depth */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "gltexStorage3DMultisample() call generated an unexpected error."); /* Try to issue the invalid glFramebufferTextureLayer() call */ glw::GLenum attachment = (is_color_renderable) ? GL_COLOR_ATTACHMENT0 : (is_depth_renderable) ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT; gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, to_id, max_level + 1, /* level - must be <= log_2(MAX_TEXTURE_SIZE) */ 0); /* layer */ /* Make sure GL_INVALID_VALUE error was generated */ glw::GLenum error_code = gl.getError(); if (error_code != GL_INVALID_VALUE) { m_testCtx.getLog() << tcu::TestLog::Message << "An unexpected error code " << error_code << " instead of GL_INVALID_VALUE was generated by an invalid glFramebufferTextureLayer() call" << tcu::TestLog::EndMessage; TCU_FAIL("Invalid error code reported by glFramebufferTextureLayer() call."); } /* Re-create the texture object */ gl.deleteTextures(1, &to_id); gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not re-create the texture object."); } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test:: MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test(Context& context) : TestCase(context, "renderbuffer_storage_multisample_invalid_samples_argument_for_noninteger_internalformats", "GL_INVALID_OPERATION error is reported for glRenderbufferStorageMultisample() " "calls, for which samples argument > MAX_SAMPLES for non-integer internalformats") , rbo_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (rbo_id != 0) { gl.deleteRenderbuffers(1, &rbo_id); rbo_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.genRenderbuffers(1, &rbo_id); gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls1Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* Retrieve GL_MAX_SAMPLES pname value */ glw::GLint gl_max_samples_value = 0; gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_SAMPLES value."); /* Iterate through a set of valid non-integer internalformats */ const glw::GLenum noninteger_internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX8 }; const unsigned int n_noninteger_internalformats = sizeof(noninteger_internalformats) / sizeof(noninteger_internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_noninteger_internalformats; ++n_internalformat) { glw::GLenum error_code = GL_NO_ERROR; const glw::GLenum internalformat = noninteger_internalformats[n_internalformat]; glw::GLint gl_max_internalformat_samples_value = -1; /* Retrieve maximum amount of samples available for the texture target considered */ gl.getInternalformativ(GL_RENDERBUFFER, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed to retrieve GL_SAMPLES"); /* Execute the test */ gl.renderbufferStorageMultisample(GL_RENDERBUFFER, gl_max_internalformat_samples_value + 1, internalformat, 1, /* width */ 1); /* height */ error_code = gl.getError(); if (error_code != GL_INVALID_OPERATION) { m_testCtx.getLog() << tcu::TestLog::Message << "glRenderbufferStorageMultisample() generated error code " << error_code << " when GL_INVALID_OPERATION was expected." << tcu::TestLog::EndMessage; TCU_FAIL("Invalid error code generated by glRenderbufferStorageMultisample() call."); } } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test:: MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test(Context& context) : TestCase(context, "renderbuffer_storage_multisample_invalid_samples_argument_for_integer_internalformats", "GL_INVALID_OPERATION error is reported for glRenderbufferStorageMultisample() calls, " "for which samples argument > MAX_INTEGER_SAMPLES for integer internalformats") , rbo_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (rbo_id != 0) { gl.deleteRenderbuffers(1, &rbo_id); rbo_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.genRenderbuffers(1, &rbo_id); gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesInvalidRenderbufferStorageMultisampleCalls2Test::iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* Retrieve GL_MAX_INTEGER_SAMPLES pname value */ glw::GLint gl_max_integer_samples_value = 0; gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve GL_MAX_INTEGER_SAMPLES value."); /* Iterate through a set of valid integer internalformats */ const glw::GLenum integer_internalformats[] = { GL_RG8UI, GL_RGBA32I }; const unsigned int n_integer_internalformats = sizeof(integer_internalformats) / sizeof(integer_internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_integer_internalformats; ++n_internalformat) { glw::GLenum error_code = GL_NO_ERROR; const glw::GLenum internalformat = integer_internalformats[n_internalformat]; /* Execute the test */ gl.renderbufferStorageMultisample(GL_RENDERBUFFER, gl_max_integer_samples_value + 1, internalformat, 1, /* width */ 1); /* height */ error_code = gl.getError(); if (error_code != GL_INVALID_OPERATION) { m_testCtx.getLog() << tcu::TestLog::Message << "glRenderbufferStorageMultisample() generated error code " << error_code << " when GL_INVALID_OPERATION was expected." << tcu::TestLog::EndMessage; TCU_FAIL("Invalid error code generated by glRenderbufferStorageMultisample() call."); } } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest:: MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest(Context& context) : TestCase(context, "no_error_generated_for_valid_framebuffer_texture2d_calls", "No error is reported for glFramebufferTexture2D() calls using " "GL_TEXTURE_2D_MULTISAMPLE texture target.") , fbo_id(0) , to_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (fbo_id != 0) { gl.deleteFramebuffers(1, &fbo_id); fbo_id = 0; } if (to_id != 0) { gl.deleteTextures(1, &to_id); to_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up a framebuffer object */ gl.genFramebuffers(1, &fbo_id); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesNoErrorGeneratedForValidFramebufferTexture2DCallsTest:: iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* For storing format specific maximum number of samples */ glw::GLint gl_max_internalformat_samples = 0; /* Iterate through all internalformats */ const glw::GLenum internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_RGBA32I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) { glw::GLenum internalformat = internalformats[n_internalformat]; /* Determine a value to be used for samples argument in subsequent * glTexStorage2DMultisample() call. */ gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve maximum supported amount of samples for internal format"); glw::GLint samples = gl_max_internalformat_samples; /* Skip formats that are not multisampled in implementation */ if (samples <= 1) { continue; } /* Set up a texture object. */ gl.genTextures(1, &to_id); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalformat, 1, /* width */ 1, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a texture object"); /* Determine attachment type for internalformat considered */ glw::GLenum attachment_type = GL_COLOR_ATTACHMENT0; if (internalformat == GL_DEPTH_COMPONENT32F) { attachment_type = GL_DEPTH_ATTACHMENT; } else if (internalformat == GL_DEPTH24_STENCIL8) { attachment_type = GL_DEPTH_STENCIL_ATTACHMENT; } /* Attach it to the FBO */ gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment_type, GL_TEXTURE_2D_MULTISAMPLE, to_id, 0); /* level */ GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed."); /* Release the texture object */ gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); gl.deleteTextures(1, &to_id); to_id = 0; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not release the texture object"); } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest:: MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest(Context& context) : TestCase(context, "no_error_generated_for_valid_renderbuffer_storage_multisample_calls", "No error is reported for valid glRenderbufferStorageMultisample() calls.") , rbo_id(0) { /* Left blank on purpose */ } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (rbo_id != 0) { gl.deleteRenderbuffers(1, &rbo_id); rbo_id = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Initializes ES objects created during test execution */ void MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest::initInternals() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.genRenderbuffers(1, &rbo_id); gl.bindRenderbuffer(GL_RENDERBUFFER, rbo_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a renderbuffer object"); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesNoErrorGeneratedForValidRenderbufferStorageMultisampleCallsTest:: iterate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); initInternals(); /* For storing format specific maximum number of samples */ glw::GLint gl_max_internalformat_samples = 0; /* Iterate through a set of valid non-integer and integer internalformats and a set of all legal samples argument values */ const glw::GLenum internalformats[] = { GL_RGB8, GL_RGB565, GL_SRGB8_ALPHA8, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_STENCIL_INDEX8, GL_RG8UI, GL_RGBA32I }; const unsigned int n_internalformats = sizeof(internalformats) / sizeof(internalformats[0]); for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat) { glw::GLenum internalformat = internalformats[n_internalformat]; /* Determine a value to be used for samples argument in subsequent * glTexStorage2DMultisample() call. */ gl.getInternalformativ(GL_RENDERBUFFER, internalformat, GL_SAMPLES, 1, &gl_max_internalformat_samples); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve maximum supported amount of samples for internal format"); for (int samples = 1; samples <= gl_max_internalformat_samples; ++samples) { /* Execute the test */ gl.renderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "A valid glRenderbufferStorageMultisample() call has reported an error."); } /* for (all legal samples argument values) */ } /* for (all internalformats) */ /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } /** Constructor. * * @param context CTS context handle. **/ MultisampleTextureDependenciesTexParameterTest::MultisampleTextureDependenciesTexParameterTest(Context& context) : TestCase(context, "tex_parameter_support", "Verifies glTexParameter*() behavior when used against multisample texture targets") , to_id_multisample_2d(0) , to_id_multisample_2d_array(0) { /* Left blank on purpose */ } /* Calls glTexParameterf(), glTexParameterfv(), glTexParameteri() and * glTexParameteriv(). For each invocation, the function checks if * the error code reported after each call matches the expected value. * If the values differ, an info message is logged and TestError exception * is thrown. * * @param expected_error_code Expected GL error code. * @param value Integer value to use. For glTexParameterf() * or glTexParameterfv(), the value will be cast * onto a float type prior to calling. * @param pname GL pname to use for glTexParameter*() calls. * @param texture_target Texture target to use for glTexParameter*() calls. */ void MultisampleTextureDependenciesTexParameterTest::checkAllTexParameterInvocations(glw::GLenum expected_error_code, glw::GLint value, glw::GLenum pname, glw::GLenum texture_target) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); glw::GLenum error_code = GL_NO_ERROR; const glw::GLfloat float_value = (glw::GLfloat)value; const glw::GLint int_value = value; /* glTexParameterf() */ gl.texParameterf(texture_target, pname, float_value); error_code = gl.getError(); if (error_code != expected_error_code) { m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameterf() call generated an error " << error_code << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage; TCU_FAIL("glTexParameterf() call generated an unexpected error."); } /* glTexParameteri() */ gl.texParameteri(texture_target, pname, int_value); error_code = gl.getError(); if (error_code != expected_error_code) { m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteri() call generated an error " << error_code << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage; TCU_FAIL("glTexParameterf() call generated an unexpected error."); } /* glTexParameterfv() */ gl.texParameterfv(texture_target, pname, &float_value); error_code = gl.getError(); if (error_code != expected_error_code) { m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameterfv() call generated an error " << error_code << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage; TCU_FAIL("glTexParameterfv() call generated an unexpected error."); } /* glTexParameteriv() */ gl.texParameteriv(texture_target, pname, &int_value); error_code = gl.getError(); if (error_code != expected_error_code) { m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteriv() call generated an error " << error_code << " instead of the expected error code " << expected_error_code << tcu::TestLog::EndMessage; TCU_FAIL("glTexParameteriv() call generated an unexpected error."); } } /** Deinitializes ES objects created during test execution */ void MultisampleTextureDependenciesTexParameterTest::deinit() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); if (to_id_multisample_2d != 0) { gl.deleteTextures(1, &to_id_multisample_2d); to_id_multisample_2d = 0; } if (to_id_multisample_2d_array != 0) { gl.deleteTextures(1, &to_id_multisample_2d_array); to_id_multisample_2d_array = 0; } /* Call base class' deinit() */ TestCase::deinit(); } /** Executes test iteration. * * @return Returns STOP when test has finished executing. */ tcu::TestNode::IterateResult MultisampleTextureDependenciesTexParameterTest::iterate() { bool are_multisample_2d_array_tos_supported = m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up texture objects */ gl.genTextures(1, &to_id_multisample_2d); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_id_multisample_2d); if (are_multisample_2d_array_tos_supported) { gl.genTextures(1, &to_id_multisample_2d_array); gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_id_multisample_2d_array); } GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects"); gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, /* samples */ GL_RGBA8, 1, /* width */ 1, /* height */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target"); if (are_multisample_2d_array_tos_supported) { gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 1, /* samples */ GL_RGBA8, 1, /* width */ 1, /* height */ 1, /* depth */ GL_FALSE); /* fixedsamplelocations */ GLU_EXPECT_NO_ERROR( gl.getError(), "gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target"); } /* Run the test for both multisample texture targets */ const glw::GLenum texture_targets[] = { GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES }; const unsigned int n_texture_targets = sizeof(texture_targets) / sizeof(texture_targets[0]); for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target) { glw::GLenum texture_target = texture_targets[n_texture_target]; if (!are_multisample_2d_array_tos_supported && texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES) { /* Skip the iteration */ continue; } /* Verify that setting GL_TEXTURE_BASE_LEVEL to 0 does not generate any 0. Using any other * value should generate GL_INVALID_OPERATION */ for (int n_iteration = 0; n_iteration < 2 /* iterations */; ++n_iteration) { glw::GLenum expected_error_code = (n_iteration == 0) ? GL_NO_ERROR : GL_INVALID_OPERATION; glw::GLint int_value = (n_iteration == 0) ? 0 : 1; checkAllTexParameterInvocations(expected_error_code, int_value, GL_TEXTURE_BASE_LEVEL, texture_target); } /* for (all iterations) */ } /* for (both texture targets) */ /* Make sure that modifying sampler state information results in an error * for multisample texture targets. */ const glw::GLenum sampler_pnames[] = { GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R, GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD, GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_COMPARE_FUNC }; const unsigned int n_sampler_pnames = sizeof(sampler_pnames) / sizeof(sampler_pnames[0]); for (unsigned int n_sampler_pname = 0; n_sampler_pname < n_sampler_pnames; ++n_sampler_pname) { glw::GLenum pname = sampler_pnames[n_sampler_pname]; for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target) { glw::GLenum texture_target = texture_targets[n_texture_target]; if (!are_multisample_2d_array_tos_supported && texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES) { /* Skip the iteration */ continue; } /* When is TEXTURE_2D_MULTISAMPLE or TEXTURE_2D_MULTISAMPLE_ARRAY, certain texture parameters may not be specified. In this case, an INVALID_ENUM */ checkAllTexParameterInvocations(GL_INVALID_ENUM, 0, pname, texture_target); } /* for (all texture targets) */ } /* for (all sampler properties) */ /* Make sure that modifying remaining texture parameters does not result in an error for * multisample texture targets. */ for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target) { glw::GLenum texture_target = texture_targets[n_texture_target]; if (!are_multisample_2d_array_tos_supported && texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES) { /* Skip the iteration */ continue; } checkAllTexParameterInvocations(GL_NO_ERROR, 10, GL_TEXTURE_MAX_LEVEL, texture_target); checkAllTexParameterInvocations(GL_NO_ERROR, GL_GREEN, GL_TEXTURE_SWIZZLE_R, texture_target); checkAllTexParameterInvocations(GL_NO_ERROR, GL_BLUE, GL_TEXTURE_SWIZZLE_G, texture_target); checkAllTexParameterInvocations(GL_NO_ERROR, GL_ALPHA, GL_TEXTURE_SWIZZLE_B, texture_target); checkAllTexParameterInvocations(GL_NO_ERROR, GL_RED, GL_TEXTURE_SWIZZLE_A, texture_target); } /* All done */ m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); return STOP; } } /* glcts namespace */