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
compareSingleColor(tcu::TestLog & log,const tcu::Surface & surface,tcu::RGBA expectedColor,tcu::RGBA threshold)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:
FragDataIndexingCase(Context & context,const char * name,const char * description,IndexExprType indexExprType)106 FragDataIndexingCase (Context& context, const char* name, const char* description, IndexExprType indexExprType)
107 : TestCase (context, name, description)
108 , m_indexExprType (indexExprType)
109 {
110 }
111
genSources(const IndexExprType indexExprType)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
iterate(void)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
ShaderFragDataTests(Context & context)222 ShaderFragDataTests::ShaderFragDataTests (Context& context)
223 : TestCaseGroup(context, "fragdata", "gl_FragData[] Tests")
224 {
225 }
226
~ShaderFragDataTests(void)227 ShaderFragDataTests::~ShaderFragDataTests (void)
228 {
229 }
230
init(void)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