1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 Clipping tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fClippingTests.hpp"
25 #include "tcuRenderTarget.hpp"
26 #include "tcuTextureUtil.hpp"
27 #include "tcuImageCompare.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "deStringUtil.hpp"
30 #include "deRandom.hpp"
31
32 #include "sglrReferenceContext.hpp"
33 #include "sglrGLContext.hpp"
34
35 #include "glwEnums.hpp"
36 #include "glwDefs.hpp"
37 #include "glwFunctions.hpp"
38
39 using namespace glw; // GLint and other GL types
40
41 namespace deqp
42 {
43 namespace gles3
44 {
45 namespace Functional
46 {
47 namespace
48 {
49
50 using tcu::PixelBufferAccess;
51 using tcu::ConstPixelBufferAccess;
52 using tcu::TestLog;
53
54 static const tcu::Vec4 MASK_COLOR_OK = tcu::Vec4(0.0f, 0.1f, 0.0f, 1.0f);
55 static const tcu::Vec4 MASK_COLOR_DEV = tcu::Vec4(0.8f, 0.5f, 0.0f, 1.0f);
56 static const tcu::Vec4 MASK_COLOR_FAIL = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f);
57
58 const int TEST_CANVAS_SIZE = 200;
59 const rr::WindowRectangle VIEWPORT_WHOLE (0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
60 const rr::WindowRectangle VIEWPORT_CENTER (TEST_CANVAS_SIZE/4, TEST_CANVAS_SIZE/4, TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2);
61 const rr::WindowRectangle VIEWPORT_CORNER (TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2);
62
63
64 const char* shaderSourceVertex = "#version 300 es\n"
65 "in highp vec4 a_position;\n"
66 "in highp vec4 a_color;\n"
67 "in highp float a_pointSize;\n"
68 "out highp vec4 varFragColor;\n"
69 "void main (void)\n"
70 "{\n"
71 " gl_Position = a_position;\n"
72 " gl_PointSize = a_pointSize;\n"
73 " varFragColor = a_color;\n"
74 "}\n";
75 const char* shaderSourceFragment = "#version 300 es\n"
76 "layout(location = 0) out mediump vec4 fragColor;"
77 "in highp vec4 varFragColor;\n"
78 "void main (void)\n"
79 "{\n"
80 " fragColor = varFragColor;\n"
81 "}\n";
82
isBlack(const tcu::IVec4 & a)83 inline bool isBlack (const tcu::IVec4& a)
84 {
85 return a.x() == 0 && a.y() == 0 && a.z() == 0;
86 }
87
isHalfFilled(const tcu::IVec4 & a)88 inline bool isHalfFilled (const tcu::IVec4& a)
89 {
90 const tcu::IVec4 halfFilled (127, 0, 0, 0);
91 const tcu::IVec4 threshold (20, 256, 256, 256);
92
93 return tcu::boolAll(tcu::lessThanEqual(tcu::abs(a - halfFilled), threshold));
94 }
95
isLessThanHalfFilled(const tcu::IVec4 & a)96 inline bool isLessThanHalfFilled (const tcu::IVec4& a)
97 {
98 const int halfFilled = 127;
99 const int threshold = 20;
100
101 return a.x() + threshold < halfFilled;
102 }
103
compareBlackNonBlackPixels(const tcu::IVec4 & a,const tcu::IVec4 & b)104 inline bool compareBlackNonBlackPixels (const tcu::IVec4& a, const tcu::IVec4& b)
105 {
106 return isBlack(a) == isBlack(b);
107 }
108
compareColoredPixels(const tcu::IVec4 & a,const tcu::IVec4 & b)109 inline bool compareColoredPixels (const tcu::IVec4& a, const tcu::IVec4& b)
110 {
111 const bool aIsBlack = isBlack(a);
112 const bool bIsBlack = isBlack(b);
113 const tcu::IVec4 threshold(20, 20, 20, 0);
114
115 if (aIsBlack && bIsBlack)
116 return true;
117 if (aIsBlack != bIsBlack)
118 return false;
119
120 return tcu::boolAll(tcu::lessThanEqual(tcu::abs(a - b), threshold));
121 }
122
blitImageOnBlackSurface(const ConstPixelBufferAccess & src,const PixelBufferAccess & dst)123 void blitImageOnBlackSurface(const ConstPixelBufferAccess& src, const PixelBufferAccess& dst)
124 {
125 const int height = src.getHeight();
126 const int width = src.getWidth();
127
128 for (int y = 0; y < height; y++)
129 for (int x = 0; x < width; x++)
130 {
131 const tcu::IVec4 cSrc = src.getPixelInt(x, y);
132 const tcu::IVec4 cDst = tcu::IVec4(cSrc.x(), cSrc.y(), cSrc.z(), 255);
133
134 dst.setPixel(cDst, x, y);
135 }
136 }
137
138 /*--------------------------------------------------------------------*//*!
139 * \brief Pixelwise comparison of two images.
140 * \note copied & modified from glsRasterizationTests
141 *
142 * Kernel radius defines maximum allowed distance. If radius is 0, only
143 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. Pixels are
144 * equal if pixelCmp returns true..
145 *
146 * Return values: -1 = Perfect match
147 * 0 = Deviation within kernel
148 * >0 = Number of faulty pixels
149 *//*--------------------------------------------------------------------*/
compareImages(tcu::TestLog & log,const ConstPixelBufferAccess & test,const ConstPixelBufferAccess & ref,const PixelBufferAccess & diffMask,int kernelRadius,bool (* pixelCmp)(const tcu::IVec4 & a,const tcu::IVec4 & b))150 inline int compareImages (tcu::TestLog& log, const ConstPixelBufferAccess& test, const ConstPixelBufferAccess& ref, const PixelBufferAccess& diffMask, int kernelRadius, bool (*pixelCmp)(const tcu::IVec4& a, const tcu::IVec4& b))
151 {
152 const int height = test.getHeight();
153 const int width = test.getWidth();
154 int deviatingPixels = 0;
155 int faultyPixels = 0;
156 int compareFailed = -1;
157
158 tcu::clear(diffMask, MASK_COLOR_OK);
159
160 for (int y = 0; y < height; y++)
161 {
162 for (int x = 0; x < width; x++)
163 {
164 const tcu::IVec4 cRef = ref.getPixelInt(x, y);
165 const tcu::IVec4 cTest = test.getPixelInt(x, y);
166
167 // Pixelwise match, no deviation or fault
168 if ((*pixelCmp)(cRef, cTest))
169 continue;
170
171 // Deviation
172 {
173 const int radius = kernelRadius;
174 bool foundRef = false;
175 bool foundTest = false;
176
177 // edges are considered a "deviation" too. The suitable pixel could be "behind" the edge
178 if (y < radius || x < radius || y + radius >= height || x + radius >= width)
179 {
180 foundRef = true;
181 foundTest = true;
182 }
183 else
184 {
185 // find ref
186 for (int kY = y - radius; kY <= y + radius; kY++)
187 for (int kX = x - radius; kX <= x + radius; kX++)
188 {
189 if ((*pixelCmp)(cRef, test.getPixelInt(kX, kY)))
190 {
191 foundRef = true;
192 break;
193 }
194 }
195
196 // find result
197 for (int kY = y - radius; kY <= y + radius; kY++)
198 for (int kX = x - radius; kX <= x + radius; kX++)
199 {
200 if ((*pixelCmp)(cTest, ref.getPixelInt(kX, kY)))
201 {
202 foundTest = true;
203 break;
204 }
205 }
206 }
207
208 // A pixel is deviating if the reference color is found inside the kernel and (~= every pixel reference draws must be drawn by the gl too)
209 // the result color is found in the reference image inside the kernel (~= every pixel gl draws must be drawn by the reference too)
210 if (foundRef && foundTest)
211 {
212 diffMask.setPixel(MASK_COLOR_DEV, x, y);
213 if (compareFailed == -1)
214 compareFailed = 0;
215 deviatingPixels++;
216 continue;
217 }
218 }
219
220 diffMask.setPixel(MASK_COLOR_FAIL, x, y);
221 faultyPixels++; // The pixel is faulty if the color is not found
222 compareFailed = 1;
223 }
224 }
225
226 log << TestLog::Message << deviatingPixels << " deviating pixel(s) found." << TestLog::EndMessage;
227 log << TestLog::Message << faultyPixels << " faulty pixel(s) found." << TestLog::EndMessage;
228
229 return (compareFailed == 1 ? faultyPixels : compareFailed);
230 }
231
232 /*--------------------------------------------------------------------*//*!
233 * \brief Pixelwise comparison of two images.
234 *
235 * Kernel radius defines maximum allowed distance. If radius is 0, only
236 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. Pixels are
237 * equal if they both are black, or both are non-black.
238 *
239 * Return values: -1 = Perfect match
240 * 0 = Deviation within kernel
241 * >0 = Number of faulty pixels
242 *//*--------------------------------------------------------------------*/
compareBlackNonBlackImages(tcu::TestLog & log,const ConstPixelBufferAccess & test,const ConstPixelBufferAccess & ref,const PixelBufferAccess & diffMask,int kernelRadius)243 int compareBlackNonBlackImages (tcu::TestLog& log, const ConstPixelBufferAccess& test, const ConstPixelBufferAccess& ref, const PixelBufferAccess& diffMask, int kernelRadius)
244 {
245 return compareImages(log, test, ref, diffMask, kernelRadius, compareBlackNonBlackPixels);
246 }
247
248 /*--------------------------------------------------------------------*//*!
249 * \brief Pixelwise comparison of two images.
250 *
251 * Kernel radius defines maximum allowed distance. If radius is 0, only
252 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. Pixels are
253 * equal if they both are black, or both are non-black with color values
254 * close to each other.
255 *
256 * Return values: -1 = Perfect match
257 * 0 = Deviation within kernel
258 * >0 = Number of faulty pixels
259 *//*--------------------------------------------------------------------*/
compareColoredImages(tcu::TestLog & log,const ConstPixelBufferAccess & test,const ConstPixelBufferAccess & ref,const PixelBufferAccess & diffMask,int kernelRadius)260 int compareColoredImages (tcu::TestLog& log, const ConstPixelBufferAccess& test, const ConstPixelBufferAccess& ref, const PixelBufferAccess& diffMask, int kernelRadius)
261 {
262 return compareImages(log, test, ref, diffMask, kernelRadius, compareColoredPixels);
263 }
264
265 /*--------------------------------------------------------------------*//*!
266 * \brief Overdraw check verification
267 *
268 * Check that image does not have at any point a
269 * pixel with red component value > 0.5
270 *
271 * Return values: false = area not filled, or leaking
272 *//*--------------------------------------------------------------------*/
checkHalfFilledImageOverdraw(tcu::TestLog & log,const tcu::RenderTarget & m_renderTarget,const ConstPixelBufferAccess & image,const PixelBufferAccess & output)273 bool checkHalfFilledImageOverdraw (tcu::TestLog& log, const tcu::RenderTarget& m_renderTarget, const ConstPixelBufferAccess& image, const PixelBufferAccess& output)
274 {
275 const int height = image.getHeight();
276 const int width = image.getWidth();
277
278 bool faulty = false;
279
280 tcu::clear(output, MASK_COLOR_OK);
281
282 for (int y = 0; y < height; y++)
283 {
284 for (int x = 0; x < width; x++)
285 {
286 const tcu::IVec4 cTest = image.getPixelInt(x, y);
287
288 const bool pixelValid = isBlack(cTest) || isHalfFilled(cTest) || (m_renderTarget.getNumSamples() > 1 && isLessThanHalfFilled(cTest));
289
290 if (!pixelValid)
291 {
292 output.setPixel(MASK_COLOR_FAIL, x, y);
293 faulty = true;
294 }
295 }
296 }
297
298 if (faulty)
299 log << TestLog::Message << "Faulty pixel(s) found." << TestLog::EndMessage;
300
301 return !faulty;
302 }
303
checkPointSize(const glw::Functions & gl,float pointSize)304 void checkPointSize (const glw::Functions& gl, float pointSize)
305 {
306 GLfloat pointSizeRange[2] = {0,0};
307 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
308 if (pointSizeRange[1] < pointSize)
309 throw tcu::NotSupportedError("Maximum point size is too low for this test");
310 }
311
checkLineWidth(const glw::Functions & gl,float lineWidth)312 void checkLineWidth (const glw::Functions& gl, float lineWidth)
313 {
314 GLfloat lineWidthRange[2] = {0,0};
315 gl.getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
316 if (lineWidthRange[1] < lineWidth)
317 throw tcu::NotSupportedError("Maximum line width is too low for this test");
318 }
319
IVec3ToVec3(const tcu::IVec3 & v)320 tcu::Vec3 IVec3ToVec3 (const tcu::IVec3& v)
321 {
322 return tcu::Vec3((float)v.x(), (float)v.y(), (float)v.z());
323 }
324
pointOnTriangle(const tcu::IVec3 & p,const tcu::IVec3 & t0,const tcu::IVec3 & t1,const tcu::IVec3 & t2)325 bool pointOnTriangle (const tcu::IVec3& p, const tcu::IVec3& t0, const tcu::IVec3& t1, const tcu::IVec3& t2)
326 {
327 // Must be on the plane
328 const tcu::IVec3 n = tcu::cross(t1 - t0, t2 - t0);
329 const tcu::IVec3 d = (p - t0);
330
331 if (tcu::dot(n, d))
332 return false;
333
334 // Must be within the triangle area
335 if (deSign32(tcu::dot(n, tcu::cross(t1 - t0, p - t0))) == deSign32(tcu::dot(n, tcu::cross(t2 - t0, p - t0))))
336 return false;
337 if (deSign32(tcu::dot(n, tcu::cross(t2 - t1, p - t1))) == deSign32(tcu::dot(n, tcu::cross(t0 - t1, p - t1))))
338 return false;
339 if (deSign32(tcu::dot(n, tcu::cross(t0 - t2, p - t2))) == deSign32(tcu::dot(n, tcu::cross(t1 - t2, p - t2))))
340 return false;
341
342 return true;
343 }
344
pointsOnLine(const tcu::IVec2 & t0,const tcu::IVec2 & t1,const tcu::IVec2 & t2)345 bool pointsOnLine (const tcu::IVec2& t0, const tcu::IVec2& t1, const tcu::IVec2& t2)
346 {
347 return (t1 - t0).x() * (t2 - t0).y() - (t2 - t0).x() * (t1 - t0).y() == 0;
348 }
349
350 // returns true for cases where polygon is (almost) along xz or yz planes (normal.z < 0.1)
351 // \note[jarkko] Doesn't have to be accurate, just to detect some obviously bad cases
twoPointClippedTriangleInvisible(const tcu::Vec3 & p,const tcu::IVec3 & dir1,const tcu::IVec3 & dir2)352 bool twoPointClippedTriangleInvisible(const tcu::Vec3& p, const tcu::IVec3& dir1, const tcu::IVec3& dir2)
353 {
354 // fixed-point-like coords
355 const deInt64 fixedScale = 64;
356 const deInt64 farValue = 1024;
357 const tcu::Vector<deInt64, 3> d1 = tcu::Vector<deInt64, 3>(dir1.x(), dir1.y(), dir1.z());
358 const tcu::Vector<deInt64, 3> d2 = tcu::Vector<deInt64, 3>(dir2.x(), dir2.y(), dir2.z());
359 const tcu::Vector<deInt64, 3> pfixed = tcu::Vector<deInt64, 3>(deFloorFloatToInt32(p.x() * fixedScale), deFloorFloatToInt32(p.y() * fixedScale), deFloorFloatToInt32(p.z() * fixedScale));
360 const tcu::Vector<deInt64, 3> normalDir = tcu::cross(d1*farValue - pfixed, d2*farValue - pfixed);
361 const deInt64 normalLen2 = tcu::lengthSquared(normalDir);
362
363 return (normalDir.z() * normalDir.z() - normalLen2/100) < 0;
364 }
365
genClippingPointInfoString(const tcu::Vec4 & p)366 std::string genClippingPointInfoString(const tcu::Vec4& p)
367 {
368 std::ostringstream msg;
369
370 if (p.x() < -p.w()) msg << "\t(-X clip)";
371 if (p.x() > p.w()) msg << "\t(+X clip)";
372 if (p.y() < -p.w()) msg << "\t(-Y clip)";
373 if (p.y() > p.w()) msg << "\t(+Y clip)";
374 if (p.z() < -p.w()) msg << "\t(-Z clip)";
375 if (p.z() > p.w()) msg << "\t(+Z clip)";
376
377 return msg.str();
378 }
379
genColorString(const tcu::Vec4 & p)380 std::string genColorString(const tcu::Vec4& p)
381 {
382 const tcu::Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
383 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
384 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
385 const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
386
387 if (p == white) return "(white)";
388 if (p == red) return "(red)";
389 if (p == yellow) return "(yellow)";
390 if (p == blue) return "(blue)";
391 return "";
392 }
393
394 class PositionColorShader : public sglr::ShaderProgram
395 {
396 public:
397 enum
398 {
399 VARYINGLOC_COLOR = 0
400 };
401
402 PositionColorShader (void);
403
404 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
405 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
406 };
407
PositionColorShader(void)408 PositionColorShader::PositionColorShader (void)
409 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
410 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
411 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
412 << sglr::pdec::VertexAttribute("a_pointSize", rr::GENERICVECTYPE_FLOAT)
413 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
414 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
415 << sglr::pdec::VertexSource(shaderSourceVertex)
416 << sglr::pdec::FragmentSource(shaderSourceFragment))
417 {
418 }
419
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const420 void PositionColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
421 {
422 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
423 {
424 const int positionAttrLoc = 0;
425 const int colorAttrLoc = 1;
426 const int pointSizeAttrLoc = 2;
427
428 rr::VertexPacket& packet = *packets[packetNdx];
429
430 // Transform to position
431 packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);
432
433 // output point size
434 packet.pointSize = rr::readVertexAttribFloat(inputs[pointSizeAttrLoc], packet.instanceNdx, packet.vertexNdx).x();
435
436 // Pass color to FS
437 packet.outputs[VARYINGLOC_COLOR] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
438 }
439 }
440
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const441 void PositionColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
442 {
443 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
444 {
445 rr::FragmentPacket& packet = packets[packetNdx];
446
447 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
448 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx));
449 }
450 }
451
452 class RenderTestCase : public TestCase
453 {
454 public:
455 RenderTestCase (Context& context, const char* name, const char* description);
456
457 virtual void testRender (void) = DE_NULL;
init(void)458 virtual void init (void) { }
459
460 IterateResult iterate (void);
461 };
462
RenderTestCase(Context & context,const char * name,const char * description)463 RenderTestCase::RenderTestCase (Context& context, const char* name, const char* description)
464 : TestCase (context, name, description)
465 {
466 }
467
iterate(void)468 RenderTestCase::IterateResult RenderTestCase::iterate (void)
469 {
470 const int width = m_context.getRenderTarget().getWidth();
471 const int height = m_context.getRenderTarget().getHeight();
472
473 m_testCtx.getLog() << TestLog::Message << "Render target size: " << width << "x" << height << TestLog::EndMessage;
474 if (width < TEST_CANVAS_SIZE || height < TEST_CANVAS_SIZE)
475 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(TEST_CANVAS_SIZE) + "x" + de::toString(TEST_CANVAS_SIZE));
476
477 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // success by default
478 testRender();
479
480 return STOP;
481 }
482
483 class PointCase : public RenderTestCase
484 {
485 public:
486 PointCase (Context& context, const char* name, const char* description, const tcu::Vec4* pointsBegin, const tcu::Vec4* pointsEnd, float pointSize, const rr::WindowRectangle& viewport);
487
488 void init (void);
489 void testRender (void);
490
491 private:
492 const std::vector<tcu::Vec4> m_points;
493 const float m_pointSize;
494 const rr::WindowRectangle m_viewport;
495 };
496
PointCase(Context & context,const char * name,const char * description,const tcu::Vec4 * pointsBegin,const tcu::Vec4 * pointsEnd,float pointSize,const rr::WindowRectangle & viewport)497 PointCase::PointCase (Context& context, const char* name, const char* description, const tcu::Vec4* pointsBegin, const tcu::Vec4* pointsEnd, float pointSize, const rr::WindowRectangle& viewport)
498 : RenderTestCase(context, name, description)
499 , m_points (pointsBegin, pointsEnd)
500 , m_pointSize (pointSize)
501 , m_viewport (viewport)
502 {
503 }
504
init(void)505 void PointCase::init (void)
506 {
507 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
508 checkPointSize (gl, m_pointSize);
509 }
510
testRender(void)511 void PointCase::testRender (void)
512 {
513 using tcu::TestLog;
514
515 const int numSamples = de::max(m_context.getRenderTarget().getNumSamples(), 1);
516
517 tcu::TestLog& log = m_testCtx.getLog();
518 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE));
519 sglr::ReferenceContextLimits limits;
520 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples);
521 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
522 PositionColorShader program;
523 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
524 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
525 sglr::Context* contexts[2] = {&glesContext, &refContext};
526 tcu::Surface* surfaces[2] = {&testSurface, &refSurface};
527
528 // log the purpose of the test
529 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage;
530 log << TestLog::Message << "Rendering points with point size " << m_pointSize << ". Coordinates:" << TestLog::EndMessage;
531 for (size_t ndx = 0; ndx < m_points.size(); ++ndx)
532 log << TestLog::Message
533 << "\tx=" << m_points[ndx].x()
534 << "\ty=" << m_points[ndx].y()
535 << "\tz=" << m_points[ndx].z()
536 << "\tw=" << m_points[ndx].w()
537 << "\t" << genClippingPointInfoString(m_points[ndx])
538 << TestLog::EndMessage;
539
540 for (int contextNdx = 0; contextNdx < 2; ++contextNdx)
541 {
542 sglr::Context& ctx = *contexts[contextNdx];
543 tcu::Surface& dstSurface = *surfaces[contextNdx];
544 const deUint32 programId = ctx.createProgram(&program);
545 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position");
546 const GLint pointSizeLoc = ctx.getAttribLocation(programId, "a_pointSize");
547 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color");
548
549 ctx.clearColor (0, 0, 0, 1);
550 ctx.clearDepthf (1.0f);
551 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
552 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height);
553 ctx.useProgram (programId);
554 ctx.enableVertexAttribArray (positionLoc);
555 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &m_points[0]);
556 ctx.vertexAttrib1f (pointSizeLoc, m_pointSize);
557 ctx.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
558 ctx.drawArrays (GL_POINTS, 0, (glw::GLsizei)m_points.size());
559 ctx.disableVertexAttribArray (positionLoc);
560 ctx.useProgram (0);
561 ctx.deleteProgram (programId);
562 ctx.finish ();
563
564 ctx.readPixels(dstSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
565 }
566
567 // do the comparison
568 {
569 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
570 const int kernelRadius = 1;
571 int faultyPixels;
572
573 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
574 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage;
575
576 faultyPixels = compareBlackNonBlackImages(log, testSurface.getAccess(), refSurface.getAccess(), diffMask.getAccess(), kernelRadius);
577
578 if (faultyPixels > 0)
579 {
580 log << TestLog::ImageSet("Images", "Image comparison")
581 << TestLog::Image("TestImage", "Test image", testSurface.getAccess())
582 << TestLog::Image("ReferenceImage", "Reference image", refSurface.getAccess())
583 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess())
584 << TestLog::EndImageSet
585 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
586
587 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
588 }
589 }
590 }
591
592 class LineRenderTestCase : public RenderTestCase
593 {
594 public:
595 struct ColoredLineData
596 {
597 tcu::Vec4 p0;
598 tcu::Vec4 c0;
599 tcu::Vec4 p1;
600 tcu::Vec4 c1;
601 };
602
603 struct ColorlessLineData
604 {
605 tcu::Vec4 p0;
606 tcu::Vec4 p1;
607 };
608 LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport);
609 LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport);
610
611 virtual void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) = DE_NULL;
612 void init (void);
613 void testRender (void);
614
615 protected:
616 const float m_lineWidth;
617
618 private:
619 std::vector<ColoredLineData> convertToColoredLines (const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd);
620
621 const std::vector<ColoredLineData> m_lines;
622 const rr::WindowRectangle m_viewport;
623 };
624
LineRenderTestCase(Context & context,const char * name,const char * description,const ColoredLineData * linesBegin,const ColoredLineData * linesEnd,float lineWidth,const rr::WindowRectangle & viewport)625 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
626 : RenderTestCase (context, name, description)
627 , m_lineWidth (lineWidth)
628 , m_lines (linesBegin, linesEnd)
629 , m_viewport (viewport)
630 {
631 }
632
LineRenderTestCase(Context & context,const char * name,const char * description,const ColorlessLineData * linesBegin,const ColorlessLineData * linesEnd,float lineWidth,const rr::WindowRectangle & viewport)633 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
634 : RenderTestCase (context, name, description)
635 , m_lineWidth (lineWidth)
636 , m_lines (convertToColoredLines(linesBegin, linesEnd))
637 , m_viewport (viewport)
638 {
639 }
640
init(void)641 void LineRenderTestCase::init (void)
642 {
643 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
644 checkLineWidth (gl, m_lineWidth);
645 }
646
testRender(void)647 void LineRenderTestCase::testRender (void)
648 {
649 using tcu::TestLog;
650
651 const int numSamples = de::max(m_context.getRenderTarget().getNumSamples(), 1);
652 const int verticesPerLine = 2;
653
654 tcu::TestLog& log = m_testCtx.getLog();
655 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE));
656 sglr::ReferenceContextLimits limits;
657 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples);
658 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
659 PositionColorShader program;
660 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
661 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
662 sglr::Context* contexts[2] = {&glesContext, &refContext};
663 tcu::Surface* surfaces[2] = {&testSurface, &refSurface};
664
665 // log the purpose of the test
666 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage;
667 log << TestLog::Message << "Rendering lines with line width " << m_lineWidth << ". Coordinates:" << TestLog::EndMessage;
668 for (size_t ndx = 0; ndx < m_lines.size(); ++ndx)
669 {
670 const std::string fromProperties = genClippingPointInfoString(m_lines[ndx].p0);
671 const std::string toProperties = genClippingPointInfoString(m_lines[ndx].p1);
672
673 log << TestLog::Message << "\tfrom (x=" << m_lines[ndx].p0.x() << "\ty=" << m_lines[ndx].p0.y() << "\tz=" << m_lines[ndx].p0.z() << "\tw=" << m_lines[ndx].p0.w() << ")\t" << fromProperties << TestLog::EndMessage;
674 log << TestLog::Message << "\tto (x=" << m_lines[ndx].p1.x() << "\ty=" << m_lines[ndx].p1.y() << "\tz=" << m_lines[ndx].p1.z() << "\tw=" << m_lines[ndx].p1.w() << ")\t" << toProperties << TestLog::EndMessage;
675 log << TestLog::Message << TestLog::EndMessage;
676 }
677
678 // render test image
679 for (int contextNdx = 0; contextNdx < 2; ++contextNdx)
680 {
681 sglr::Context& ctx = *contexts[contextNdx];
682 tcu::Surface& dstSurface = *surfaces[contextNdx];
683 const deUint32 programId = ctx.createProgram(&program);
684 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position");
685 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color");
686
687 ctx.clearColor (0, 0, 0, 1);
688 ctx.clearDepthf (1.0f);
689 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
690 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height);
691 ctx.useProgram (programId);
692 ctx.enableVertexAttribArray (positionLoc);
693 ctx.enableVertexAttribArray (colorLoc);
694 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_lines[0].p0);
695 ctx.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_lines[0].c0);
696 ctx.lineWidth (m_lineWidth);
697 ctx.drawArrays (GL_LINES, 0, verticesPerLine * (glw::GLsizei)m_lines.size());
698 ctx.disableVertexAttribArray (positionLoc);
699 ctx.disableVertexAttribArray (colorLoc);
700 ctx.useProgram (0);
701 ctx.deleteProgram (programId);
702 ctx.finish ();
703
704 ctx.readPixels(dstSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
705 }
706
707 // compare
708 verifyImage(testSurface.getAccess(), refSurface.getAccess());
709 }
710
convertToColoredLines(const ColorlessLineData * linesBegin,const ColorlessLineData * linesEnd)711 std::vector<LineRenderTestCase::ColoredLineData> LineRenderTestCase::convertToColoredLines(const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd)
712 {
713 std::vector<ColoredLineData> ret;
714
715 for (const ColorlessLineData* it = linesBegin; it != linesEnd; ++it)
716 {
717 ColoredLineData r;
718
719 r.p0 = (*it).p0;
720 r.c0 = tcu::Vec4(1, 1, 1, 1);
721 r.p1 = (*it).p1;
722 r.c1 = tcu::Vec4(1, 1, 1, 1);
723
724 ret.push_back(r);
725 }
726
727 return ret;
728 }
729
730 class LineCase : public LineRenderTestCase
731 {
732 public:
733 LineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColorlessLineData* linesBegin, const LineRenderTestCase::ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport, int searchKernelSize = 1);
734
735 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess);
736
737 private:
738 const int m_searchKernelSize;
739 };
740
LineCase(Context & context,const char * name,const char * description,const LineRenderTestCase::ColorlessLineData * linesBegin,const LineRenderTestCase::ColorlessLineData * linesEnd,float lineWidth,const rr::WindowRectangle & viewport,int searchKernelSize)741 LineCase::LineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColorlessLineData* linesBegin, const LineRenderTestCase::ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport, int searchKernelSize)
742 : LineRenderTestCase (context, name, description, linesBegin, linesEnd, lineWidth, viewport)
743 , m_searchKernelSize (searchKernelSize)
744 {
745 }
746
verifyImage(const tcu::ConstPixelBufferAccess & testImageAccess,const tcu::ConstPixelBufferAccess & referenceImageAccess)747 void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
748 {
749 const int faultyLimit = 6;
750 int faultyPixels;
751
752 const bool isMsaa = m_context.getRenderTarget().getNumSamples() > 1;
753 tcu::TestLog& log = m_testCtx.getLog();
754 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
755
756 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
757 log << TestLog::Message << "Deviation within radius of " << m_searchKernelSize << " is allowed." << TestLog::EndMessage;
758 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage;
759
760 faultyPixels = compareBlackNonBlackImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), m_searchKernelSize);
761
762 if (faultyPixels > faultyLimit)
763 {
764 log << TestLog::ImageSet("Images", "Image comparison")
765 << TestLog::Image("TestImage", "Test image", testImageAccess)
766 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess)
767 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess())
768 << TestLog::EndImageSet
769 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
770
771 if (m_lineWidth != 1.0f && isMsaa)
772 {
773 log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage;
774 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed");
775 }
776 else
777 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
778 }
779 }
780
781 class ColoredLineCase : public LineRenderTestCase
782 {
783 public:
784 ColoredLineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColoredLineData* linesBegin, const LineRenderTestCase::ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport);
785
786 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess);
787 };
788
ColoredLineCase(Context & context,const char * name,const char * description,const LineRenderTestCase::ColoredLineData * linesBegin,const LineRenderTestCase::ColoredLineData * linesEnd,float lineWidth,const rr::WindowRectangle & viewport)789 ColoredLineCase::ColoredLineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColoredLineData* linesBegin, const LineRenderTestCase::ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport)
790 : LineRenderTestCase (context, name, description, linesBegin, linesEnd, lineWidth, viewport)
791 {
792 }
793
verifyImage(const tcu::ConstPixelBufferAccess & testImageAccess,const tcu::ConstPixelBufferAccess & referenceImageAccess)794 void ColoredLineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
795 {
796 const bool msaa = m_context.getRenderTarget().getNumSamples() > 1;
797 tcu::TestLog& log = m_testCtx.getLog();
798
799 if (!msaa)
800 {
801 const int kernelRadius = 1;
802 const int faultyLimit = 6;
803 int faultyPixels;
804
805 tcu::Surface diffMask(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
806
807 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
808 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage;
809 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage;
810
811 faultyPixels = compareColoredImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), kernelRadius);
812
813 if (faultyPixels > faultyLimit)
814 {
815 log << TestLog::ImageSet("Images", "Image comparison")
816 << TestLog::Image("TestImage", "Test image", testImageAccess)
817 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess)
818 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess())
819 << TestLog::EndImageSet
820 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
821
822 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
823 }
824 }
825 else
826 {
827 const float threshold = 0.3f;
828 if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
829 {
830 if (m_lineWidth != 1.0f)
831 {
832 log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage;
833 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed");
834 }
835 else
836 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
837 }
838 }
839 }
840
841 class TriangleCaseBase : public RenderTestCase
842 {
843 public:
844 struct TriangleData
845 {
846 tcu::Vec4 p0;
847 tcu::Vec4 c0;
848 tcu::Vec4 p1;
849 tcu::Vec4 c1;
850 tcu::Vec4 p2;
851 tcu::Vec4 c2;
852 };
853
854 TriangleCaseBase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport);
855
856 virtual void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) = DE_NULL;
857 void testRender (void);
858
859 private:
860 const std::vector<TriangleData> m_polys;
861 const rr::WindowRectangle m_viewport;
862 };
863
TriangleCaseBase(Context & context,const char * name,const char * description,const TriangleData * polysBegin,const TriangleData * polysEnd,const rr::WindowRectangle & viewport)864 TriangleCaseBase::TriangleCaseBase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport)
865 : RenderTestCase(context, name, description)
866 , m_polys (polysBegin, polysEnd)
867 , m_viewport (viewport)
868 {
869 }
870
testRender(void)871 void TriangleCaseBase::testRender (void)
872 {
873 using tcu::TestLog;
874
875 const int numSamples = de::max(m_context.getRenderTarget().getNumSamples(), 1);
876 const int verticesPerTriangle = 3;
877
878 tcu::TestLog& log = m_testCtx.getLog();
879 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE));
880 sglr::ReferenceContextLimits limits;
881 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples);
882 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
883 PositionColorShader program;
884 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
885 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
886 sglr::Context* contexts[2] = {&glesContext, &refContext};
887 tcu::Surface* surfaces[2] = {&testSurface, &refSurface};
888
889 // log the purpose of the test
890 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage;
891 log << TestLog::Message << "Rendering triangles. Coordinates:" << TestLog::EndMessage;
892 for (size_t ndx = 0; ndx < m_polys.size(); ++ndx)
893 {
894 const std::string v0Properties = genClippingPointInfoString(m_polys[ndx].p0);
895 const std::string v1Properties = genClippingPointInfoString(m_polys[ndx].p1);
896 const std::string v2Properties = genClippingPointInfoString(m_polys[ndx].p2);
897 const std::string c0Properties = genColorString(m_polys[ndx].c0);
898 const std::string c1Properties = genColorString(m_polys[ndx].c1);
899 const std::string c2Properties = genColorString(m_polys[ndx].c2);
900
901 log << TestLog::Message << "\tv0 (x=" << m_polys[ndx].p0.x() << "\ty=" << m_polys[ndx].p0.y() << "\tz=" << m_polys[ndx].p0.z() << "\tw=" << m_polys[ndx].p0.w() << ")\t" << v0Properties << "\t" << c0Properties << TestLog::EndMessage;
902 log << TestLog::Message << "\tv1 (x=" << m_polys[ndx].p1.x() << "\ty=" << m_polys[ndx].p1.y() << "\tz=" << m_polys[ndx].p1.z() << "\tw=" << m_polys[ndx].p1.w() << ")\t" << v1Properties << "\t" << c1Properties << TestLog::EndMessage;
903 log << TestLog::Message << "\tv2 (x=" << m_polys[ndx].p2.x() << "\ty=" << m_polys[ndx].p2.y() << "\tz=" << m_polys[ndx].p2.z() << "\tw=" << m_polys[ndx].p2.w() << ")\t" << v2Properties << "\t" << c2Properties << TestLog::EndMessage;
904 log << TestLog::Message << TestLog::EndMessage;
905 }
906
907 // render test image
908 for (int contextNdx = 0; contextNdx < 2; ++contextNdx)
909 {
910 sglr::Context& ctx = *contexts[contextNdx];
911 tcu::Surface& dstSurface = *surfaces[contextNdx];
912 const deUint32 programId = ctx.createProgram(&program);
913 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position");
914 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color");
915
916 ctx.clearColor (0, 0, 0, 1);
917 ctx.clearDepthf (1.0f);
918 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
919 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height);
920 ctx.useProgram (programId);
921 ctx.enableVertexAttribArray (positionLoc);
922 ctx.enableVertexAttribArray (colorLoc);
923 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_polys[0].p0);
924 ctx.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_polys[0].c0);
925 ctx.drawArrays (GL_TRIANGLES, 0, verticesPerTriangle * (glw::GLsizei)m_polys.size());
926 ctx.disableVertexAttribArray (positionLoc);
927 ctx.disableVertexAttribArray (colorLoc);
928 ctx.useProgram (0);
929 ctx.deleteProgram (programId);
930 ctx.finish ();
931
932 ctx.readPixels(dstSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
933 }
934
935 verifyImage(testSurface.getAccess(), refSurface.getAccess());
936 }
937
938 class TriangleCase : public TriangleCaseBase
939 {
940 public:
941 TriangleCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport);
942
943 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess);
944 };
945
TriangleCase(Context & context,const char * name,const char * description,const TriangleData * polysBegin,const TriangleData * polysEnd,const rr::WindowRectangle & viewport)946 TriangleCase::TriangleCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport)
947 : TriangleCaseBase(context, name, description, polysBegin, polysEnd, viewport)
948 {
949 }
950
verifyImage(const tcu::ConstPixelBufferAccess & testImageAccess,const tcu::ConstPixelBufferAccess & referenceImageAccess)951 void TriangleCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
952 {
953 const int kernelRadius = 1;
954 const int faultyLimit = 6;
955 tcu::TestLog& log = m_testCtx.getLog();
956 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
957 int faultyPixels;
958
959 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
960 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage;
961 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage;
962
963 faultyPixels = compareBlackNonBlackImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), kernelRadius);
964
965 if (faultyPixels > faultyLimit)
966 {
967 log << TestLog::ImageSet("Images", "Image comparison")
968 << TestLog::Image("TestImage", "Test image", testImageAccess)
969 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess)
970 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess())
971 << TestLog::EndImageSet
972 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
973
974 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
975 }
976 }
977
978 class TriangleAttributeCase : public TriangleCaseBase
979 {
980 public:
981 TriangleAttributeCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport);
982
983 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess);
984 };
985
TriangleAttributeCase(Context & context,const char * name,const char * description,const TriangleData * polysBegin,const TriangleData * polysEnd,const rr::WindowRectangle & viewport)986 TriangleAttributeCase::TriangleAttributeCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport)
987 : TriangleCaseBase(context, name, description, polysBegin, polysEnd, viewport)
988 {
989 }
990
verifyImage(const tcu::ConstPixelBufferAccess & testImageAccess,const tcu::ConstPixelBufferAccess & referenceImageAccess)991 void TriangleAttributeCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess)
992 {
993 const bool msaa = m_context.getRenderTarget().getNumSamples() > 1;
994 tcu::TestLog& log = m_testCtx.getLog();
995
996 if (!msaa)
997 {
998 const int kernelRadius = 1;
999 const int faultyLimit = 6;
1000 int faultyPixels;
1001 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1002
1003 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
1004 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage;
1005 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage;
1006 faultyPixels = compareColoredImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), kernelRadius);
1007
1008 if (faultyPixels > faultyLimit)
1009 {
1010 log << TestLog::ImageSet("Images", "Image comparison")
1011 << TestLog::Image("TestImage", "Test image", testImageAccess)
1012 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess)
1013 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess())
1014 << TestLog::EndImageSet
1015 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
1016
1017 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
1018 }
1019 }
1020 else
1021 {
1022 const float threshold = 0.3f;
1023 if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
1024 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
1025 }
1026 }
1027
1028 class FillTest : public RenderTestCase
1029 {
1030 public:
1031 FillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport);
1032
1033 virtual void render (sglr::Context& ctx) = DE_NULL;
1034 void testRender (void);
1035
1036 protected:
1037 const rr::WindowRectangle m_viewport;
1038 };
1039
FillTest(Context & context,const char * name,const char * description,const rr::WindowRectangle & viewport)1040 FillTest::FillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport)
1041 : RenderTestCase(context, name, description)
1042 , m_viewport (viewport)
1043 {
1044 }
1045
testRender(void)1046 void FillTest::testRender (void)
1047 {
1048 using tcu::TestLog;
1049
1050 const int numSamples = 1;
1051
1052 tcu::TestLog& log = m_testCtx.getLog();
1053 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE));
1054 sglr::ReferenceContextLimits limits;
1055 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples);
1056 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
1057 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1058 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1059
1060 render(glesContext);
1061 glesContext.readPixels(testSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1062
1063 render(refContext);
1064 refContext.readPixels(refSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1065
1066 // check overdraw
1067 {
1068 bool overdrawOk;
1069 tcu::Surface outputImage(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1070
1071 log << TestLog::Message << "Checking for overdraw " << TestLog::EndMessage;
1072 overdrawOk = checkHalfFilledImageOverdraw(log, m_context.getRenderTarget(), testSurface.getAccess(), outputImage.getAccess());
1073
1074 if (!overdrawOk)
1075 {
1076 log << TestLog::ImageSet("Images", "Image comparison")
1077 << TestLog::Image("TestImage", "Test image", testSurface.getAccess())
1078 << TestLog::Image("InvalidPixels", "Invalid pixels", outputImage.getAccess())
1079 << TestLog::EndImageSet
1080 << tcu::TestLog::Message << "Got overdraw." << tcu::TestLog::EndMessage;
1081
1082 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got overdraw");
1083 }
1084 }
1085
1086 // compare & check missing pixels
1087 {
1088 const int kernelRadius = 1;
1089 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE);
1090 int faultyPixels;
1091
1092 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage;
1093 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage;
1094
1095 blitImageOnBlackSurface(refSurface.getAccess(), refSurface.getAccess()); // makes images look right in Candy
1096
1097 faultyPixels = compareBlackNonBlackImages(log, testSurface.getAccess(), refSurface.getAccess(), diffMask.getAccess(), kernelRadius);
1098
1099 if (faultyPixels > 0)
1100 {
1101 log << TestLog::ImageSet("Images", "Image comparison")
1102 << TestLog::Image("TestImage", "Test image", testSurface.getAccess())
1103 << TestLog::Image("ReferenceImage", "Reference image", refSurface.getAccess())
1104 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess())
1105 << TestLog::EndImageSet
1106 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
1107
1108 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
1109 }
1110 }
1111 }
1112
1113 class TriangleFillTest : public FillTest
1114 {
1115 public:
1116 struct FillTriangle
1117 {
1118 tcu::Vec4 v0;
1119 tcu::Vec4 c0;
1120 tcu::Vec4 v1;
1121 tcu::Vec4 c1;
1122 tcu::Vec4 v2;
1123 tcu::Vec4 c2;
1124 };
1125
1126 TriangleFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport);
1127
1128 void render (sglr::Context& ctx);
1129
1130 protected:
1131 std::vector<FillTriangle> m_triangles;
1132 };
1133
TriangleFillTest(Context & context,const char * name,const char * description,const rr::WindowRectangle & viewport)1134 TriangleFillTest::TriangleFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport)
1135 : FillTest(context, name, description, viewport)
1136 {
1137 }
1138
render(sglr::Context & ctx)1139 void TriangleFillTest::render (sglr::Context& ctx)
1140 {
1141 const int verticesPerTriangle = 3;
1142 PositionColorShader program;
1143 const deUint32 programId = ctx.createProgram(&program);
1144 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position");
1145 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color");
1146 tcu::TestLog& log = m_testCtx.getLog();
1147
1148 // log the purpose of the test
1149 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage;
1150 log << TestLog::Message << "Rendering triangles. Coordinates:" << TestLog::EndMessage;
1151 for (size_t ndx = 0; ndx < m_triangles.size(); ++ndx)
1152 {
1153 const std::string v0Properties = genClippingPointInfoString(m_triangles[ndx].v0);
1154 const std::string v1Properties = genClippingPointInfoString(m_triangles[ndx].v1);
1155 const std::string v2Properties = genClippingPointInfoString(m_triangles[ndx].v2);
1156
1157 log << TestLog::Message << "\tv0 (x=" << m_triangles[ndx].v0.x() << "\ty=" << m_triangles[ndx].v0.y() << "\tz=" << m_triangles[ndx].v0.z() << "\tw=" << m_triangles[ndx].v0.w() << ")\t" << v0Properties << TestLog::EndMessage;
1158 log << TestLog::Message << "\tv1 (x=" << m_triangles[ndx].v1.x() << "\ty=" << m_triangles[ndx].v1.y() << "\tz=" << m_triangles[ndx].v1.z() << "\tw=" << m_triangles[ndx].v1.w() << ")\t" << v1Properties << TestLog::EndMessage;
1159 log << TestLog::Message << "\tv2 (x=" << m_triangles[ndx].v2.x() << "\ty=" << m_triangles[ndx].v2.y() << "\tz=" << m_triangles[ndx].v2.z() << "\tw=" << m_triangles[ndx].v2.w() << ")\t" << v2Properties << TestLog::EndMessage;
1160 log << TestLog::Message << TestLog::EndMessage;
1161 }
1162
1163 ctx.clearColor (0, 0, 0, 1);
1164 ctx.clearDepthf (1.0f);
1165 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1166 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height);
1167 ctx.useProgram (programId);
1168 ctx.blendFunc (GL_ONE, GL_ONE);
1169 ctx.enable (GL_BLEND);
1170 ctx.enableVertexAttribArray (positionLoc);
1171 ctx.enableVertexAttribArray (colorLoc);
1172 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_triangles[0].v0);
1173 ctx.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_triangles[0].c0);
1174 ctx.drawArrays (GL_TRIANGLES, 0, verticesPerTriangle * (glw::GLsizei)m_triangles.size());
1175 ctx.disableVertexAttribArray (positionLoc);
1176 ctx.disableVertexAttribArray (colorLoc);
1177 ctx.useProgram (0);
1178 ctx.deleteProgram (programId);
1179 ctx.finish ();
1180 }
1181
1182 class QuadFillTest : public TriangleFillTest
1183 {
1184 public:
1185 QuadFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport, const tcu::Vec3& d1, const tcu::Vec3& d2, const tcu::Vec3& center_ = tcu::Vec3(0, 0, 0));
1186 };
1187
QuadFillTest(Context & context,const char * name,const char * description,const rr::WindowRectangle & viewport,const tcu::Vec3 & d1,const tcu::Vec3 & d2,const tcu::Vec3 & center_)1188 QuadFillTest::QuadFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport, const tcu::Vec3& d1, const tcu::Vec3& d2, const tcu::Vec3& center_)
1189 : TriangleFillTest(context, name, description, viewport)
1190 {
1191 const float radius = 40000.0f;
1192 const tcu::Vec4 center = tcu::Vec4(center_.x(), center_.y(), center_.z(), 1.0f);
1193 const tcu::Vec4 halfWhite = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
1194 const tcu::Vec4 halfRed = tcu::Vec4(0.5f, 0.0f, 0.0f, 0.5f);
1195 const tcu::Vec4 e1 = radius * tcu::Vec4(d1.x(), d1.y(), d1.z(), 0.0f);
1196 const tcu::Vec4 e2 = radius * tcu::Vec4(d2.x(), d2.y(), d2.z(), 0.0f);
1197
1198 FillTriangle triangle1;
1199 FillTriangle triangle2;
1200
1201 triangle1.c0 = halfWhite;
1202 triangle1.c1 = halfWhite;
1203 triangle1.c2 = halfWhite;
1204 triangle1.v0 = center + e1 + e2;
1205 triangle1.v1 = center + e1 - e2;
1206 triangle1.v2 = center - e1 - e2;
1207 m_triangles.push_back(triangle1);
1208
1209 triangle2.c0 = halfRed;
1210 triangle2.c1 = halfRed;
1211 triangle2.c2 = halfRed;
1212 triangle2.v0 = center + e1 + e2;
1213 triangle2.v1 = center - e1 - e2;
1214 triangle2.v2 = center - e1 + e2;
1215 m_triangles.push_back(triangle2);
1216 }
1217
1218 class TriangleFanFillTest : public TriangleFillTest
1219 {
1220 public:
1221 TriangleFanFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport);
1222 };
1223
TriangleFanFillTest(Context & context,const char * name,const char * description,const rr::WindowRectangle & viewport)1224 TriangleFanFillTest::TriangleFanFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport)
1225 : TriangleFillTest(context, name, description, viewport)
1226 {
1227 const float radius = 70000.0f;
1228 const int trianglesPerVisit = 40;
1229 const tcu::Vec4 center = tcu::Vec4(0, 0, 0, 1.0f);
1230 const tcu::Vec4 halfWhite = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
1231 const tcu::Vec4 oddSliceColor = tcu::Vec4(0.0f, 0.0f, 0.5f, 0.0f);
1232
1233 // create a continuous surface that goes through all 6 clip planes
1234
1235 /*
1236 * / /
1237 * /_ _ _ _ _ /x
1238 * | | |
1239 * | | /
1240 * | / --xe /
1241 * | | | /
1242 * |_ _ _ e _ _|/
1243 *
1244 * e = enter
1245 * x = exit
1246 */
1247 const struct ClipPlaneVisit
1248 {
1249 const tcu::Vec3 corner;
1250 const tcu::Vec3 entryPoint;
1251 const tcu::Vec3 exitPoint;
1252 } visits[] =
1253 {
1254 { tcu::Vec3( 1, 1, 1), tcu::Vec3( 0, 1, 1), tcu::Vec3( 1, 0, 1) },
1255 { tcu::Vec3( 1,-1, 1), tcu::Vec3( 1, 0, 1), tcu::Vec3( 1,-1, 0) },
1256 { tcu::Vec3( 1,-1,-1), tcu::Vec3( 1,-1, 0), tcu::Vec3( 0,-1,-1) },
1257 { tcu::Vec3(-1,-1,-1), tcu::Vec3( 0,-1,-1), tcu::Vec3(-1, 0,-1) },
1258 { tcu::Vec3(-1, 1,-1), tcu::Vec3(-1, 0,-1), tcu::Vec3(-1, 1, 0) },
1259 { tcu::Vec3(-1, 1, 1), tcu::Vec3(-1, 1, 0), tcu::Vec3( 0, 1, 1) },
1260 };
1261
1262 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(visits); ++ndx)
1263 {
1264 const ClipPlaneVisit& visit = visits[ndx];
1265
1266 for (int tri = 0; tri < trianglesPerVisit; ++tri)
1267 {
1268 tcu::Vec3 vertex0;
1269 tcu::Vec3 vertex1;
1270
1271 if (tri == 0) // first vertex is magic
1272 {
1273 vertex0 = visit.entryPoint;
1274 }
1275 else
1276 {
1277 const tcu::Vec3 v1 = visit.entryPoint - visit.corner;
1278 const tcu::Vec3 v2 = visit.exitPoint - visit.corner;
1279
1280 vertex0 = visit.corner + tcu::normalize(tcu::mix(v1, v2, tcu::Vec3(float(tri)/trianglesPerVisit)));
1281 }
1282
1283 if (tri == trianglesPerVisit-1) // last vertex is magic
1284 {
1285 vertex1 = visit.exitPoint;
1286 }
1287 else
1288 {
1289 const tcu::Vec3 v1 = visit.entryPoint - visit.corner;
1290 const tcu::Vec3 v2 = visit.exitPoint - visit.corner;
1291
1292 vertex1 = visit.corner + tcu::normalize(tcu::mix(v1, v2, tcu::Vec3(float(tri+1)/trianglesPerVisit)));
1293 }
1294
1295 // write vec out
1296 {
1297 FillTriangle triangle;
1298
1299 triangle.c0 = (tri % 2) ? halfWhite : halfWhite + oddSliceColor;
1300 triangle.c1 = (tri % 2) ? halfWhite : halfWhite + oddSliceColor;
1301 triangle.c2 = (tri % 2) ? halfWhite : halfWhite + oddSliceColor;
1302 triangle.v0 = center;
1303 triangle.v1 = tcu::Vec4(vertex0.x() * radius, vertex0.y() * radius, vertex0.z() * radius, 1.0f);
1304 triangle.v2 = tcu::Vec4(vertex1.x() * radius, vertex1.y() * radius, vertex1.z() * radius, 1.0f);
1305
1306 m_triangles.push_back(triangle);
1307 }
1308
1309 }
1310 }
1311 }
1312
1313 class PointsTestGroup : public TestCaseGroup
1314 {
1315 public:
1316 PointsTestGroup (Context& context);
1317
1318 void init (void);
1319 };
1320
PointsTestGroup(Context & context)1321 PointsTestGroup::PointsTestGroup (Context& context)
1322 : TestCaseGroup(context, "point", "Point clipping tests")
1323 {
1324 }
1325
init(void)1326 void PointsTestGroup::init (void)
1327 {
1328 const float littleOverViewport = 1.0f + (2.0f / (TEST_CANVAS_SIZE)); // one pixel over the viewport edge in VIEWPORT_WHOLE, half pixels over in the reduced viewport.
1329
1330 const tcu::Vec4 viewportTestPoints[] =
1331 {
1332 // in clip volume
1333 tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f),
1334 tcu::Vec4( 0.1f, 0.1f, 0.1f, 1.0f),
1335 tcu::Vec4(-0.1f, 0.1f, -0.1f, 1.0f),
1336 tcu::Vec4(-0.1f, -0.1f, 0.1f, 1.0f),
1337 tcu::Vec4( 0.1f, -0.1f, -0.1f, 1.0f),
1338
1339 // in clip volume with w != 1
1340 tcu::Vec4( 2.0f, 2.0f, 2.0f, 3.0f),
1341 tcu::Vec4(-2.0f, -2.0f, 2.0f, 3.0f),
1342 tcu::Vec4( 0.5f, -0.5f, 0.5f, 0.7f),
1343 tcu::Vec4(-0.5f, 0.5f, -0.5f, 0.7f),
1344
1345 // near the edge
1346 tcu::Vec4(-2.0f, -2.0f, 0.0f, 2.2f),
1347 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.1f),
1348 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.1f),
1349
1350 // not in the volume but still between near and far planes
1351 tcu::Vec4( 1.3f, 0.0f, 0.0f, 1.0f),
1352 tcu::Vec4(-1.3f, 0.0f, 0.0f, 1.0f),
1353 tcu::Vec4( 0.0f, 1.3f, 0.0f, 1.0f),
1354 tcu::Vec4( 0.0f, -1.3f, 0.0f, 1.0f),
1355
1356 tcu::Vec4(-1.3f, -1.3f, 0.0f, 1.0f),
1357 tcu::Vec4(-1.3f, 1.3f, 0.0f, 1.0f),
1358 tcu::Vec4( 1.3f, 1.3f, 0.0f, 1.0f),
1359 tcu::Vec4( 1.3f, -1.3f, 0.0f, 1.0f),
1360
1361 // outside the viewport, wide points have fragments in the viewport
1362 tcu::Vec4( littleOverViewport, littleOverViewport, 0.0f, 1.0f),
1363 tcu::Vec4( 0.0f, littleOverViewport, 0.0f, 1.0f),
1364 tcu::Vec4( littleOverViewport, 0.0f, 0.0f, 1.0f),
1365 };
1366 const tcu::Vec4 depthTestPoints[] =
1367 {
1368 // in clip volume
1369 tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f),
1370 tcu::Vec4( 0.1f, 0.1f, 0.1f, 1.0f),
1371 tcu::Vec4(-0.1f, 0.1f, -0.1f, 1.0f),
1372 tcu::Vec4(-0.1f, -0.1f, 0.1f, 1.0f),
1373 tcu::Vec4( 0.1f, -0.1f, -0.1f, 1.0f),
1374
1375 // not between the near and the far planes. These should be clipped
1376 tcu::Vec4( 0.1f, 0.0f, 1.1f, 1.0f),
1377 tcu::Vec4(-0.1f, 0.0f, -1.1f, 1.0f),
1378 tcu::Vec4(-0.0f, -0.1f, 1.1f, 1.0f),
1379 tcu::Vec4( 0.0f, 0.1f, -1.1f, 1.0f)
1380 };
1381
1382 addChild(new PointCase(m_context, "point_z_clip", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 1.0f, VIEWPORT_WHOLE));
1383 addChild(new PointCase(m_context, "point_z_clip_viewport_center", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 1.0f, VIEWPORT_CENTER));
1384 addChild(new PointCase(m_context, "point_z_clip_viewport_corner", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 1.0f, VIEWPORT_CORNER));
1385
1386 addChild(new PointCase(m_context, "point_clip_viewport_center", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 1.0f, VIEWPORT_CENTER));
1387 addChild(new PointCase(m_context, "point_clip_viewport_corner", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 1.0f, VIEWPORT_CORNER));
1388
1389 addChild(new PointCase(m_context, "wide_point_z_clip", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 5.0f, VIEWPORT_WHOLE));
1390 addChild(new PointCase(m_context, "wide_point_z_clip_viewport_center", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 5.0f, VIEWPORT_CENTER));
1391 addChild(new PointCase(m_context, "wide_point_z_clip_viewport_corner", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 5.0f, VIEWPORT_CORNER));
1392
1393 addChild(new PointCase(m_context, "wide_point_clip", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 5.0f, VIEWPORT_WHOLE));
1394 addChild(new PointCase(m_context, "wide_point_clip_viewport_center", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 5.0f, VIEWPORT_CENTER));
1395 addChild(new PointCase(m_context, "wide_point_clip_viewport_corner", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 5.0f, VIEWPORT_CORNER));
1396 }
1397
1398 class LinesTestGroup : public TestCaseGroup
1399 {
1400 public:
1401 LinesTestGroup (Context& context);
1402
1403 void init (void);
1404 };
1405
LinesTestGroup(Context & context)1406 LinesTestGroup::LinesTestGroup (Context& context)
1407 : TestCaseGroup(context, "line", "Line clipping tests")
1408 {
1409 }
1410
init(void)1411 void LinesTestGroup::init (void)
1412 {
1413 const float littleOverViewport = 1.0f + (2.0f / (TEST_CANVAS_SIZE)); // one pixel over the viewport edge in VIEWPORT_WHOLE, half pixels over in the reduced viewport.
1414
1415 // lines
1416 const LineRenderTestCase::ColorlessLineData viewportTestLines[] =
1417 {
1418 // from center to outside of viewport
1419 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.0f, 1.5f, 0.0f, 1.0f)},
1420 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.5f, 1.0f, 0.0f, 1.0f)},
1421 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.5f, 0.0f, 0.0f, 1.0f)},
1422 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.2f, 0.4f, 1.5f, 1.0f)},
1423 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-2.0f, -1.0f, 0.0f, 1.0f)},
1424 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.0f, 0.1f, 0.0f, 0.6f)},
1425
1426 // from outside to inside of viewport
1427 {tcu::Vec4( 1.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.8f, -0.2f, 0.0f, 1.0f)},
1428 {tcu::Vec4( 0.0f, -1.5f, 0.0f, 1.0f), tcu::Vec4( 0.9f, -0.7f, 0.0f, 1.0f)},
1429
1430 // from outside to outside
1431 {tcu::Vec4( 0.0f, -1.3f, 0.0f, 1.0f), tcu::Vec4( 1.3f, 0.0f, 0.0f, 1.0f)},
1432
1433 // outside the viewport, wide lines have fragments in the viewport
1434 {tcu::Vec4(-0.8f, -littleOverViewport, 0.0f, 1.0f), tcu::Vec4( 0.0f, -littleOverViewport, 0.0f, 1.0f)},
1435 {tcu::Vec4(-littleOverViewport - 1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.0f, -littleOverViewport - 1.0f, 0.0f, 1.0f)},
1436 };
1437 const LineRenderTestCase::ColorlessLineData depthTestLines[] =
1438 {
1439 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.3f, 1.0f, 2.0f, 1.0f)},
1440 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.3f, -1.0f, 2.0f, 1.0f)},
1441 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.0f, -1.1f, -2.0f, 1.0f)},
1442 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.0f, 1.1f, -2.0f, 1.0f)},
1443 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.0f, 0.1f, 2.0f, 0.6f)},
1444 };
1445 const LineRenderTestCase::ColorlessLineData longTestLines[] =
1446 {
1447 {tcu::Vec4( -41000.0f, -40000.0f, -1000000.0f, 1.0f), tcu::Vec4( 41000.0f, 40000.0f, 1000000.0f, 1.0f)},
1448 {tcu::Vec4( 41000.0f, -40000.0f, 1000000.0f, 1.0f), tcu::Vec4(-41000.0f, 40000.0f, -1000000.0f, 1.0f)},
1449 {tcu::Vec4( 0.5f, -40000.0f, 100000.0f, 1.0f), tcu::Vec4( 0.5f, 40000.0f, -100000.0f, 1.0f)},
1450 {tcu::Vec4( -0.5f, 40000.0f, 100000.0f, 1.0f), tcu::Vec4(-0.5f, -40000.0f, -100000.0f, 1.0f)},
1451 };
1452
1453 // line attribute clipping
1454 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
1455 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
1456 const tcu::Vec4 lightBlue (0.3f, 0.3f, 1.0f, 1.0f);
1457 const LineRenderTestCase::ColoredLineData colorTestLines[] =
1458 {
1459 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.3f, 1.0f, 2.0f, 1.0f), yellow },
1460 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.3f, -1.0f, 2.0f, 1.0f), lightBlue },
1461 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4(-1.0f, -1.0f, -2.0f, 1.0f), yellow },
1462 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4(-1.0f, 1.0f, -2.0f, 1.0f), lightBlue },
1463 };
1464
1465 // line clipping
1466 addChild(new LineCase(m_context, "line_z_clip", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 1.0f, VIEWPORT_WHOLE));
1467 addChild(new LineCase(m_context, "line_z_clip_viewport_center", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 1.0f, VIEWPORT_CENTER));
1468 addChild(new LineCase(m_context, "line_z_clip_viewport_corner", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 1.0f, VIEWPORT_CORNER));
1469
1470 addChild(new LineCase(m_context, "line_clip_viewport_center", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 1.0f, VIEWPORT_CENTER));
1471 addChild(new LineCase(m_context, "line_clip_viewport_corner", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 1.0f, VIEWPORT_CORNER));
1472
1473 addChild(new LineCase(m_context, "wide_line_z_clip", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 5.0f, VIEWPORT_WHOLE));
1474 addChild(new LineCase(m_context, "wide_line_z_clip_viewport_center", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 5.0f, VIEWPORT_CENTER));
1475 addChild(new LineCase(m_context, "wide_line_z_clip_viewport_corner", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 5.0f, VIEWPORT_CORNER));
1476
1477 addChild(new LineCase(m_context, "wide_line_clip", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 5.0f, VIEWPORT_WHOLE));
1478 addChild(new LineCase(m_context, "wide_line_clip_viewport_center", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 5.0f, VIEWPORT_CENTER));
1479 addChild(new LineCase(m_context, "wide_line_clip_viewport_corner", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 5.0f, VIEWPORT_CORNER));
1480
1481 addChild(new LineCase(m_context, "long_line_clip", "line viewport clipping", DE_ARRAY_BEGIN(longTestLines), DE_ARRAY_END(longTestLines), 1.0f, VIEWPORT_WHOLE, 2));
1482 addChild(new LineCase(m_context, "long_wide_line_clip", "line viewport clipping", DE_ARRAY_BEGIN(longTestLines), DE_ARRAY_END(longTestLines), 5.0f, VIEWPORT_WHOLE, 2));
1483
1484 // line attribute clipping
1485 addChild(new ColoredLineCase(m_context, "line_attrib_clip", "line attribute clipping", DE_ARRAY_BEGIN(colorTestLines), DE_ARRAY_END(colorTestLines), 1.0f, VIEWPORT_WHOLE));
1486 addChild(new ColoredLineCase(m_context, "wide_line_attrib_clip", "line attribute clipping", DE_ARRAY_BEGIN(colorTestLines), DE_ARRAY_END(colorTestLines), 5.0f, VIEWPORT_WHOLE));
1487 }
1488
1489 class PolysTestGroup : public TestCaseGroup
1490 {
1491 public:
1492 PolysTestGroup (Context& context);
1493
1494 void init (void);
1495 };
1496
PolysTestGroup(Context & context)1497 PolysTestGroup::PolysTestGroup (Context& context)
1498 : TestCaseGroup(context, "polygon", "Polygon clipping tests")
1499 {
1500 }
1501
init(void)1502 void PolysTestGroup::init (void)
1503 {
1504 const float large = 100000.0f;
1505 const float offset = 0.9f;
1506 const tcu::Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
1507 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
1508 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
1509 const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
1510
1511 // basic cases
1512 {
1513 const TriangleCase::TriangleData viewportPolys[] =
1514 {
1515 // one vertex clipped
1516 {tcu::Vec4(-0.8f, -0.2f, 0.0f, 1.0f), white, tcu::Vec4(-0.8f, 0.2f, 0.0f, 1.0f), white, tcu::Vec4(-1.3f, 0.05f, 0.0f, 1.0f), white},
1517
1518 // two vertices clipped
1519 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), white, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), white, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), white},
1520
1521 // three vertices clipped
1522 {tcu::Vec4(-1.1f, 0.6f, 0.0f, 1.0f), white, tcu::Vec4(-1.1f, 1.1f, 0.0f, 1.0f), white, tcu::Vec4(-0.6f, 1.1f, 0.0f, 1.0f), white},
1523 {tcu::Vec4( 0.8f, 1.1f, 0.0f, 1.0f), white, tcu::Vec4( 0.95f,-1.1f, 0.0f, 1.0f), white, tcu::Vec4( 3.0f, 0.0f, 0.0f, 1.0f), white},
1524 };
1525 const TriangleCase::TriangleData depthPolys[] =
1526 {
1527 // one vertex clipped to Z+
1528 {tcu::Vec4(-0.2f, 0.7f, 0.0f, 1.0f), white, tcu::Vec4( 0.2f, 0.7f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, 0.9f, 2.0f, 1.0f), white},
1529
1530 // two vertices clipped to Z-
1531 {tcu::Vec4( 0.9f, 0.4f, -1.5f, 1.0f), white, tcu::Vec4( 0.9f, -0.4f, -1.5f, 1.0f), white, tcu::Vec4( 0.6f, 0.0f, 0.0f, 1.0f), white},
1532
1533 // three vertices clipped
1534 {tcu::Vec4(-0.9f, 0.6f, -2.0f, 1.0f), white, tcu::Vec4(-0.9f, -0.6f, -2.0f, 1.0f), white, tcu::Vec4(-0.4f, 0.0f, 2.0f, 1.0f), white},
1535
1536 // three vertices clipped by X, Y and Z
1537 {tcu::Vec4( 0.0f, -1.2f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, 0.5f, -1.5f, 1.0f), white, tcu::Vec4( 1.2f, -0.9f, 0.0f, 1.0f), white},
1538 };
1539 const TriangleCase::TriangleData largePolys[] =
1540 {
1541 // one vertex clipped
1542 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, -large, 2.0f, 1.0f), white},
1543
1544 // two vertices clipped
1545 {tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f), white, tcu::Vec4( large, 0.5f, 0.0f, 1.0f), white, tcu::Vec4( 0.5f, large, 0.0f, 1.0f), white},
1546
1547 // three vertices clipped
1548 {tcu::Vec4(-0.9f, -large, 0.0f, 1.0f), white, tcu::Vec4(-1.1f, -large, 0.0f, 1.0f), white, tcu::Vec4(-0.9f, large, 0.0f, 1.0f), white},
1549 };
1550 const TriangleCase::TriangleData largeDepthPolys[] =
1551 {
1552 // one vertex clipped
1553 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, -large, large, 1.0f), white},
1554
1555 // two vertices clipped
1556 {tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f), white, tcu::Vec4( 0.9f, large/2, -large, 1.0f), white, tcu::Vec4( large/4, 0.0f, -large, 1.0f), white},
1557
1558 // three vertices clipped
1559 {tcu::Vec4(-0.9f, large/4, large, 1.0f), white, tcu::Vec4(-0.5f, -large/4, -large, 1.0f), white, tcu::Vec4(-0.2f, large/4, large, 1.0f), white},
1560 };
1561 const TriangleCase::TriangleData attribPolys[] =
1562 {
1563 // one vertex clipped to edge, large
1564 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -large, 2.0f, 1.0f), blue},
1565
1566 // two vertices clipped to edges
1567 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1568
1569 // two vertices clipped to edges, with non-uniform w
1570 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1571
1572 // three vertices clipped, large, Z
1573 {tcu::Vec4(-0.9f, large/4, large, 1.0f), red, tcu::Vec4(-0.5f, -large/4, -large, 1.0f), yellow, tcu::Vec4(-0.2f, large/4, large, 1.0f), blue},
1574 };
1575
1576 addChild(new TriangleCase(m_context, "poly_clip_viewport_center", "polygon viewport clipping", DE_ARRAY_BEGIN(viewportPolys), DE_ARRAY_END(viewportPolys), VIEWPORT_CENTER));
1577 addChild(new TriangleCase(m_context, "poly_clip_viewport_corner", "polygon viewport clipping", DE_ARRAY_BEGIN(viewportPolys), DE_ARRAY_END(viewportPolys), VIEWPORT_CORNER));
1578
1579 addChild(new TriangleCase(m_context, "poly_z_clip", "polygon z clipping", DE_ARRAY_BEGIN(depthPolys), DE_ARRAY_END(depthPolys), VIEWPORT_WHOLE));
1580 addChild(new TriangleCase(m_context, "poly_z_clip_viewport_center", "polygon z clipping", DE_ARRAY_BEGIN(depthPolys), DE_ARRAY_END(depthPolys), VIEWPORT_CENTER));
1581 addChild(new TriangleCase(m_context, "poly_z_clip_viewport_corner", "polygon z clipping", DE_ARRAY_BEGIN(depthPolys), DE_ARRAY_END(depthPolys), VIEWPORT_CORNER));
1582
1583 addChild(new TriangleCase(m_context, "large_poly_clip_viewport_center", "polygon viewport clipping", DE_ARRAY_BEGIN(largePolys), DE_ARRAY_END(largePolys), VIEWPORT_CENTER));
1584 addChild(new TriangleCase(m_context, "large_poly_clip_viewport_corner", "polygon viewport clipping", DE_ARRAY_BEGIN(largePolys), DE_ARRAY_END(largePolys), VIEWPORT_CORNER));
1585
1586 addChild(new TriangleCase(m_context, "large_poly_z_clip", "polygon z clipping", DE_ARRAY_BEGIN(largeDepthPolys), DE_ARRAY_END(largeDepthPolys), VIEWPORT_WHOLE));
1587 addChild(new TriangleCase(m_context, "large_poly_z_clip_viewport_center", "polygon z clipping", DE_ARRAY_BEGIN(largeDepthPolys), DE_ARRAY_END(largeDepthPolys), VIEWPORT_CENTER));
1588 addChild(new TriangleCase(m_context, "large_poly_z_clip_viewport_corner", "polygon z clipping", DE_ARRAY_BEGIN(largeDepthPolys), DE_ARRAY_END(largeDepthPolys), VIEWPORT_CORNER));
1589
1590 addChild(new TriangleAttributeCase(m_context, "poly_attrib_clip", "polygon clipping", DE_ARRAY_BEGIN(attribPolys), DE_ARRAY_END(attribPolys), VIEWPORT_WHOLE));
1591 addChild(new TriangleAttributeCase(m_context, "poly_attrib_clip_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(attribPolys), DE_ARRAY_END(attribPolys), VIEWPORT_CENTER));
1592 addChild(new TriangleAttributeCase(m_context, "poly_attrib_clip_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(attribPolys), DE_ARRAY_END(attribPolys), VIEWPORT_CORNER));
1593 }
1594
1595 // multiple polygons
1596 {
1597 {
1598 const TriangleAttributeCase::TriangleData polys[] =
1599 {
1600 // one vertex clipped to edge
1601 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1602
1603 // two vertices clipped to edges
1604 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1605
1606 // two vertices clipped to edges, with non-uniform w
1607 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1608 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1609 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1610 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1611
1612 // three vertices clipped, Z
1613 {tcu::Vec4(-0.9f, offset/4, offset, 1.0f), red, tcu::Vec4(-0.5f, -offset/4, -offset, 1.0f), yellow, tcu::Vec4(-0.2f, offset/4, offset, 1.0f), blue},
1614 };
1615
1616 addChild(new TriangleAttributeCase(m_context, "multiple_0", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1617 addChild(new TriangleAttributeCase(m_context, "multiple_0_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1618 addChild(new TriangleAttributeCase(m_context, "multiple_0_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1619 }
1620
1621 {
1622 const TriangleAttributeCase::TriangleData polys[] =
1623 {
1624 // one vertex clipped to z
1625 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1626
1627 // two vertices clipped to edges
1628 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1629
1630 // two vertices clipped to edges, with non-uniform w
1631 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1632 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1633 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1634 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1635 };
1636
1637 addChild(new TriangleAttributeCase(m_context, "multiple_1", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1638 addChild(new TriangleAttributeCase(m_context, "multiple_1_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1639 addChild(new TriangleAttributeCase(m_context, "multiple_1_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1640 }
1641
1642 {
1643 const TriangleAttributeCase::TriangleData polys[] =
1644 {
1645 // one vertex clipped to z
1646 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1647
1648 // two vertices clipped to edges
1649 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1650
1651 // two vertices clipped to edges
1652 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1653 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1654 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1655 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1656 };
1657
1658 addChild(new TriangleAttributeCase(m_context, "multiple_2", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1659 addChild(new TriangleAttributeCase(m_context, "multiple_2_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1660 addChild(new TriangleAttributeCase(m_context, "multiple_2_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1661 }
1662
1663 {
1664 const TriangleAttributeCase::TriangleData polys[] =
1665 {
1666 // one vertex clipped to z
1667 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, -2.0f, 1.0f), blue},
1668
1669 // two vertices clipped to edges
1670 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1671 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1672 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1673 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1674 };
1675
1676 addChild(new TriangleAttributeCase(m_context, "multiple_3", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1677 addChild(new TriangleAttributeCase(m_context, "multiple_3_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1678 addChild(new TriangleAttributeCase(m_context, "multiple_3_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1679 }
1680
1681 {
1682 const TriangleAttributeCase::TriangleData polys[] =
1683 {
1684 // one vertex clipped to z
1685 {tcu::Vec4(0.3f, 0.2f, 0.0f, 1.0f), red, tcu::Vec4( 0.3f, -0.2f, 0.0f, 1.0f), yellow, tcu::Vec4( offset, 0.0f, 2.0f, 1.0f), blue},
1686
1687 // two vertices clipped to edges
1688 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1689 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1690 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1691 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1692 };
1693
1694 addChild(new TriangleAttributeCase(m_context, "multiple_4", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1695 addChild(new TriangleAttributeCase(m_context, "multiple_4_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1696 addChild(new TriangleAttributeCase(m_context, "multiple_4_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1697 }
1698
1699 {
1700 const TriangleAttributeCase::TriangleData polys[] =
1701 {
1702 // one vertex clipped to z
1703 {tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f), red, tcu::Vec4(-0.3f, -0.2f, 0.0f, 1.0f), yellow, tcu::Vec4(-offset, 0.0f, 2.0f, 1.0f), blue},
1704
1705 // two vertices clipped to edges
1706 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1707 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1708 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1709 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1710 };
1711
1712 addChild(new TriangleAttributeCase(m_context, "multiple_5", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1713 addChild(new TriangleAttributeCase(m_context, "multiple_5_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1714 addChild(new TriangleAttributeCase(m_context, "multiple_5_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1715 }
1716
1717 {
1718 const TriangleAttributeCase::TriangleData polys[] =
1719 {
1720 // one vertex clipped to z
1721 {tcu::Vec4(-0.2f, 0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, 0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, offset, 2.0f, 1.0f), blue},
1722
1723 // two vertices clipped to edges
1724 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1725 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1726 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1727 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1728 };
1729
1730 addChild(new TriangleAttributeCase(m_context, "multiple_6", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1731 addChild(new TriangleAttributeCase(m_context, "multiple_6_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1732 addChild(new TriangleAttributeCase(m_context, "multiple_6_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1733 }
1734
1735 {
1736 const TriangleAttributeCase::TriangleData polys[] =
1737 {
1738 // two vertices clipped to edges
1739 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1740
1741 // two vertices clipped to edges
1742 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue},
1743 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue},
1744 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue},
1745 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue},
1746 };
1747
1748 addChild(new TriangleAttributeCase(m_context, "multiple_7", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1749 addChild(new TriangleAttributeCase(m_context, "multiple_7_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1750 addChild(new TriangleAttributeCase(m_context, "multiple_7_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1751 }
1752
1753 {
1754 const TriangleAttributeCase::TriangleData polys[] =
1755 {
1756 // one vertex clipped to z
1757 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1758
1759 // fill
1760 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), white},
1761 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), blue},
1762 };
1763
1764 addChild(new TriangleAttributeCase(m_context, "multiple_8", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1765 addChild(new TriangleAttributeCase(m_context, "multiple_8_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1766 addChild(new TriangleAttributeCase(m_context, "multiple_8_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1767 }
1768
1769 {
1770 const TriangleAttributeCase::TriangleData polys[] =
1771 {
1772 // one vertex clipped to z
1773 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1774
1775 // fill
1776 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), red},
1777 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue},
1778 };
1779
1780 addChild(new TriangleAttributeCase(m_context, "multiple_9", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1781 addChild(new TriangleAttributeCase(m_context, "multiple_9_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1782 addChild(new TriangleAttributeCase(m_context, "multiple_9_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1783 }
1784
1785 {
1786 const TriangleAttributeCase::TriangleData polys[] =
1787 {
1788 // one vertex clipped to z
1789 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1790
1791 // fill
1792 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), white},
1793 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), red},
1794 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue},
1795 };
1796
1797 addChild(new TriangleAttributeCase(m_context, "multiple_10", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1798 addChild(new TriangleAttributeCase(m_context, "multiple_10_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1799 addChild(new TriangleAttributeCase(m_context, "multiple_10_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1800 }
1801
1802 {
1803 const TriangleAttributeCase::TriangleData polys[] =
1804 {
1805 // one vertex clipped to z
1806 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue},
1807
1808 // fill
1809 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), white},
1810 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), red},
1811 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue},
1812 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), yellow, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), yellow, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), yellow},
1813 };
1814
1815 addChild(new TriangleAttributeCase(m_context, "multiple_11", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE));
1816 addChild(new TriangleAttributeCase(m_context, "multiple_11_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER));
1817 addChild(new TriangleAttributeCase(m_context, "multiple_11_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER));
1818 }
1819 }
1820 }
1821
1822 class PolyEdgesTestGroup : public TestCaseGroup
1823 {
1824 public:
1825 PolyEdgesTestGroup (Context& context);
1826
1827 void init (void);
1828 };
1829
PolyEdgesTestGroup(Context & context)1830 PolyEdgesTestGroup::PolyEdgesTestGroup (Context& context)
1831 : TestCaseGroup(context, "polygon_edge", "Polygon clipping edge tests")
1832 {
1833 }
1834
init(void)1835 void PolyEdgesTestGroup::init (void)
1836 {
1837 // Quads via origin
1838 const struct Quad
1839 {
1840 tcu::Vec3 d1; // tangent
1841 tcu::Vec3 d2; // bi-tangent
1842 } quads[] =
1843 {
1844 { tcu::Vec3( 1, 1, 1), tcu::Vec3( 1, -1, 1) },
1845 { tcu::Vec3( 1, 1, 1), tcu::Vec3(-1, 1.1f, 1) },
1846 { tcu::Vec3( 1, 1, 0), tcu::Vec3(-1, 1, 0) },
1847 { tcu::Vec3( 0, 1, 0), tcu::Vec3( 1, 0, 0) },
1848 { tcu::Vec3( 0, 1, 0), tcu::Vec3( 1, 0.1f, 0) },
1849 };
1850
1851 // Quad near edge
1852 const struct EdgeQuad
1853 {
1854 tcu::Vec3 d1; // tangent
1855 tcu::Vec3 d2; // bi-tangent
1856 tcu::Vec3 center; // center
1857 } edgeQuads[] =
1858 {
1859 { tcu::Vec3( 1, 0.01f, 0 ), tcu::Vec3( 0, 0.01f, 0), tcu::Vec3( 0, 0.99f, 0 ) }, // edge near x-plane
1860 { tcu::Vec3( 0.01f, 1, 0 ), tcu::Vec3( 0.01f, 0, 0), tcu::Vec3( 0.99f, 0, 0 ) }, // edge near y-plane
1861 { tcu::Vec3( 1, 1, 0.01f), tcu::Vec3( 0.01f, -0.01f, 0), tcu::Vec3( 0, 0, 0.99f) }, // edge near z-plane
1862 };
1863
1864 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(quads); ++ndx)
1865 addChild(new QuadFillTest(m_context, (std::string("quad_at_origin_") + de::toString(ndx)).c_str(), "polygon edge clipping", VIEWPORT_CENTER, quads[ndx].d1, quads[ndx].d2));
1866 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(edgeQuads); ++ndx)
1867 addChild(new QuadFillTest(m_context, (std::string("quad_near_edge_") + de::toString(ndx)).c_str(), "polygon edge clipping", VIEWPORT_CENTER, edgeQuads[ndx].d1, edgeQuads[ndx].d2, edgeQuads[ndx].center));
1868
1869 // Polyfan
1870 addChild(new TriangleFanFillTest(m_context, "poly_fan", "polygon edge clipping", VIEWPORT_CENTER));
1871 }
1872
1873 class PolyVertexClipTestGroup : public TestCaseGroup
1874 {
1875 public:
1876 PolyVertexClipTestGroup (Context& context);
1877
1878 void init (void);
1879 };
1880
PolyVertexClipTestGroup(Context & context)1881 PolyVertexClipTestGroup::PolyVertexClipTestGroup (Context& context)
1882 : TestCaseGroup(context, "triangle_vertex", "Clip n vertices")
1883 {
1884 }
1885
init(void)1886 void PolyVertexClipTestGroup::init (void)
1887 {
1888 const float far = 30000.0f;
1889 const tcu::IVec3 outside[] =
1890 {
1891 // outside one clipping plane
1892 tcu::IVec3(-1, 0, 0),
1893 tcu::IVec3( 1, 0, 0),
1894 tcu::IVec3( 0, 1, 0),
1895 tcu::IVec3( 0, -1, 0),
1896 tcu::IVec3( 0, 0, 1),
1897 tcu::IVec3( 0, 0, -1),
1898
1899 // outside two clipping planes
1900 tcu::IVec3(-1, -1, 0),
1901 tcu::IVec3( 1, -1, 0),
1902 tcu::IVec3( 1, 1, 0),
1903 tcu::IVec3(-1, 1, 0),
1904
1905 tcu::IVec3(-1, 0, -1),
1906 tcu::IVec3( 1, 0, -1),
1907 tcu::IVec3( 1, 0, 1),
1908 tcu::IVec3(-1, 0, 1),
1909
1910 tcu::IVec3( 0, -1, -1),
1911 tcu::IVec3( 0, 1, -1),
1912 tcu::IVec3( 0, 1, 1),
1913 tcu::IVec3( 0, -1, 1),
1914
1915 // outside three clipping planes
1916 tcu::IVec3(-1, -1, 1),
1917 tcu::IVec3( 1, -1, 1),
1918 tcu::IVec3( 1, 1, 1),
1919 tcu::IVec3(-1, 1, 1),
1920
1921 tcu::IVec3(-1, -1, -1),
1922 tcu::IVec3( 1, -1, -1),
1923 tcu::IVec3( 1, 1, -1),
1924 tcu::IVec3(-1, 1, -1),
1925 };
1926
1927 de::Random rnd(0xabcdef);
1928
1929 TestCaseGroup* clipOne = new TestCaseGroup(m_context, "clip_one", "Clip one vertex");
1930 TestCaseGroup* clipTwo = new TestCaseGroup(m_context, "clip_two", "Clip two vertices");
1931 TestCaseGroup* clipThree = new TestCaseGroup(m_context, "clip_three", "Clip three vertices");
1932
1933 addChild(clipOne);
1934 addChild(clipTwo);
1935 addChild(clipThree);
1936
1937 // Test 1 point clipped
1938 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(outside); ++ndx)
1939 {
1940 const float w0 = rnd.getFloat(0.2f, 16.0f);
1941 const float w1 = rnd.getFloat(0.2f, 16.0f);
1942 const float w2 = rnd.getFloat(0.2f, 16.0f);
1943 const tcu::Vec4 white = tcu::Vec4( 1, 1, 1, 1);
1944 const tcu::Vec3 r0 = tcu::Vec3( 0.2f, 0.3f, 0);
1945 const tcu::Vec3 r1 = tcu::Vec3(-0.3f, -0.4f, 0);
1946 const tcu::Vec3 r2 = IVec3ToVec3(outside[ndx]) * far;
1947 const tcu::Vec4 p0 = tcu::Vec4(r0.x() * w0, r0.y() * w0, r0.z() * w0, w0);
1948 const tcu::Vec4 p1 = tcu::Vec4(r1.x() * w1, r1.y() * w1, r1.z() * w1, w1);
1949 const tcu::Vec4 p2 = tcu::Vec4(r2.x() * w2, r2.y() * w2, r2.z() * w2, w2);
1950
1951 const std::string name = std::string("clip") +
1952 (outside[ndx].x() > 0 ? "_pos_x" : (outside[ndx].x() < 0 ? "_neg_x" : "")) +
1953 (outside[ndx].y() > 0 ? "_pos_y" : (outside[ndx].y() < 0 ? "_neg_y" : "")) +
1954 (outside[ndx].z() > 0 ? "_pos_z" : (outside[ndx].z() < 0 ? "_neg_z" : ""));
1955
1956 const TriangleCase::TriangleData triangle = {p0, white, p1, white, p2, white};
1957
1958 // don't try to test with degenerate (or almost degenerate) triangles
1959 if (outside[ndx].x() == 0 && outside[ndx].y() == 0)
1960 continue;
1961
1962 clipOne->addChild(new TriangleCase(m_context, name.c_str(), "clip one vertex", &triangle, &triangle + 1, VIEWPORT_CENTER));
1963 }
1964
1965 // Special triangles for "clip_z" cases, default triangles is not good, since it has very small visible area => problems with MSAA
1966 {
1967 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1968
1969 const TriangleCase::TriangleData posZTriangle =
1970 {
1971 tcu::Vec4( 0.0f, -0.7f, -0.9f, 1.0f), white,
1972 tcu::Vec4( 0.8f, 0.0f, -0.7f, 1.0f), white,
1973 tcu::Vec4(-0.9f, 0.9f, 3.0f, 1.0f), white
1974 };
1975 const TriangleCase::TriangleData negZTriangle =
1976 {
1977 tcu::Vec4( 0.0f, -0.7f, 0.9f, 1.0f), white,
1978 tcu::Vec4( 0.4f, 0.0f, 0.7f, 1.0f), white,
1979 tcu::Vec4(-0.9f, 0.9f, -3.0f, 1.0f), white
1980 };
1981
1982 clipOne->addChild(new TriangleCase(m_context, "clip_pos_z", "clip one vertex", &posZTriangle, &posZTriangle + 1, VIEWPORT_CENTER));
1983 clipOne->addChild(new TriangleCase(m_context, "clip_neg_z", "clip one vertex", &negZTriangle, &negZTriangle + 1, VIEWPORT_CENTER));
1984 }
1985
1986 // Test 2 points clipped
1987 for (int ndx1 = 0; ndx1 < DE_LENGTH_OF_ARRAY(outside); ++ndx1)
1988 for (int ndx2 = ndx1 + 1; ndx2 < DE_LENGTH_OF_ARRAY(outside); ++ndx2)
1989 {
1990 const float w0 = rnd.getFloat(0.2f, 16.0f);
1991 const float w1 = rnd.getFloat(0.2f, 16.0f);
1992 const float w2 = rnd.getFloat(0.2f, 16.0f);
1993 const tcu::Vec4 white = tcu::Vec4( 1, 1, 1, 1);
1994 const tcu::Vec3 r0 = tcu::Vec3( 0.2f, 0.3f, 0);
1995 const tcu::IVec3 r1 = outside[ndx1];
1996 const tcu::IVec3 r2 = outside[ndx2];
1997 const tcu::Vec4 p0 = tcu::Vec4(r0.x() * w0, r0.y() * w0, r0.z() * w0, w0);
1998 const tcu::Vec4 p1 = tcu::Vec4(float(r1.x()) * far * w1, float(r1.y()) * far * w1, float(r1.z()) * far * w1, w1);
1999 const tcu::Vec4 p2 = tcu::Vec4(float(r2.x()) * far * w2, float(r2.y()) * far * w2, float(r2.z()) * far * w2, w2);
2000
2001 const std::string name = std::string("clip") +
2002 (outside[ndx1].x() > 0 ? "_pos_x" : (outside[ndx1].x() < 0 ? "_neg_x" : "")) +
2003 (outside[ndx1].y() > 0 ? "_pos_y" : (outside[ndx1].y() < 0 ? "_neg_y" : "")) +
2004 (outside[ndx1].z() > 0 ? "_pos_z" : (outside[ndx1].z() < 0 ? "_neg_z" : "")) +
2005 "_and" +
2006 (outside[ndx2].x() > 0 ? "_pos_x" : (outside[ndx2].x() < 0 ? "_neg_x" : "")) +
2007 (outside[ndx2].y() > 0 ? "_pos_y" : (outside[ndx2].y() < 0 ? "_neg_y" : "")) +
2008 (outside[ndx2].z() > 0 ? "_pos_z" : (outside[ndx2].z() < 0 ? "_neg_z" : ""));
2009
2010 const TriangleCase::TriangleData triangle = {p0, white, p1, white, p2, white};
2011
2012 if (twoPointClippedTriangleInvisible(r0, r1, r2))
2013 continue;
2014
2015 clipTwo->addChild(new TriangleCase(m_context, name.c_str(), "clip two vertices", &triangle, &triangle + 1, VIEWPORT_CENTER));
2016 }
2017
2018 // Test 3 points clipped
2019 for (int ndx1 = 0; ndx1 < DE_LENGTH_OF_ARRAY(outside); ++ndx1)
2020 for (int ndx2 = ndx1 + 1; ndx2 < DE_LENGTH_OF_ARRAY(outside); ++ndx2)
2021 for (int ndx3 = ndx2 + 1; ndx3 < DE_LENGTH_OF_ARRAY(outside); ++ndx3)
2022 {
2023 const float w0 = rnd.getFloat(0.2f, 16.0f);
2024 const float w1 = rnd.getFloat(0.2f, 16.0f);
2025 const float w2 = rnd.getFloat(0.2f, 16.0f);
2026 const tcu::Vec4 white = tcu::Vec4(1, 1, 1, 1);
2027 const tcu::IVec3 r0 = outside[ndx1];
2028 const tcu::IVec3 r1 = outside[ndx2];
2029 const tcu::IVec3 r2 = outside[ndx3];
2030 const tcu::Vec4 p0 = tcu::Vec4(float(r0.x()) * far * w0, float(r0.y()) * far * w0, float(r0.z()) * far * w0, w0);
2031 const tcu::Vec4 p1 = tcu::Vec4(float(r1.x()) * far * w1, float(r1.y()) * far * w1, float(r1.z()) * far * w1, w1);
2032 const tcu::Vec4 p2 = tcu::Vec4(float(r2.x()) * far * w2, float(r2.y()) * far * w2, float(r2.z()) * far * w2, w2);
2033
2034 // ignore cases where polygon is along xz or yz planes
2035 if (pointsOnLine(r0.swizzle(0, 1), r1.swizzle(0, 1), r2.swizzle(0, 1)))
2036 continue;
2037
2038 // triangle is visible only if it intersects the origin
2039 if (pointOnTriangle(tcu::IVec3(0, 0, 0), r0, r1, r2))
2040 {
2041 const TriangleCase::TriangleData triangle = {p0, white, p1, white, p2, white};
2042 const std::string name = std::string("clip") +
2043 (outside[ndx1].x() > 0 ? "_pos_x" : (outside[ndx1].x() < 0 ? "_neg_x" : "")) +
2044 (outside[ndx1].y() > 0 ? "_pos_y" : (outside[ndx1].y() < 0 ? "_neg_y" : "")) +
2045 (outside[ndx1].z() > 0 ? "_pos_z" : (outside[ndx1].z() < 0 ? "_neg_z" : "")) +
2046 "_and" +
2047 (outside[ndx2].x() > 0 ? "_pos_x" : (outside[ndx2].x() < 0 ? "_neg_x" : "")) +
2048 (outside[ndx2].y() > 0 ? "_pos_y" : (outside[ndx2].y() < 0 ? "_neg_y" : "")) +
2049 (outside[ndx2].z() > 0 ? "_pos_z" : (outside[ndx2].z() < 0 ? "_neg_z" : "")) +
2050 "_and" +
2051 (outside[ndx3].x() > 0 ? "_pos_x" : (outside[ndx3].x() < 0 ? "_neg_x" : "")) +
2052 (outside[ndx3].y() > 0 ? "_pos_y" : (outside[ndx3].y() < 0 ? "_neg_y" : "")) +
2053 (outside[ndx3].z() > 0 ? "_pos_z" : (outside[ndx3].z() < 0 ? "_neg_z" : ""));
2054
2055 clipThree->addChild(new TriangleCase(m_context, name.c_str(), "clip three vertices", &triangle, &triangle + 1, VIEWPORT_CENTER));
2056 }
2057 }
2058 }
2059
2060 } // anonymous
2061
ClippingTests(Context & context)2062 ClippingTests::ClippingTests (Context& context)
2063 : TestCaseGroup(context, "clipping", "Clipping tests")
2064 {
2065 }
2066
~ClippingTests(void)2067 ClippingTests::~ClippingTests (void)
2068 {
2069 }
2070
init(void)2071 void ClippingTests::init (void)
2072 {
2073 addChild(new PointsTestGroup (m_context));
2074 addChild(new LinesTestGroup (m_context));
2075 addChild(new PolysTestGroup (m_context));
2076 addChild(new PolyEdgesTestGroup (m_context));
2077 addChild(new PolyVertexClipTestGroup(m_context));
2078 }
2079
2080 } // Functional
2081 } // gles3
2082 } // deqp
2083