1/*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24#include "esextcGeometryShaderClipping.hpp" 25 26#include "gluDefs.hpp" 27#include "glwEnums.hpp" 28#include "glwFunctions.hpp" 29#include "tcuTestLog.hpp" 30#include <cstring> 31 32namespace glcts 33{ 34/* Fragment shader code */ 35const char* GeometryShaderClipping::m_fs_code = "${VERSION}\n" 36 "\n" 37 "precision highp float;\n" 38 "\n" 39 "out vec4 result;\n" 40 "\n" 41 "void main()\n" 42 "{\n" 43 " result = vec4(0, 1, 0, 0);\n" 44 "}\n"; 45 46/* Vertex shader code */ 47const char* GeometryShaderClipping::m_vs_code = "${VERSION}\n" 48 "\n" 49 "precision highp float;\n" 50 "\n" 51 "void main()\n" 52 "{\n" 53 " gl_Position = vec4(-10, -10, -10, 0);\n" 54 "}\n"; 55 56/* Geometry shader code */ 57const char* GeometryShaderClipping::m_gs_code = "${VERSION}\n" 58 "${GEOMETRY_SHADER_REQUIRE}\n" 59 "\n" 60 "precision highp float;\n" 61 "\n" 62 "layout(points) in;\n" 63 "layout(triangle_strip, max_vertices=4) out;\n" 64 "\n" 65 "void main()\n" 66 "{\n" 67 "\n" 68 " gl_Position = vec4(1, 1, 0, 1);\n" 69 " EmitVertex();\n" 70 "\n" 71 " gl_Position = vec4(1, -1, 0, 1);\n" 72 " EmitVertex();\n" 73 "\n" 74 " gl_Position = vec4(-1, 1, 0, 1);\n" 75 " EmitVertex();\n" 76 "\n" 77 " gl_Position = vec4(-1, -1, 0, 1);\n" 78 " EmitVertex();\n" 79 "\n" 80 " EndPrimitive();\n" 81 "}\n"; 82 83/** Constructor 84 * 85 * @param context Test context 86 * @param name Test case's name 87 * @param description Test case's desricption 88 **/ 89GeometryShaderClipping::GeometryShaderClipping(Context& context, const ExtParameters& extParams, const char* name, 90 const char* description) 91 : TestCaseBase(context, extParams, name, description) 92 , m_fbo_id(0) 93 , m_fs_id(0) 94 , m_gs_id(0) 95 , m_po_id(0) 96 , m_to_id(0) 97 , m_vao_id(0) 98 , m_vs_id(0) 99{ 100} 101 102/** Deinitializes GLES objects created during the test. 103 * 104 */ 105void GeometryShaderClipping::deinit(void) 106{ 107 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 108 109 /* Reset OpenGL ES state */ 110 gl.useProgram(0); 111 gl.bindTexture(GL_TEXTURE_2D, 0); 112 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 113 gl.bindVertexArray(0); 114 115 if (m_po_id != 0) 116 { 117 gl.deleteProgram(m_po_id); 118 } 119 120 if (m_fs_id != 0) 121 { 122 gl.deleteShader(m_fs_id); 123 } 124 125 if (m_gs_id != 0) 126 { 127 gl.deleteShader(m_gs_id); 128 } 129 130 if (m_vs_id != 0) 131 { 132 gl.deleteShader(m_vs_id); 133 } 134 135 if (m_to_id != 0) 136 { 137 gl.deleteTextures(1, &m_to_id); 138 } 139 140 if (m_fbo_id != 0) 141 { 142 gl.deleteFramebuffers(1, &m_fbo_id); 143 } 144 145 if (m_vao_id != 0) 146 { 147 gl.deleteVertexArrays(1, &m_vao_id); 148 } 149 150 /* Release base class */ 151 TestCaseBase::deinit(); 152} 153 154/** Executes the test. 155 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 156 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 157 * Note the function throws exception should an error occur! 158 **/ 159tcu::TestNode::IterateResult GeometryShaderClipping::iterate(void) 160{ 161 unsigned char buffer[m_texture_width * m_texture_height * m_texture_n_components]; 162 163 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 164 const unsigned char reference_color[] = { 0, 255, 0, 0 }; 165 const unsigned int row_size = m_texture_width * m_texture_n_components; 166 167 if (!m_is_geometry_shader_extension_supported) 168 { 169 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 170 } 171 172 /* Create shader objects we'll need */ 173 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 174 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 175 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 176 m_po_id = gl.createProgram(); 177 178 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &m_fs_code, m_gs_id, 1 /* part */, &m_gs_code, m_vs_id, 179 1 /* part */, &m_vs_code)) 180 { 181 TCU_FAIL("Could not create program object from valid vertex/geometry/fragment shaders!"); 182 } 183 184 /* Create and configure texture object we'll be rendering to */ 185 gl.genTextures(1, &m_to_id); 186 gl.bindTexture(GL_TEXTURE_2D, m_to_id); 187 gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height); 188 189 GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating texture object!"); 190 191 /* Create and configure the framebuffer object */ 192 gl.genFramebuffers(1, &m_fbo_id); 193 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 194 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */); 195 196 GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring framebuffer object!"); 197 198 /* Create and bind vertex array object */ 199 gl.genVertexArrays(1, &m_vao_id); 200 gl.bindVertexArray(m_vao_id); 201 202 GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex array object"); 203 204 /* Render */ 205 gl.viewport(0 /* x */, 0 /* y */, m_texture_width /* width */, m_texture_height /* height */); 206 gl.useProgram(m_po_id); 207 208 gl.clearColor(1.0f, 0.0f, 0.0f, 0.0f); 209 gl.clear(GL_COLOR_BUFFER_BIT); 210 211 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 212 213 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!"); 214 215 /* Read the rendered data */ 216 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id); 217 gl.readPixels(0 /* x */, 0 /* y */, m_texture_height /* width */, m_texture_width /* height */, GL_RGBA, 218 GL_UNSIGNED_BYTE, buffer); 219 220 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed!"); 221 222 /* Loop over all pixels and compare the rendered data with reference value */ 223 for (int y = 0; y < m_texture_height; ++y) 224 { 225 unsigned char* data_row = buffer + y * row_size; 226 227 for (int x = 0; x < m_texture_width; ++x) 228 { 229 unsigned char* data = data_row + x * m_texture_n_components; 230 231 if (memcmp(data, reference_color, sizeof(reference_color)) != 0) 232 { 233 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << data[0] << ", " << data[1] << ", " 234 << data[2] << ", " << data[3] << "] is different from reference data [" 235 << reference_color[0] << ", " << reference_color[1] << ", " << reference_color[2] 236 << ", " << reference_color[3] << "] !" << tcu::TestLog::EndMessage; 237 238 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 239 240 return STOP; 241 } /* if (memcmp(data, reference_color, sizeof(reference_color)) != 0) */ 242 } /* for (all columns) */ 243 } /* for (all rows) */ 244 245 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 246 return STOP; 247} 248 249} // namespace glcts 250