1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 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 gl_FragData[] tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fShaderFragDataTests.hpp" 25 26 #include "glsShaderLibrary.hpp" 27 28 #include "gluRenderContext.hpp" 29 #include "gluShaderProgram.hpp" 30 #include "gluDrawUtil.hpp" 31 #include "gluPixelTransfer.hpp" 32 #include "gluObjectWrapper.hpp" 33 34 #include "tcuRenderTarget.hpp" 35 #include "tcuStringTemplate.hpp" 36 #include "tcuTestLog.hpp" 37 #include "tcuSurface.hpp" 38 39 #include "glwFunctions.hpp" 40 #include "glwEnums.hpp" 41 42 namespace deqp 43 { 44 namespace gles2 45 { 46 namespace Functional 47 { 48 49 using std::string; 50 using tcu::TestLog; 51 52 namespace 53 { 54 55 enum IndexExprType 56 { 57 INDEX_EXPR_STATIC = 0, 58 INDEX_EXPR_UNIFORM, 59 INDEX_EXPR_DYNAMIC, 60 61 INDEX_EXPR_TYPE_LAST 62 }; 63 64 static bool compareSingleColor (tcu::TestLog& log, const tcu::Surface& surface, tcu::RGBA expectedColor, tcu::RGBA threshold) 65 { 66 const int maxPrints = 10; 67 int numFailedPixels = 0; 68 69 log << TestLog::Message << "Expecting " << expectedColor << " with threshold " << threshold << TestLog::EndMessage; 70 71 for (int y = 0; y < surface.getHeight(); y++) 72 { 73 for (int x = 0; x < surface.getWidth(); x++) 74 { 75 const tcu::RGBA resultColor = surface.getPixel(x, y); 76 const bool isOk = compareThreshold(resultColor, expectedColor, threshold); 77 78 if (!isOk) 79 { 80 if (numFailedPixels < maxPrints) 81 log << TestLog::Message << "ERROR: Got " << resultColor << " at (" << x << ", " << y << ")!" << TestLog::EndMessage; 82 else if (numFailedPixels == maxPrints) 83 log << TestLog::Message << "..." << TestLog::EndMessage; 84 85 numFailedPixels += 1; 86 } 87 } 88 } 89 90 if (numFailedPixels > 0) 91 { 92 log << TestLog::Message << "Found " << numFailedPixels << " invalid pixels, comparison FAILED!" << TestLog::EndMessage; 93 log << TestLog::Image("ResultImage", "Result Image", surface); 94 return false; 95 } 96 else 97 { 98 log << TestLog::Message << "Image comparison passed." << TestLog::EndMessage; 99 return true; 100 } 101 } 102 103 class FragDataIndexingCase : public TestCase 104 { 105 public: 106 FragDataIndexingCase (Context& context, const char* name, const char* description, IndexExprType indexExprType) 107 : TestCase (context, name, description) 108 , m_indexExprType (indexExprType) 109 { 110 } 111 112 static glu::ProgramSources genSources (const IndexExprType indexExprType) 113 { 114 const char* const fragIndexExpr = indexExprType == INDEX_EXPR_STATIC ? "0" : 115 indexExprType == INDEX_EXPR_UNIFORM ? "u_index" : 116 indexExprType == INDEX_EXPR_DYNAMIC ? "int(v_index)" : DE_NULL; 117 glu::ProgramSources sources; 118 119 DE_ASSERT(fragIndexExpr); 120 121 sources << glu::VertexSource( 122 "attribute highp vec4 a_position;\n" 123 "attribute highp float a_index;\n" 124 "attribute highp vec4 a_color;\n" 125 "varying mediump float v_index;\n" 126 "varying mediump vec4 v_color;\n" 127 "void main (void)\n" 128 "{\n" 129 " gl_Position = a_position;\n" 130 " v_color = a_color;\n" 131 " v_index = a_index;\n" 132 "}\n"); 133 134 sources << glu::FragmentSource(string( 135 "varying mediump vec4 v_color;\n" 136 "varying mediump float v_index;\n" 137 "uniform mediump int u_index;\n" 138 "void main (void)\n" 139 "{\n" 140 " gl_FragData[") + fragIndexExpr + "] = v_color;\n" 141 "}\n"); 142 143 return sources; 144 } 145 146 IterateResult iterate (void) 147 { 148 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 149 const glw::Functions& gl = renderCtx.getFunctions(); 150 const glu::ShaderProgram program (renderCtx, genSources(m_indexExprType)); 151 const int viewportW = de::min(renderCtx.getRenderTarget().getWidth(), 128); 152 const int viewportH = de::min(renderCtx.getRenderTarget().getHeight(), 128); 153 154 const float positions[] = 155 { 156 -1.0f, -1.0f, 157 +1.0f, -1.0f, 158 -1.0f, +1.0f, 159 +1.0f, +1.0f 160 }; 161 const float colors[] = 162 { 163 0.0f, 1.0f, 0.0f, 1.0f, 164 0.0f, 1.0f, 0.0f, 1.0f, 165 0.0f, 1.0f, 0.0f, 1.0f, 166 0.0f, 1.0f, 0.0f, 1.0f 167 }; 168 const float indexValues[] = { 0.0f, 0.0f, 0.0f, 0.0f }; 169 const deUint8 indices[] = { 0, 1, 2, 2, 1, 3 }; 170 171 const glu::VertexArrayBinding vertexArrays[] = 172 { 173 glu::va::Float("a_position", 2, 4, 0, &positions[0]), 174 glu::va::Float("a_color", 4, 4, 0, &colors[0]), 175 glu::va::Float("a_index", 1, 4, 0, &indexValues[0]) 176 }; 177 178 m_testCtx.getLog() << program; 179 180 if (!program.isOk()) 181 { 182 if (m_indexExprType == INDEX_EXPR_STATIC) 183 TCU_FAIL("Compile failed"); 184 else 185 throw tcu::NotSupportedError("Dynamic indexing of gl_FragData[] not supported"); 186 } 187 188 gl.clearColor (1.0f, 0.0f, 0.0f, 1.0f); 189 gl.clear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 190 191 gl.viewport (0, 0, viewportW, viewportH); 192 gl.useProgram (program.getProgram()); 193 gl.uniform1i (gl.getUniformLocation(program.getProgram(), "u_index"), 0); 194 195 glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 196 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 197 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed"); 198 199 { 200 tcu::Surface result (viewportW, viewportH); 201 const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1); 202 bool isOk; 203 204 glu::readPixels(renderCtx, 0, 0, result.getAccess()); 205 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed"); 206 207 isOk = compareSingleColor(m_testCtx.getLog(), result, tcu::RGBA::green(), threshold); 208 209 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 210 isOk ? "Pass" : "Image comparison failed"); 211 } 212 213 return STOP; 214 } 215 216 private: 217 const IndexExprType m_indexExprType; 218 }; 219 220 } // anonymous 221 222 ShaderFragDataTests::ShaderFragDataTests (Context& context) 223 : TestCaseGroup(context, "fragdata", "gl_FragData[] Tests") 224 { 225 } 226 227 ShaderFragDataTests::~ShaderFragDataTests (void) 228 { 229 } 230 231 void ShaderFragDataTests::init (void) 232 { 233 addChild(new FragDataIndexingCase(m_context, "valid_static_index", "Valid gl_FragData[] assignment using static index", INDEX_EXPR_STATIC)); 234 addChild(new FragDataIndexingCase(m_context, "valid_uniform_index", "Valid gl_FragData[] assignment using uniform index", INDEX_EXPR_UNIFORM)); 235 addChild(new FragDataIndexingCase(m_context, "valid_dynamic_index", "Valid gl_FragData[] assignment using dynamic index", INDEX_EXPR_DYNAMIC)); 236 237 // Negative cases. 238 { 239 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo()); 240 std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/fragdata.test"); 241 242 for (std::vector<tcu::TestNode*>::iterator i = negativeCases.begin(); i != negativeCases.end(); i++) 243 addChild(*i); 244 } 245 } 246 247 } // Functional 248 } // gles2 249 } // deqp 250