| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.1 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * 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 Framebuffer without attachments (GL_ARB_framebuffer_no_attachments) tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es31fFboNoAttachmentTests.hpp" |
| |
| #include "glwDefs.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| |
| #include "gluRenderContext.hpp" |
| #include "gluDefs.hpp" |
| #include "gluShaderProgram.hpp" |
| |
| #include "tcuTestContext.hpp" |
| #include "tcuVectorType.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuCommandLine.hpp" |
| #include "tcuResultCollector.hpp" |
| |
| #include "deMemory.h" |
| #include "deRandom.hpp" |
| #include "deString.h" |
| #include "deStringUtil.hpp" |
| |
| #include <string> |
| #include <vector> |
| |
| namespace deqp |
| { |
| namespace gles31 |
| { |
| namespace Functional |
| { |
| namespace |
| { |
| |
| using namespace glw; |
| |
| using tcu::IVec2; |
| using tcu::TestLog; |
| |
| using std::stringstream; |
| using std::string; |
| using std::vector; |
| |
| bool checkFramebufferSize (TestLog& log, const glu::RenderContext& renderCtx, GLuint framebuffer, const IVec2& size) |
| { |
| const glw::Functions& gl = renderCtx.getFunctions(); |
| |
| const char* const vertexSource = "#version 310 es\n" |
| "in layout(location = 0) highp vec2 a_position;\n\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(a_position, 0.0, 1.0);\n" |
| "}\n"; |
| |
| const char* const fragmentSource = "#version 310 es\n" |
| "uniform layout(location = 0) highp ivec2 u_expectedSize;\n" |
| "out layout(location = 0) mediump vec4 f_color;\n\n" |
| "void main()\n" |
| "{\n" |
| " if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;\n" |
| " f_color = vec4(1.0, 0.5, 0.25, 1.0);\n" |
| "}\n"; |
| |
| const glu::ShaderProgram program (renderCtx, glu::makeVtxFragSources(vertexSource, fragmentSource)); |
| GLuint query = 0; |
| GLuint insidePassed = 0; |
| GLuint outsideXPassed = 0; |
| GLuint outsideYPassed = 0; |
| |
| if (!program.isOk()) |
| log << program; |
| |
| TCU_CHECK(program.isOk()); |
| |
| gl.useProgram(program.getProgram()); |
| gl.enable(GL_DEPTH_TEST); |
| gl.depthFunc(GL_ALWAYS); |
| gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); |
| gl.viewport(0, 0, size.x()*2, size.y()*2); // Oversized viewport so that it will not accidentally limit us to the correct size |
| |
| log << TestLog::Message << "Using " << size.x()*2 << "x" << size.y()*2 << " viewport" << TestLog::EndMessage; |
| log << TestLog::Message << "Discarding fragments outside pixel of interest" << TestLog::EndMessage; |
| log << TestLog::Message << "Using occlusion query to check for rendered fragments" << TestLog::EndMessage; |
| |
| TCU_CHECK(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); |
| |
| // Render |
| { |
| const float data[] = |
| { |
| 1.0f, 1.0f, |
| 1.0f, -1.0f, |
| -1.0f, 1.0f, |
| -1.0f, 1.0f, |
| 1.0f, -1.0f, |
| -1.0f, -1.0f, |
| }; |
| |
| GLuint vertexArray = 0; |
| GLuint vertexBuffer = 0; |
| |
| gl.genQueries(1, &query); |
| gl.genVertexArrays(1, &vertexArray); |
| gl.bindVertexArray(vertexArray); |
| |
| gl.genBuffers(1, &vertexBuffer); |
| gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer); |
| gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); |
| |
| gl.enableVertexAttribArray(0); |
| gl.vertexAttribPointer(0, 2, GL_FLOAT, false, 0, DE_NULL); |
| |
| gl.uniform2i(0, size.x()-1, size.y()-1); |
| gl.beginQuery(GL_ANY_SAMPLES_PASSED, query); |
| gl.drawArrays(GL_TRIANGLES, 0, 6); |
| gl.endQuery(GL_ANY_SAMPLES_PASSED); |
| gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &insidePassed); |
| log << TestLog::Message << "A fragment was not discarded at (" << size.x()-1 << ", " << size.y()-1 << "). " |
| << "Occlusion query reports it was " << (insidePassed > 0 ? "rendered." : "not rendered") << TestLog::EndMessage; |
| |
| gl.uniform2i(0, size.x(), size.y()-1); |
| gl.beginQuery(GL_ANY_SAMPLES_PASSED, query); |
| gl.drawArrays(GL_TRIANGLES, 0, 6); |
| gl.endQuery(GL_ANY_SAMPLES_PASSED); |
| gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &outsideXPassed); |
| log << TestLog::Message << "A fragment was not discarded at (" << size.x() << ", " << size.y()-1 << "). " |
| << "Occlusion query reports it was " << (outsideXPassed > 0 ? "rendered." : "not rendered") << TestLog::EndMessage; |
| |
| gl.uniform2i(0, size.x()-1, size.y()); |
| gl.beginQuery(GL_ANY_SAMPLES_PASSED, query); |
| gl.drawArrays(GL_TRIANGLES, 0, 6); |
| gl.endQuery(GL_ANY_SAMPLES_PASSED); |
| gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &outsideYPassed); |
| log << TestLog::Message << "A fragment was not discarded at (" << size.x()-1 << ", " << size.y() << "). " |
| << "Occlusion query reports it was " << (outsideYPassed > 0 ? "rendered." : "not rendered") << TestLog::EndMessage; |
| |
| gl.disableVertexAttribArray(0); |
| gl.bindBuffer(GL_ARRAY_BUFFER, 0); |
| gl.bindVertexArray(0); |
| gl.deleteBuffers(1, &vertexBuffer); |
| gl.deleteVertexArrays(1, &vertexArray); |
| } |
| |
| gl.deleteQueries(1, &query); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed"); |
| |
| return insidePassed && !outsideXPassed && !outsideYPassed; |
| } |
| |
| bool checkFramebufferRenderable (TestLog& log, const glu::RenderContext& renderCtx, GLuint framebuffer, const IVec2& size) |
| { |
| const glw::Functions& gl = renderCtx.getFunctions(); |
| |
| const char* const vertexSource = "#version 310 es\n" |
| "in layout(location = 0) highp vec2 a_position;\n\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(a_position, 0.0, 1.0);\n" |
| "}\n"; |
| |
| const char* const fragmentSource = "#version 310 es\n" |
| "out layout(location = 0) mediump vec4 f_color;\n\n" |
| "void main()\n" |
| "{\n" |
| " f_color = vec4(1.0, 0.5, 0.25, 1.0);\n" |
| "}\n"; |
| |
| const glu::ShaderProgram program (renderCtx, glu::makeVtxFragSources(vertexSource, fragmentSource)); |
| GLuint query = 0; |
| |
| if (!program.isOk()) |
| log << program; |
| |
| TCU_CHECK(program.isOk()); |
| |
| gl.useProgram(program.getProgram()); |
| gl.enable(GL_DEPTH_TEST); |
| gl.depthFunc(GL_ALWAYS); |
| gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); |
| gl.viewport(0, 0, size.x(), size.y()); |
| |
| TCU_CHECK(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); |
| |
| log << TestLog::Message << "Rendering full framebuffer quad with color ouput, verifying output presence with occlusion query" << TestLog::EndMessage; |
| |
| // Render |
| { |
| const float data[] = |
| { |
| 1.0f, 1.0f, |
| 1.0f, -1.0f, |
| -1.0f, 1.0f, |
| -1.0f, 1.0f, |
| 1.0f, -1.0f, |
| -1.0f, -1.0f, |
| }; |
| |
| GLuint vertexArray = 0; |
| GLuint vertexBuffer = 0; |
| |
| gl.genQueries(1, &query); |
| gl.genVertexArrays(1, &vertexArray); |
| gl.bindVertexArray(vertexArray); |
| |
| gl.genBuffers(1, &vertexBuffer); |
| gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer); |
| gl.bufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); |
| |
| gl.enableVertexAttribArray(0); |
| gl.vertexAttribPointer(0, 2, GL_FLOAT, false, 0, DE_NULL); |
| |
| gl.beginQuery(GL_ANY_SAMPLES_PASSED, query); |
| gl.drawArrays(GL_TRIANGLES, 0, 6); |
| gl.endQuery(GL_ANY_SAMPLES_PASSED); |
| |
| gl.disableVertexAttribArray(0); |
| gl.bindBuffer(GL_ARRAY_BUFFER, 0); |
| gl.bindVertexArray(0); |
| gl.deleteBuffers(1, &vertexBuffer); |
| gl.deleteVertexArrays(1, &vertexArray); |
| } |
| |
| // Read |
| { |
| GLuint passed = 0; |
| |
| gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &passed); |
| gl.deleteQueries(1, &query); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed"); |
| |
| if (passed) |
| log << TestLog::Message << "Query passed" << TestLog::EndMessage; |
| else |
| log << TestLog::Message << "Query did not pass" << TestLog::EndMessage; |
| |
| return passed != 0; |
| } |
| } |
| |
| class FramebufferCompletenessCase : public tcu::TestCase |
| { |
| public: |
| FramebufferCompletenessCase (tcu::TestContext& testCtx, |
| const glu::RenderContext& renderCtx, |
| const char* name, |
| const char* desc); |
| virtual ~FramebufferCompletenessCase (void) {} |
| virtual IterateResult iterate (void); |
| |
| private: |
| const glu::RenderContext& m_renderCtx; |
| tcu::ResultCollector m_results; |
| }; |
| |
| FramebufferCompletenessCase::FramebufferCompletenessCase (tcu::TestContext& testCtx, |
| const glu::RenderContext& renderCtx, |
| const char* name, |
| const char* desc) |
| : TestCase (testCtx, name, desc) |
| , m_renderCtx (renderCtx) |
| { |
| } |
| |
| FramebufferCompletenessCase::IterateResult FramebufferCompletenessCase::iterate (void) |
| { |
| const glw::Functions& gl = m_renderCtx.getFunctions(); |
| GLuint framebuffer = 0; |
| |
| gl.genFramebuffers(1, &framebuffer); |
| gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); |
| |
| m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "Framebuffer was incorrectly reported as complete when it had no width, height or attachments"); |
| |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 16); |
| m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "Framebuffer was incorrectly reported as complete when it only had a width"); |
| |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 16); |
| m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Framebuffer not reported as complete when it had width and height set"); |
| |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0); |
| m_results.check(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "Framebuffer was incorrectly reported as complete when it only had a height"); |
| |
| gl.deleteFramebuffers(1, &framebuffer); |
| |
| m_results.setTestContextResult(m_testCtx); |
| return STOP; |
| } |
| |
| struct FboSpec |
| { |
| int width; |
| int height; |
| int samples; |
| |
| FboSpec(int width_, int height_, int samples_) : width(width_), height(height_), samples(samples_){} |
| }; |
| |
| class SizeCase : public tcu::TestCase |
| { |
| public: |
| SizeCase (tcu::TestContext& testCtx, |
| const glu::RenderContext& renderCtx, |
| const char* name, |
| const char* desc, |
| const FboSpec& spec); |
| virtual ~SizeCase (void) {} |
| |
| virtual IterateResult iterate (void); |
| |
| enum |
| { |
| USE_MAXIMUM = -1 |
| }; |
| private: |
| int getWidth (void) const; |
| int getHeight (void) const; |
| int getSamples (void) const; |
| |
| const glu::RenderContext& m_renderCtx; |
| |
| const FboSpec m_spec; |
| }; |
| |
| SizeCase::SizeCase (tcu::TestContext& testCtx, |
| const glu::RenderContext& renderCtx, |
| const char* name, |
| const char* desc, |
| const FboSpec& spec) |
| : TestCase (testCtx, name, desc) |
| , m_renderCtx (renderCtx) |
| , m_spec (spec) |
| { |
| } |
| |
| SizeCase::IterateResult SizeCase::iterate (void) |
| { |
| const glw::Functions& gl = m_renderCtx.getFunctions(); |
| TestLog& log = m_testCtx.getLog(); |
| GLuint framebuffer = 0; |
| const int width = getWidth(); |
| const int height = getHeight(); |
| const int samples = getSamples(); |
| |
| gl.genFramebuffers(1, &framebuffer); |
| gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, width); |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, height); |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, samples); |
| |
| log << TestLog::Message << "Verifying " << width << "x" << height << " framebuffer with " << samples << "x multisampling" << TestLog::EndMessage; |
| |
| if(checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(width, height)) && checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(width, height))) |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected"); |
| |
| gl.deleteFramebuffers(1, &framebuffer); |
| |
| return STOP; |
| } |
| |
| int SizeCase::getWidth (void) const |
| { |
| if (m_spec.width != USE_MAXIMUM) |
| return m_spec.width; |
| else |
| { |
| const glw::Functions& gl = m_renderCtx.getFunctions(); |
| GLint width = 0; |
| |
| gl.getIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &width); |
| |
| return width; |
| } |
| } |
| |
| int SizeCase::getHeight (void) const |
| { |
| if (m_spec.height != USE_MAXIMUM) |
| return m_spec.height; |
| else |
| { |
| const glw::Functions& gl = m_renderCtx.getFunctions(); |
| GLint height = 0; |
| |
| gl.getIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &height); |
| |
| return height; |
| } |
| } |
| |
| int SizeCase::getSamples (void) const |
| { |
| if (m_spec.samples != USE_MAXIMUM) |
| return m_spec.samples; |
| else |
| { |
| const glw::Functions& gl = m_renderCtx.getFunctions(); |
| GLint samples = 0; |
| |
| gl.getIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &samples); |
| |
| return samples; |
| } |
| } |
| |
| class AttachmentInteractionCase : public tcu::TestCase |
| { |
| public: |
| AttachmentInteractionCase (tcu::TestContext& testCtx, |
| const glu::RenderContext& renderCtx, |
| const char* name, |
| const char* desc, |
| const FboSpec& defaultSpec, |
| const FboSpec& attachmentSpec); |
| virtual ~AttachmentInteractionCase (void) {} |
| |
| virtual IterateResult iterate (void); |
| |
| private: |
| const glu::RenderContext& m_renderCtx; |
| const FboSpec m_defaultSpec; |
| const FboSpec m_attachmentSpec; |
| }; |
| |
| AttachmentInteractionCase::AttachmentInteractionCase (tcu::TestContext& testCtx, |
| const glu::RenderContext& renderCtx, |
| const char* name, |
| const char* desc, |
| const FboSpec& defaultSpec, |
| const FboSpec& attachmentSpec) |
| : TestCase (testCtx, name, desc) |
| , m_renderCtx (renderCtx) |
| , m_defaultSpec (defaultSpec) |
| , m_attachmentSpec (attachmentSpec) |
| { |
| } |
| |
| AttachmentInteractionCase::IterateResult AttachmentInteractionCase::iterate (void) |
| { |
| const glw::Functions& gl = m_renderCtx.getFunctions(); |
| TestLog& log = m_testCtx.getLog(); |
| GLuint framebuffer = 0; |
| GLuint renderbuffer= 0; |
| |
| gl.genFramebuffers(1, &framebuffer); |
| gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer); |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, m_defaultSpec.width); |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, m_defaultSpec.height); |
| gl.framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, m_defaultSpec.samples); |
| |
| gl.genRenderbuffers(1, &renderbuffer); |
| gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer); |
| gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_attachmentSpec.samples, GL_RGBA8, m_attachmentSpec.width, m_attachmentSpec.height); |
| gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); |
| |
| log << TestLog::Message << "Verifying " << m_attachmentSpec.width << "x" << m_attachmentSpec.height << " framebuffer with " << m_attachmentSpec.samples << "x multisampling" |
| << " and defaults set to " << m_defaultSpec.width << "x" << m_defaultSpec.height << " with " << m_defaultSpec.samples << "x multisampling" << TestLog::EndMessage; |
| |
| if(checkFramebufferRenderable(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height)) |
| && checkFramebufferSize(log, m_renderCtx, framebuffer, IVec2(m_attachmentSpec.width, m_attachmentSpec.height))) |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| else |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Framebuffer did not behave as expected"); |
| |
| gl.deleteRenderbuffers(1, &renderbuffer); |
| gl.deleteFramebuffers(1, &framebuffer); |
| |
| return STOP; |
| } |
| |
| } // Anonymous |
| |
| tcu::TestCaseGroup* createFboNoAttachmentTests(Context& context) |
| { |
| const glu::RenderContext& renderCtx = context.getRenderContext(); |
| tcu::TestContext& testCtx = context.getTestContext(); |
| |
| const int maxWidth = 2048; // MAX_FRAMEBUFFER_WIDTH in ES 3.1 |
| const int maxHeight = 2048; // MAX_FRAMEBUFFER_HEIGHT in ES 3.1 |
| const int maxSamples = 4; |
| |
| tcu::TestCaseGroup* const root = new tcu::TestCaseGroup(testCtx, "no_attachments", "Framebuffer without attachments"); |
| |
| // Size |
| { |
| tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "size", "Basic functionality tests with varying default size"); |
| |
| root->addChild(group); |
| |
| for (int width = 16; width <= maxWidth; width *= 4) |
| { |
| for (int height = 16; height <= maxHeight; height *= 4) |
| { |
| const FboSpec spec (width, height, 0); |
| stringstream name; |
| |
| name << width << "x" << height; |
| |
| group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec)); |
| } |
| } |
| } |
| |
| // NPOT size |
| { |
| const FboSpec specs[] = |
| { |
| // Square |
| FboSpec(1, 1, 0), |
| FboSpec(3, 3, 0), |
| FboSpec(15, 15, 0), |
| FboSpec(17, 17, 0), |
| FboSpec(31, 31, 0), |
| FboSpec(33, 33, 0), |
| FboSpec(63, 63, 0), |
| FboSpec(65, 65, 0), |
| FboSpec(127, 127, 0), |
| FboSpec(129, 129, 0), |
| FboSpec(255, 255, 0), |
| FboSpec(257, 257, 0), |
| FboSpec(511, 511, 0), |
| FboSpec(513, 513, 0), |
| FboSpec(1023, 1023, 0), |
| FboSpec(1025, 1025, 0), |
| FboSpec(2047, 2047, 0), |
| |
| // Non-square |
| FboSpec(15, 511, 0), |
| FboSpec(127, 15, 0), |
| FboSpec(129, 127, 0), |
| FboSpec(511, 127, 0), |
| FboSpec(2047, 1025, 0), |
| }; |
| tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "npot_size", "Basic functionality with Non-power-of-two size"); |
| |
| root->addChild(group); |
| |
| for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(specs); caseNdx++) |
| { |
| const FboSpec& spec = specs[caseNdx]; |
| stringstream name; |
| |
| name << spec.width << "x" << spec.height; |
| |
| group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec)); |
| } |
| } |
| |
| // Multisample |
| { |
| tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "multisample", "Basic functionality with multisampled fbo"); |
| |
| root->addChild(group); |
| |
| for (int samples = 0; samples <= maxSamples; samples++) |
| { |
| const FboSpec spec (128, 128, samples); |
| stringstream name; |
| |
| name << "samples" << samples; |
| |
| group->addChild(new SizeCase(testCtx, renderCtx, name.str().c_str(), name.str().c_str(), spec)); |
| } |
| } |
| |
| // Randomized |
| { |
| tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "random", "Randomized size & multisampling"); |
| de::Random rng (0xF0E1E2D3 ^ testCtx.getCommandLine().getBaseSeed()); |
| |
| root->addChild(group); |
| |
| for (int caseNdx = 0; caseNdx < 16; caseNdx++) |
| { |
| const int width = rng.getInt(1, maxWidth); |
| const int height = rng.getInt(1, maxHeight); |
| const int samples = rng.getInt(0, maxSamples); |
| const FboSpec spec (width, height, samples); |
| const string name = de::toString(caseNdx); |
| |
| group->addChild(new SizeCase(testCtx, renderCtx, name.c_str(), name.c_str(), spec)); |
| } |
| } |
| |
| // Normal fbo with defaults set |
| { |
| tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "interaction", "Interaction of default parameters with normal fbo"); |
| |
| root->addChild(group); |
| |
| const FboSpec specs[][2] = |
| { |
| { FboSpec(256, 256, 0), FboSpec(128, 128, 1) }, |
| { FboSpec(256, 256, 1), FboSpec(128, 128, 0) }, |
| { FboSpec(256, 256, 0), FboSpec(512, 512, 2) }, |
| { FboSpec(256, 256, 2), FboSpec(128, 512, 0) }, |
| { FboSpec(127, 127, 0), FboSpec(129, 129, 0) }, |
| { FboSpec(17, 512, 4), FboSpec(16, 16, 2) }, |
| { FboSpec(2048, 2048, 4), FboSpec(1, 1, 0) }, |
| { FboSpec(1, 1, 0), FboSpec(2048, 2048, 4) }, |
| }; |
| |
| for (int specNdx = 0; specNdx < DE_LENGTH_OF_ARRAY(specs); specNdx++) |
| { |
| const FboSpec& baseSpec = specs[specNdx][0]; |
| const FboSpec& altSpec = specs[specNdx][1]; |
| stringstream baseSpecName, altSpecName; |
| |
| baseSpecName << baseSpec.width << "x" << baseSpec.height << "ms" << baseSpec.samples; |
| altSpecName << altSpec.width << "x" << altSpec.height << "ms" << altSpec.samples; |
| |
| { |
| const string name = baseSpecName.str() + "_default_" + altSpecName.str(); |
| |
| group->addChild(new AttachmentInteractionCase(testCtx, renderCtx, name.c_str(), name.c_str(), altSpec, baseSpec)); |
| } |
| } |
| } |
| |
| // Maximums |
| { |
| tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(testCtx, "maximums", "Maximum dimensions"); |
| |
| root->addChild(group); |
| group->addChild(new SizeCase(testCtx, renderCtx, "width", "Maximum width", FboSpec(SizeCase::USE_MAXIMUM, 128, 0))); |
| group->addChild(new SizeCase(testCtx, renderCtx, "height", "Maximum height", FboSpec(128, SizeCase::USE_MAXIMUM, 0))); |
| group->addChild(new SizeCase(testCtx, renderCtx, "size", "Maximum size", FboSpec(SizeCase::USE_MAXIMUM, SizeCase::USE_MAXIMUM, 0))); |
| group->addChild(new SizeCase(testCtx, renderCtx, "samples", "Maximum samples", FboSpec(128, 128, SizeCase::USE_MAXIMUM))); |
| group->addChild(new SizeCase(testCtx, renderCtx, "all", "Maximum size & samples", FboSpec(SizeCase::USE_MAXIMUM, SizeCase::USE_MAXIMUM, SizeCase::USE_MAXIMUM))); |
| } |
| |
| return root; |
| } |
| |
| tcu::TestCaseGroup* createFboNoAttachmentCompletenessTests(Context& context) |
| { |
| TestCaseGroup* const group = new TestCaseGroup(context, "completeness", "Completeness tests"); |
| |
| group->addChild(new FramebufferCompletenessCase(context.getTestContext(), context.getRenderContext(), "no_attachments", "No attachments completeness")); |
| |
| return group; |
| } |
| |
| } // Functional |
| } // gles31 |
| } // deqp |